1

remoteIOレンダリングコールバックでマイクを監視しています。iOS:音声処理に必要なスレッディングソリューション

簡単なアルゴリズムを実行して、可聴信号が検出されたかどうかを検出します。

もしそうなら、再び沈黙するまでバッファーに記録し始めます。

再び沈黙が検出されると、処理の準備が整ったバッファがあることをアプリに伝える必要があります。アプリは処理を実行します。

これは別のスレッドで行う必要があります。 (remoteIOレンダリングコールバックスレッドはブロックできません。リアルタイムスレッドであり、システムを詰まらせます)。

レンダリングコールバックからNSNotificationを送信することができず、別のスレッドでピックアップされることが想定されていました。しかし、これは起こりません! SAMEスレッドで実行されます。

これを行うにはどうすればよい方法ですか?

私はおそらく別のスレッドを生成する必要があります。メインスレッドで処理してもちょっとしたことが起きているように見えますが、2分の1もかかるかもしれませんが、UXの人為的要因を引き起こすのに十分でしょう。

答えて

2

私は、シリアル・ディスパッチ・キューを作成し、オーディオ・ユニットのレンダリング・コールバックでデータを取得し、新しいオーディオ・データをシリアル・キューに渡すためにdispatch_asyncを使用します。私はオーディオユニットがコールバックでできるだけ短い時間を費やすことを必要とするようにセカンダリキューを使用します。また、メモリをmallocしたり、割り込みなどを生成したりしないでください。

ここでlockDataとunlockDataは事前割り当てされたNSMutableDataオブジェクトを取得し、ロックされた/ロックされていない配列に格納します。レンダリングコールバックで//あなたのinitメソッドで

self.captureQueue = dispatch_queue_create("AudioCaptureQueue", NULL); 

__block NSMutableData * audiodata = [audioIO lockData]; 

status = AudioUnitRender(audioIO.audioUnit, 
      ioActionFlags, 
      inTimeStamp, 
      inBusNumber, 
        inNumberFrames, 
        &auBufferList); 

dispatch_async(audioIO.captureQueue, ^{ 
    [audioIO.sampleCaptureDelegate audioComponent:audioIO 
        hasSampleBuffer:audiodata]; 

     [audioIO unlockData:audiodata]; 
}); 

シリアルキューでは、私がとき、シリアル、その後、音声データにすべてのデータ処理を行う場所でありますキューは、それが

dispatch_async(dispatch_get_main_queue(), ^{ 
     [[NSNotificationCenter defaultCenter] postNotificationName:kAPPAudioQueueDidDetect 
                  object:nil]; 
    }); 

dispatch_get_main_queueのMEAを使用することができるために、そのが探しているものを検出し、それはメインスレッド上で実行されるので、UIの更新などを行うことができます。

+1

[audioIO lockData]がロックを取得するのを待っている間にスレッドが停止することはありませんか? –

+0

2つの関数lockとunlockは実際には 'ロック'ではなく、単にある配列から別の配列にポインタを移動するだけで、どのブロックに使用可能なデータがあるか、再利用できるかがわかります。私はそれが必要ではないと思って以来、コードを貼り付けていませんが、標準の 'ロックフリー'リングバッファです –

関連する問題