2

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?

Jan Deinhard
  • 19,645
  • 24
  • 81
  • 137

1 Answers1

3

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.

hotpaw2
  • 70,107
  • 14
  • 90
  • 153