wavファイルの波形を表示させる(2)

スポンサーリンク

今回はwavファイルから必要なデータを抜き出す処理を作ります。前回ウィンドウを作りました。グラフの領域は横が余白をのぞいて780ピクセルあります。ここに波形を表示したいと思います。問題はサンプルしている全てのデータを表示しきれないことです。サンプルレートが48000、長さが3秒なので14万以上のサンプル数、これを780ピクセルに表示するには間引きが必要です。また3秒間全てを表示したいわけではなく波形を見たいので前後3周期で純分でしょう。440Hzの音の1周期の長さは1/440秒ですから3周期のサンプル数は
48000 / 440 x 3
で327と少し。これであれば2ピクセルごとに1サンプルを描画すれば良いでしょう。780ピクセルなので余裕をもって400サンプル取ります。
今回は処理の流れのみ見ていきます。

wavファイルの波形を表示させる(1)

処理の説明

インポートは以下の通りです。

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

次に前回作ったファイルを読み込む準備をします。

AudioInputStream input_stream = AudioSystem.getAudioInputStream(new File("/Users/myaccount/mywork/square_440.wav"));

こちらで動かして見たところ読み込みフォーマットのうちBigEndienではなくLittleEndienになっていました。このため他の項目を変えずBigEndienにして開き直します。

AudioFormat format = input_stream.getFormat();
format = new AudioFormat(format.getFrameRate(), format.getSampleSizeInBits(), format.getChannels(), true, true);
input_stream = AudioSystem.getAudioInputStream(format, input_stream);

サンプルサイズをバイトで取得します。

int sample_size = format.getSampleSizeInBits() / 8;

データを保持する可変の配列を準備します。

ArrayList data = new ArrayList<>();

とりあえず400個のサンプリングを取るように取得サイズを決めておきます。

int size = 400;

サイズ通り取得できるようにwhile文を使います。

while (data.size() < size) {
  //取得処理
}

ここから取得処理の詳細です。まずlongに変換できるように8つのバイト配列を作ります。実際には2バイトしか読みませんが下段の処理で8個の配列が用意されていないと変換できません。

byte[] buffer = new byte[8];

2バイト分を下二桁に読み込みます。

input_stream.read(buffer, 8 - sample_size, sample_size);

このままでは負の数字の処理がうまくいきません。今のままでは2バイトであれば
11111111 00000001
となり-32767になるのですがbyte配列の上6桁は未設定のため0になります。すると

00000000 00000000 00000000 00000000 00000000 00000000 11111111 00000001

となりlong値では32769という正の数字になってしまいます。long値で同じ値にするには以下のように上6桁のビット全てを立てます。

11111111 11111111 11111111 11111111 11111111 11111111 11111111 00000001

以下のような処理を追加します。

if(buffer[8 - sample_size] < 0){
  for(int i = 0; i < 8 - sample_size;i++){
    buffer[i] = -1;
  }
}

これをlong値にして配列に追加すれば取得処理は終わりです。

data.add(ByteBuffer.wrap(buffer).getLong());

表示確認
最後に取得したデータが正しいか確かめます。

for(long value:data){
  System.out.println(value);
}

結果は以下の通り、正しい値が取れました。

32767
32767
(中略)
32767
-32767
-32767
(中略)
-32767
32767
32767
(中略)

wavファイルの波形を表示させる(3)

スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

%d人のブロガーが「いいね」をつけました。