BufferingAudioSource and non-realtime: waitForNextAudioBlock (with code)


#1

Hi all, hi Jules,

I just implemented an offline renderer using an AudioProcessorGraph reading from 50+ AudioReaderSources…
Thanks to @jules post I could fix the buffer underruns, that inherently happen when calling getNextAudioBuffer as fast as I can


So yes, this solved the problem, thanks.
However, why I still want to use BufferingAudioSource is, the renderer runs now only on one CPU while the rest is idle…
I understand the reasons not to use a blocking getNextAudioBlock. But would it be possible to add a

bool waitForNextAudioBuffer (const AudioSourceChannelInfo &, const int sleepusecs, const int timeout); ?
It would simply check if buffer is valid, and if not do a sleep so the other buffering timeslices can work.

I know that calling this in realtime is off limits, because it needs to synchronize the reading of the buffer internals…
But it would enable to do offline rendering on more than one cpu…

Thanks for thoughts
Daniel


#2

I implemented this and it works for me:

/** Wait for buffer ready. This will block until the buffer is prepared. DO NOT USE IN REALTIME! */
bool BufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChannelInfo& info, const uint32 sleepMiliSecs, const uint32 timeout)
{
    if (nextPlayPos + info.numSamples < 0 ||
        (! isLooping() && nextPlayPos > getTotalLength())) {
        return true;
    }

    const uint32 endTime = Time::getMillisecondCounter () + timeout;
    int validStart;
    int validEnd;
    while (Time::getMillisecondCounter() < endTime) {
        {
            const ScopedLock sl (bufferStartPosLock);
            validStart = (int) (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos);
            validEnd   = (int) (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos);
        }
        if (validStart <= 0 &&
            validStart < validEnd &&
            validEnd >= info.numSamples) {
            return true;
        }
        Thread::sleep (sleepMiliSecs);

    }

    return false;
}

And right before a getNextAudioBlock I call
waitForNextAudioBlock (info, 10, 500);

Is this a sensible approach or has this some hazzard I didn’t realize?


BufferingAudioSource prepareToPlay blocks MessageThread
How does the audio plugin host example actually tick