1

我正在使用音频队列构建一个用于学习目的的简单录音机。回调函数接收一个指向结构体的指针,该结构体的定义如下:

typedef struct RecorderUserData {
    AudioFileID outputFileID;
    SInt64 recordPacket;
    BOOL recording;
} RecorderUserData;

访问该结构的回调函数字段。这个回调函数被Core Audio异步调用。

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

    UXAudioRecorderUserData *recorderUserData = (UXAudioRecorderUserData *)inUserData;

    if (recorderUserData->recording) {
        // do something while recording
    }

    // much more code
}

问题是,我想从外部方法调用开始/停止录制。当记录开始时,结构体准备好,记录字段设置为 YES。

当录制必须结束时,我必须将录制字段设置为 NO。

在 Kevin Avila 和 Chris Adamson 撰写的 Core Audio 书中,他们在一个巨大的单片主函数中完成了这一切,我仍然可以在脚下访问这个结构。

但是由于 Core Audio 正在异步访问这个结构,一旦我的 -stopRecording 方法被调用,我怎样才能安全地将录制字段设置为 NO?问题是我可能需要在我的记录器类中指向该结构的指针,但也需要一种锁定对它的访问的方法,因此我不会在回调函数读取它时将其更改为 NO。

4

1 回答 1

0

不应等待 Core Audio 回调中的任何锁。

处理此问题的一种方法是使用简单的原子写入大小(1 个字)标志,该​​标志只能在一个线程中写入,并且只能在任何其他回调或方法中读取一次。然后,只要音频回调不能写入标志,并且在开始时只读取一次,从主线程切换该标志应该是安全的。但请注意,在切换标志(并且数据缓存被刷新等)之后,回调仍然可能“做某事”,因此您可能需要等待一段时间(最大音频单元缓冲区大小),或者等待另一个完成握手标志,然后确保您的记录标志状态的变化被识别。

于 2013-01-14T20:43:24.517 回答