空音開発Kuon R&D
TECHNICAL ARTICLE

FLAC エンコーダの仕組み

RFC 9639 (IETF 2024) を一次資料にした、Fixed Predictor・Rice 符号化・LPC・MD5 整合性チェックの完全解説。

記事執筆: 朝比奈幸太郎 (Kuon R&D) · 公開日: 2026 年 5 月 6 日 · 一次資料: IETF RFC 9639 (2024)

1. なぜいま FLAC か

FLAC (Free Lossless Audio Codec) は 2001 年に Josh Coalson により設計され、長らく Xiph.Org による事実上の標準として運用されてきました。2024 年、ついに IETF の正式 RFC として標準化されました — RFC 9639。これにより仕様の曖昧性が解消され、それ以前の Xiph ドキュメント (古い記述が混在) ではなく RFC 9639 を一次資料とする実装が「正解」となります。新規実装は必ず RFC 9639 をベースにすべきです。

2. ストリーム構造

FLAC ストリームは「fLaC」マーカ (4 バイト) に続いて連続したメタデータブロック群、その後に複数のオーディオフレームが並びます。最初のメタデータブロックは必ず STREAMINFO で、サンプリング周波数・チャンネル数・ビット深度・最小/最大ブロックサイズ・最小/最大フレームサイズ・総サンプル数・MD5 ハッシュ (16 バイト) を保持します。STREAMINFO に続く任意のメタデータブロックは VORBIS_COMMENT (タグ) / SEEKTABLE / PICTURE (アートワーク) / PADDING / APPLICATION / CUESHEET。

3. フレームヘッダの詳細

フレームヘッダは 14 ビットの同期コード (0x3FFE) で始まり、続いて 1 ビットの reserved・1 ビットの blocking strategy (固定/可変ブロックサイズ)。ブロックサイズコード (4 bit) とサンプリング周波数コード (4 bit) で典型値はテーブル参照、非典型値はヘッダ末尾に追加情報として書かれます。チャンネル割り当て (4 bit) は単純な 1〜8 ch から「左右 + 中央」「左右 + 差分」「中央 + 差分」のジョイントステレオまでを表します。ビット深度 (3 bit + 1 bit reserved)。次にフレーム番号またはサンプル番号が UTF-8 風可変長で書かれます (1〜7 バイト)。最後に CRC-8 (poly 0x07) で全ヘッダの整合性を保護。

4. サブフレームの 4 種

FLAC は 1 チャンネルにつき 1 サブフレームを持ち、4 種から最適なものを選択します。Constant は同一値が続く区間で有効・1 サンプルだけ書く極限圧縮。Verbatim は無圧縮・PCM をそのまま書く。Fixed Predictor は次数 0〜4 の固定多項式で予測 (前サンプル差分・2 階差分など) して残差のみを残す方式で、軽くて高速。LPC (Linear Predictive Coding) は最大次数 32 の自己回帰モデルを各ブロックで学習し、最適な係数で予測 — 最高圧縮率だが最も計算コストが高い。エンコーダは 4 種すべてを試して最小ビット数のものを選ぶブルートフォースが標準。

5. Rice 符号化

Fixed Predictor または LPC の残差は Rice (Golomb-Rice) 符号で圧縮します。各残差を unary 符号 (商) + バイナリ符号 (剰余) で表現する手法です。最適パラメータ K は概ね K ≈ log2(mean(|residual|)) で初期値が決まり、周辺を探索します。実装では「パーティション」と呼ばれるブロック内分割を導入し、それぞれ最適 K を選ぶことで圧縮率が向上します。RFC 9639 ではパーティション順序 0〜15 (1〜32768 個に分割) が定義されています。

6. LPC の数学

LPC は最大 32 次の自己回帰モデル s[n] ≈ a₁·s[n-1] + a₂·s[n-2] + … + aₚ·s[n-p] の係数を学習します。手順は (1) 自己相関 R(k) = Σ s[n]·s[n+k] を計算 (Welch 窓で先に窓掛け推奨)、(2) Levinson-Durbin 再帰でトプリッツ行列 R を効率的に解いて係数を得る、(3) 係数を 4-15 ビット精度に量子化する。係数の精度は重要で、量子化が荒すぎると残差が増えて圧縮率が落ちます。Levinson-Durbin は f64 で計算してから最終係数のみ量子化するのが定石です。途中で f32 にすると数値不安定になります。

7. CRC と MD5 整合性

FLAC は 3 つの整合性レイヤーを持ちます。フレームヘッダ末尾の CRC-8 (生成多項式 0x07) はヘッダのビット化けを検出。各フレーム末尾の CRC-16 (生成多項式 0x8005) はフレーム全体の整合性を保証。最後に STREAMINFO に書き込まれる MD5 ハッシュは、ストリーム全体のデコード後 PCM の MD5 です。デコーダは再生時にこれを検証することで、エンコード→保存→転送→デコードの全工程でビット完全性を担保できます。本物のロスレスかどうかが客観的に検証可能なのは FLAC の決定的な強みです。

8. Rust + WebAssembly の優位性

JavaScript で FLAC エンコーダを書く場合、最も律速になるのはビット操作と整数演算です。FLAC の Rice 符号化・CRC・ビットパッキングは「u32 / u64 ネイティブ整数 + leading_zeros / count_ones / wrapping_add などのビット系イントリンシック」が支配的なワークロードで、JavaScript の Number 型 (常に倍精度浮動小数点) では本来不要な変換コストが発生し続けます。Rust なら C と同じ効率でこれらが書け、WebAssembly にコンパイルしても性能が保たれます。さらに WASM SIMD (V128) で 4-8 サンプル並列処理、Web Worker プールで複数ブロック並列エンコードを実現すると、純 JS 実装比で 30〜100 倍の速度向上が現実的なレンジです。 KUON FLAC ENCODER は現在 JavaScript Verbatim 実装で動作しています。仕様準拠の正確な FLAC を出力するため `flac -t output.flac` (公式デコーダの整合性チェック) は通ります。Rust + WebAssembly 実装に差し替わった暁には、4 分のステレオ 44.1 kHz / 16-bit WAV の変換が数秒で終わり、ハイレゾ 192 kHz / 24-bit でも実用速度に届きます。

まとめ

FLAC は IETF 標準 (RFC 9639) として 23 年の実戦経験を経て成熟したフォーマットです。Verbatim → Fixed Predictor → LPC と圧縮の選択肢が階層的になっており、エンコーダの実装難度に応じて段階的に拡張できます。MD5 整合性検証はロスレスを「主張」ではなく「証明」できる仕組みです。Rust + WebAssembly + SIMD + Web Worker の組み合わせは、ブラウザのなかで実用速度のロスレスエンコードを実現する正解です。KUON FLAC ENCODER はこの正解を音楽家の手元に届けることを目指しています。

参考文献
  • · IETF RFC 9639 — FLAC Format (2024-12)
  • · Coalson, J. — FLAC: Free Lossless Audio Codec (Xiph.Org Foundation, 2001-2024)
  • · Robinson, T. — Compressing Audio (1998) — Levinson-Durbin への入口

いま試す

KUON FLAC ENCODER を開くLP に戻る