Help with TPCircularBuffer: Peek always returns 0

edited March 2016

I'm having a hard time understanding how TPCircularBuffer+ABL works (and why it doesn't work when it doesn't). Tried to follow Michael's example in this comment: http://forum.theamazingaudioengine.com/discussion/comment/2207/#Comment_2207

I have an effect processor that requires 512 frame blocks, no more no less. My implementation of the callback looks like this:

    TPCircularBufferCopyAudioBufferList(&self->_inCircular, audio, NULL, kTPCircularBufferCopyAll, NULL);

    while (TPCircularBufferPeek(&self->_inCircular, NULL, &self->_descr) >= CIRCULAR_BUFFER_FRAMES * 2)
    {
        AudioBufferList* scratchBuffer = TPCircularBufferPrepareEmptyAudioBufferListWithAudioFormat(&self->_outCircular, &self->_descr, CIRCULAR_BUFFER_FRAMES, NULL);
        UInt32 outFrames = CIRCULAR_BUFFER_FRAMES;
        TPCircularBufferDequeueBufferListFrames(&self->_inCircular, &outFrames, scratchBuffer, NULL, &self->_descr);
        effectProcess(self, scratchBuffer);
        TPCircularBufferProduceAudioBufferList(&self->_outCircular, NULL);
    }

    TPCircularBufferDequeueBufferListFrames(&self->_outCircular, &frames, audio, NULL, &self->_descr);

But what I get is, TPCircularBufferPeek always returning zero.

Could someone help?

P.S. my initialization:

    TPCircularBufferInit(&_inCircular, CIRCULAR_BUFFER_FRAMES * _descr.mBytesPerFrame * 2);
    TPCircularBufferInit(&_outCircular, CIRCULAR_BUFFER_FRAMES * _descr.mBytesPerFrame * 2);

Comments

  • Turns out the problem is in the initialization. You need to allow extra bytes above what you think you might need when calling TPCircularBufferInit(). No mentioning of this in the docs unfortunately, a bit confusing.

    Another problem was TPCircularBufferPeek() returns the number of audio frames, so you should compare it with just CIRCULAR_BUFFER_FRAMES. My bad.

  • edited March 2016

    Thanks @Michael.

    With 1024 extra it worked fine on my iPhone 6S but didn't work on the iPhone 5! Now with 8192 extra it seems to be working everywhere (including OS X).

    I think it would be nice to have a specific safe number or a formula. The side effect of not getting it right is that your filter where you use the circular buffer will simply pass on data unmodified (because Peek returns 0). Is there a safe amount that will work everywhere?

  • edited March 2016

    Good question! I wonder what it was about the iPhone 5 that stopped it working...

    The 5% measure I proposed in the header comments came from a guesstimate of 256 buffer size, 32-bit noninterleaved stereo:

    • each entry on the buffer consists of a TPCircularBufferABLBlockHeader and then the audio data
    • TPCircularBufferABLBlockHeader is 96 bytes + one extra AudioBuffer for noninterleaved audio, which is 16 bytes = 112 bytes
    • 256 frames of 32-bit stereo = 2048 bytes
    • 112 / 2048 = 5%

    Now I think about it, perhaps 15% extra might be a safer suggestion, so that it works with more fragmented audio, or 128 frames...

  • I'm using 512 frames per channel for FFT, and as it turns out even 1024 extra bytes wasn't enough on the iPhone 5. It's the last 32-bit iPhone afaik, but other than that the same iOS 9.2 etc.

  • Hmm. What's the total buffer size?

  • The formula is

    CIRCULAR_BUFFER_FRAMES * _descr.mBytesPerFrame * _descr.mChannelsPerFrame + 1024

    for both input and output circular buffers. CIRCULAR_BUFFER_FRAMES = 512

Sign In or Register to comment.