プレーヤー作成中、ブロックデコード関数を公開したけど、仕様の厳しさを感じている。末端でブロックサンプル数が少なくなったときの処理が難しい。
ブロックヘッダにサンプル数を記録すべきでは無いかと考えている。そしてヘッダのブロックあたりサンプル数は最大ブロックサンプル数に変更。そうしないと現在のブロックをデコードするときに何サンプルデコードすべきかわからなくなる。末端までサンプル数固定にするのもありだけど、無音が挿入されるのが汚い。
論文についての返事がないので実装を進めた。ブロックヘッダにサンプル数を入れた。
単純再生サンプル作った。この春できるのはここらへんまでかな。参考にしたリンクは以下。
- Audio Queue example CoreAudio出力の参考に。
- WASAPIが一番大変だった
- WASAPI Play .wav File.cpp わかりやすかったがWAVEFORMATEXを0クリアしてなくてCbsizeが未初期化クラッシュ。ドハマリ
- WASAPIをプログラムしてみる
- WASAPIによる音声再生
- System Interface Library for games ピュアCでやろうとするとGUIDが取れない。自力でGUIDを定義しているのがこれ。
- pacat-simple.c pulseaudio出力の参考に。pa_simpleで十分だった。
データフォーマット
ヘッダフォーマット
| bit幅 | 内容 | 補足 |
|---|---|---|
| 32 | 'N', 'A', 'R', 'U' | NARUファイルであることを示すシグネチャ |
| 32 | フォーマットバージョン番号 | エンコードしたときのフォーマットバージョン |
| 32 | エンコーダバージョン番号 | エンコードしたときのエンコーダバージョン |
| 16 | チャンネル数 | |
| 32 | サンプル数 | 1チャンネルあたりの全サンプル数 |
| 32 | サンプリングレート | |
| 8 | サンプルあたりビット数 | |
| 16 | ブロックあたりサンプル数 | 現状固定の想定。 |
| 8 | フィルタ次数N | 2の冪定数に限定 |
| 8 | AR(p) モデルの次数p | N > 2*p を満たさなければならない |
| 8 | チャンネル毎の処理法 |
ブロックフォーマット
| bit幅 | 内容 | 補足 |
|---|---|---|
| 16 | '0xFFFF' | ブロック先頭を示す同期コード |
| 32 | ブロックサイズ | この領域以降のブロックのサイズ[byte] |
| 16 | CRC16 | この領域以降のブロックのCRC16値 |
| 8 | ブロックデータタイプ | 0:残差、1:無音(ランレングス符号化)、2:生データ |
| 16 | チャンネルあたりサンプル数 | このブロックに含まれる1チャンネルあたりのサンプル数 |
| 不定 | データ | 圧縮済みデータ or 生データ |
TODOリスト
- リングバッファアクセス高速化: 済
- ハンドルのワーク配置化: 済
- 将来的にフィルタもワーク配置したい。自己割当なしで実装すれば良さそう。
- CRC16対応: 済
- コマンドライン整理: 済
- プリセット選定: 済
- いまのところ、(NGSA次数, SA次数, ブロックサイズ) と書くとしたとき
- 高速(低圧縮モード)は(4, 4, 8192)
- 通常(デフォルト)は(8, 8, 8192)
- 低速(高圧縮モード)は(16, 8, 16384)
- でいこうと思ってたけど、フィルタ次数を増やしても負荷インパクトが大きくならない+圧縮率が向上し続けるのを見て、次数は4, 8, 16, 32, 64まで選べるようにした。
- いまのところ、(NGSA次数, SA次数, ブロックサイズ) と書くとしたとき
- MSVC環境で _BitScanReverse を使う: 済
- MSVC環境で gtest できるようにする: 手が空いたらでよい。
- 評価開始(評価スクリプトを作る。Rubyでいい。)