我可以设置一个音频队列进行录制,AudioQueueStart 可以很好地开始录制。
但是在调用AudioQueueStop之后,我发现同样的Audio Queue不能再启动了,我需要创建一个新的Audio Queue和Buffers来再次开始录制。
停止后是否可以重用相同的音频队列?
谢谢。
我可以设置一个音频队列进行录制,AudioQueueStart 可以很好地开始录制。
但是在调用AudioQueueStop之后,我发现同样的Audio Queue不能再启动了,我需要创建一个新的Audio Queue和Buffers来再次开始录制。
停止后是否可以重用相同的音频队列?
谢谢。
我遇到了同样的问题。仔细研究文档并没有发现任何关于此问题根源的线索,但查看示例代码,所有记录队列仅使用一次 - 没有迹象表明它们可以重复使用。
文档中唯一的提示是 AudioQueueStart 用于在使用AudioQueuePause暂停队列后恢复。
录音队列似乎是为一次性使用而设计的,需要在最后处理(AudioQueueDispose)并为任何后续录音重新创建。
尽管没有任何文档,但似乎确实有一种方法可以做到这一点。
它需要确保在AudioQueueStop
异步调用之后,任何仍在队列中的数据都得到正确处理。
因此,在停止录制的调用中,我们有一个状态变量 ( recordingState
) 来跟踪正在发生的事情。鉴于此函数和回调在不同的线程中执行,我们尝试通过同步到当前类(Listener
在此示例中调用)来避免任何可能的并发症:
-(void) stopRecording
{
@synchronized(self)
{
if(self.recordingState != RecordingStateRunning) {return;}
self.recordingState = RecordingStateStopping;
AudioQueueStop(self.audioQueue, false);
}
}
实验表明,在异步调用后AudioQueueStop
(即参数inImmediate
设置为false
),回调会被多调用几次,所以我们有机会整理一下:
static void AQInputCallback(void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumberPacketDescriptions,
const AudioStreamPacketDescription *inPacketDescs)
{
Listener *listener = (__bridge Listener *) inUserData;
@synchronized(listener)
{
if(listener.recordingState == RecordingStateRunning)
{
// Do audio processing here.
// ...
}
else if(listener.recordingState == RecordingStateStopping)
{
listener.recordingState = RecordingStateStopped;
// Do tidying here.
// ...
}
AudioQueueEnqueueBuffer(listener.audioQueue, inBuffer, 0, NULL);
}
}