
2026/11/05 21:51
マニアックなオーディオコーデックがN64にぴったりです
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
11 月 3 日(2026 年)に、研究チームは Nintendo 64 に対して高忠実度かつ圧縮されていない 44100Hz ステレオオーディオの成功実装により、レトロゲーミングにおいて大きな決定的な飛躍を成し遂げた。歴史的に、このコンソールは厳格なプロセッサ速度(93MHz)および制限されたカートリッジ容量(最大 64MB)によって制約されており、高ビットレートオーディオの実用性は低かった;以前の試みである『Xibalba 64』では、サウンド alone にほぼ半分のカートリッジ容量を浪費していた。研究チームは、GBA に基づくフルバンド変換符号化器である Ultra Low Complexity Codec(ULC)—これは低電力環境用に設計されたもの—を発見することでこれらの課題を克服した。リアルタイム Opus(遅すぎる)、MP3(限界の利点のみ)などの代替案を却下した後、デコーダーを N64 の RSP コプロセッサ上で完全に動作するように再実装し、検証済みのアセンブリコード約 1400 行を利用した。この最適化により、オーディオ処理負荷は総 CPU 時間の約 4%、RSP 時間の約 5% に削減された。このソリューションは Libdragon オープンソースフレームワークにマージされ、現代タイトルの現実的な移植を可能にし、『Half-Life』のように数千のサウンドエフェクトとフル音楽トラックを標準メモリライト内にはめ込みながらゲームプレイパフォーマンスを損なわずに機能するようになった。
本文
N64 上で動作する Opus レベルの音声再生を可能にした超低複雑性コーデック(ULC)
📅 記事の概要
- 公開日: 2026 年 11 月 3 日(火)
- 主要成果: N64 の CPU 使用量の約 4%のみで動作し、ほぼ Opus レベルのビットレートを必要とする44,100 Hz ステレオオーディオを実現。
- 結論: 既存の ADPCM や MP3 では不可能だった高音質・低容量な音声データを N64 カートリッジに実装することに成功しました。
📜 N64 の音声技術における歴史的背景
N64 で音データを扱うことには、以下の厳しい制約がありました。
- メディア容量の限界
- プレイステーションとは異なり、CD から未圧縮音を流すことができない。
- カートリッジ容量が極めて貴重であり、大容量データは搭載できなかった。
- CPU 処理時間の制約
- メイン CPU は93 MHzと性能が制限されていた。
- RSP へのアクセス制限(重要)
- ベクトル演算プロセッサであるRSPへの直接アクセス権限は、長らく任天堂公式ライブラリ「Libultra」に独占されていた。
- サードパーティの開発者に対しては、RSP を直接用いてコードを書くことを認めない方針だった。
既存の技術的な課題
Libultra が提供した ADPCM 復号化機能には以下の問題がありました。
- データサイズの膨張
- RSP を利用してオンザフライで復号化しても、5 分間のステレオ音源(44,100 Hz)を再生するには約12 MBの容量が必要になる。
- カートリッジ収容不可能
- 『マリオ 64』全体 ROM サイズが 8 MB、『大乱闘スマッシュブラザーズ DX』でも 64 MB と、ADPCM のデータ量には全く追いつかない。
これまでの代替手法とその限界
- トラッカー方式の採用
- カートリッジ容量不足のため、「録音された」完全な音源ではなく、短く区切られたサンプルをスケジュールして再生する手法(トラッキング)が主流になった。
- RSP 解放後の試み
- 『コンカーズ バッド・ファー・デイ』などで RSP への直接アクセスが許可され、MP3 復号化に成功した。
- 課題: MP3 復号化は計算コストが高く、プレイ中の背景音楽など連続再生には重すぎる。エンディングなどのカットシーン用ではのみ対応可能だった。
🚀 オープンソースライブラリ「Libdragon」における音声処理の進化
任天堂公式ライブラリの代替案であるオープンソースライブラリ**『Libdragon』**では、以下のようなアプローチが試みられました。
1. ROM スペース優先のアプローチ
- 全音楽データ ADPCM 圧縮: Xibalba 64 プロジェクトにおいて、ROM スペースの安価化に伴い、全音楽データを ADPCM で圧縮して ROM に格納する手法を採用。
- 成果: 32 MB の ROM のうち約31 MBを音源に使用した。
- 比較: 『マリオ 64』 (8 MB) より単純な構成ながら音楽のみで 15 分再生可能だが、スペースの浪費となる。
2. Opus 復号化の試行錯誤
- RSP による Opus 復号化の実現
- Giovanni Bajo 氏が、N64 という「廃棄物」とも呼ばれるハードウェア上で、16 年後に公開された Opus フォーマットを動作させることに成功。
- 限界: 圧縮率と音質は優秀だが、計算負荷が高くプレイ中の使用には遅すぎる(MP3 より僅かに高速)。
- その他のコーデックの問題
- QOA: ADPCM より良いが、ベクトルプロセッサとの親和性が低く、並列化が困難。
結論:変換型コーデックへの回帰
- 既存の変換型コーデック(MP3, Opus)は N64 では「高品質だが重すぎる」。
- この矛盾を解消すべく、制約に縛られないシンプルな変換型コーデックの開発が必要とされました。
🔬 超低複雑性コーデック(ULC)の概要
深夜の研究で発見された Game Boy Advance (GBA) の古いデモが、N64 開発の突破口となりました。
GBA デモの驚異的な性能
- 仕様: GBA で録音、16 MHz ARM CPU、ベクトル命令なし。
- 実績: 70 kbpsという低ビットレートで、一般的な MP3 と同等の品質を実現。
- ※ ulcplayer-gba by Aikku93(GBA エミュレーター上で録画)
既存コーデックとの比較
| コーデックタイプ | 代表例 | N64/GBA 環境での課題 |
|---|---|---|
| 時間領域型 | ADPCM | この品質を得るにはビットレートが遠回り。 |
| サブバンド型 | MP2 | 低ビットレートでは質が著しく低下。 |
| 変換型 (古典) | MP3 | 通常80–100 MHzの CPU が必須(N64 は不足)。 |
ULC の特徴と仕組み
Aikku93 氏が開発した「Ultra Low Complexity Codec (ULC)」は、MP3 と似た変換型コーデックですが、冗長な要素を排除した「MP3 が本来持つべき姿」です。
- MDCT(改良離散コサイン変換)の使用:
- MP3 のようにバンド分割せず、「フルバンド」として全帯域を処理。
- エントロピー符号化の排除:
- MP3 が Huffman 符号化を使用するのに対し、ULC は使用しません。
- ニブル(4 ビット)ベースの文法:
- 変換係数を非常にシンプルな 4 ビット単位で格納。
- 任意のビット読み出しや複雑なエントロピー復号化不要。
- C コードでの実装: ブロック分の係数を読み出して展開するだけで約150 行。
ニブルベースデータ構造の意味
各係数は 4 ビットで符号付き整数として解釈されます。特殊な値の定義:
- -7 … -2, 2 … 7: 実際の係数値
- 0: ゼロラン(ゼロ連続区間)開始 → 次のニブルにラン長 (1…16)
- 1: 長いゼロランを示す → 次の 2 ニブルでラン長 (17…288)
- -1: 量子化器変更 → 次のニブルに新しい値
- -8: ノイズ埋め込み開始 → 次の 3 ニブルで長さおよび振幅
ノイズ埋め込み機能の恩恵:
- シンバル、ハイハット、スネアドラムなどが特に効果大。
- MP3 は準無作為な係数をそのまま符号化する必要があるが、ULC では効率的に処理可能。
- 性能: 16 kbps でも利用可能な音質が得られる。
🎮 N64 上での ULC 実装プロセス
LLM(大規模言語モデル)登場前の時代、数晩かけて N64 向けリファレンスデコーダを作成し成功しましたが、CPU が忙しすぎるという課題がありました(RSP にオフロード未)。これを解決するために以下の最適化を行いました。
1. フloatingポイントから 16 ビット固定点への変換
IMDCT を RSP コプロセッサに移す際のメモリの制約に対応しました。
-
問題点:
- RSP は DMEM/IMEM が各4,096 バイトしか確保できない。
- ベクトル命令は浮動小数点数を扱えず、固定点のみ対応(16 ビットまたは 32 ビット)。
- ULC のデフォルトブロックサイズ(2,048 サンプル)では容量不足に陥る可能性大。
-
解決策:
- 参考実装を再設計し、**16 ビット固定点(Q1.14 形式)**を採用。
- メモリ使用量を確保しつつ、DMA トラフィック削減と計算速度向上を実現。
- 最終判断: 最大音量でも僅かにホワイトノイズが聞こえるか、あるいは想像上のものなのか確認した結果、16 ビット固定点を採用。
2. RSP への実装(C コードから MIPS アセンブリへ)
C コードを手作業で RSP に移植するのは一大プロジェクトであり、当初は一時停止されました。LLM の能力向上を受け、以下の段階的アプローチで開発を再開。
-
RSPL 言語の活用:
- Max Bebök 氏が作成した RSP 向け C 風の言語「RSPL」を使用。
- Codex に C コードを RSPL へ逐次翻訳させ、結果を確認する作業を実行。
-
最適化手順:
- 意味のある API デザインへの到達。
- Codex に RSPL から生成されるアセンブリコードの最適化を依頼。
- 一部を直接アセンブリで書き換え、RSP の内部 Optimizer を活用してパイラインストール最小化を実施。
-
最終成果:
- IMDCT、ラッピング、ステレオインターリーブ、出力スケール調整を担当する約1,400 行の MIPS アセンブリコード完成。
- RSP の IMEM (4,096 bytes) に収まるサイズ設計。
3. デコーダのパフォーマンスと機能拡張
- Seek 機能の実装:
- ULC ファイル末尾に、各 8 フレームごとのバイトオフセットを含む疎表(sparse table)を追加。
- 目的のフレームへ素早くジャンプ可能(オーバーヘッド約 20 bytes/秒)。
✅ 最終評価とまとめ
パフォーマンス指標
| メトリック | 値 / 評価 |
|---|---|
| CPU 使用量 | 約 4% (メイン CPU) 約 5% (RSP) |
| 音質 | Opus レベルに匹敵 |
| ビットレート | Opus と同等の効率的な圧縮率 |
| 複雑性 | ADPCM の約 4 倍程度(許容範囲内) |
利便性と汎用性
- 透明な動作: Libdragon 内で他のコーデックと同様に、ユーザーが気にせず使用可能。
- 適用シーン: 背景音楽、セリフ音声、環境音、長時間の効果音など幅広く利用可能。
- 現在のステータス: プレビューブランチへマージ済み。
他プロジェクトでの実績
「……libdragon の ULC オーディオコーデックは、2,500 の音声と 27 の楽曲トラックを収めるため、すべてを 1 つの 64 MB カートリッジイメージに収めるのに役立ちました。」
~ github.com/ToxyCola/Half-Life-Nintendo-64-Port
🙏 おわりに
N64 で Opus レベルの音声を再生するという夢を現実にした**超低複雑性コーデック(ULC)**に深く感謝申し上げます。
- ULC の開発には Aikku93 氏が多大な貢献をされたため、心より謝意を表します。
- 私自身は単に見つけ出し、適応改良を行ったのみですが、このプロジェクトを通じて「シンプルさと優雅さ」を追求する価値を確認できました。