その時々

その時々で違うんです。特に決まっていないんです。

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個というようなパターンですと大きな音が鳴ります。

これらのことから波の間隔が狭いと高い音が鳴り、広いと低い音が鳴り、
波が高いと大きな音が鳴ることが分ります。