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>

↓実際に入れるデータ

&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;BWFXML&gt;&lt;IXML_VERSION&gt;2.02&lt;/IXML_VERSION&gt;&lt;TRACK_LIST&gt;&lt;TRACK_COUNT&gt;1&lt;/TRACK_COUNT&gt;&lt;TRACK&gt;&lt;CHANNEL_INDEX&gt;1&lt;/CHANNEL_INDEX&gt;&lt;INTERLEAVE_INDEX&gt;1&lt;/INTERLEAVE_INDEX&gt;&lt;NAME&gt;role name&lt;/NAME&gt;&lt;/TRACK&gt;&lt;/TRACK_LIST&gt;&lt;/BWFXML&gt;


結論。ダメだった。BWFの仕様に合わせる必要があって、
他にも入れないとイケナイデータがある。
それと、Chunkの順番が決まっているようだ。