1

I would like to analyze chunks of audio data of one second. For this purpose I implemented an audio unit that fills a ringbuffer (TPCircularBuffer by Michael Tyson). In another file I try to read chunks of one second using a NStimer. Unfortunately, I receive errors with consuming these data.

The buffer is filled in a kAudioOutputUnitProperty_SetInputCallback and works fine

Device * THIS = (__bridge Device *)inRefCon;
// Render audio into buffer
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = 2;
bufferList.mBuffers[0].mData = NULL;
bufferList.mBuffers[0].mDataByteSize = inNumberFrames * sizeof(SInt16) * 2;
CheckError(AudioUnitRender(THIS -> rioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, &bufferList), "AudioUnitRender");

// Put audio into circular buffer
TPCircularBufferProduceBytes(&circBuffer, bufferList.mBuffers[0].mData, inNumberFrames * 2 * sizeof(SInt16));

To read one second of samples I implemented te following code:

    - (void)initializeTimer {
        timer = [NSTimer scheduledTimerWithTimeInterval:1
                                                 target:self
                                               selector:@selector(timerFired:)
                                               userInfo:nil
                                                repeats:YES];
    }

    - (void) timerFired:(NSTimer *)theTimer {
        NSLog(@"Reading %i second(s) from ring",1);

        int32_t availableBytes;
        SInt16 *tail = TPCircularBufferTail(&circBuffer, &availableBytes);
        int availableSamples = availableBytes / sizeof(SInt16);
        NSLog(@"Available samples %i", availableSamples);

        for (int i = 0; i < availableSamples; i++) {
            printf("%i\n",tail[i]);
        }

        TPCircularBufferConsume(&circBuffer, sizeof(SInt16) * availableBytes);
    }

However, when I run this code the number of samples is printed but then I receive the following error: Assertion failed: (buffer->fillCount >= 0), function TPCircularBufferConsume, file …/TPCircularBuffer.h, line 142.

Unfortunately, I don’t know what is going wrong with consuming the data. The buffer length is set to samplerate * 2 to be long enough.

I would be very happy if someone knows what is going wrong here.

Gerard
  • 349
  • 2
  • 16

1 Answers1

2

Your circular buffer isn't long enough. You don't check that the available size is positive before emptying, and the time all your print statements take let the buffer get over-filled. Make the buffer at least 2X larger than your timer, check before emptying, empty the buffer before printing, and use far fewer print statements.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153
  • I will incorporate these suggestions! The main problem with the buffer appeared that too much data was consumed (sizeof(SInt16) * availableBytes) instead of only availableBytes. A related question that I still have is, can I also enforce to consume exactly one second of samples (so that I can use memcopy to an allocated array)? – Gerard Jan 28 '16 at 14:52
  • Use a repeating timer and wait until at least the amount you want to memcpy is available. Otherwise do nothing. – hotpaw2 Jan 28 '16 at 15:09
  • I have implemented all you suggestions and it works like a charm! – Gerard Jan 29 '16 at 09:01