0

マイクからの生の入力サンプルを処理する必要がある CoreAudio アプリケーションを構築しています。2 つのスレッドを使用します。1 つのスレッドはマイク入力からサンプルを生成し、もう 1 つのスレッドはサンプルを消費します。これらのスレッドは、(うまく機能する) 循環バッファーを共有します。その実装は、Github から取得しました (良い例は、著者のブログにあります)。

私の問題の最小限の例として、Github に小さな XCode プロジェクトをまとめたので、完全なコードを見ることができます。アプリはマイク サンプルを循環バッファーに入れ、別のスレッドからバッファーを読み取ります。消費スレッドは、500 サンプルの平均整流値(ARV) を計算し、ARV をコンソールに出力します。

iOS シミュレーター (5.1) でアプリを実行すると、すべて正常に動作し、目的の出力が得られます。

2012-08-21 20:58:31.882 BufferedSamples[23505:6003] 88
2012-08-21 20:58:31.890 BufferedSamples[23505:6003] 108
2012-08-21 20:58:31.890 BufferedSamples[23505:6003] 137
2012-08-21 20:58:31.891 BufferedSamples[23505:6003] 137
2012-08-21 20:58:31.892 BufferedSamples[23505:6003] 106
2012-08-21 20:58:31.901 BufferedSamples[23505:6003] 140
...

代わりにデバイス (iPhone 3/3GS/4 を試しました) でアプリを実行しようとすると、ポインターEXC_BAD_ACCESSが原因で実行時にエラーが発生します。NULLしたがってNULL、CoreAudio コールバック関数 (ファイル内DummyRecorder.m)にポインターのチェックを追加しました。

// render samples into buffer
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mDataByteSize = inNumberFrames * kTwoBytesPerSInt16;
bufferList.mBuffers[0].mData = NULL;
AudioUnitRender(dummyRecorder->audioUnit, ioActionFlags, inTimeStamp, kInputBus, inNumberFrames, &bufferList);

// move samples to ring buffer
if (bufferList.mBuffers[0].mData != NULL)
    TPCircularBufferProduceBytes(&dummyRecorder->buffer, bufferList.mBuffers[0].mData, bufferList.mBuffers[0].mDataByteSize);
else
    NSLog(@"null pointer");

シミュレーターでアプリを実行すると、目的の出力が得られますが、デバイスでは次のようになります。

2012-08-21 21:15:38.903 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:38.926 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:38.949 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:38.972 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:38.996 BufferedSamples[544:3b03] null pointer
2012-08-21 21:15:39.019 BufferedSamples[544:3b03] null pointer
...

シミュレーターでは CoreAudio がバッファーを正しく割り当てて満たすのに、デバイスではバッファーをそのままにしておくことができるのはなぜですか? 私は何を逃したのですか?

私の例の完全なコードは、Github で見つけることができます。

編集

提案どおり、CoreAudio の呼び出し後にエラーをチェックするメソッドを追加しました。@MichaelTyson今、私はコールバックでこれをやっています:

OSStatus err = AudioUnitRender(dummyRecorder->audioUnit, ioActionFlags, inTimeStamp, kInputBus, inNumberFrames, &bufferList);

// move samples to ring buffer
if (checkResult(err, "AudioUnitRender"))
    TPCircularBufferProduceBytes(&dummyRecorder->buffer, bufferList.mBuffers[0].mData, bufferList.mBuffers[0].mDataByteSize);

Github のコードも更新しました。シミュレーターでアプリを実行してもエラーは発生しませんが、デバイスで実行すると次のエラーが発生します。

2012-08-22 11:19:49.248 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.271 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.294 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.317 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.341 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
2012-08-22 11:19:49.364 BufferedSamples[637:3b03] /DummyRecorder.m:50: AudioUnitRender result -50 FFFFFFCE Œˇˇˇ
...
4

1 に答える 1

3

すべてのパラメータを覚えておくのは難しいので、通常、このことを理解するのに少し推測作業が必要ですが、私が最初に試みることは、オーディオユニットの入力バス(バス)の出力スコープでストリームフォーマットを設定することです1)。

現在、出力バス(バス0)の入力スコープにのみ設定していますが、それで十分かどうかは100%わかりません。

于 2012-08-22T21:25:03.143 に答える