これは ADC に関する連載記事の第3回です。前回までの記事はこちらとこちらです。
最初の2本では、主に ADC を取り巻く主張を見てきました。マーケティング文句、曖昧なバズワード、MDCT をなぜか倒すべき敵のように扱う妙な語り口、そして技術っぽく聞こえるのに実際にはそうでもない言い回しの数々です。
今回は、ようやく最初からやるべきだったことをやります。つまり、コーデックそのものを見るということです。
この記事では、公開されている ADC エンコーダ/デコーダの2つのバージョンについて、私が確認したことと観察結果をまとめます。
v0.82v0.84 rev.0この2つは関係していますが、同一ではありません。0.84 rev.0 は全面書き直しというより、同じ基本コーデックを、ストリーミングとランダムアクセスを意識したフレーム形式に包み直そうとしたものに見えます。
では、順番に見ていきましょう。
「audio DNA」だの、MDCT への謎の敵意だのを剥がしてしまうと、ADC は音声符号化の歴史上いまだかつて誰も見たことのない革命的な新技術、というわけではありません。
一言で言えば、サブバンド予測型コーデックです。つまり、やっていることはこうです。
以上です。かなり昔ながらの発想に、追加でマーケティング文が盛られているだけです。
v0.82 と v0.84 rev.0 は、どちらも同じような中核構造を共有しているように見えます。
MxB によって駆動される適応量子化2つのバージョンの最大の違いは、コンテナ、フレーミング、そして状態の扱い方です。
まずは v0.82 から始めましょう。私が最初にこのコーデックを見かけたときに公開されていたのがこの版ですし、対外的な言い方がいちばん強気だったのもこの版です。2026年1月3日のウェブサイトのスナップショットは、その当時 v0.82 がどう位置づけられていたのかをかなりよく示しています。
ここが重要です。なぜなら、そうした主張を実際のビットストリームやバイナリの動作と比べると、その落差はまったく微妙ではないからです。
さらに面白いのが、少し前のリリースノートです。v0.80 の時点ですでに 8 サブバンドの話は出ていました。そのあと v0.81 では 4 バンドに戻り、8 サブバンドの開発版は不安定で、数 dB レベルの可聴ノイズを生む可能性があるとはっきり書かれていました。ところが v0.82 でまた 8 サブバンドに戻り、それを品質と効率の大きな飛躍として再登場させています。
つまり解析に入る前から、すでにひとつのパターンは見えていました。不安定さを認め、しばらくしてから、ほぼ同じ大枠の発想を新しい自信とより大きな主張付きで再発売する、という流れです。
v0.82 の仕様が示しているのは、かなり単純なコンテナです。
この時点で、もうひとつ赤旗です。ビットストリーム内にフレームごとのヘッダも、同期語も、シークテーブルも、ブロックマーカーすらありません。ここまでないと、これをコンテナと呼ぶのもだいぶ苦しい。符号化状態が、ファイルの先頭から末尾までひたすら転がり続けるだけです。
これが重要なのは、それだけで ADC が繰り返し主張していた点のひとつ、つまりランダムアクセスが即座に崩れるからです。算術符号器の状態も予測器の状態もファイル全体で連続しているなら、はい、インスタントシークなんてありません。それにもかかわらず、開発側はこれを MDCT ベースのコーデック最大の問題であるかのように語っています。現実には、MDCT ベースのコーデックにとってそんなものはそもそも問題ではありません。(ええ、HE-AAC にはビットリザーバ由来のプリロールが必要なことは知っています。でもそれは AAC の事情であって、MDCT の事情ではありません。)
大まかに言うと、v0.82 は次のように動いているようです。
こういう説明こそ、最初からサイトに書いておくべきでした。「音声圧縮の DNA を再定義する」みたいな文より、よほど明快です。もちろん、そんな書き方はされていませんでした。なぜなら、はっきり書いてしまうと類縁関係が一気に見えてしまうからです。ADC は従来の音声符号化の世界から脱出しているわけではありません。むしろその中にどっぷりいます。位置としては、かなり昔ながらのサブバンドコーダ群の近所で、フロントエンドの雰囲気は、想像上のポスト MDCT な未来よりも MP2 や SBC あたりの系譜に近いです。
flowchart TD
PCM["PCM 入力<br>16/24-bit、モノラルまたはステレオ"] --> JS["任意の mid/side 変換"]
JS --> QMF["8 バンド QMF 解析"]
QMF --> PRED["帯域ごとの 4 タップ予測器"]
PRED --> QUANT["適応量子化<br>+ MxB 下限"]
QUANT --> RANGE["コンテキストベースの二値算術符号器"]
RANGE --> BITSTREAM["ADC ビットストリーム"]v0.82 は、16 タップの Johnston プロトタイプを使った、木構造の 8 バンド QMF バンクを使っているように見えます。平たく言えば、信号を再帰的に分割していきます。
その結果として、最終的な 8 サブバンドが得られます。
もし ADC のマーケティングが正直なら、「時間領域に純粋なまま留まる」などとは言わないはずです。やっているのは、MDCT の代わりにサブバンド表現を使うことにすぎません。
ただ、より深刻なのは別の点です。v0.82 の実装は、かなり基本的なところで QMF の構造を取り違えているように見えます。必要なポリフェーズ遅延を片側の枝に入れず、偶数/奇数の単純な和差分割をそのままやっているようなのです。これは重要です。QMF バンクは、エイリアシングをきちんと打ち消すために、位相関係が正確であることを前提にしています。そこを壊すと、近似的な完全再構成系として振る舞わなくなり、信号に色付けを始めます。
しかも、それは実際の挙動と嫌なくらい一致します。
ちなみに、この 13.8 kHz という数字は適当ではありません。44.1 kHz を 8 個の等幅帯域に分けると、帯域境界のひとつがちょうどそのあたりに来ます。つまりスペクトルに空いたあの妙な穴は、壊れたクロスオーバーが顔を出す場所として、まさに期待通りの位置にあるわけです。
各サブバンドサンプルが得られると、v0.82 はそれを小さな適応予測器に通します。
中身はだいたいこんな感じです。
予測器は、直近の再構成サンプルから次の値を見積もり、その推定値と実際のサブバンドサンプルとの差分を量子化します。繰り返しになりますが、これは「なぜ誰も今まで思いつかなかったんだ!」という類の革命的な発想ではありません。サブバンド分割の後ろにぶら下がった、小さな予測コーダです。
ここで支配的なのが MxB という変数で、これは有効ステップサイズがどこまで小さくなれるかの下限として機能しているように見えます。MxB が大きいほど量子化は粗くなり、必要ビット数は減ります。MxB が小さいほど量子化は細かくなり、必要ビット数は増えます。
つまり、あの有名な MxB という名前も、響きほどわくわくするものではありません。謎の新しい符号化原理などではなく、要するに量子化の荒さを決めるノブです。おそらく、コーデックはこれでビットレートを制御しているのでしょう。
2026年1月3日のサイトのスナップショットでも、VBR はかなり強く押し出されていて、ADC にとって自然で最適なスイートスポットであるかのように語られていました。なので、実際にはどう振る舞うのかを確かめてみました。
ジャン=ミッシェル・ジャールの "The Opening (movement 8)" を使い、開発者がやたら使いたがるあの曲ですね、要求ビットレート 64 kbps で少しずつ長い区間を順に符号化し、ADC と Opus を比較しました。結果をいちばん簡単に読むと、こうです。
WAV は当然ながら、およそ 1411 kbps で一定Opus は普通の制約付き VBR エンコーダらしく、だいたい目標近辺で、少し上に振れたり下に振れたりするADC は冒頭で大きくオーバーシュートし、その後は要求値へ向けて平均をじわじわ引き戻していく最初の数点だけでも、かなりよく物語っています。
| Length | Opus average | ADC average | Opus added bitrate | ADC added bitrate |
|---|---|---|---|---|
| 10s | 65 kbps | 94 kbps | 65 kbps | 94 kbps |
| 20s | 67 kbps | 79 kbps | 68 kbps | 64 kbps |
| 30s | 65 kbps | 74 kbps | 62 kbps | 62 kbps |
| 60s | 66 kbps | 69 kbps | 70 kbps | 66 kbps |
| 120s | 66 kbps | 67 kbps | 62 kbps | 60 kbps |
| 256s | 65 kbps | 65 kbps | 61 kbps | 69 kbps |
つまり、ADC は「64 kbps をください」と言われても、64 から始まりません。だいたい 94 から始まります。そして、最初に使いすぎたことに途中で気づいたのか、あとから平均を下げて帳尻を合わせていくように見えます。
もちろん、これだけで「曲が進むほどコーデックが悪くなる理由はすべてビットレート制御である」と証明できるわけではありません。ですが、聴感上の印象とは驚くほどよく噛み合っています。
要するに、「VBR の本来のスイートスポット」という話は、賢い知覚的ビット配分というより、最初にパニックになって使いすぎ、その後ずっと請求書を払い続けているコーデックに見えてきます。
xychart-beta
title "要求 64 kbps: ファイル長を伸ばしたときの平均ビットレート"
x-axis ["10s", "20s", "30s", "60s", "120s", "256s"]
y-axis "kbps" 0 --> 100
line "Opus" [65, 67, 65, 66, 66, 65]
line "ADC" [94, 79, 74, 69, 67, 65]量子化のあと、v0.82 は記号列をコンテキストベースの二値算術符号器に通します。
これは ADC 自身の説明が、いちばんまだ嘘っぽくない部分かもしれません。まあ、たしかに算術符号化ではありますし、たしかに一応コンテキスト適応っぽいものもあります。でも、正直に言えば、それでコーデックが特別になるわけではありません。本当に重要なのは、前段が「圧縮する価値のあるもの」を供給できているかどうかです。予測が雑で、量子化が荒くて、フィルタバンクの時点ですでに信号を傷つけているなら、最後にきれいなエントロピー符号器を付けても、失敗しているシステムを少しだけ効率よく失敗させるだけです。
v0.82 には、大きく3つの構造的問題があります。
フィルタバンクは、位相整合が最も重要な箇所で、数学的に間違っているように見えます。その結果として、打ち消されないエイリアシングと、クロスオーバー点での破壊的干渉が起きています。
つまり、「完全再構成より品質」という文句は、大胆な設計思想というより、「再構成の数式が壊れている」の婉曲表現に見えてきます。
予測器の状態も算術符号器の状態も、ファイル全体を通してリセットなしに持ち越されているようです。つまりこのコーデックは、音声を圧縮しているだけではなく、自分の過去も丸ごと引きずって進んでいます。しかも旅行カバンみたいに。
予測器が悪い状態に滑り込むと、その悪い状態が次に来る部分まで汚染します。そして実に都合のいいことに、これは私が先に観測した「時間が経つほど音が悪くなる」という挙動とぴったり一致します。
ビットストリームにまともなフレーム境界や状態チェックポイントが存在しないので、デコーダは途中から綺麗に飛び込めません。ファイルの後半をデコードしたければ、その時点以前のすべてを通ってはじめて意味を持つ予測器状態と符号器状態が必要になります。
なので、「0 ms シーキング」という主張は、単に楽観的だったのではありません。技術的に上下逆でした。
ここからが少し面白いところです。v0.84 rev.0 まで来ると、ADC はかなり本気でストリーミングコーデックになりたがっているように見えます。バイナリには文字どおり Streaming & Random Access Mode Enabled. と出ます。勢いはあります。ただし、実態としてはせいぜい半分本当、下手をするとそれ以下です。音質面で劣っているのはもう立証されてしまったので、MDCT 系コーデックにぶつける別のカードとして「AAC と MP3 はストリーミングできない!」路線に切り替えたのかもしれません。(Opus が最初からストリーミング最適化を前提に作られていることはいったん見なかったことにしましょう。)
この時期の公開ノートでも、「独立した 1 秒ブロック」「完全なコンテキストリセット」「ゼロレイテンシのユーザー体験」「瞬時に安定するシークポイント」などが並んでいました。つまり、ハードルを上げたのは私ではありません。ADC 自身のリリースノートです。
v0.82 と違って、v0.84 rev.0 はもはや終わりのない 1 本の塊には見えません。
形式としては、どうやら次のようになっています。
0x54 バイトのグローバルヘッダADCS各フレームには、次のものが入っているようです。
つまり、実際の圧縮ペイロードが始まる前に、固定オーバーヘッドとして 0x12a バイトが毎回かかっています。
なので、たしかに v0.84 rev.0 は v0.82 よりはかなりパケット化されています。
ただし、その代償を見てください。副情報を最小限に抑えたコンパクトなフレーム形式を設計する代わりに、ADC は巨大なデコーダ状態の塊を各フレームに丸ごと吐き出しているように見えます。これは、洗練された現代的ストリーミングコーデックの姿ではありません。
flowchart TB
subgraph V082["v0.82"]
direction TB
H82["32 バイトのヘッダ"]
P82["1 本だけ続く連続ペイロード"]
S82["予測器と符号器の状態がずっと前進し続ける"]
H82 --> P82 --> S82
end
subgraph V084["v0.84 rev.0"]
direction TB
H84["0x54 バイトのグローバルヘッダ"]
R1["フレーム 1 レコード"]
C1["payload size -> 状態スナップショット群 -> count/MxB/checksum -> payload"]
R2["フレーム 2 レコード"]
C2["payload size -> 状態スナップショット群 -> count/MxB/checksum -> payload"]
R3["フレーム 3 レコード"]
C3["payload size -> 状態スナップショット群 -> count/MxB/checksum -> payload"]
H84 --> R1 --> C1 --> R2 --> C2 --> R3 --> C3
end
S82 -. コンテナ再設計 .-> H84ファイル形式はかなり変わったものの、符号化コア自体は基本的に見覚えのあるままです。
MxB 下限なので v0.84 rev.0 は、v0.82 からの根本的なアーキテクチャ変更ではありません。同じ基本アイデアをフレームレコードに包み直しただけです。
この意味で、私は v0.84 rev.0 を「ADC だけど修正済み」とは呼びません。むしろ「古いコンテナでは自分たちのマーケティング上の主張を支えられないと気づいて、同じコーデックをもっと重い輸送用の殻で包んだ ADC」と呼ぶほうが近いです。
公平のために言っておくと、v0.84 rev.0 は v0.82 に比べて、ひとつだけ確実に改善した点があります。再開可能性です。各フレームに大きな適応状態のスナップショットが含まれているので、理屈の上ではデコーダはファイル先頭から全再生しなくても、フレーム境界から開始できます。これは実際に変化しています。
ただし、それは「きれいで、正確で、頑丈なランダムアクセス」と同じ意味ではありません。
しかもこれは、素直な意味での「完全なコンテキストリセット」とも読みづらいです。どちらかというと、「デコーダはまだ大量のコンテキストを必要とするので、毎フレームごとにチェックポイントを同梱する」に見えます。
シーク処理は、おそらく次のような流れです。
0x120 バイトを飛ばすcount << 3 を積算する……あまりエレガントではありません。
サンプル単位の正確さはありません。しかも内部整合性すら怪しい。スキャナは 0x120 バイト飛ばしているのに、固定フレームオーバーヘッドは 0x12a バイトあるように見えるからです。
なので、v0.84 rev.0 にランダムアクセス的なモードがあるのは確かです。だいたいそのへん、くらいには飛べます。まあ。たぶん。
-h フラグは何もしていないように見えるv0.84 rev.0 の中で私がわりと気に入っている小ネタのひとつが、この -h オプションです。
バイナリ上では「高品質」モードとして公開されています。すごい。高品質。Wow。
でも、この版では本当に何もしていないように見えます。パーサはグローバルフラグを立てていますが、その後エンコーダがそのフラグを参照している意味のある痕跡が見当たりません。挙動テストでも、その結論と一致しました。
なので、もし「このモードを入れると急にちゃんとしたコーデックになる」みたいな隠しプレミアム機能を期待していたなら、まあ……
v0.84 rev.0 ではフレームごとの整合性チェックも追加されています。ただし、ここでも実装は、発想ほど立派ではありません。
復元できたチェックサムは、小さな 16-bit のローリング更新にすぎず、現代的な整合性機構として真面目に使うにはかなり弱いです。なので、ここでもまた同じパターンが出ます。
もうこれだけ書いて連載を終えてもよかったかもしれません。
この記事は両方のバージョンを扱っているので、比較をはっきり書いておきます。
| 項目 | v0.82 | v0.84 rev.0 | 実際の意味 |
|---|---|---|---|
| コンテナ | 32-byte ヘッダ + 1 本の連続ペイロード | 0x54-byte ヘッダ + 明示的なフレーム列 | 0.84 はストリーミング対応を目指している |
| マジック | ADC\0 | ADCS | 新しいコンテナ識別子 |
| 再開性 | 実質なし | フレーム境界で可能 | 0.82 よりはマシだが粗い |
| シーク | 先頭から再生しない限り事実上不可能 | おおざっぱなフレーム単位シーク | 改善ではあるが、「0 ms」の魔法にはほど遠い |
| 副情報 | 先頭の最小限ヘッダ | 毎フレーム巨大な状態スナップショット | 再開性は上がるがオーバーヘッドも増える |
| コア前段 | 8-band QMF | やはり 8-band QMF | 同じ系統、同じ限界 |
| 予測 | 小さな適応帯域予測器 | 基本思想は同じ | 再発明ではない |
| 量子化制御 | MxB 主導の適応ステップ制御 | 同じ MxB ロジックが残る | 同じノブを別包装にしただけ |
| エントロピー符号器 | コンテキストベースの二値算術符号器 | 同じく自家製っぽい符号器 | 発想は同じ、やはり素朴 |
| 整合性チェック | 実質的な枠組みなし | フレームごとの弱い 16-bit チェックサム | 新機能だが出来は弱い |
| ストリーミング主張 | マーケティング上の幻想 | 部分的には実装された | 現実には少し近づいたが、半分止まり |
ADC を最初から怪しく見せていた要素は、根本的にもっと良いものへ置き換えられたようには見えません。
それを「QMF」と呼ぼうが、「時間領域」と呼ぼうが、「生波形ネイティブ圧縮」と呼ぼうが、現実は同じです。このコーデックは今でも、信号を少数の広いサブバンドに分け、それを予測的な道具で符号化しています。これで現代的な変換コーデックと同列になるわけではありません。ただ、設計空間の別の場所を選んだだけです。しかも周波数分解能がずっと粗い側を。
どちらのバージョンにも、成熟した心理音響モデルを示すものは見当たりません。重み付けや制御ヒューリスティクスのようなものはありますが、現代の非可逆コーデックを本当に効率的にしている、細粒度でマスキングを意識した仕組みとはほど遠いです。
だから根本的な制約は残ったままです。ADC は、AAC や Opus や xHE-AAC が扱っている表現よりも、知覚的にずっと粗い表現を圧縮することに労力を使っています。
小さな帯域テーブル、小さな整数予測器、自家製符号器、弱いチェックサム、変な命名。おっと失礼。コーデックの名前みたいな非技術的な話で判断してはいけませんね。
ただまあ、これのどこを見ても「最先端エンジニアリング」という感じはしません。どちらかというと実験です。しかも、自信だけは妙に大きい人の。
とはいえ、もしこれが「実験です」として提示されていたなら、それでまったく問題はありませんでした。問題なのは、このコーデックが風変わりとか、荒削りとか、そういうことではありません。問題なのは、他のコーデックがすでに解決している問題を自分たちが解決したかのように売り込み続けているのに、その内部を見れば、まだそこでもたついているのがはっきりわかることです。
ここまで見たうえで、私がいちばん正直だと思う説明はこれです。
ADC は、野心は大きく、状態量も多く、でも設計の節度が足りていない、実験的なサブバンド予測コーデックです。
v0.82 は、壊れたフィルタバンク前段と、本当のランダムアクセスを持たない、巨大な単一予測ストリームに見えました。v0.84 rev.0 は、その実用面の問題を埋め合わせるために、ストリームをフレーム化し、各フレームにデコーダ状態を直列化して押し込んだように見えます。これは確かに実際の変更です。でも、それは音声符号化の革命とは同義ではありません。むしろ、他のコーデックなら MDCT で普通に解決していることに対して、開発者が自分で余計な制約を課した結果、その後始末をしているようにすら見えます。
しかも、基盤となる符号化コアは同じ 8 バンド予測器という基本発想のままに見えるので、このコーデックは結局、同じ大枠の弱点をそのまま引き継いでいます。
この記事は、ADC とその主張を検証していく連載の第3回です。
以下が記事一覧です。
<- 現在地マーケティングのたわごとを2本続けて見たあとだと、技術面に入るのはむしろ清々しいです。ADC の中身を見ても、「native sound」も「audio DNA」も出てきません。あるのは、理解可能で、大枠ではかなり普通で、そして自分のサイトが言いたがるほどには全然すごくないコーデックだけです。
私は、ADC の内部を見ることの本当の教訓はそこにあると思っています。
処理系を実際にたどってみると、全体の話は一気に大げさでなくなります。v0.82 は、深刻な構造問題を抱えた単一の 8 バンド予測コーダです。v0.84 rev.0 はフレームと状態スナップショットと雑なシーク機構を追加していますが、根本設計の限界や問題から逃げられてはいません。
この記事まで来ると、ADC が実際には何なのかを、平たく説明できます。そして、平たい説明というのは、だいたい大げさな hype を台無しにするものです。