2016-07-08 5 views
3

iOS Audio Unit render callbackで私のカスタムシンセコードから低レイテンシーのオーディオをレンダリングしています。明らかに私のレンダリングコードが遅すぎると、コールバックから遅すぎて戻ってバッファアンダーランが発生します。私はこの経験から、無音が出力されることを知っています。iOSで時間制限内でオーディオをレンダリングする方法を教えてください。

私は(試料中の)バッファの長さは、音声の存在の持続時間を決定明らかに

..私は、デバイスの制限などに合わせて、処理のレベルを管理できるように、私が持っているもの、時間制限を知りたいですレンダリングされ、全体的な制限が設定されます。しかし、Appleオーディオエンジンは、レンダリングコールバックを発行してからレスポンスを要求するまでの時間制限が小さくなると思われます。

  1. この制限時間はどのようにして知ることができますか?コールバック関数自体で何ができるのでしょうか?
  2. 制限時間を超えてバッファアンダーランが発生した場合、私が受け取ることができる通知か質問することができるステータスオブジェクトがありますか?

NB:私のアプリでは、1つの「出力」オーディオユニットを作成しているので、オーディオユニットを連鎖させることについて心配する必要はありません。

答えて

2

オーディオユニットのコールバックで実行できるオーディオレンダリングの量は、iOSデバイスのモデルとOSのバージョン、および温度やバックグラウンドモードによるCPUクロック速度の低下の可能性があります。したがって、アプリのサポートを予定している最古の、最も遅いiOSデバイスで、いくらかマージンを取ってプロファイリングする必要があります。

iOS 9をサポートするために、iPhone 4Sテストデバイス(ARM Cortex A9 CPU in 800 MHz)、または以前のiOSバージョンを使用してより古い低速デバイスで、私のアプリケーションを非常に保守的にプロファイリングします。このプロファイリングを行う際には、オーディオコールバックをテストし、マージンがあるかどうかを確認するために、ある程度の割合で "make work"を追加することができます(マージンが50%の場合、サンプルバッファを2回生成するなど) 。

これは、モバイルオーディオ開発者が複数のiOSデバイスを所有している(またはアクセスしている)方が重要な理由です(古い方が良い)。コールバックが古い低速テキストデバイスの時間制限を満たしていれば、新しいiOSデバイスでは十分に速くなりそうです。

OSのバージョンによっては、アンダーランによって無音状態になるか、オーディオユニットが停止またはクラッシュする可能性があります(予測可能な時間内にコールバックが不足または不足していると検出される可能性があります)。

しかし、アンダーランを避ける最善の方法は、オーディオユニットのスレッドの外側の別のスレッドで大量のオーディオを処理し、ロックフリーのFIFO /キューを使用してオーディオユニットのコールバックとの間でサンプルを渡すことです。

+0

を設定することができます。これは、iOSが動的なデータを提供できるかどうかについてです。私のアプリで 私は古いデバイスのために、私は最悪のデバイスのための固定された合成エンジンを設計するのではなく、品質と処理時間を短縮することができますので、その場で合成の複雑さを適合させることができるしています。これは、オンザフライ、利用可能な時間、およびアンダーランが発生したかどうかを知る必要があることを意味します。あなたはこれを手伝うことができますか? (特にあなたのアプリが認識されないとの措置oerformance事前に校正されているデバイスの機種)オーディオを開始する前に –

+1

は、あなたのアプリが、それは、N個のサンプルを生成するのにかかる秒数またはミリ秒を参照するためにいくつかのベンチマーク合成ルーチンを実行する可能性があります。 Nを適切に変更して、少なくとも10分の1秒にわたって複数の反復可能な測定値を取得します。マッハタイマーを使用してベンチマークコードの時間を計測します。このためのパブリックAPIはありません(CPUサイクルタイマーとクロックレートはユーザー空間から隠されています)。アンダーラン(遅すぎる)は、1秒あたりのコールバック数をカウントして平均化することで検出できます。 – hotpaw2

+0

ありがとうございます。私はベンチマークについて疑問に思っていました。残念ながら、「あなたはどれくらいの時間を持っていますか」、「やあ、期限を逃しました」という明確な情報を得るための公開APIはありません。私はあなたのコメントからあなたの答えにいくつかのノートを追加し、それらの編集が受け入れられたらそれを正しい答えにします。 –

0

私が遭遇した最悪の性能のiOSデバイスは、iPhoneのタッチ16G(背面にカメラが面していない)です。私は、iPod touch 16G以外のすべてのデバイスがスムーズにオーディオを再生するプロジェクトを行ってきました。私はバッファの持続時間を次のサイズに合わせて調整しなければなりませんでした。

レンダリングコールバックの前にすべてのオーディオ準備を別々のロックレスリングバッファで行い、レンダリングコールバックをデータのコピーに限定しておきます。バッファアンダーランでアプリケーションを "処理"させました。

私は個人的にレンダリングコールバックの変動を測定したことはありませんが、私はそれがバッファの継続時間に一貫等しいこととなること推測だろう非常に最小限のジッタ(例えば5msの)。私はそれが4.9ミリ秒、次に5.1ミリ秒になるとは思っていません。

タイミング情報を取得するには、mach_time.hmach_absolute_time()を使用してタイミングを取ってください。

あなたは本当にあなたのタイミング要件が何であるかを言いませんでした。低レイテンシーのオーディオが必要だと思う。それ以外の場合は、バッファの持続時間をかなり長く設定することができます。私はこのコードを使って遅いデバイスの待ち時間を増やしたいと思っています。私は通常、iPod 16Gで動作するものを見つけ、それを最悪の場合として使用します。

NSTimeInterval _preferredDuration = ... 
NSError* err; 
[[AVAudioSession sharedInstance]setPreferredIOBufferDuration:_preferredDuration error:&err]; 

もちろん、実際の使用時間を取得する必要があります。 OSはサンプルレートに基づいて2の累乗を選択します:

NSTimeInterval _actualBufferDuration; 
_actualBufferDuration = [[AVAudioSession sharedInstance] IOBufferDuration]; 

デバイスのパフォーマンスを調整する限りです。あなたはいくつかの良い練習のポイントを概説しましたが、私は、私は尋ねた2つの具体的な質問に答えた後、まだよバッファ時間

関連する問題