macosaudiocore-audioaudio-recordingaudioqueueservices

Why does the packet number in my audio queue input callback vary?


I use Audio Queue Services to record PCM audio data on Mac OS X. It works but the number of frames I get in my callback varies.

static void MyAQInputCallback(void *inUserData, AudioQueueRef inQueue, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription *inPacketDesc)

On each call of my audio input queue I want to get 5 ms (240 frames/inNumPackets, 48 kHz) of audio data.

This is the audio format I use:

AudioStreamBasicDescription recordFormat = {0};
memset(&recordFormat, 0, sizeof(recordFormat));
recordFormat.mFormatID = kAudioFormatLinearPCM;
recordFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
recordFormat.mBytesPerPacket = 4;
recordFormat.mFramesPerPacket = 1;
recordFormat.mBytesPerFrame = 4;
recordFormat.mChannelsPerFrame = 2;
recordFormat.mBitsPerChannel = 16;

I have two buffers of 960 bytes enqueued:

for (int i = 0; i < 2; ++i) {
    AudioQueueBufferRef buffer;
    AudioQueueAllocateBuffer(queue, 960, &buffer);
    AudioQueueEnqueueBuffer(queue, buffer, 0, NULL);
}

My problem: For every 204 times of 240 frames (inNumPackets) the callback is once called with only 192 frames.

Why does that happen and is there something I can do to get 240 frames constantly?


Solution

  • Audio Queues run on top of Audio Units. The Audio Unit buffers are very likely configured by the OS to be a power-of-two in size, and your returned Audio Queue buffers are chopped out of the larger Audio Unit buffers.

    204 * 240 + 192 = 12 audio unit buffers of 4096.

    If you want fixed length buffers that are not a power-of-two, your best bet is to have the app re-buffer the incoming buffers (save up until you have enough data) to your desired length. A lock-free circular fifo/buffer might be suitable for this purpose.