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 はこの構造体に非同期でアクセスしているので、-stopRecording メソッドが呼び出されたら、録音フィールドを安全に NO に設定するにはどうすればよいでしょうか? 問題は、おそらくレコーダー クラスでこの構造体へのポインターが必要になることですが、それへのアクセスをロックする方法も必要になるため、コールバック関数がそれを読み取っている間は NO に変更しません。

4

1 に答える 1

0

Core Audio コールバック内でロックを待つべきではありません。

これを処理する 1 つの方法は、単純なアトミック書き込みサイズ (1 ワード) フラグを使用することです。このフラグは、1 つのスレッドでのみ書き込むことができ、他のコールバックまたはメソッドで 1 回だけ読み取られます。次に、オーディオ コールバックがフラグを書き込むことができず、最初に 1 回だけ読み取る限り、メイン スレッドからそのフラグを安全に切り替えられるはずです。ただし、フラグが切り替えられた後 (およびデータ キャッシュがフラッシュされた後など) にコールバックがまだ「何かを実行中」である可能性があることに注意してください。記録フラグの状態の変化が認識されたことを確認する前に、別の完了ハンドシェイク フラグ。

于 2013-01-14T20:43:24.517 に答える