0
0

Hello,

i’ve been looking at the usercreatedsound sample a lot. what i want to do, is write an oscillator class, that generates random sinus values and stores them into a buffer, this buffer then should be played back via fmod. the function in the sample uses a static sample, i would like to be able to dynamically put data into the playback channel, so it always reflects my current sinus data..

the function the sample uses is the pcmreadcallback from the FMOD_CREATESOUNDEXINFO structure:

[code:2t9dpc33]
FMOD_RESULT F_CALLBACK SoundStreamer::pcmreadcallback(FMOD_SOUND *sound, void *data, unsigned int datalen) {
unsigned int count;
static float t1 = 0, t2 = 0; // time
static float v1 = 0, v2 = 0; // velocity
signed short *stereo16bitbuffer = (signed short *)data;

for (count=0; count<datalen>>2; count++)        // >>2 = 16bit stereo (4 bytes per sample)
{
    *stereo16bitbuffer++ = (signed short)(sin(t1) * 32767.0f);    // left channel
    *stereo16bitbuffer++ = (signed short)(sin(t2) * 32767.0f);    // right channel

    t1 += 0.01f   + v1;
    t2 += 0.0142f + v2;
    v1 += (float)(sin(t1) * 0.002f);
    v2 += (float)(sin(t2) * 0.002f);
}
}

return FMOD_OK;

}
[/code:2t9dpc33]

i can hear the sound, so the soundsystem is initialized correctly and everything works.. i just havent been able to add randomly generated data to the sample, so the playback always contains, what my sinus oscillator randomly creates.

any thoughts on how to achieve that? i dont want to change existing sound, so dsp is the wrong answer for me i guess, its user created sound on the fly. do i have to work with lock / unlock and set/reset the sound data that way?

the function i wrote looks like that at the moment:

[code:2t9dpc33]
bool DataSourceSineGenerator::doWork()
{
const int buffSize = static_cast<int> (round(samplingRate * timeSpan / 1000.0));
int16_t buff[buffSize];
int indeksGeneriranja = 1;
bool sineRiseFlag = true;
while (looping)
{
for (int i = 0; i < buffSize; i++, indeksGeneriranja++)
{
buff[i] = static_cast<int16_t> (32766 * sin(2 * 3.14 * this->frequency / this->samplingRate * indeksGeneriranja));
if (buff[i] == 0)
{
sineRiseFlag = !sineRiseFlag;
if (sineRiseFlag)
{
indeksGeneriranja = 1;
}
}

    }
    for (vector&lt;DataSourceListener*&gt;::iterator it = dataSourceListeners.begin(); it != dataSourceListeners.end(); ++it)
    {
        (*it)-&gt;giveData(buff, buffSize);
    }
    // Sleep(1000);
}
return true;

}
[/code:2t9dpc33]

the giveData() functions passes the buffer and its size to the sound system, i want fmod to immediately take that and replay it until the giveData() function passes in new data…

i hope you understood what i want do to, i’d be greatful for some sample code aswel.

cheers.

  • You must to post comments
0
0

Hi Krisso, welcome to the forums.

From what you said I think the usercreatedsound example is a good place to start. Here is some example code [untested]

Assuming your data is in [i:1wai1dwo]myBuffer[/i:1wai1dwo] and the size of the buffer in samples is [i:1wai1dwo]myBufferSize[/i:1wai1dwo]:

[code:1wai1dwo]FMOD_RESULT F_CALLBACK SoundStreamer::pcmreadcallback(FMOD_SOUND *sound, void *data, unsigned int datalen)
{
typedef signed short sample; //16-bit

signed short *stereo16bitbuffer = (sample *)data;
unsigned int numsamples = datalen / sizeof(sample);

static bufferIndex = 0;
for (unsigned int count = 0; count &lt; numsamples; ++count)
{
    stereo16bitbuffer[count] = myBuffer[bufferIndex];

    //wrap around to zero when we reach the end of the buffer
    if (++myBufferIndex &gt;= myBufferSize) myBufferIndex = 0;
}

return FMOD_OK;

}[/code:1wai1dwo]

The only thing you might need to be careful with is changing the buffer. You don’t want to be writing to [i:1wai1dwo]myBuffer[/i:1wai1dwo] while the pcmreadcallback is reading from it.

-Pete

  • You must to post comments
0
0

[quote="peter":1mdahiky]Hi Krisso, welcome to the forums.

From what you said I think the usercreatedsound example is a good place to start. Here is some example code [untested]

Assuming your data is in [i:1mdahiky]myBuffer[/i:1mdahiky] and the size of the buffer in samples is [i:1mdahiky]myBufferSize[/i:1mdahiky]:

[code:1mdahiky]FMOD_RESULT F_CALLBACK SoundStreamer::pcmreadcallback(FMOD_SOUND *sound, void *data, unsigned int datalen)
{
typedef signed short sample; //16-bit

signed short *stereo16bitbuffer = (sample *)data;
unsigned int numsamples = datalen / sizeof(sample);

static bufferIndex = 0;
for (unsigned int count = 0; count &lt; numsamples; ++count)
{
    stereo16bitbuffer[count] = myBuffer[bufferIndex];

    //wrap around to zero when we reach the end of the buffer
    if (++myBufferIndex &gt;= myBufferSize) myBufferIndex = 0;
}

return FMOD_OK;

}[/code:1mdahiky]

The only thing you might need to be careful with is changing the buffer. You don’t want to be writing to [i:1mdahiky]myBuffer[/i:1mdahiky] while the pcmreadcallback is reading from it.

[/quote:1mdahiky]

well thats greate peter, but how do i trigger the pcm callback function, i did some logging, and it only triggers sveral times at the beginning of the playback and then later, never gets called again.

how can i play the buffer "myBuffer" once, then update it with the new data and resume palyback with the modified data? i dont get, where i have to place the hook and how to retrigger the callback.. some help would be appreciated peter, thanks.

  • You must to post comments
0
0

[quote:1wpwmp64]and it only triggers sveral times at the beginning of the playback and then later, never gets called again. [/quote:1wpwmp64]
Adding FMOD_CREATESTREAM flag to the FMOD_MODE flags for createSound should fix that.

[quote:1wpwmp64]how can i play the buffer "myBuffer" once, then update it with the new data and resume palyback with the modified data?[/quote:1wpwmp64]
Depending on your application, you might be better off creating a new sound with the new buffer and cross-fading between them.

-Pete

  • You must to post comments
Showing 3 results
Your Answer

Please first to submit.