pcmreadcallback not being called

I create two sounds, one to record pcm from a microphone and another to send pcm to a speaker. The first sound works fine - I include it’s initialization below just for context. The initialization for both is:

// SOUND 1

memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
exinfo.cbsize           = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.numchannels      = recordchannels;
exinfo.format           = FMOD_SOUND_FORMAT_PCM16;
exinfo.defaultfrequency = recordrate;
exinfo.length           = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * 1; 

result = Asystem->createSound(0, FMOD_LOOP_NORMAL | FMOD_OPENUSER, &exinfo, &sound);
ERRCHECK(result);

result = Asystem->recordStart(DEVICE_INDEX, sound, true);
ERRCHECK(result);

result = sound->getLength(&soundlength, FMOD_TIMEUNIT_PCM);
ERRCHECK(result);

// SOUND 2
// Note: I use a different exinfo (exinfo2) for sound2. Is this correct practice?

memset(&exinfo2, 0, sizeof(FMOD_CREATESOUNDEXINFO));
exinfo2.cbsize            = sizeof(FMOD_CREATESOUNDEXINFO);  // Required.
exinfo2.numchannels       = 2;                               // Number of channels in the sound.
exinfo2.defaultfrequency  = 1024;                           // Default playback rate of sound.
exinfo2.decodebuffersize  = 1024;                           // Chunk size of stream update in samples. This will be the amount of data passed to the user callback.
exinfo2.length            = exinfo2.defaultfrequency * exinfo2.numchannels * sizeof(signed short) * 1; // Length of PCM data in bytes of whole song (for Sound::getLength)
exinfo2.format            = FMOD_SOUND_FORMAT_PCM16;         // Data format of sound.
exinfo2.pcmreadcallback   = pcmreadcallback;                 // User callback for reading.

result = Asystem->createSound(0, FMOD_OPENUSER, &exinfo2, &sound2);
ERRCHECK(result);

result = Asystem->playSound(sound2, 0, true, &channel2);
ERRCHECK(result);


channel2->setMode(FMOD_LOOP_NORMAL);
channel2->setPosition(0, FMOD_TIMEUNIT_MS); // this flushes the buffer to ensure the loop mode takes effect

channel2->setPaused(false);

I implement the pcmreadcallback function as:

FMOD_RESULT F_CALLBACK pcmreadcallback(FMOD_SOUND* sound2, void *data, unsigned int datalen)
{

signed short *stereo16bitbuffer = (signed short *)data;

for (unsigned int sample = 0; sample < datalen / 4; sample++)     //16bit stereo (4 bytes per sample)
{

    *stereo16bitbuffer++ = (signed short) speaker_buff[sample] * 32767.0f;    // left channel
    *stereo16bitbuffer++ = (signed short) speaker_buff[sample] * 32767.0f;    // right channel
}
return FMOD_OK;

}

The callback function stops being called at some point. I’d like to send ~1024 (newly generated) values to the speaker every frame. Am I making a mistake in how to do this, and if so, where?

1 Like

It sounds like you want to record sound from a microphone and play it back while recording. You can actually do this with one sound, and we have an example of this in our LowLevel API examples called ‘record’.

I need to send PCM samples to the speaker which are independent of those coming from the microphone stream. They’re two different sounds with seperate PCM streams that both need to be handled each frame.
The pcmreadcallback function seems to be called only once. How can I call it periodically to fill the Sound with new values to send to the speaker?

When creating the sound, using FMOD_CREATESTREAM will stream the data in chunks as it plays which will need to continuously read the data to play the sand, also using far less memory.

Without that flag,a sound will open as a static sound that is decompressed fully into memory after one read callback.

In our examples project there is a solution called ‘user_created_sound’ which shows these two options at work.

Thanks. I set the mode to FMOD_CREATESTREAM and now the readcallback function is executing regularly.

I try use FMOD_USERDATA | FMOD_CREATESTREAM mode to create a sound. This is good in Windows as pcmreadcallback function is called coutinuously. However, pcmreadcallback function only called once when I try use same code in my iphone, How can I solve it?

I’m guessing you mean FMOD_OPENUSER not FMOD_USERDATA (which doesnt exist).
The callback will call as long as you have a long enough sound for it to be called repeatedly, and you return FMOD_OK from the callback