AudioQueue回调仅在iOS 7上获取空缓冲区

我有一个奇怪的问题。 我的代码在iOS 5和6上运行良好,但在iOS 7上运行时,我在AudioQueue回调上获得了空缓冲区。

可能的相关代码:

- (void)setUpAudioFormat { audioFormat.mFormatID = kAudioFormatLinearPCM; audioFormat.mSampleRate = SAMPLE_RATE;//16000.0; audioFormat.mChannelsPerFrame = CHANNELS;//1; audioFormat.mBitsPerChannel = 16; audioFormat.mFramesPerPacket = 1; audioFormat.mBytesPerFrame = audioFormat.mChannelsPerFrame * sizeof(SInt16); audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket; audioFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; bufferNumPackets = 2048; // must be power of 2 for FFT! bufferByteSize = [self byteSizeForNumPackets:bufferNumPackets]; } - (UInt32)numPacketsForTime:(Float64)seconds { return (UInt32) (seconds * audioFormat.mSampleRate / audioFormat.mFramesPerPacket); } - (UInt32)byteSizeForNumPackets:(UInt32)numPackets { return numPackets * audioFormat.mBytesPerPacket; } - (void)setUpRecordQueue { NSLog(@"\n+++ setUpRecordQueue"); OSStatus errorStatus = AudioQueueNewInput( &audioFormat, recordCallback, self, // userData CFRunLoopGetMain(), // run loop NULL, // run loop mode 0, // flags &recordQueue); if (errorStatus) { NSLog(@"\n\n ERROR : Error %ld on AudioQueueNewInput\n", errorStatus ); } if (recordQueue == nil) { NSLog(@"\n\n ----- Record Queue is nil! -----"); } UInt32 trueValue = true; AudioQueueSetProperty(recordQueue,kAudioQueueProperty_EnableLevelMetering,&trueValue,sizeof (UInt32)); } - (void)setUpRecordQueueBuffers { NSLog(@"\n+++ setUpRecordQueueBuffers"); assert(recordQueue != nil); for (int t = 0; t < NUMBER_AUDIO_DATA_BUFFERS; ++t) { OSStatus errorStatus = AudioQueueAllocateBuffer( recordQueue, bufferByteSize, &recordQueueBuffers[t]); if (errorStatus) { NSLog(@"\n\n ERROR : Error %ld on AudioQueueAllocateBuffer\n", errorStatus ); } } } - (void)primeRecordQueueBuffers { NSLog(@"\n+++ primeRecordQueueBuffers"); assert(recordQueue != nil); for (int t = 0; t < NUMBER_AUDIO_DATA_BUFFERS; ++t) { OSStatus errorStatus = AudioQueueEnqueueBuffer( recordQueue, recordQueueBuffers[t], 0, NULL); if (errorStatus) { NSLog(@"\n\n ERROR : Error %ld on AudioQueueEnqueueBuffer\n", errorStatus ); } } } - (void)startRecording { [self startRecording:FALSE]; } - (void)startRecording:(BOOL) autoStop { NSLog(@"Starting to record"); recording = YES; shouldStopRecording = NO; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) , ^{ NSLog(@"PPPP C1"); _frameIndex= 0; self.fileWasCreated = NO; [self setUpRecordQueue]; NSLog(@"PPPP C2"); [self setUpRecordQueueBuffers]; NSLog(@"PPPP C3"); [self primeRecordQueueBuffers]; NSLog(@"PPPP C4"); AudioQueueStart(recordQueue, NULL); NSLog(@"PPPP C5"); if (autoStop) { [self stopRecording]; } }); } - (void)stopRecording { NSLog(@"Stoping to record"); if (recordQueue != nil) { NSString *osVersion = [[UIDevice currentDevice] systemVersion]; if ([osVersion doubleValue]<6){ AudioQueueDispose(recordQueue, TRUE); } else { AudioQueueStop(recordQueue, FALSE); } recordQueue = nil; } NSLog(@"Stopped recording"); shouldStopRecording = YES; recording = NO; } 

回调:

 static void recordCallback( void* inUserData, AudioQueueRef inAudioQueue, AudioQueueBufferRef inBuffer, const AudioTimeStamp* inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription* inPacketDesc) { NSLog(@"recordCallback %u", (unsigned int)inBuffer->mAudioDataByteSize); // I get always zero here... } 

顺便说一下,麦克风的许可是可以的(启用麦克风访问权限)。

更新:似乎AudioQueueStart失败,错误-50。 这仅在iOS 7上发生。 我设置的参数有什么问题吗?

我发现了这个问题! 似乎在iOS 7上也需要设置它(我认为这只是实际上很难找到,不会写在任何地方)。 只需在调用任何AudioQueue函数之前添加此代码:

 AudioSessionInitialize(NULL, NULL, nil, ( void *)(self) ); UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord; AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory ); AudioSessionSetActive(true); 

希望能帮助别人。

可以在这里找到另一种可以提供帮助的资源。

@Idan你的答案是正确和有效但它只显示警告,如果app minimun部署目标是iOS 7.对于iOS 7,我们可以做这样的事情:

 NSError *audioSessionError; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&audioSessionError]; if(audioSessionError) { NSLog(@"AVAudioSession error setting category:%@",audioSessionError); } else { [audioSession setActive:YES error:&audioSessionError]; if(audioSessionError) NSLog(@"AVAudioSession error activating: %@",audioSessionError); }