niszetの日記

10年目エンジニアが最近勉強したことを忘れないようにメモをする

前回プロットしたwavファイルの説明

read_wav()の関連知識

さて、条件付きとはいえwavファイルをrで読み込み、data.tabelの形式にしてggplot2で表示させることが出来ました。
前回はCsoundによって生成したwavファイルが、1Hzで非常に見やすいという理由で使っていました。
今回は、Csoundで生成したwavファイルをバイナリエディタで見つつ、read_wav関数内でどのように処理をしているかについて、簡単に説明をしようと思います。

Csoundで生成したwavファイルについて。

前回の記事で使用したwavファイルについては下記をご参照ください。ここで生成した、1Hzのサイン波を説明に使います。

niszet.hatenablog.com

wavのフォーマットについて

前回も紹介した、下記のサイトを見るのが良いと思います。見比べてください。

WAV形式音声ファイル

バイナリエディタでデータを見てみる。

さて、

52 49 46 46 08 00 00 00 57 41 56 45 66 6D 74 20
10 00 00 00 01 00 02 00 44 AC 00 00 10 B1 02 00
04 00 10 00 64 61 74 61 00 00 00 00 00 00 00 00
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
05 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00

こんな感じです。バイナリなので、52は0x52、10進数で82(=16*5+2)を表しています。これで1byteの単位です。
さて、順に見ていきます。
適宜、先のサイトから説明を引用させていただきます。

52 49 46 46

wavファイルの先頭4byteはRIFFヘッダとなっていて、それぞれR,I,F,Fの文字をasciiコードで表しています。

asciiの文字コードはググれば一発ですがこちらが見やすいかな。
検索するときは52なら0x52、49は0x49で探してみてください。それぞれRとIに対応しています。

参考: ASCIIコード表

08 00 00 00

来ました。Csound第一の謎。 wavのフォーマット的に、次の4byteはファイルサイズ-8のはずです。しかしここでの値は8。

あ、ちなみにここ、リトルエンディアンです。良く調べてないけど。 エンディアン - Wikipedia

別のwavファイルはちゃんとファイルサイズ-8で入っていたので正しかろう…。
ともかく、Csoundで生成したwavには不備があります。そのため、通常のプレーヤで再生できない(WMPfoobar2000で確認)のだと思います。read_wavはこの値を無視し、ファイルサイズ-8を使用するようにしています。今後、csoundオプションで指定するかもしれませんが。

57 41 56 45

それぞれ、'W' ‘A’ ‘V’ ‘E'です。

66 6D 74 20

それぞれ、'f' ’m' ’t' ‘ 'です。

10 00 00 00

引用。

4 byte   バイト数    fmt チャンクのバイト数。リニアPCM ならば 16(10 00 00 00)

ということで、このファイルのfmtチャンクのバイト数は16ということを表しています。

余談ですが、PrintMusic2011Jで生成したwavファイルはこの値が18となっていました。リニアPCMフォーマットなのに…なぜ…

01 00

再び引用。

2 byte   フォーマットID    リニアPCM ならば 1(01 00)

ということで、リニアPCMのようです。

02 00

どんどん行きましょう。

2 byte   チャンネル数  モノラル ならば 1(01 00)、 ステレオ ならば 2(02 00)

ステレオのようですね。これ、Csoundの謎その2です。のちに出てきますが、実際は片方にしか音が入っていません。何のためのステレオ…

44 AC 00 00

44.1KHzでした。

4 byte   サンプリングレート 44.1kHz ならば 44100(44 AC 00 00)

10 B1 02 00

こちらもそのままですね。

4 byte   データ速度 (Byte/sec)  44.1kHz 16bitステレオならば 44100×2×2=176400(10 B1 02 00)

04 00

こちらも。

2 byte   ブロックサイズ (Byte/sample×チャンネル数) 16bit ステレオ ならば 2×2 = 4(04 00)

10 00

こちらも想定通り。

2 byte   サンプルあたりのビット数 (bit/sample)   WAV フォーマットでは 8bit か 16bit。16bit ならば 16(10 00)

64 61 74 61

それぞれ、’d' ‘a’ ’t' ‘a'ですね。

00 00 00 00

来ました、第三の謎。
ここで、残りのデータのサイズを示しているはずなのですが、サイズ0となっています。
read_wavではこの値を無視し、ファイルサイズからヘッダのサイズを引いた値でデータサイズを計算しました。値が0以外の場合は使った方が良いかもしれませんね。

データ部分

さて、データ部分についてはこちらを読むと良いです。
wav ファイルフォーマット

16bitステレオなので、L,R,L,R…の順に16bit= 2byteで並んでいるはずです。つまり、1byte毎に見ればL L R Rのまとまりが1秒間に44.1kだけあるはずです。

実際のデータは…

00 00 00 00
01 00 00 00
02 00 00 00
03 00 00 00
04 00 00 00
05 00 00 00
07 00 00 00
08 00 00 00
09 00 00 00

のように、L側だけデータが入っています。これは設定で変えられるのかもしれませんので謎カウントしません。
1サンプルごとに少しずつ増えていることが見れますね。

16bit ならば符号付き signed (-32768 ~ +32767, 無音は 0)

ということで、負値は0xFFみたいな値になります。実際、末尾は

F3 FF 00 00 F4 FF 00 00 F5 FF 00 00 F6 FF 00 00 
F7 FF 00 00 F8 FF 00 00 FA FF 00 00

のようになっています。
そしてまた謎の、ファイル末尾で-1あたりになっていないという。-6て…。
そして、read_wavで読めばわかりますが、44128行あるのでした。44.1kHzじゃなかったっけ( ^ω^)・・・?

というわけで、細かいことを気にするときりがないのですが、Csoundの生成するwavファイルはなんか奇妙だなというお話でした。
値自体はCsound+バイナリエディタ、あとは気合で見れますので、見てみると良いのではと思いまする。