Waveファイルフォーマットの領域に踏み入れる
波形というものに興味がありました。
音声や電波とか無線とか(もちろん相場だって好きです。)聞くとなんだか不思議であって身近な存在であり、とても難しいものだというふうに考えていました。
フーリエとかクーロンとかローレンヅとか、もう周波数変調の数式なんかでてくると、これはも学者とかがやるようなもので、学のない私のような人間が踏み入れる領域ではないと思ってたんですね。
ですけど、やっぱりちょっと触れてみたかったんです。
というわけで自己流で触れてみることにしました。
OSはUbuntu10.04です。
まずはWaveファイルのフォーマットについて勉強です。
WAV ファイルフォーマット
ここを見れば大体理解できました。
私流の覚え方としては、実際に作ってみることですかね。
Emacsで。
まずは参考に1秒のwavファイルを作成してみます。
eshellから
$ arecord -d 1 wavdata.wav
これで録音出来ます。
8 bitのサンプリングレート8000Hz、モノラルのwavファイルが完成です。
いちおう比較のためにファイルの情報を確認しておきます。
$ file wavdata.wav wavdata.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8 bit, mono 8000 Hz
さあいじりましょう。
emacsからwavdata.wavを開いてM-x hexl-modeでhexl-modeにします。
00000000: 5249 4646 641f 0000 5741 5645 666d 7420 RIFFd...WAVEfmt 00000010: 1000 0000 0100 0100 401f 0000 401f 0000 ........@...@... 00000020: 0100 0800 6461 7461 401f 0000 8080 8080 ....data@....... 00000030: 8080 8080 8183 8281 8281 8182 8181 8182 ................
こんな感じで出来ているようです。
先程のページと照し合せていくと
5249 4646 | RIFF |
641f 0000 | リトリエンディアンなので0x1f64を10進数にすると8036となって 8036+8=8044byte |
5741 5645 | WAVE |
666d 7420 | fmt |
1000 0000 | fmtチャンクは16byte |
0100 | リニアPCM |
0100 | モノラル |
401f 0000 | サンプリングレート 8000Hz |
401f 0000 | 8000×1×1= 8000bps |
0100 | ブロックサイズ 1×1= 1 |
0800 | サンプルあたり8bit |
6461 7461 | data |
401f 0000 | 波形データ 8000byte |
例えばステレオに変えてみます。
0100を0200にするだけです。
C-M-xでhexを書き換えることが出来ます。
00000000: 5249 4646 641f 0000 5741 5645 666d 7420 RIFFd...WAVEfmt 00000010: 1000 0000 0100 0200 401f 0000 401f 0000 ........@...@... 00000020: 0100 0800 6461 7461 401f 0000 8080 8080 ....data@....... 00000030: 8080 8080 8183 8281 8281 8182 8181 8182 ................
確認してみましょう。
$ file wavdata.wav wavdata.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 8 bit, stereo 8000 Hz
steraoに変っています。
もちろんヘッダだけですけど。
ステレオになると波形データがL R L R..となるようです。
波形データをテキストファイルにする
さきほどのwavファイルを使いますのでモノラルに戻しておきます。
こちらのCソースを使わせていただきました。
WAVE (.WAV) file format
$ wget http://oku.edu.mie-u.ac.jp/~okumura/dumpwave.c $ gcc -o dumpwave dumpwave.c $ ./dumpwave wavdata.wav > wavdata
emacsで開いてみると、きちんと8000個の数値が並んでいることがわかります。
gnuplotで波形を表示してみる
$ gnuplot gnuplot> set terminal wxt gnuplot> set xrange[0:8000] set xrange[0:8000] gnuplot> set yrange[-20:5] set yrange[-20:5] gnuplot> plot "wavdata" using 1 with lines gnuplot> quit
それでも1秒でも8000Hzとなると8000もの数値データが必要なんですね。
再生するには次のコマンドです。
$ aplay wavdata.wav
Waveをテキストから作ってみる
WAV ファイルフォーマット
もう一度こちらのページを表示しtxt2wavというCのソースを使わせていただきます。
$ wget http://www.kk.iij4u.or.jp/~kondo/wave/txt2wav.c $ gcc -o txt2wav txt2wav.c
emacsで次のような数値のテキストファイルを作ってみます。
10
10
10
.
.
.
えっと10を8000個並べたものです。
[F3] 10 RET [F4] C-u 7999 [F4]
これだけで作れます。
wavdata2という名前で保存します。
それではwavファイルを作ってみます。
$ ./txt2wav -8000 wavdata2 wavdata2.wav : 8000 Hz sampling, 8 bit, 1 channel file size (header + data) = 8036 [Byte] PCM type = 1 sampling rate = 8000 [Hz] Byte / second = 8000 [Byte] Byte / block = 1 [Byte] bit / sample = 8 [bit] file size (data) = 8000 [Byte] 8000 points write wavdata2.wav : 8044 bytes (1 sec)
出来ました。
$ aplay wavdata2.wav
ポツっと鳴って終わりました・・・
波がなければ音は鳴らないのですね。
それではこんなファイルにしてみましょうか。
0
100
.
.
.
というようなファイルです。
emacsで
[F3] 0 RET 10 RET [F4] C-u 3999 [F4]
で作ります。
今度は非常に高い音が鳴りました。
0が5個、10が5個というようなパターンですとさっきより低い音が鳴ります。
0が5個、10が5個というようなパターンですと大きな音が鳴ります。
これらのことから波の間隔が狭いと高い音が鳴り、広いと低い音が鳴り、
波が高いと大きな音が鳴ることが分ります。