オーディオをサンプリングする

Android 5.0(Lollipop)以降、オーディオ リサンプラーは、Kaiser windowed-sinc 関数から派生した FIR フィルタを完全にベースにするようになりました。Kaiser windowed-sinc には、次のような特性があります。

  • 設計パラメータ(阻止域リップル、遷移帯域幅、遮断周波数、フィルタ長)の計算がシンプルであす。
  • 全エネルギー比で、阻止域エネルギーの削減にほぼ最適です。

カイザー窓とその最適性、ならびにカイザー窓と偏長回転楕円体窓の関係については、P.P. Vaidyanathan 著『マルチレート信号処理とフィルタバンク』の 50 ページをご覧ください。

設計パラメータは、内部の品質測定と、望ましいサンプリング比に基づいて自動的に計算されます。設計パラメータに基づいて、windowed-sinc フィルタが生成されます。音楽に使用する場合、44.1 kHz から 48 kHz へのリサンプラー(逆の場合も同様)は、任意周波数変換よりも高い品質で生成されます。

オーディオ リサンプラーは、品質が向上するだけでなく、この品質を達成するための速度も向上します。ただし、リサンプラーは少量の通過域リップルとエイリアシング高調波ノイズを発生させることがあり、遷移帯域に高周波損失が生じる可能性があるため、不必要に使用することは避けてください。

サンプリングとリサンプリングのベスト プラクティス

このセクションでは、サンプリング レートに関する問題を回避するためのベスト プラクティスをいくつか紹介します。

デバイスに合ったサンプリング レートを選択する

通常は、デバイスに合ったサンプリング レート(通常は 44.1 kHz~48 kHz)を選択することをおすすめします。リサンプラーはファイルの再生に使用する必要があるため、48 kHz を超えるサンプルレートを使用すると、通常は品質が低下します。

シンプルなリサンプリング比を使用する(固定ポリフェーズと補間ポリフェーズ)

リサンプラーは、以下のいずれかのモードで動作します。

  • 固定ポリフェーズ モード: 各ポリフェーズのフィルタ係数は、事前に計算されています。
  • 補間ポリフェーズ モード: 各ポリフェーズのフィルタ係数は、最も近い 2 つの計算済みポリフェーズから補間する必要があります。

リサンプラーは、入力レートと出力レートの比率「L/M」(最大公約数で除算した値)の M が 256 未満の場合に、固定ポリフェーズ モードで最速になります。たとえば、44,100 から 48,000 への変換(L = 147、M = 160)の場合などです。

固定ポリフェーズ モードの場合、サンプリング レートはロックされ、変化しません。補間ポリフェーズ モードの場合、サンプリング レートは概数になります。48 kHz のデバイスで再生するとき、サンプリング レートのドリフトは通常、数時間で 1 つのサンプルになります。近似誤差は、内部の水晶振動子や、熱ドリフト、ジッターによる周波数誤差(一般的には数十 ppm)に比べてはるかに小さいため、通常は問題になりません。

AudioTrack で他のサンプリング レートやサンプリング比が使用可能な場合でも、48 kHz のデバイスで再生する場合は、24 kHz(1:2)や 32 kHz(2:3)など、シンプルな比率のサンプリング レートを選択するようにしてください。

サンプルレートを変更する際はダウンサンプリングではなくアップサンプリングを使用する

サンプリング レートは瞬時に変更できます。このような変更の粒度は、個々のサンプルではなく、内部バッファリング(通常は数百個のサンプル)に基づきます。これは、エフェクトに使用できます。

ダウンサンプリングする際は、サンプリング レートを動的に変更しないようにします。オーディオ トラックの作成後にサンプルレートを変更する場合、元のレートとの相違が 5~10% 程度に達していると、ダウンサンプリングの際にフィルタの再計算がトリガーされることがあります(エイリアシングを適切に抑制するため)。その結果、演算リソースが消費されることになり、フィルタがリアルタイムで交換されるときにクリック雑音が発生することがあります。

ダウンサンプリングを 6:1 未満に制限する

ダウンサンプリングは通常、ハードウェア デバイス要件によってトリガーされます。ダウンサンプリングにサンプルレート コンバーターを使用する場合、エイリアシングを適切に抑制するために、ダウンサンプリングの比率を 6:1 未満に制限するようにしてください(たとえば、48,000 対 8,000 以上のダウンサンプリングは避けます)。フィルタ長は、ダウンサンプリング比に合致するように調整されますが、ダウンサンプリング比が大きくなると、フィルタ長が過度に増加するのを避けるために、多くの遷移帯域幅が犠牲になります。アップサンプリングの場合、エイリアシングに関して同様の問題は発生しません。なお、オーディオ パイプラインの各部分の影響により、2:1 を超えるダウンサンプリングを実行できない場合があります。

レイテンシの懸念がある場合はリサンプリングしない

リサンプリングを実行すると、トラックが FastMixer パスに配置されなくなります。したがって、通常の Mixer パスに大きなバッファが追加されることにより、非常に大きなレイテンシが発生することになります。また、リサンプラーのフィルタ長から暗黙的な遅延が発生しますが、これは通常は 1 ミリ秒未満の長さであり、通常の Mixer パスの追加バッファリング(通常は 20 ミリ秒)を超えることはありません。

浮動小数点オーディオを使用する

浮動小数点数を使用してオーディオ データを生成すると、高性能オーディオ アプリの音質を大幅に高めることができます。浮動小数点には、以下のメリットがあります。

  • ダイナミック レンジが広くなります。
  • ダイナミック レンジ全体で精度が一貫します。
  • ヘッドルームが増えるため、中間計算時やトランジェント時のクリッピングを回避できます。

浮動小数点は音質を高めますが、以下のようなデメリットもあります。

  • 浮動小数点数を使用すると、メモリの消費量が増えます。
  • 浮動小数点演算には予想外の性質があります(たとえば、加算が結合的ではないなど)。
  • 浮動小数点演算では、端数処理のアルゴリズムや数値的安定性に欠けるアルゴリズムが原因で、計算精度が低下することがあります。
  • 浮動小数点を効果的に使用して正確で再現可能な結果を得るためには、浮動小数点について深く理解する必要があります。

以前、浮動小数点は、使用できない場合や低速になる場合があり、評判がよくありませんでした。現在でも、ローエンド プロセッサや組み込みプロセッサの場合には、同じことが当てはまります。しかし、最新のモバイル デバイスのプロセッサの場合、整数と同様のパフォーマンスを実現するハードウェア浮動小数点がサポートされています(整数よりも高速になることもあります)。また、最新の CPU は SIMD(Single Instruction / Multiple Data)もサポートしているため、パフォーマンスをさらに高めることができます。

浮動小数点オーディオのベスト プラクティス

以下では、浮動小数点演算に関する問題を回避するためのベスト プラクティスを紹介します。

  • フィルタ係数の計算など、使用頻度の低い演算には倍精度浮動小数点を使用します。
  • 演算の順序に注意します。
  • 中間値に明示的な変数を宣言します。
  • かっこをふんだんに使用します。
  • NaN や infinity の結果を受け取った場合は、バイナリ検索を使用して、原因となった場所を見つけます。

浮動小数点オーディオの場合、AudioFormat.ENCODING_PCM_FLOAT をエンコードするオーディオ形式が、AudioTrack データ形式を指定する ENCODING_PCM_16_BITENCODING_PCM_8_BIT に対しても同じように使用されます。対応するオーバーロード メソッド AudioTrack.write() は、浮動小数点配列を受け取ってデータを提供します。

Kotlin

    fun write(
            audioData: FloatArray,
            offsetInFloats: Int,
            sizeInFloats: Int,
            writeMode: Int
    ): Int
    

Java

    public int write(float[] audioData,
            int offsetInFloats,
            int sizeInFloats,
            int writeMode)
    

詳細情報

このセクションでは、サンプリングと浮動小数点に関する参考リンクをいくつか紹介します。

サンプリング

サンプルレート

リサンプリング

高ビット深度と高 kHz に関する考察

浮動小数点

浮動小数点オーディオの詳細については、以下の Wikipedia ページをご覧ください。

コンピュータ システム設計者に直接影響する浮動小数点の情報については、以下の記事をご覧ください。