[ Main Page ]

GPT-5.3 Instant / Sonnet 4.6 Ext

リバーブアルゴリズム

技術解説文書

理論・実装・知覚・現代的手法の統合解説

Freeverb3 / FDN / Dattorro / Lexicon / 畳み込みリバーブ / ニューラルFDN

第1章 リバーブの本質と概論

1.1 リバーブとは何か

大きなホールで音楽を聴くと、楽器が演奏を停止した後もしばらく音が響き続ける。演奏中も音は響いており、それが音楽に艶やかさを与えるため、ホールでの演奏が好まれる。響きの美しいホールとして、東京・赤坂のサントリーホールなどが有名である。

リバーブとは単なる「残り音」ではなく、空間の情報そのものであり、音の奥行き・距離感・質感を決定する要素である。音響的には以下の2つの時間領域が同時に存在する。

1.2 リバーブ生成の2大方式

実際のホールを使うことは時間的・金銭的に難しく、CDマスタリング等では仮想的にホールの響きを作り出すソフトウェアが使われる。Freeverb3はその代表例である。響きを作り出す方式には大きく分けて2つある。

方式

概要・特徴

FIR(畳み込みリバーブ)

実際の空間のインパルス応答を録音して使用。リアルだが柔軟性低く計算負荷が高い。「そのホールをコピーする技術」

IIR(アルゴリズミックリバーブ)

数学モデルで人工的に生成。軽量・調整可能・創造的だが設計が難しい。「ホールらしさを作る技術」。Lexicon等の商用ハードはほぼこちら

1.3 音の奥行き感の正体

音の前後感(奥行き)は主に次の3要素で決まる。

つまり奥行きはリバーブ設計そのものである。

1.4 人間の知覚特性とリバーブ設計の関係

人間は「個々の反射」ではなく、エネルギー分布と時間変化のパターンを知覚している。ミックスで必要なのは正確な反射配置ではなく、密度(density)・減衰(decay)・周波数バランスである。

FIR(IR)リバーブが使いにくい場面がある理由として、以下が挙げられる。

これに対してアルゴリズミックリバーブは「聴感最適化された嘘」として機能し、ポップス・映画音楽・ゲーム音響など「音楽としての気持ちよさ」が優先される場面で有利となる。

第2章 アルゴリズムの系譜

2.1 Schroeder Reverb(古典・基本形)

もっとも古くから実装され、フリーソフトでも広く使われているのが、comb filterとallpass filterを組み合わせたリバーブである。ARI-WEBのページに詳しい説明がある。Freeverb3の前身であるFreeverbもこのアルゴリズムに基づいており、「Schroeder(シュレーダ)のリバーブ」と呼ばれる。

構成

特性

問題の本質はモード(共鳴)の偏り、すなわちランダム性の不足にある。comb filterが等間隔の周波数ピーク(定在波的な構造)を生じさせることが「チーン」という金属感の原因である。

そのため「高品質さ」を求める場面では使われることが少ない。一方で、金属的な音からプレートリバーブ(金属板に音を入力して振動を出力とする実機)の代わりとして使われることがある。

Freeverbは経験的に求めた数値に基づいてフィルタが作成されており、比較的金属的な音が少ないとされるが、限界はある。

2.2 Schroeder系の改良版(Freeverb3_VSTの実装群)

実装名

特徴

Freeverb

Schroeder改良型。軽量・簡易。経験的パラメータで比較的金属感を抑制

CCRMAのNRev

Freeverbと同様のアルゴリズムをより洗練させたもの

NVerb(v2)

Allpassの入れ子+入力フィードバックを利用してリンギングを極力抑制。低音の響きが改善

Allpass filterの入れ子構造(Nested Allpass)

通常(直列):input → AP → AP → AP と接続するのに対し、入れ子では AP の内部に別のリバーブアルゴリズムを挿入する。これにより:

直列のオールパスフィルタより入れ子の方が品質が高いことはあまり知られていないが、Schroeder自身も昔からこのアルゴリズムに言及していた。

◆ comb filterのfeedback部分にmodulationを加えてChorusとすることでリンギングが抑えられやすく、LexiconのConcert Hallアルゴリズムは「Chorus comb filter + allpass filter + 入れ子allpass filter」に基づいていると推測される。

2.3 FDN(Feedback Delay Networks)

Schroederリバーブの問題を解決するために生まれた方式の一つ。いくつかの異なった長さのdelay lineと、それを撹拌・出力するための行列からなるアルゴリズムである。Freeverb3ではHibiki Reverbとして実装。

基本モデル(数式)

FDNは多入力多出力の再帰システムとして以下のように記述できる。

x(n) = A · x(n-D) + B · u(n)

y(n) = C · x(n)

安定性

システムが安定 ⟺ スペクトル半径 ρ(A) < 1 が条件となる。ただしFDNではディレイがあるため、より正確には「Aがユニタリ(または直交)かつ減衰が入っている状態で安定」となる。

固有値と音の関係

つまりFDNは「多数の減衰振動モードの集合」である。固有値が偏ると特定周波数が強調(リンギング)し、ディレイ長が単純比になるとモードが重なる。これはSchroederが金属的になる理由と同じ構造的問題である。

8個以上のディレイラインとアダマール行列

8個以上のディレイラインとアダマール行列を使えば、かなり簡単に高品質な残響が作れる。実際の残響にあるような周波数の位相変化などについては、リアルタイムに行列を変化させることで対応する実装が多い。初期残響音の生成にもアルゴリズム的に対応しやすく、広く活用されている。

2.4 Loop Tank Reverb(ループタンク型)

ビンテージデジタルリバーブとして広まったLexicon 224やEMT 250は「暖かい」きれいなリバーブとして高く評価されているが、allpass filterを利用したループ(タンク)のアルゴリズムによるところが大きい。大きなループを作ることで、FDNと同様に時間とともに密度が高くなるリバーブを作ることができる。

EMT 250の構成

アルゴリズムとしては単純だが、各最適なdelay長とgainを探すのが難しい。

Lexicon 224の構成(Dattorroアルゴリズム)

Lexicon 224はリバースエンジニアリングによってESPのリバーブとしても実装され、論文にも掲載されている。ESPのマニュアルはFreeverb3のサイトにミラーされている。

feedback loopの長さがあまり長くなく、Plate Reverbとされているが、係数を調整すれば相応の響きが得られる。Freeverb3_VSTではSTRevとして、ホール用の別ループに基づいたProG Reverb(Progenitor Reverb)としても実装されている。

◆ Progenitor Reverbのメインfeedback loopはDattorroの公開アルゴリズムに基づくが、入力のdiffuser・出力のタップは独自の経験に基づく。ループ内部やdiffuserのfeedback係数は0.5程度が基本で、実験によると0.4〜0.8の間に最適値があるとされる。

Dattorroアルゴリズムのブロック構造

全体構造は以下の流れとなる:入力 → プリディレイ → 複数のAllpass(diffuser) → メインループ(2系統クロスフィードバック) → タップ出力(複数点) → ダンピング

核心はクロスフィードバックである。左ループと右ループがそれぞれ自分自身にフィードバックしながら、相手にもフィードバック(クロス)する。これにより情報が混ざり、密度が爆発的に増える。

構成要素

知覚的役割

Allpass diffuser(入力直後)

トランジェントを分散、初期エコーを消す「空間に入った瞬間の拡散」

ループ内Allpass

追加拡散。フィードバック係数0.4〜0.8が最適

ダンピング(LPF)

高域を自然に減衰。これがないと「デジタル臭い」

モジュレーション

固定モードを時間的に破壊。金属感を除去し「生きている」感を生む

タップ出力(複数点)

異なる時間位置・位相からの出力。ステレオ感・広がりを生成

FDNとの本質的違いは以下のとおり。FDNが行列で一気に混ぜるのに対し、Dattorroは構造的に(時間的・段階的に)混ぜる。これによりより「音楽的」に調整しやすい。

2.5 周波数分割(マルチバンド処理)

ある程度新しいLexiconのリバーブは周波数分割により、それぞれの帯域に最適なアルゴリズムを利用して残響を生成している。

パラメータBass XOVは、低周波を分割処理して低音域の残響時間を延長等するための仕組みである。Lexiconはかなり初期からこの分割アルゴリズムを採用しており、低音に強い暖かみのあるリバーブとなっている。実際の環境でも、低音は指向性が低く高音は指向性が高いため、分割処理の採用には物理的な合理性がある。

周波数依存性の知覚的意味

情報理論的には、低域はエントロピー増加(豊かさ)、高域は相互情報量減少(拡散)を早期に達成する。

2.6 アルゴリズム進化の系譜(まとめ)

世代

代表例

核心構造

音の特徴

第1世代

EMT 250(1976)

短ループ+Allpass

不完全だが暖かい粒状感

第2世代

Lexicon 224 / 480L

知覚最適化+マルチバンド+ランダム化

音楽的・魔法的な尾

第3世代

Bricasti M7

Waveguide的物理近似

現実の空間を再現

第4世代

DiffFDN / PINN

学習による統合

知覚・物理・情報の統合

第3章 コンボリューション・IRリバーブ技術

3.1 「コンボリューション」用語の正確な定義

convolution の正確な訳語は「畳み込み」である。「叩き込み」という表記は画像処理ソフトの誤訳に端を発する誤りであり、技術文書では使用しない。

数学的定義:

y(n) = Σ_k x(k) · h(n-k)

音響的意味:IR = 空間(または機器)の「応答の全て」であり、コンボリューション = 「入力をその空間で鳴らした結果を計算すること」である。

3.2 IRとデコンボリューション(逆フィルタ)

マイク変換(例:SM57 → U87)に必要なのはデコンボリューション(逆フィルタ)である。

H_IR(ω) = Y(ω) / X(ω)

実務上の問題として、周波数でゼロに近い箇所での「ゼロ割」によるノイズ増幅がある。対策として正則化(regularization)や帯域制限が用いられる。

3.3 IR計測:スイープ信号の使用

理想はデルタ関数入力だが、実際にはS/Nが悪すぎて使えない。現代の標準手法はサイン波スイープまたはTSP(Time-Stretched Pulse)を使う方式である。

手順

スイープが優れている理由

3.4 リアルタイム畳み込みとFFT高速化

計算量

FFT畳み込みの式:Y = IFFT(FFT(X) · FFT(H))

レイテンシ問題

FFTはブロック処理のため、ブロックサイズ分の遅延が発生する(例:1024サンプル → 約20ms)。

解決策:ハイブリッド方式

これにより低レイテンシと高速処理を両立する。

3.5 IRの本質的限界(LTI系のみ)

IRが表現できるのはLTI(Linear Time-Invariant)系のみである。

再現できるもの

再現できないもの

周波数特性・残響・位相応答

真空管アンプの偶数次倍音歪み(非線形歪み)

空間の線形応答全般

スピーカーの非線形コンプレッション効果

FM的変調(時間依存の周波数変化)

IRは「音の形」は再現できるが「振る舞い」は再現できない。また、収録機材(スピーカー・マイク)の特性はデコンボリューションである程度除去できるが、S/N比・ダイナミックレンジ・歪みの制約から完全除去は不可能である。

3.6 ソフトウェア史と主要製品

当時の代表的なコンボリューションリバーブソフトは以下のとおりである。

ソフトウェア

特徴

SIR(Windows専用・フリー)

初期は高レイテンシ。バージョンアップで順次改善

WAVES IR-1 / IR-L

業界標準クラスの商用製品

Altiverb

4ch IRによりステレオI/Oに対応。定位再現性が高く付属ライブラリの質も高い。ただしiLok必須・高価格が障壁

Voxengo Pristine Space

高コストパフォーマンスの商用製品

WizooVerb W2

商用製品

◆ AltiverbはステレオI/Oに対応した4chのIRを持つため定位再現性に優れる。Altiverb専用フォーマット(リトルエンディアン24bit PCM+リソースフォークのゲイン補正情報)のWAV変換手順が共有された。フリーのIR素材配布サイトとしてNoisevault・Voxengo・memi.comなどが活用された。

3.7 IRの創造的応用

IRは「空間の録音」だけではなく、様々な創造的応用がある。

第4章 FDN実装(C++)

4.1 FDNの基本実装

以下はC++によるFDNの基本実装例である。テンプレートパラメータ length がFDNの次元数を指定する。feedbackの範囲は [-1.0, 1.0] で、範囲外では発散する。

template<typename Sample, size_t length>

struct FeedbackDelayNetwork {

size_t bufIndex = 0;

std::array<std::array<Sample, length>, 2> buf{};

std::array<std::array<Sample, length>, length> matrix{};

std::array<Delay<Sample>, length> delay;

std::array<RateLimiter<Sample>, length> delayTimeSample;

Sample process(Sample input, Sample feedback) {

bufIndex ^= 1;

auto &front = buf[bufIndex];

auto &back = buf[bufIndex ^ 1];

front.fill(0);

for (size_t i = 0; i < length; ++i)

for (size_t j = 0; j < length; ++j)

front[i] += matrix[i][j] * back[j];

input /= Sample(length);

for (size_t idx = 0; idx < length; ++idx) {

auto &&sig = input + feedback * front[idx];

front[idx] = delay[idx].process(

sig, delayTimeSample[idx].process());

}

return std::accumulate(front.begin(), front.end(), Sample(0));

}

};

◆ リセット関連のメソッドは省略。テンプレートパラメータ length が大きい時はstd::vectorへの書き換えを推奨(dim=200程度が上限の目安)。

処理ループの構造

引数 feedback はフィードバック行列の値をまとめて変更するスカラー係数。ただし Delay は線形補間を行っているため、ディレイ時間が整数でなければ徐々に出力が減衰する。

4.2 安定性の本質

安定条件

FDNが発散しない条件:ρ(g·A) ≤ 1(ρ:スペクトル半径)

直交行列の意味

直交行列 A について A^T · A = I が成立する。これにより |λ_i| = 1 となり、エネルギーが保存される。

‖y‖² = ‖Ay‖²

つまり、直交行列 + |g| < 1 の組み合わせで必ず安定となる。減衰は g のみで制御される。

◆ Schlecht と Habets の "On lossless feedback delay networks" によると、FDNが発散しないためにはフィードバック行列をユニタリ行列か三角行列にするとよい。

4.3 ディレイ長の設計

重要条件

悪い例と良い例

自動生成アルゴリズム

最適解は解析的に求まらず、探索と経験則のハイブリッドとなる。

第5章 フィードバック行列の設計

5.1 行列の種類と音響特性

Schlecht と Habets の研究によると、FDNが発散しないフィードバック行列の主な種類として、ユニタリ行列(複素数を含む場合あり)と三角行列がある。今回の実装では直交行列(実数のユニタリ行列)で十分である。

行列の種類

特徴・音の傾向

ランダム直交行列

高い拡散性・均一なエネルギー分布。金属感少なく滑らか。scipy.stats.ortho_group.rvs()相当

特殊直交行列

行列式=1。ランダム直交との音の違いは聴き取りにくい

Householder行列

H = I - 2(vv^T)/(v^Tv)の形。dim個の乱数から構築可能。拡散は弱めでキャラが出やすい

アダマール行列

±1のみ。完全直交。高速(加算のみ)。ランダム直交と似た音でCPU効率良好

巡回行列

シフト構造・周期性あり。「管っぽい」音。DFTで対角化可能

三角行列

初期反射が強く金属感あり。ショートディレイが目立つ

Conference行列

対角成分が0。非常に自然で自己ループ(金属音源)が最小。大変良い音

吸収オールパス行列

Schlecht-Habets論文の式(10)。FDNを使わない方が効率的な場合あり

行列選択の指針

5.2 直交行列のランダマイズ(C++実装)

Mezzadri の "How to generate random matrices from the classical compact groups" を参考にした実装。scipy.stats.ortho_group.rvs() のC++翻訳版。

template<size_t dim>

void randomOrthogonal(unsigned seed,

std::array<std::array<Sample, dim>, dim> &H) {

pcg64 rng{}; rng.seed(seed);

std::normal_distribution<Sample> dist{};

H.fill({});

for (size_t i = 0; i < dim; ++i) H[i][i] = Sample(1);

std::array<Sample, dim> x;

for (size_t n = 0; n < dim; ++n) {

auto xRange = dim - n;

for (size_t i = 0; i < xRange; ++i) x[i] = dist(rng);

Sample norm2 = 0;

for (size_t i = 0; i < xRange; ++i) norm2 += x[i] * x[i];

Sample x0 = x[0];

Sample D = x0 >= 0 ? Sample(1) : Sample(-1);

x[0] += D * std::sqrt(norm2);

Sample denom = std::sqrt(

(norm2 - x0*x0 + x[0]*x[0]) / Sample(2));

for (size_t i = 0; i < xRange; ++i) x[i] /= denom;

for (size_t row = 0; row < dim; ++row) {

Sample dotH = 0;

for (size_t col = 0; col < xRange; ++col)

dotH += H[col][row] * x[col];

for (size_t col = 0; col < xRange; ++col)

H[col][row] = D * (H[col][row] - dotH * x[col]);

}

}

}

◆ 乱数生成器にPCGを使用するのはNumPyのdefault_rng()で採用されているため。安定性が重要なのでstd::minstd_randより好ましい。

5.3 アダマール行列(Sylvester's construction)

初期値として 1/sqrt(dim) を使い、タイリングで再帰的に構成する。dim は2の冪乗でなければならない。

template<size_t dim>

void constructHadamardSylvester(

std::array<std::array<Sample, dim>, dim> &mat) {

static_assert(dim && ((dim & (dim-1)) == 0), ...);

mat[0][0] = Sample(1) / std::sqrt(Sample(dim));

size_t start = 1; size_t end = 2;

while (start < dim) {

for (size_t row = start; row < end; ++row)

for (size_t col = start; col < end; ++col) {

auto &&value = mat[row-start][col-start];

mat[row-start][col] = value; // Upper right

mat[row][col-start] = value; // Lower left

mat[row][col] = -value; // Lower right

}

start *= 2; end *= 2;

}

}

5.4 Householder行列

H = I - 2(vv^T)/(v^Tv) の形で表現される。dim個の乱数から直交行列を組み立てられ、対称行列になる(H = H^T)特徴がある。

template<size_t dim>

void randomHouseholder(unsigned seed,

std::array<std::array<Sample, dim>, dim> &matrix) {

// ... (一様乱数でvecを初期化)

auto scale = Sample(-2) / denom;

for (size_t i = 0; i < dim; ++i) {

matrix[i][i] = Sample(1) + scale * vec[i] * vec[i];

for (size_t j = i+1; j < dim; ++j) {

auto value = scale * vec[i] * vec[j];

matrix[i][j] = value; matrix[j][i] = value;

}

}

}

5.5 Conference行列

Conference行列の大きさは「2つの平方数の和となる偶数 q(OEISのA286636相当)に対してq+1」という条件を満たす必要がある。OEIS数列A000952(候補:62, 54, 50, 46, 42, 38, 30, 26, 18, 14, 10, 6, 2)を候補として使用。

対角成分が0であるため、単純なコムフィルタになっている部分がなく音質が良い。

構成手順

5.6 吸収オールパス行列(Absorbent Allpass Matrix)

Schlecht-Habets の "Time-varying feedback matrices in FDN" で紹介された行列。オールパスフィルタの入れ子を表現する。α の範囲が (-1, 1) なら収束する。

template<size_t dim>

void randomAbsorbent(unsigned seed, Sample low, Sample high,

std::array<std::array<Sample, dim>, dim> &mat) {

// dim は偶数必須

constexpr size_t half = dim / 2;

// 上半分(half×half)の直交行列 A を生成

randomOrthogonal(seeder(rng), A);

for (size_t col = 0; col < half; ++col) {

auto gain = dist(rng);

mat[half+col][half+col] = gain; // 右下

mat[half+col][col] = Sample(1) - gain*gain; // 左下

for (size_t row = 0; row < half; ++row) {

mat[row][half+col] = A[row][col]; // 右上

mat[row][col] = -A[row][col]*gain; // 左上

}

}

}

5.7 単位行列に近いランダム特殊直交行列の生成

randomSpecialOrthogonal の乱数生成部分を以下のように変更することで、単位行列への近さを調整できる。

x[0] = Sample(1);

for (size_t i = 1; i < xRange; ++i)

x[i] = identityAmount * dist(rng);

音響的には identityAmount を下げると初期反射が強化され後期残響が弱化する傾向がある。

5.8 固有値を直接設計する方法

通常はフィードバック行列 A から固有値が決まるが、逆に固有値を先に設計する「固有値直接設計」も可能である。

設計手順

実用解

固有値設計の本質は「減衰スペクトルの設計」である。

第6章 知覚モデルとリバーブ設計

6.1 「良いリバーブ」の知覚条件

良いリバーブ

悪いリバーブ

エコーを感じない(密度が時間と共に増える)

金属的(metallic)

低音が自然に伸びる

周期的(ピンポン感)

高音がうるさくない

濁る or 輪郭が消える

音像を壊さない

特定帯域が強い

エネルギー分布が時間とともに均一化する

リンギングが明確に聴こえる

6.2 JND(Just Noticeable Difference)

人間が違いを感じる最小量(JND)の目安:

JNDを知ることで「無駄に精密な設計は不要」という設計原則が導かれる。1ms単位の最適化や聴覚限界以下の周波数分解能設計は実質的な意味を持たない。

6.3 聴覚マスキング

周波数マスキング

強い音が近い帯域の弱い音を隠す。EMT 250の「粒状感」がマスキングを生み、完全拡散よりも心地よく聴こえる場合がある(「不完全さが知覚的最適」というパラドックス)。

時間マスキング

直後の音が聞こえなくなる効果。初期反射は直接音にマスクされるため完全な物理再現は不要。

設計原則

6.4 情報理論的視点

音場を「波」ではなく「情報源」として捉える。

良いリバーブの目標:時間とともにエントロピーが滑らかに増加すること。

相互情報量の観点

金属音の情報理論的解釈:情報が拡散されず、構造が知覚されてしまう現象である。

6.5 リバーブ設計の3層構造

① 初期反射(Early Reflections)

② 拡散(Diffusion)

③ 後期残響(Late Reverb)

第7章 商用リバーブの知覚最適化

7.1 Lexicon 480L Random Hall

Lexicon 480Lの知覚的な「魔法」は、Bass XOV(マルチバンド処理)・制御されたモジュレーション・Loop Tank構造の組み合わせによる。

CHO値(モジュレーション)

Random Hallでは内部モジュレーション(Decay Optimization)がCHOに相当する。

Bass XOVの聴感最適値

◆ マニュアルでは「BASS MULT最大、RT HF CUT中、HF CUTOFF低」が理想的なコンサートホール設定として明記されている。

Lexiconが「暖かい」理由(数理的解釈)

Bass XOVは周波数ごとに最適な情報拡散速度を変える機構であり、以下の物理的・知覚的事実に基づく。

7.2 M7 V2 Modulationの数理的再現

公式マニュアルによると、V2 modulationはlate reverb tailのpitch variationであり、chorusやflangeとは異なる。

各delay tapの時間 D_i(t) を独立に変調:D_i(t) = D_i + Δ · m(t, level)

level依存の変調関数 m(t)

// C++実装(簡略)

Sample sine = std::sin(2.0f * M_PI * modFreqBase * phase[i]);

Sample noise = 0;

for (int k = 0; k < 3; ++k)

noise += std::sin(2.0f * M_PI * (modFreqBase*(k+1)) * np[i])

/ (k+1);

noise /= 3.0f;

// Lowはsine支配、Highはnoise支配、Midはブレンド

7.3 EMT 250の知覚最適化

世界初の商用デジタルリバーブ(1976年)。Loop Tankの元祖。

7.4 Bricasti M7のアルゴリズム推測(Waveguide風)

Bricasti M7の内部アルゴリズムは完全非公開だが、音響特性から散乱型Waveguide Networkを強く意識した構造と広く推測されている。

Waveguide風の特徴

FDNとの対比

7.5 現代プラグイン比較

特性

Lexicon 480L

Valhalla VintageVerb

Bricasti M7

3D感/奥行き

魔法的(知覚最適化)

美しい広がり

圧倒的リアリティ

暖かさ/低域

多バンドで豊か

十分暖かい

自然だが肉厚

音楽性

最高(感情を誘う)

高い(Lexicon風)

やや控えめ

金属音

ランダム化で良好

非常に優秀

ほぼゼロ

ミックス適性

前に出て埋もれにくい

前に出る・ポップス向き

自然に溶け込む

キャラクター

ヴィンテージ魔法

現代的Lush

現代的リアル

◆ Lexicon 480Lは「物理的正しさより知覚的正しさ」を体現した存在。DiffFDNやPINNが目指す「perceptual loss最適化」を、1980年代に人間の耳で先取りしていた。

第8章 現代的手法:ニューラル・物理ハイブリッド

8.1 知覚最適化を目的関数にしたDiffFDN

従来のFDN設計は安定性と拡散性を数学的に追求してきたが、「人間がどう聞こえるか」を直接最適化することができる。

目的関数

J(θ) = Σ_t w_t · d(P(y_θ(t)), P(y_target(t)))

mel-spectrogramベースのperceptual loss(実装例)

def perceptual_loss(y, y_target):

Y = loudness(mel(y))

Yt = loudness(mel(y_target))

return torch.mean(torch.abs(Y - Yt))

8.2 ニューラルFDN(制約付き学習)

FDN自体をニューラルネットで学習させる。直交制約はパラメータ化によって保持する。

class FDN(nn.Module):

def __init__(self, N=8):

super().__init__()

self.S = nn.Parameter(torch.randn(N, N))

self.delay = nn.Parameter(torch.rand(N) * 2000)

def orthogonal_matrix(self):

S = self.S - self.S.T # 反対称行列

return torch.matrix_exp(S) # exp(S) は常に直交

反対称行列 S の matrix_exp をとることで、A = exp(S) が常に直交行列となり安定性が保証される。

8.3 総合Loss関数

def total_loss(x, y, y_target):

lp = perceptual_loss(y, y_target)

le = -entropy_loss(y) # エントロピー最大化

lmi = mutual_info_loss(x, y) # 相互情報量最小化

ld = decorrelation_loss(y) # デコリレーション

return lp + 0.1*le + 0.1*lmi + 0.1*ld

8.4 ニューラル+物理ハイブリッドモデル(PINN)

分解

Physics-Informed Neural Networkの応用

波動方程式 ∂²p/∂t² = c² ∇²p を損失関数に組み込む。

Loss = DataLoss + PhysicsLoss

PhysicsLoss = ‖∂²p/∂t² - c² ∇²p‖²

ハイブリッドの利点

8.5 ニューラルIR(動的IR)

従来IR:y(n) = x(n) * h(n)(hが固定)に対し、ニューラルIRは:y(n) = Σ_k x(k) · h(n, k)(hが時間依存)。

8.6 LiquidSonics Seventh HeavenとM7の比較

Seventh HeavenはFusion-IR(複数IRのmodulated capture)という独自技術でM7を再現している。静的IR(Samplicity M7 IR等)とは根本的に異なる。

8.7 固有値分布のリアルタイム制御

固有値を動的に制御するモデル:λ_k(t) = r_k(t) · exp(jθ_k(t))

実装方法

効果と注意点

◆ これは残響を「静的構造から動的場へ」移行させる重要なアイデアである。

第9章 Volterra非線形拡張

9.1 なぜ非線形が必要か

IRはVolterra系列の「1次項だけ」である。現実の音響環境には以下の非線形性が存在する。

これらはすべてVolterraの2次・3次項で表現可能である。単なる後段歪み(waveshaper)は不十分で、畳み込みの中に非線形性を入れる必要がある。

9.2 Volterra系列の定義

線形系:y(t) = ∫ h₁(τ) x(t-τ) dτ

Volterra系列(非線形に拡張):

y(t) = ∫ h₁(τ) x(t-τ) dτ

+ ∬ h₂(τ₁,τ₂) x(t-τ₁) x(t-τ₂) dτ₁dτ₂

+ ...

9.3 FDNへの組み込み(線形+非線形)

非線形FDN(Volterra型)

x_i(n+1) = Σ_j A_ij x_j(n) + Σ_{j,k} B_ijk x_j(n) x_k(n)

実用簡略化(軽量2次近似)

// C++実装例

y[i] += alpha * x[i] * x[i]; // 2次Volterra項

◆ α は 0.001〜0.01 程度の小さな値にする。クリッピング防止(tanh等)が必須。

9.4 PyTorchでの学習可能Volterra

class NonlinearFDN(nn.Module):

def __init__(self, N=8):

super().__init__()

self.S = nn.Parameter(torch.randn(N, N))

self.alpha = nn.Parameter(torch.tensor(0.01))

def forward(self, x):

A = torch.matrix_exp(self.S - self.S.T)

y_lin = x @ A

y_nl = self.alpha * (x ** 2)

return y_lin + y_nl

9.5 動的Volterra(時間変化非線形)

非線形係数 α を固定せず時間・状態依存にする。

α(t)の設計パターン

本質:非線形を「状態依存システム」にすることで、より自然な空間応答を模擬する。

9.6 Neural Volterra(学習型非線形核)

Volterra核 h₂(τ₁,τ₂) の次元爆発問題をNNで近似する。

class NeuralVolterra(nn.Module):

def __init__(self):

super().__init__()

self.net = nn.Sequential(

nn.Linear(128, 64),

nn.ReLU(),

nn.Linear(64, 1)

)

def forward(self, x):

return self.net(x) # xは時系列フレーム

9.7 FDN + Neural Volterra 統合モデル

class HybridReverb(nn.Module):

def __init__(self):

super().__init__()

self.fdn = FDN()

self.nl = NeuralVolterra()

def forward(self, x):

y_lin = self.fdn(x)

y_nl = self.nl(frame_signal(x))

return y_lin + y_nl.squeeze()

9.8 安定性の確保

9.9 推奨実装構成

以下の処理パイプラインが非線形を含む高品質リバーブの推奨構成である。

実装のポイント

第10章 統合理論と展望

10.1 リバーブ設計の階層構造

レベル

観点・手法

レベル1:物理

波動方程式 ∂²p/∂t² = c² ∇²p

レベル2:構造

FDN / Waveguide Network(波動の低次元近似)

レベル3:統計

モード分散・拡散・エネルギー分布

レベル4:知覚

JND・マスキング・ERBフィルタ・perceptual loss

レベル5:学習

Differentiable FDN・PINN・Neural Volterra

レベル6:情報

エントロピー最大化・相互情報量最小化

10.2 商用リバーブの本質を統合理論で再解釈

商用機は次の暗黙の目的関数を人間の耳で最適化した結果である。

J(θ) = d_spec + d_time + d_info + d_mask

各商用機の本質

10.3 「良いリバーブ」の最終定義

各観点から統合すると、良いリバーブとは以下の条件を満たすものである。

一言でまとめると:

「音のエネルギー・情報・知覚が時間とともに制御された拡散をする動的システム」

10.4 今後の研究フロンティア

10.5 主要参考文献

FORTUNE PROVIDES QUESTIONS FOR THE GREAT ANSWERS: #19
A:	To be or not to be.
Q:	What is the square root of 4b^2?

Rule of Open-Source Programming #1:

Don't whine unless you are going to implement it yourself.

    -- Shlomi Fish
    -- "Rules of Open Source Programming"


Powered by UNIX fortune(6)
[ Main Page ]