mcelp 1.0.1

Mitsubishi CELP speech codec: a 3.6 kbit/s speech encoder and decoder
Documentation
# ビットストリーム

1フレームは18バイト——144ビット——で、うち139ビットがペイロード、残る5ビットが
フレーミングです。ペイロードは合計138ビットの14フィールドと、その後ろの抑圧
フラグ1ビットからなります。

## フィールド構成

フィールドは MSB 先頭で、次の幅で並びます。

```
[8, 12, 8, 16, 7, 5, 16, 7, 8, 16, 7, 5, 16, 7]
```

| フィールド | ビット | 意味 |
|---|---|---|
| 0 | 8 | 線スペクトル:bit 7 が予測器モード、bit 6–0 が第1段索引 |
| 1 | 12 | 線スペクトル:第2段、6ビットずつの2つの半分 |
| 2 | 8 | サブフレーム0 — ピッチラグ(絶対) |
| 3 | 16 | サブフレーム0 — 固定コードブック索引 |
| 4 | 7 | サブフレーム0 — 利得索引 |
| 5 | 5 | サブフレーム1 — サブフレーム0 に対する相対ラグ |
| 6, 7 | 16, 7 | サブフレーム1 — 符号と利得 |
| 8–10 | 8, 16, 7 | サブフレーム2 — 2つめの絶対ラグ、符号、利得 |
| 11–13 | 5, 16, 7 | サブフレーム3 — 相対ラグ、符号、利得 |

フレームの前半と後半は対称です。それぞれ絶対ピッチラグで始まり、差分が続きます。
`Params::subframe(half, sub)` が1サブフレーム分の3フィールドを名前付きで返す
ので、`bitstream` の外側がこの並び順を知る必要はありません。

フレームごとに1回送られるのは線スペクトルだけです。他はすべてサブフレーム
単位で、固定コードブック索引だけでパラメータ138ビット中64ビットを占めます。

## 抑圧とリセット

bit 138 がフレーム抑圧フラグで、復号せず補償すべきフレームを示します。
bit 143——最終バイトの最下位ビット——には同じフラグの伝送用の写しが乗っており、
正規化の際に bit 138 へ畳み込まれてから、他のどの処理よりも先に参照されます。

最終バイトの上位ニブルは帯域内リセット標識も兼ねます。ただし判定は**正規化後**の
ペイロードに対して行われ、その時点で当該ビットは既にクリアされているため、この
伝送路ではリセットが発火することはありません。それでも判定を残しているのは、
2つのデコーダがビット単位で一致する必要があり、一度も通らない経路も含めて一致
させるためです。

## コンテナ形式

同梱のサンプルは単純なテキスト形式を使います。1行1フレーム、各行は18バイトを
表す36文字の16進文字列です。

```
27ef9c1000701f00070182000e03e000e000
...
```

`bitstream::parse_hex_line` が1行を読み、`to_hex_line` が1行を書きます。
どちらもコーデック本体ではありません。ビットストリームをテキストファイルに
保存し、差分を取れるようにするための形式です。

## フレームより下の層を扱う

ライブラリはバイト層に加えてパラメータ層も公開しています。

```rust
use mcelp::bitstream;

let words = bitstream::canonicalize(&frame);   // 18バイト → 9ワード
let params = bitstream::unpack(&words);        // → 14フィールド + 抑圧フラグ
let again = bitstream::to_bytes(&bitstream::pack(&params));
assert_eq!(again, frame);
```

`Encoder::frame` がバイト列ではなく `Params` を返すのも同じ理由です。コーダを
調べる用途ではフィールドそのものが欲しいことが多く、詰め込みは別の関心事です。