Hi Fabian,
because then all reading is done from one rendering thread.
I have a AudioProcessor, that mixes ~30 audiosources according to a special algorithm. If the getNextAudioBlock of the IO callback drives the whole chain from reading from disk to mixing, everything runs in one thread, i.e. on one CPU core.
So I have the BufferingAudioSource to prepare the buffers. This uses TimeSliceThreads to distribute the load of reading (I use 4 threads, runs perfectly).
a) Situation live: everything is perfect, because the calls from the audio device are coming at a fixed interval, leaving enough time to read
b) Situation rendering: the writer calls the mixing as fast as possible. So the background threads have not enough time to fetch the next audio block.
With the bool waitForNextAudioBlockReady (const AudioSourceChannelInfo &, const int sleepMiliSecs=10, const uint32 timeout=500)
the reading is happening on several threads, but mixing is easy when using on the audioSource:
BufferingAudioSource source;
AudioSourceChannelInfo info (&buffer, 0, bufferSize);
if (isNonRealtime ())
source.waitForNextAudioBlockReady (info);
source.getNextAudioBlock (info);
This way you can easily synchronize the threads.
Does this make sense?
Thanks for your time
Correction for the wait method: don’t block if source cannot produce any samples:
/** Wait for buffer ready. This will block until the buffer is prepared. DO NOT USE IN REALTIME! */
bool BufferingAudioSource::waitForNextAudioBlockReady (const AudioSourceChannelInfo& info, const int sleepMilliSecs, const uint32 timeout)
{
if (!source || source->getTotalLength() <= 0)
return false;
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 (sleepMilliSecs);
}
return false;
}