WAVファイルのフォーマットの確認
アプリで出力したWAVファイルが正しくないのではないか、という問題に遭遇して、
その際、バイナリファイルといろいろな資料を読みながら、
WAVファイルがどのような仕様になっているか調べたので、その時の調査メモ。
用意したもの
バイナリエディタと電卓。
大きな数値の項目はリトルエンディアンで、文字の項目はASCII。
16進数を10進数で読む。
なので、用意する電卓は↑の変換が出来るものでないと読めないですのぅ。
バイナリファイルを読む
実際に作ったWAVファイルをバイナリエディタで読んでみつつ、
どの位置にどのような値が入っているか確認。
WAVEファイル その1
bytes | 定義 | 入っていた値 | 解読 | 説明、または検算 |
---|---|---|---|---|
1-4 | Chunk ID | 52 49 46 46 | RIFF | "RIFF"固定 |
5-8 | Chunk Size | FC 72 00 00 | 29436 | ファイルサイズ - 8bytes |
ファイルサイズからChunk ID Chunk Size除いた分か | ||||
29444 - 8 = 29436 | ||||
9-12 | Format | 57 41 56 45 | WAVE | "WAVE"固定 |
13-16 | Subchunk1 ID | 66 6D 74 | fmt | "fmt"固定 |
17-20 | Subchunk1 Size | 20 10 00 00 | 16 | "16"固定。Subchunk1の長さ(21-36)なので |
21-22 | Audio Format | 01 00 | 1 | "1"固定。(PCMなら) |
23-24 | Num Channels | 01 00 | 1 | チャネル数 |
25-28 | Sample Rate | 40 1F 00 00 | 8000 | サンプリングレート |
29-32 | Byte Rate | 80 3E 00 00 | 16000 | ブロックサイズ |
SampleRate * NumChannels * BitsPerSample/8 | ||||
(8000 * 1 * 16) / 8 = 16000 | ||||
33-34 | Block Align | 02 00 | 2 | 1サンプルあたりのビット数 |
NumChannels * BitsPerSample / 8 | ||||
(1 * 16) / 8 = 2 | ||||
35-36 | Bits Per Sample | 10 00 | 16 | 8 bits = 8, 16 bits = 16 |
37-40 | Subchunk2 ID | 64 61 74 61 | data | "data"固定 |
41-44 | Subchunk2 Size | D8 72 00 00 | 29400 | このチャンクのデータのサイズ |
ここからファイルの最後までが波形データだから | ||||
ファイルサイズ - ここまでのサイズ(44)になるはず | ||||
29444 - 44 = 29400 | ||||
45- | data | ここからファイルの最後まで波形データが入っている |
WAVEファイル その2
bytes | 定義 | 入っていた値 | 解読 | 説明、または検算 |
---|---|---|---|---|
1-4 | Chunk ID | 52 49 46 46 | RIFF | "RIFF"固定 |
5-8 | Chunk Size | 24 00 02 00 | 131108 | ファイルサイズ - 8bytes |
131116 - 8 = 131108 | ||||
9-12 | Format | 57 41 56 45 | WAVE | "WAVE"固定 |
13-16 | Subchunk1 ID | 66 6D 74 | fmt | "fmt"固定 |
17-20 | Subchunk1 Size | 20 10 00 00 | 16 | "16"固定。 |
21-22 | Audio Format | 01 00 | 1 | "1"固定。(PCMなら) |
23-24 | Num Channels | 01 00 | 1 | チャネル数 |
25-28 | Sample Rate | 44 AC 00 00 | 44100 | サンプリングレート |
29-32 | Byte Rate | 88 58 01 00 | 88200 | ブロックサイズ |
SampleRate * NumChannels * BitsPerSample/8 | ||||
(44100 * 1 * 16) / 8 = 88200 | ||||
33-34 | Block Align | 02 00 | 2 | 1サンプルあたりのビット数 |
NumChannels * BitsPerSample / 8 | ||||
(1 * 16) / 8 = 2 | ||||
35-36 | Bits Per Sample | 10 00 | 16 | 8 bits = 8, 16 bits = 16 |
37-40 | Subchunk2 ID | 64 61 74 61 | data | "data"固定 |
41-44 | Subchunk2 Size | 00 00 02 00 | 131072 | このチャンクのデータのサイズ |
131116 - 44 = 131072 | ||||
45- | data | ここから波形データ |
WAVEのバイナリ読んだ感想
読みやすいフォーマット。
アプリからPCMのWAVEファイルを出力すると仮定した時、
ファイルサイズの箇所以外は割と固定値になる。
RIFFの仕様
WAVEで使われているRIFF (Resource Interchange File Format)の仕様も見ておく。
なるほどなー。
bytes | 定義 | 説明、または検算 | |
---|---|---|---|
1-4 | Chunk ID | ChunkのID | |
5-8 | Chunk Size | Chunkのサイズ - IDとSizeフィールドを除いた値 | |
9- | data | チャンクのデータ。データのサイズが偶数で無いなら埋める |
もし、WAVEファイルにiXMLチャンクを差し込むなら
WAVEファイルにiXMLチャンクという仕様があって、
ずっと、どうやってデータを入れれば良いのかサンプルが見つからなくて困っていたんだけど、
RIFFの仕様をみたら、分かってきた。
同じように入れれば良いのだろう。(試してない)
bytes | 定義 | 入れる値 | 解読 | 説明、または検算 |
---|---|---|---|---|
1-4 | Chunk ID | 69 58 4D 4C | iXML | "iXML"固定 |
5-8 | Chunk Size | iXMLのデータサイズ - 8 | ||
9- | data | iXMLのデータ |
chunkのdataに入れるデータは次のようなものになるだろう。
role nameの所以外は固定になりそう?
<?xml version="1.0" encoding="UTF-8"?> <BWFXML> <IXML_VERSION>2.02</IXML_VERSION> <TRACK_LIST> <TRACK_COUNT>1</TRACK_COUNT> <TRACK> <CHANNEL_INDEX>1</CHANNEL_INDEX> <INTERLEAVE_INDEX>1</INTERLEAVE_INDEX> <NAME>role name</NAME> </TRACK> </TRACK_LIST> </BWFXML>
↓実際に入れるデータ
<?xml version="1.0" encoding="UTF-8"?><BWFXML><IXML_VERSION>2.02</IXML_VERSION><TRACK_LIST><TRACK_COUNT>1</TRACK_COUNT><TRACK><CHANNEL_INDEX>1</CHANNEL_INDEX><INTERLEAVE_INDEX>1</INTERLEAVE_INDEX><NAME>role name</NAME></TRACK></TRACK_LIST></BWFXML>
結論。ダメだった。BWFの仕様に合わせる必要があって、
他にも入れないとイケナイデータがある。
それと、Chunkの順番が決まっているようだ。