Javaで読み込むwavファイルを解析します。
情報の表示
wavファイルを読み込むにはAUdioInputStreamというオブジェクトをAudioSystemから取得します。またこのオブジェクトからフォーマットを取得できます。
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("wav/sine.wav")); AudioFormat format = ais.getFormat();
以下はこの二つのオブジェクトからファイルの情報を取得して出力する処理です。
System.out.println("frame length : " + ais.getFrameLength()); System.out.println("sample rate : " + format.getSampleRate()); System.out.println("samble size : " + format.getSampleSizeInBits()); System.out.println("channels : " + format.getChannels()); System.out.println("big endian : " + format.isBigEndian()); System.out.println("mark supported : " + ais.markSupported());
以下はあるファイルを指定して実行した結果です。
frame length : 240000 sample rate : 48000.0 samble size : 16 channels : 2 big endian : false mark supported : false
ここからわかるのは以下のようなことです。
- サンプルの数は240000個あること
- サンプルレートが48000つまり一秒あたり48000個のサンプルが収められている
- 一つのサンプルが16ビットつまり2バイトの量であること
- 二つのチャンネルがあること、つまりステレオであること
- データの並び方がビッグ・エンディアンでないこと、つまりリトル・エンディアンであること
- マークをサポートしない、つまり巻き戻しや早送りができないこと
さらに以下のようなこともわかります。
- 音声の長さが5秒であること(サンプル数 ÷ サンプルレート)
- サンプルあたり4バイト使うこと(サンプルサイズのバイト × チャンネル)
ビッグ・エンディアンとリトル・エンディアンについて
一つのサンプルの音量を求める時データの並びが重要になります。ここではサンプルサイズが16ビットか24ビットの場合です。
これらのサンプルサイズはバイトにすると2バイトか3バイトなのでファイルに書き出す時には複数のバイトデータを並べる必要があります。ビッグエンディアンは大きい位から小さい位へ、リトルエンディアンは小さい位から大きい位へと並べます。
音量の求め方
さらに16ビットまたは24ビットの音声データは正負の情報を持っていてこれは一番大きいくらいが持つことになっています。
24ビットの場合をまとめると以下のようになります。それぞれの位の値を合計すると音量が求められます。同じバイトでも値の範囲が一番大きいくらいだけ異なることに注意してください。
位 | 範囲 | 最小値 | 最大値 |
---|---|---|---|
82 = 65,536 | -128 〜 127 | -128 | 127 |
81 = 256 | 0 〜 255 | 0 | 255 |
80 = 1 | 0 〜 255 | 0 | 255 |
-8,388,608 | 8,388,607 |
82の位が-10、81の位が200、80の位が210だとすると
-10 * 65536 + 200 * 256 + 210 = -603950
となります。以下は16ビットの時です。考え方は24ビットと同じです。
位 | 範囲 | 最大値 | 最小値 |
---|---|---|---|
81 = 256 | -128 〜 127 | -128 | 127 |
80 = 1 | 0 〜 255 | 0 | 255 |
-32,768 | 32,767 |