Input queue callback called but no data
In an effort to start getting into macOS programming, I'm trying to make a simple program that would record audio from an input device (eg. the built-in microphone on my MacBook Pro). I have created a Objective-C Cocoa project in Xcode and the code is a slightly adapted version of this tutorial from developer.apple.com.
Here's my code:
// AppDelegate.m:
#include <AudioToolbox/AudioToolbox.h>
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
struct AQRecorderState S;
#define PRINT_R do{
printf("%d: r = %dn",__LINE__, r);
}while(0)
AudioStreamBasicDescription *fmt = &S.mDataFormat;
fmt->mFormatID = kAudioFormatLinearPCM;
fmt->mSampleRate = 44100.0;
fmt->mChannelsPerFrame = 1;
fmt->mBitsPerChannel = 32;
fmt->mBytesPerFrame = fmt->mChannelsPerFrame * sizeof (float);
fmt->mFramesPerPacket = 1;
fmt->mBytesPerPacket = fmt->mBytesPerFrame * fmt->mFramesPerPacket;
fmt->mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved;
OSStatus r = 0;
r = AudioQueueNewInput(&S.mDataFormat, HandleInputBuffer, &S, NULL, kCFRunLoopCommonModes, 0, &S.mQueue);
PRINT_R;
UInt32 dataFormatSize = sizeof (S.mDataFormat);
r = AudioQueueGetProperty (
S.mQueue,
kAudioConverterCurrentInputStreamDescription,
&S.mDataFormat,
&dataFormatSize
);
S.bufferByteSize = 22050;
for (int i = 0; i < NUM_BUFFERS; ++i) {
r = AudioQueueAllocateBuffer(S.mQueue, S.bufferByteSize, &S.mBuffers[i]);
PRINT_R;
r = AudioQueueEnqueueBuffer(S.mQueue, S.mBuffers[i], 0, NULL);
PRINT_R;
}
S.mCurrentPacket = 0;
S.mIsRunning = true;
r = AudioQueueStart(S.mQueue, NULL);
PRINT_R;
r = AudioQueueStop(S.mQueue, true);
S.mIsRunning = false;
PRINT_R;
r = AudioQueueDispose(S.mQueue, true);
}
Here's my input callback function (defined in a separate C file):
void HandleInputBuffer (
void *aqData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc
) {
struct AQRecorderState *pAqData = (struct AQRecorderState *) aqData;
if (inNumPackets == 0 && pAqData->mDataFormat.mBytesPerPacket != 0) {
inNumPackets =
inBuffer->mAudioDataByteSize / pAqData->mDataFormat.mBytesPerPacket;
}
printf("%fn", *(float*)inBuffer->mAudioData);
if (pAqData->mIsRunning == 0)
return;
AudioQueueEnqueueBuffer(pAqData->mQueue, inBuffer, 0, NULL);
}
When the program is run, all of the Core Audio function calls return 0, which (I believe) represents "no error", and HandleInputBuffer is called NUM_BUFFERS times in a very rapid succession or almost instantly (most definitely not every 0.5 secs like the buffer size of 22050 would suggest at this sample rate), and all the first samples are 0.0. What am I missing here?
S.bufferByteSize
is in bytes, not frames, so 22050 bytes is not half a second, but 22050/sizeof(float)
frames, so about an eighth of a second.
If you want half a second, try
S.bufferByteSize = fmt->mSampleRate * fmt->mBytesPerFrame / 2;
In your above code (and also in the git repo you linked), you immediately AudioQueueStop
and AudioQueueDispose
the audio queue after AudioQueueStart
ing it. Don't do that.
上一篇: 如何推迟使用jQuery?
下一篇: 输入队列回调调用但没有数据