mcelp 1.0.1

Mitsubishi CELP speech codec: a 3.6 kbit/s speech encoder and decoder
Documentation
# 聴覚重み付け

エンコーダのすべての探索——ピッチ、固定コードブック、利得——は同じ問いを立て
ます。どの候補が入力に最も近く聴こえるか。重み付けフィルタは「近く聴こえる」を
数値に変える装置であり、3.6 kbit/s の CELP コーダが聴けるものになる最大の理由
です。

## そもそもなぜ重みを掛けるのか

素の二乗誤差を最小化するコーダは、量子化雑音をスペクトル全体に均等にばら撒き
ます。それは誤った振る舞いです。耳は雑音を均等には聴かないからです。フォルマント
の下にある雑音はフォルマントにマスクされますが、同じ量の雑音がスペクトルの谷に
あれば明確に聴こえます。

そこで誤差は、フォルマント領域を*強調しなくする*フィルタを通してから測ります。
するとコーダは、信号が大きい場所——まさに聴こえない場所——に誤差を多く残す自由を
得ます。

## フィルタ

```
        A(z/γ₁)
W(z) = ---------           γ₁ > γ₂
        A(z/γ₂)
```

分子・分母とも同じ予測器 `A(z)` から**帯域拡張**で作ります。係数 `aₖ` に `γᵏ` を
掛ける操作です。

```rust
out[i] = a[i] · γⁱ            // i = 1 … 10
```

1未満の係数を掛けるとフィルタの極が原点方向へ引き寄せられ、共振の位置を動かさず
に幅を広げます。分子は γ₁ が1に近いのでフォルマント構造をほぼそのまま保ち、
分母は γ₂ がずっと小さいので同じ包絡をぼかしたものになります。両者の比は、
フォルマントに追従しつつ峰を平らにしたフィルタ——マスキングの議論が要求する形
そのもの——になります。

## 2つの係数の選択

係数は定数ではありません。**半フレームに1回**選ばれ、その2つのサブフレームに
それぞれ1組ずつ与えられます。

| 状態 | γ₁(分子) | γ₂(分母) |
|---|---|---|
| 鋭い | 32113 ≈ 0.980 | 線スペクトルから決定、0.400 … 0.700 |
| 平坦 | 30802 ≈ 0.940 | 19661 = 0.600 固定 |

**鋭い**状態では、分母は線スペクトルがどれだけ密集しているかから決まります。
隣接 LSF 間の最小間隔を取り、直線に通し、上記の範囲にクランプします。2本の線が
近いことは鋭い共振を意味し、鋭い共振は重み付けフィルタがより密に追従すべき対象
です——したがって間隔が小さいほど γ₂ は大きくなり、重み付けは狭くなります。

**平坦**状態では両係数とも固定です。強い共振のないスペクトルには追従すべきものが
なく、雑音に適応させてもサブフレーム間でフィルタが揺れるだけです。

## 鋭い/平坦の判定

状態は、その半フレームの予測器の**最初の2つの反射係数**から決めます。この2数は
スペクトルの大まかな傾きを要約しています。1つめは本質的に正規化された1標本
自己相関、2つめは2標本のそれです。

比較は直接ではなく**対数面積比**として行います。係数が1に近づいても比較が意味を
保つようにする、おおよそ対数の変換です。実装では膝点より上を3本の直線で近似して
おり、膝点より下では係数自体が既に自身の対数に十分近いのでそのまま使います。

判定には**ヒステリシス**があります。平坦状態に入るための閾値と、出るための閾値が
別々です。

```
平坦へ入る:  area₀ ≤ −3113  かつ  area₁ ≥  881
平坦から出る:area₀ <  −3564  かつ  area₁ >  1331
```

ここでヒステリシスが効く理由は音声区間検出と同じです。単一の閾値の真上に居座る
スペクトルは半フレームごとに重み付けフィルタの形を反転させてしまい、信号より
速く形を変えるフィルタはそれ自体が変調を生みます。

もう1つの工夫があります。半フレームの2つのサブフレームは、わずかに異なる判断を
受けます。第1サブフレームは前半フレームの対数面積と**平滑化**した値で、第2
サブフレームは今回の半フレームの値だけで判断されます。したがってフィルタは
半フレームの先頭では変化するスペクトルにやや遅れ、末尾で追いつく——段差ではなく
——形になります。

## どこで使われるか

重み付けフィルタは3か所に現れ、それらは一致していなければなりません。

1. **目標信号。** 探索が合わせにいく信号は、これから符号化すべき残りの重み付け
   版です——[encoder-loop.md]encoder-loop.md を参照。
2. **インパルス応答。** 候補はすべて重み付き合成フィルタを通してから比較されるので、
   探索はそのフィルタのインパルス応答をサブフレームごとに1回だけ事前計算します。
3. **量子化器の重み。** 線スペクトル量子化器は、同じフィルタから導いた重みで自身の
   歪みを測ります。

デコーダはこれらを一切見ません。重み付けは完全にエンコーダ側の測定装置であり、
*どの*パラメータが送られるかを形作るだけで、デコーダがそれをどう扱うかには
関与しません。