1

AVAssetReader を使用して PCM データを iPod トラックからバッファにコピーし、RemoteIO オーディオ ユニットで再生しています。サウンドデータをロードするための別のスレッドを作成しようとしています。これにより、ロード中にバッファからデータにアクセスして再生できます。

現在、最終的に曲のデータ全体を保持する大きな NSMutableData オブジェクトがあります。現在、次のように NSOperation を使用して別のスレッドにオーディオ データをロードします。

  1. AVAssetReaderOutput は、一度に最大 8192 バイトを CMBlockBuffer にコピーします
  2. これらのバイトを NSData オブジェクトにコピーします
  3. この NSData オブジェクトをより大きな NSMutableData オブジェクト (最終的に曲全体を保持する) に追加します。
  4. 終了したら、NSMutableData オブジェクトの各パケットにアクセスして曲を再生します

これらのバイトをコピーしながら曲を再生できるようにしようとしています。同時にファイルへの書き込みと読み取りを行う良い方法が何であるかはわかりません。

私が持っていた短いアイデア:

  1. それぞれ長さが 8192 バイトの 3 つの NSData オブジェクトをバッファとして作成し、埋めます。
  2. プレイを開始します。最初のバッファの再生が終了したら、新しいデータを最初のバッファにロードします。
  3. 2 番目のバッファーの再生が終了したら、新しいデータを 2 番目のバッファーに読み込みます。三代目も同じ
  4. 再び最初のバッファから再生を開始し、3 番目のバッファを埋めます。等々。

または、3 * 8192 PCM ユニットを保持する 1 つの NSData オブジェクトを作成し、何らかの方法で 2 つの異なるスレッドで同時に書き込みおよび読み取りを行います。

現在、2 つの異なるスレッドでコードを実行しています。再生を押すまで配列にデータを追加します。その時点で停止し (おそらくスレッドがブロックされているためですが、今はわかりません)、ロードしたものの最後に到達するまで再生され、EXC_BAD_ACCESS 例外が発生します。

要するに、コピー中に PCM データを再生する正しい方法を見つけたいと思っています。たとえば、一度に 8192 バイトです。おそらく別のスレッドで行う必要があります(現在NSOperationを使用しています)が、できればより高いレベルのObjective-Cメソッドを使用して、同時にバッファへの書き込みと読み取りを行う方法が不明です。

4

1 に答える 1

1

私はまさにこのことをやっています。必ず別のスレッドでオーディオを再生する必要があります (私はこれを RemoteIO で行っています)。また、循環バッファーを使用する必要があります。このタイプの操作によく使用されるため、このデータ構造に慣れていない場合は、おそらくこのデータ構造を調べたいと思うでしょう。私の一般的な設定は次のとおりです。

  • LoadTrackThread が起動し、AVAssetReader からデータを読み込み、PCM としてファイルに保存し始めます。
  • LoadPCMThread は、十分なデータが PCM ファイルに読み込まれると起動し、基本的にそのファイルを必要に応じて RemoteIO スレッドのローカル メモリに読み込みます。これは、RemoteIO スレッドがリモートでサンプルを使い果たしそうになるたびに、このデータを循環バッファーにフィードすることによって行われます。
  • RemoteIO 再生コールバック スレッドは循環バッファ フレームを消費し、それらを RemoteIO インターフェイスに送ります。さらにサンプルの読み込みを開始する必要がある場合は、LoadPCMThread にウェイクアップするよう通知します。

スレッドに関しては、これで十分です。2 つのスレッド間にある種のミューテックスまたはセマフォを配置して、ファイルに同時に書き込みを行っている間にファイルを読み取ろうとしないようにする必要があります (これは不適切な形式であり、クラッシュの原因となります)。両方のスレッドにブール値を設定し、設定が解除されるまでしばらくスリープさせます。これを行うにはおそらくもっと洗練された方法がありますが、それは私の目的には適しています。

それが役立つことを願っています!

于 2011-06-07T04:20:51.560 に答える