Playing non-file audio

New to FreeBASIC? Post your questions here.
tone
Posts: 26
Joined: Dec 17, 2019 21:31

Playing non-file audio

Post by tone »

Hi,

I have not linked to a library in c over 5 years, and haven't linked to a freebasic library in over ten years, so I'm really rusty. So if anyone can suggest any useful libraries to download, that would be interesting.

I haven't tried FMOD, BASS, SDL_MIXER, although I think back in the day I did use one for playing .mp3s. I am really new to linux and I read that the kernal uses something called ALSA to play audio (I assume it's like a driver). However, that seems like it may be too much effort to use directly.

What I am specifically interested in is making mathematical functions audio output on the operating system. For instance imagine a programme which outputted a sine wave at various frequencies. Which library would be the best, and any advise as to how I would tell it the amplitude over time? (Like a varying sine wave).

Thanks in advance,

Rob
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Playing non-file audio

Post by badidea »

Some suggestions:
* Audio library for FreeBasic - Features
* fbsound 1.1 (dynamic) Windows/Linux 32 and 64-bit (wav mp3 ogg mod it xm s3m)
* Help testing ALSA streaming
fbsound is more focused on playing different file formats, but you can also create your own wave forms in memory (with some additional functions of your own).
tone
Posts: 26
Joined: Dec 17, 2019 21:31

Re: Playing non-file audio

Post by tone »

Thanks for the reply.
It's really late where I am and I have to go to bed ASAP, however I just searched 'fbsound' in the manual and Adobe reader didn't find it, do you happen to know roughly which page or section it's in?

I had a super quick look at the 'help testing ALSA' link you gave, so do I have it correct that I can stream data to it directly? I.e. not from a file, but just generate it 'live' from the code?

Thanks again!
jdebord
Posts: 547
Joined: May 27, 2005 6:20
Location: Limoges, France
Contact:

Re: Playing non-file audio

Post by jdebord »

FBSound is here:

http://shiny3d.de/public/fbsound/fbsound-1.1.zip

See the sample program fbs_create_wave.bas in the `tests` subdirectory.
tone
Posts: 26
Joined: Dec 17, 2019 21:31

Re: Playing non-file audio

Post by tone »

I tried the fbs_create_wave.bas code (I'm on a windows machine unfortunately ATM), thank you.

Being so out-of-practice I'm struggling on a bit of the detail for how it works (wish where was a few more comments). One thing I'm wondering is that: Is the code actually dependent on time, or does it just execute at the speed of the CPU? I.e. will it sound the same on a really old PC as it would on a very high end modern CPU?

I presume that 44100 is the sampling frequency (Hz), in the fbs_Create_Wave function, what is the @hWave used for? I remember that the @ means it's specifying an address in the memory, but I need to revise how pointers work.

Similarly, why is the 'i' multiplied by 2 here in the pSamples memory: pSamples[i*2 ] ?
I assume this is used similarly to an array? Again, I'm rusty.

Is sin in degrees or radians? I assume radians because "wstep=PI2/44100.0 * 400.0", so what is the '400' for? Because to sample 44100 times I wouldn't expect the 400 to be there. However, by modifying it I see that it IS necessary.

Note: I do get the error: FBS_INIT() message, I think it's caused by my AVG antivirus, but the code then does execute.

Thank you in advance
tone
Posts: 26
Joined: Dec 17, 2019 21:31

Re: Playing non-file audio

Post by tone »

Hi,
All my questions from my last post still apply (I.e. what some of the constants were for), however I've been playing with the code to try and make it be a bit flexible with the amplitude and frequency of the sine wave and I'm having an issue. The issue is that when you loop fbs_play_sound, the initial instance still plays forever and I can't kill it, so when it loops again with a slightly different sine wave it is a superposition. Similarly, I tried CLSing to wipe off the old waveform, but it just clears so fast you can't see the next loopings waveform, and the screen just looks blank. Can anyone please offer some tips on how to remedy this?
Here is the code (use the keyboard arrow keys to do volume and frequency changes):

Code: Select all

'  #######################
' # fbs_create_wave.bas #
'#######################

'#include "../inc/fbsound.bi"
#include "../inc/fbsound_dynamic.bi"

' example of:
' fbs_Create_Wave(nSamples,@hWAve,@lpSamples)

function GetKeyNB() as integer
    dim as string key
    key = inkey
    select case len(key)
        case 0
            return 0
        case 1
            return key[0]
        case 2
            return key[0] + (key[1] shl 8)
    end select
end function

const data_path = "../data/"

chdir(exepath())

' only if not same as exe path
' fbs_Set_PlugPath("./")

if fbs_Init()=false then
  print "error: FBS_INIT() " & FBS_Get_PlugError()
  beep : sleep : end 1
end if


dim as integer nSamples = 44100
dim as integer hWave,hSound
dim as double  w,wstep=PI2/44100.0 * 400.0
dim as FBS_SAMPLE ptr pSamples
dim as FBS_SAMPLE ptr pS,pP,pE

' !!! create window before init fbsound !!!
dim as integer sw=640,sh=480
screenres sw,sh

dim as double j = 1
dim as integer key
dim as integer A = 4000



do

key = GetKeyNB
select case(hex(key))
case "48FF"
    A = A + 1000
case "50FF"
    A = A - 1000
case "4DFF"
    j = j + 0.1
case "4BFF"
    j = j - 0.1
end select

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=sin(w*j   )*A:w+=wstep
  ' left channel
  pSamples[i*2+1]=sin(w*j+PI)*A:w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)

sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

fbs_Play_Sound(hSound,-1) ' loop endless

loop until key = 27
print "playing clean sin wave endless"
sleep
end
jdebord
Posts: 547
Joined: May 27, 2005 6:20
Location: Limoges, France
Contact:

Re: Playing non-file audio

Post by jdebord »

If I understand correctly :

The samples are stored in an array of signed 16-bit integers. The values are -32768 to 32767. There are 65536 possible values. The dynamic is 20*log(65536) ~ 96 dB

For stereo the channels L = left and R = right are alterned :

Code: Select all

channel:	L	R	L	R	...	L	R
index:	0	1	2	3	...	n-2	n-1


where n is the number of samples.

This explains the multiplication by 2

Also, in the sample program 400 is the sound frequency in Hz
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Playing non-file audio

Post by badidea »

Yes, if you look at 'fbs_init.bas' you see some details:

' FBS_Init( [playbackrate in Hz.] optional default 44100
' ,[number of channels] optional default 2
' ,[number of buffers] optional default 3
' ,[frames per buffer] optional default 2048
' ,[nPlugIndex] optional default 0 = first
' ,[nDeviceIndex] optional default 0 = first) as boolean


So 2 channels: left & right. What you also see is buffers. These data buffer are transmitted [note1] to the soundcard/chip. As long as the CPU keeps sending these buffers in time, the sounds keeps going at a fixed rate (44100 Hz in this case).

[note1] Not sure if the data buffer is actually copied or if the soundchip directly plays the data at the location pointed to. But not so important for the functionality.

And yes, sin() uses radians 0..2*π for 1 full cycle.
tone
Posts: 26
Joined: Dec 17, 2019 21:31

Re: Playing non-file audio

Post by tone »

Ah, okay you're getting things to make more sense to me. I haven't thought about db in a long time, so that is informative. Also, I was making a conceptual mistake in the size of the pSamples array, but I get it now, thanks.

Thanks for explaining that the 400 is the frequency in hz. So do you know if this is actually based on time, like some sort of operating system clock. Or is just like 400 hz, but might vary running the code on various CPUs of different computing power?

In the code, why do they get the sine waves to change colour half way across the screen? Because all you need is:

Code: Select all

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next
Any tips on how to kill the fbs_play_sound function, so I can re-call it at a different frequency?

P.S. I thought of a dodgy way to delete the old sine waves when the amplitude of frequency change, but I don't really think it's the best way, I modified the case statement code, it just puts black sine waves over the old ones, but it doesn't work very well because some dots remain:

Code: Select all

select case(hex(key))
case "48FF"
    A = A + 1000
    for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),0 ' end of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),0 ' end of samples
next
case "50FF"
    A = A - 1000
    for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),0 ' end of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),0 ' end of samples
next
case "4DFF"
    j = j + 0.1
    for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),0 ' end of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),0 ' end of samples
next
case "4BFF"
    j = j - 0.1
    for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),0 ' end of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),0 ' end of samples
next
end select
I would be grateful for any tips on how to improve this too. EDIT: (P.P.S I suppose I could just CLS instead of using black sine waves in the case select statement)

Much appreciate you help
badidea
Posts: 2591
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Playing non-file audio

Post by badidea »

tone wrote:Thanks for explaining that the 400 is the frequency in hz. So do you know if this is actually based on time, like some sort of operating system clock. Or is just like 400 hz, but might vary running the code on various CPUs of different computing power?
The soundchip plays it samples exactly at 44100 Hz. So if your sample content is high - low - high - low, etc. you get a 22050 Hz sound (in theory, it is likely that some ~20 kHz low pass is used and most humans don't year this frequency).
A better test: 10 x high sample value, 10 x low sample value, etc. That should give a 2205 kHz square wave. And should be (crystal-oscillator) accurate. But be sure that sequential data buffers align, else you get weird 'blibs'.
angros47
Posts: 2324
Joined: Jun 21, 2005 19:04

Re: Playing non-file audio

Post by angros47 »

Try my library at: https://sourceforge.net/projects/freeba ... ary/files/

It has specific commands to emit sine waves, or also other waveforms, and to shape and filter them
tone
Posts: 26
Joined: Dec 17, 2019 21:31

Re: Playing non-file audio

Post by tone »

I'll be honest badidea, I had to read that three times to understand what you were saying, but that's a reflection on me, not you (haha). Thanks for the explanation. I am happy to hear the soundchip should use a crystal oscillator, but does the 'backend' like the library of FBSound interface with the soundchip directly? Or were you just speaking in general terms?

Back to my code, I found this sort of list of FBSound functions here:
http://shiny3d.de/public/fbsound/english.html

In it there is 'fbs_Destroy_Sound(@hSound)', I'm not sure if I'm using it correctly, but it seems to work well but please run the code and tell me your thoughts:

Code: Select all

'  #######################
' # fbs_create_wave.bas #
'#######################

'#include "../inc/fbsound.bi"
#include "../inc/fbsound_dynamic.bi"

' example of:
' fbs_Create_Wave(nSamples,@hWAve,@lpSamples)

function GetKeyNB() as integer
    dim as string key
    key = inkey
    select case len(key)
        case 0
            return 0
        case 1
            return key[0]
        case 2
            return key[0] + (key[1] shl 8)
    end select
end function

function mathsFunctRight(w as double,A as integer) as double
    return sin(w)*A + sin(w*3)*A/3
    
end function

function mathsFunctLeft(w as double,A as integer) as double
    return sin(w+PI)*A + sin(w*3+PI)*A/3
end function


const data_path = "../data/"

chdir(exepath())

' only if not same as exe path
' fbs_Set_PlugPath("./")

if fbs_Init()=false then
  print "error: FBS_INIT() " & FBS_Get_PlugError()
  beep : sleep : end 1
end if


dim as integer nSamples = 44100
dim as integer hWave,hSound
dim as double  w,wstep
dim as FBS_SAMPLE ptr pSamples
dim as FBS_SAMPLE ptr pS,pP,pE

' !!! create window before init fbsound !!!
dim as integer sw=640,sh=480
screenres sw,sh

dim as double j = 400
dim as integer key
dim as integer A = 4000



do



key = GetKeyNB
select case(hex(key))
case "48FF"
    A = A + 1000
fbs_Destroy_Sound(@hSound):cls
wstep = PI2/44100.0 * j

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=mathsFunctRight(w,A)
  w+=wstep
  ' left channel
  pSamples[i*2+1]=mathsFunctLeft(w,A)
  w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)
fbs_Play_Sound(hSound,-1) ' loop endless

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

case "50FF"
    A = A - 1000
fbs_Destroy_Sound(@hSound):cls
wstep = PI2/44100.0 * j

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=mathsFunctRight(w,A)
  w+=wstep
  ' left channel
  pSamples[i*2+1]=mathsFunctLeft(w,A)
  w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)
fbs_Play_Sound(hSound,-1) ' loop endless

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

case "4DFF"
    j = j + 10
fbs_Destroy_Sound(@hSound):cls
wstep = PI2/44100.0 * j

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=mathsFunctRight(w,A)
  w+=wstep
  ' left channel
  pSamples[i*2+1]=mathsFunctLeft(w,A)
  w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)
fbs_Play_Sound(hSound,-1) ' loop endless

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

case "4BFF"
    j = j - 10
fbs_Destroy_Sound(@hSound):cls
wstep = PI2/44100.0 * j

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=mathsFunctRight(w,A)
  w+=wstep
  ' left channel
  pSamples[i*2+1]=mathsFunctLeft(w,A)
  w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)
fbs_Play_Sound(hSound,-1) ' loop endless

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

end select

loop until key = 27
print "playing clean sin wave endless"
sleep
end
Thanks all!
tone
Posts: 26
Joined: Dec 17, 2019 21:31

Re: Playing non-file audio

Post by tone »

tone wrote:I'll be honest badidea, I had to read that three times to understand what you were saying, but that's a reflection on me, not you (haha). Thanks for the explanation. I am happy to hear the soundchip should use a crystal oscillator, but does the 'backend' like the library of FBSound interface with the soundchip directly? Or were you just speaking in general terms?

Back to my code, I found this sort of list of FBSound functions here:
http://shiny3d.de/public/fbsound/english.html

In it there is 'fbs_Destroy_Sound(@hSound)', I'm not sure if I'm using it correctly, but it seems to work well but please run the code and tell me your thoughts (go easy on me, I'm not a programmer, heehee):

Code: Select all

'  #######################
' # fbs_create_wave.bas #
'#######################

'#include "../inc/fbsound.bi"
#include "../inc/fbsound_dynamic.bi"

' example of:
' fbs_Create_Wave(nSamples,@hWAve,@lpSamples)

function GetKeyNB() as integer
    dim as string key
    key = inkey
    select case len(key)
        case 0
            return 0
        case 1
            return key[0]
        case 2
            return key[0] + (key[1] shl 8)
    end select
end function

function mathsFunctRight(w as double,A as integer) as double
    return sin(w)*A + sin(w*3)*A/3
    
end function

function mathsFunctLeft(w as double,A as integer) as double
    return sin(w+PI)*A + sin(w*3+PI)*A/3
end function


const data_path = "../data/"

chdir(exepath())

' only if not same as exe path
' fbs_Set_PlugPath("./")

if fbs_Init()=false then
  print "error: FBS_INIT() " & FBS_Get_PlugError()
  beep : sleep : end 1
end if


dim as integer nSamples = 44100
dim as integer hWave,hSound
dim as double  w,wstep
dim as FBS_SAMPLE ptr pSamples
dim as FBS_SAMPLE ptr pS,pP,pE

' !!! create window before init fbsound !!!
dim as integer sw=640,sh=480
screenres sw,sh

dim as double j = 400
dim as integer key
dim as integer A = 4000



do



key = GetKeyNB
select case(hex(key))
case "48FF"
    A = A + 1000
fbs_Destroy_Sound(@hSound):cls
wstep = PI2/44100.0 * j

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=mathsFunctRight(w,A)
  w+=wstep
  ' left channel
  pSamples[i*2+1]=mathsFunctLeft(w,A)
  w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)
fbs_Play_Sound(hSound,-1) ' loop endless

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

case "50FF"
    A = A - 1000
fbs_Destroy_Sound(@hSound):cls
wstep = PI2/44100.0 * j

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=mathsFunctRight(w,A)
  w+=wstep
  ' left channel
  pSamples[i*2+1]=mathsFunctLeft(w,A)
  w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)
fbs_Play_Sound(hSound,-1) ' loop endless

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

case "4DFF"
    j = j + 10
fbs_Destroy_Sound(@hSound):cls
wstep = PI2/44100.0 * j

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=mathsFunctRight(w,A)
  w+=wstep
  ' left channel
  pSamples[i*2+1]=mathsFunctLeft(w,A)
  w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)
fbs_Play_Sound(hSound,-1) ' loop endless

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

case "4BFF"
    j = j - 10
fbs_Destroy_Sound(@hSound):cls
wstep = PI2/44100.0 * j

fbs_Create_Wave(nSamples,@hWave,@pSamples)
for i as integer=0 to nSamples-1
  ' right channel
  pSamples[i*2  ]=mathsFunctRight(w,A)
  w+=wstep
  ' left channel
  pSamples[i*2+1]=mathsFunctLeft(w,A)
  w+=wstep
next
fbs_Create_Sound(hWave,@hSound)
fbs_Get_SoundPointers(hSound,@pS,@pP,@pE)
fbs_Play_Sound(hSound,-1) ' loop endless

'sw = 640 /2
sh = 480 /2
for x as integer=0 to sw-1
  ' right channel
  pset (x   ,sh+pE[-sw*2+x*2  ]*0.01),3 ' end of samples
  'pset (sw+x,sh+pS[      x*2  ]*0.01),4 ' start of samples
  ' left channel
  pset (x   ,sh+pE[-sw*2+x*2+1]*0.01),5 ' end of samples
  'pset (sw+x,sh+pS[      x*2+1]*0.01),6 ' start of samples
next

end select

loop until key = 27
print "playing clean sin wave endless"
sleep
end
Also, you can see I commented out the "Start of samples" on the PSET drawings, because I don't understand what they're for, if anyone can explain that too, that would satisfy my curiosity.

Thanks all!
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Playing non-file audio

Post by D.J.Peters »

@tone if you need support for FBSound use the right forum section please.
viewtopic.php?f=14&t=27272

If you will create playback samples on the fly
you don't need any hWave or hSound object
a callback method is the key :-)

Joshy

Code: Select all

#include "../inc/fbsound_dynamic.bi"

dim shared as integer gSampleRate
dim shared as integer gMIDINote = 57

sub MasterCB(byval pSamples  as FBS_SAMPLE ptr, _
             byval nChannels  as integer, _
             byval nSamples   as integer)
  static as double w=0.0

  ' no active MIDI note do nothing
  if gMIDINote<1 then exit sub
  ' midi note to frequency
  dim as double frequency = fbs_pow(2.0,(gMIDINote-69)/12.0)*440.0              
  dim as double wStep = PI2/gSampleRate*frequency
  ' render one or two channels with your own code !
  select case as const nChannels
  case 1 ' MONO
    dim as FBS_SAMPLE ptr p = pSamples
    for i as integer=0 to nSamples-1
      *p=sin(w)*8000.0 : w+=wStep : p+=1
    next
  case 2 ' STEREO
    dim as FBS_SAMPLE ptr pL = pSamples,pR=pL+1
    for i as integer=0 to nSamples-1
      *pL=sin(w)*8000.0 : *pR=*pL * -1 : w+=wStep
      pL+=2 : pR+=2
    next
  end select
  print "MIDI note: " & gMIDINote & " frequency: " & frequency
end sub


' init fbSound
ChDir(ExePath())
if fbs_Init()=false then
  print "error: FBS_INIT() " & FBS_Get_PlugError()
  beep : sleep : end 1
end if
' get playback sample rate
gSampleRate=FBS_Get_PlugRate()
' set and enable master callback
FBS_Set_MasterCallback(@MasterCB)
FBS_Enable_MasterCallback()

dim as double tRuntime,tNow,tStart=Timer()
dim as integer oldSeconds=-1,Seconds,noteStep=2
while inkey()=""
  tNow=Timer():tRuntime=tNow-tStart:Seconds=int(tRuntime)
  if Seconds<>oldSeconds then
    gMIDINote += noteStep
    if gMIDINote<57 or gMIDINote>82 then noteStep*=-1
    oldSeconds = Seconds
  end if
  sleep 10
wend
' disable master callback
FBS_Disable_MasterCallback()
tone
Posts: 26
Joined: Dec 17, 2019 21:31

Re: Playing non-file audio

Post by tone »

Thanks for the tip about callback, I'll go through your code again and try to get my head around it. Oh, okay, I didn't realise there was a FBSOUND section, I'll migrate over there because I have a question about getting my code to work on Linux now.
Cheers,
Rob
Post Reply