0
0

Hello all

I am getting my PCM data from a stream. At load time i have no clue how long the stream will be, it just streams continuous data until it says ‘thats it’. The data comes in chunks of raw PCM data. Right now im using the following code for sound creation:
[code:2r6yxr3c]
FMOD_CREATESOUNDEXINFO info = { 0 };
info.cbsize = sizeof(info);
info.decodebuffersize = mInfo->audioContext->sample_rate;
info.length = -1;
info.numchannels = mInfo->audioContext->channels;
info.defaultfrequency = mInfo->audioContext->sample_rate;
info.format = FMOD_SOUND_FORMAT_PCM16;
info.pcmreadcallback = audioRead;
info.pcmsetposcallback = audioSetPos;
info.userdata = this;

    FMOD::Sound* sound;
    auto result = system->createSound(nullptr, FMOD_NONBLOCKING | FMOD_CREATESTREAM | FMOD_OPENUSER, &info, &sound);
    mSound = sound;

[/code:2r6yxr3c]

And audioRead is behaving like this:
[code:2r6yxr3c]
FMOD_RESULT F_CALLBACK AudioDecoder::audioRead(FMOD_SOUND* sound, void* buffer, uint32 length) {
void* userData = nullptr;
auto res = FMOD_Sound_GetUserData(sound, &userData);
if (res != FMOD_OK || userData == nullptr) {
return FMOD_ERR_INVALID_PARAM;
}

    AudioDecoder* decoder = (AudioDecoder*) userData;
    try {
        decoder->mAudioStream.readData(buffer, length, decoder->mIsStarving);
    } catch (System::EndOfStream&) {
        decoder->mIsEndOfStream = true;
        return FMOD_ERR_FILE_EOF;
    }

    return FMOD_OK;
}

[/code:2r6yxr3c]

The readData function tries to read the amount of bytes and starts blocking if there is not enough data ready. If the stream indicated, that its finished the next time it would enter a blocking state it throws the EndOfStream exception which causes the ERR_FILE_EOF error to be returned.

While during the normal playback everything sounds and works fine at the end i have a problem. My return value seems to be ignored (the EOF) and FMOD keeps calling audioRead on and on. I guess this is due to the fact that i created the sound with length -1. I also tried setting it to 0 as its said to be optional, but then launching the sound wont work, i launch it like this:
[code:2r6yxr3c]
auto res = mSound->getOpenState(&openState, &pct, &starving, &busy);
if (res != FMOD_OK) {
return;
}

std::cout << starving << " " << (uint32)openState << std::endl;

if (openState == FMOD_OPENSTATE_READY && mChannel == nullptr) {
res = mInfo->threadItem->getSoundSystem()->getSystem()->playSound(FMOD_CHANNEL_FREE, mSound, true, &mChannel);
[/code:2r6yxr3c]

if i set length to 0 res is FMOD_ERR_FILE_COULDNOTSEEK.

When the stream reaches the end of the data available it starts repeating the last decoded buffer. I hoped that then starving would become true, but no, it says ‘false’ the entire time and openState is constantly ‘PLAYING’. I also thought that maybe instead of returning FMOD_ERR_FILE_EOF just keeping it blocked may cause starving to become true but sadly no, i get no hint that fmod has reached the end of its available data. Is there no way i can create a sound that doesnt know yet how long it will be?

Many thanks in advance and greetings
Cromon

  • You must to post comments
0
0

Unfortunately there is no way for an infinite user created PCM stream to signal end-of-stream from the callback.

Possible work arounds:
1) On reaching EOS, fill the buffer with zeros, and signal to another piece of code that can call Channel::Stop() on the main thread.
2) Implement a custom codec instead of a PCM callback. See System::registerCodec. If your current implementation has specific input needs, you’ll also need to override the file open/read callbacks. Returning FMOD_ERR_FILE_EOF from a FMOD_CODEC_READCALLBACK will stop the stream.

  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.