初めに
誰もが一度はやってみたい、著作権切れのコーデックのデコーダを書く、そうじゃありませんか?
AAC-LC であれば MPEG2 の特許が切れているので、大丈夫なはず!
一番簡単な AAC-LC の CPE なし、TNS 無しなモノラル音源をデコードしてみましょう!
というわけで、昨年やってみた AAC のデコーダ実装からエッセンスを抽出して紹介します。
https://github.com/monyone/AAC.ts
皆さんも実装してコーデックを理解し、一つ上のプログラマになりましょう!
全体の流れ
- AAC のビット列をパースする (仕様書を見て頑張りましょう)
- AAC のビット列のうち SCE 以外を無視する (特に CPE は面倒なので扱いません)
- SCE をデコードする
- 窓関数を使ってデータをつなぎ合わせる
この辺の敵
AACのビット列
AAC はビット列を逐次パースしなければ、何がどこにあるかわかりません。
(H264 の NALu みたいな構造ではないので、全てパースはする必要があります)
必要な物全ての構造を頭に入れてパースしましょう。
ハフマン符号
scalefactor データと spectrum データ はハフマン符号にエンコードされます。
この符号のコードブックは頑張って仕様書から入力しましょう!
入力したものはこちらになります。
逆修正コサイン変換
spectrum データを IQ した後に、IMDCT を行なって、
周波数領域から時間領域に変換を行う必要があります。
IMDCT は DCT-IV へ変換してから DCT-II に帰着するのが一番楽です。
DCT-IV への変換は 独自の音声圧縮をJavaScriptで作ってみた を参考にしており
コードに元の部分が少し残っています。(DCT-II への変換を変更して分かりやすくしています)
窓関数
SIN 窓と KBD 窓があります。
ics_info で指定されるので、どっちも対応しましょう。
波形のつなぎ合わせ
MDCT で端の音声が揺らぐため、窓関数でつなぎ合わせます。
波形の表現が 4 種類ありますので、場合分けを頑張りましょう。
まとめ
そんな実装量はかからないので、皆さんやってみましょう。
たぶん、小一時間程度で実装できますので、ffmpeg 片手に let's try!
あとがき
実際に WebAudio に接続するサンプルを作ればなと思いましたが
WebAudio で AAC は読めるので、劣後するなと思って未着手です...