ACM の畳み込み
ACM の畳み込みは、FMOD の分割リバーブを CPU で実行します。共有入力のバッチは 1 つのドライ信号を変換し、浮動小数点か半精度のインパルスの分割を適用し、ウェットの結果をオーバーラップ加算します。
2026年10月10日 までのリポジトリノート
修正したバグ
Subnautica: Below Zero は、パチパチ音とともに始まって無音になり、数分後に回復することがありました。ホストのデバイスに届く PCM に、有限でない浮動小数点値が含まれていたのです。FMOD の DSP のコールバックをメモリ上でトレースすると、有限の音声が畳み込みリバーブに入り、ゴミが出ていることがわかりました。HLE の関数 sceAcm_ConvReverb_SharedInput、バッチの送信、sceAcmBatchWait が、出力を書かずに成功を返していました。
FMOD はその書き込まれていないウェットのバッファをグラフに混ぜていました。NaN はその後のエフェクトに広がりました。AudioOut の無害化はそれを無音に置き換えるだけで、汚染されたフィルターの履歴は修復できませんでした。2 つ目の誤りとして、最初のバッチ識別子 -1 に対する待機が成功していました。FMOD は最初の待機の失敗を「まだ前のウェットのバッファはない」と解釈し、本当に完了したジョブの後でだけミックスします。
分割畳み込み
ディスクリプターのレイアウトは、FMOD の ACM バックエンドで観測したものと一致します。インパルス応答の分割は、インターリーブされた複素数のビンです。B 個のビンのブロックは長さ 2B の変換に属します。入力、出力、オーバーラップのバッファは別々で、平面形式です。観測した、オフセットがゼロの float32 と float16 のスペクトルのレイアウトだけを受け付けます。
バッチは CPU で動きます。入力の履歴はグレインをまたいでも、リングの折り返しをまたいでも保たれ、オーバーラップは次の出力グレインに持ち越されます。複数の出力がひとつの入力の変換と履歴の前進を共有できます。モノラルの入力で複数のチャンネルに供給できます。逆変換は正規化されます。本物のインパルスの分割を独立に逆変換すると、エネルギーはゼロ埋めしたブロックの前半に入り、スペクトルの符号が確認できます。ゲームが使うパックされたインパルスはナイキストのビンを省きます。
待機、上限、再テスト
ビルダーはポインターの配列とゲインを上限付きのコマンドレコードに取り込みます。PCM そのものはバッチの開始時に読みます。待機が成功するのは、このコンテキストが実際に完了したバッチだけです。コンテキストを破棄すると履歴を解放します。無効な範囲、不明なコマンドのエンコーディング、未対応のレイアウトはエラーを返します。
単独の ACM の FFT、IFFT、パンナーの操作は実装していません。チャンネルは 8、出力は 32、ブロックは 1024 が上限です。履歴のストレージにも上限があります。署名済みのランナーでは、1 秒ごとの PCM のスナップショット 90 個に有限でないサンプルはなく、ピークは 0.1255、0.001 を超える最初の音は 11.03 秒でした。メンテナーが音を確認しています。これらのサンプルはプローブであり、ゲームが出したすべてのサンプルではありません。
実装済みのこと
- FMOD の共有入力と共有 IR のリバーブのバッチに対する分割 FFT 畳み込み。
- float32 と float16 の複素スペクトル、オーバーラップ加算、グレインをまたぐ履歴。
- そのコンテキストの完了したバッチに対してだけ成功する待機。最初の識別子 -1 は失敗します。
- Subnautica の再テストでの有限の PCM。パチパチ音とその後の無音はなくなりました。
まだ足りないこと
- 単独の ACM の FFT、IFFT、パンナーの呼び出しは未実装です。
- ゼロでないスペクトルのオフセットと、計測していないルーティングのレイアウトは拒否します。
- 畳み込みは CPU で動きます。GPU での FFT の経路はありません。
関連するしくみ
これらのページについて