JavaでPCMファイル波形データ読み書き:メモ
メモです。Javaで波形データ作成再生サンプル:メモの続きです。
ファイル出力
波形データからAudioInputStreamを作成し、AudioSystem.write()メソッドで
ファイルに出力することができます。
// Test07.java import javax.sound.sampled.*; import java.io.*; class Test07 { public static void main(String[] args_){ try{ byte[] wave_data= new byte[44100*2]; double L1 = 44100.0/440.0; double L2 = 44100.0/455.0; for(int i=0;i<wave_data.length;i++){ pcm_data[i]= (byte)(55*Math.sin((i/L1)*Math.PI*2)); pcm_data[i]+= (byte)(55*Math.sin((i/L2)*Math.PI*2)); } AudioFormat frmt= new AudioFormat(44100,8,1,true,false); AudioInputStream ais = new AudioInputStream( new ByteArrayInputStream(wave_data) ,frmt ,wave_data.length); AudioSystem.write( ais ,AudioFileFormat.Type.WAVE ,new File("test07.wav")); } catch(Exception e){e.printStackTrace(System.err);} } }
参考までに、実際に生成したファイルを置きます。
test07.wav
少し複雑な音声合成を行い、生成したファイルを置きます。(.wavを作成し、
mp3に変換したものです)
sample5.mp3
この音声合成は
▲「ん」「な行」「ま行」と「が」音声合成試験で行っています。
Java設定の波形情報値とwavファイル上の波形情報値
上のプログラムで生成されたファイルの先頭部の16進ダンプを示します。
0000: 5249 4646 f004 0200 5741 5645 666d 7420
0010: 1000 0000 0100 0100 44ac 0000 44ac 0000
0020: 0100 0800 6461 7461 cc04 0200 8086 8d94
0030: 9aa1 a8ae b4bb c0c5 cbd0 d5d9 dde0 e3e6
0040: e8ea ebec ecec ecec ebe9 e7e5 e1df dbd7
0050: d2ce c8c3 beb7 b1ab a59e 9891 8a83 7d76
0060: 706a 625c 564f 4843 3e38 332e 2925 221f
0070: 1c1a 1715 1514 1414 1415 1618 1a1d 1f23
0080: 272c 3035 3a3f 464b 5157 5f65 6b72 797f
0090: 878c 939a a0a7 adb4 b9bf c5ca d0d4 d8db
00a0: dfe2 e5e7 eaeb ebec ecec ebea e9e7 e4e2
.......
注目して欲しいのは波形を表す値です。青い部分が波形値となっています。
Javaでbyte配列に入れたデータは0を中心とした正負127~-127の値ですが wavファイル上は128のゲタを履かせ、128を中心とした255~0の値となります。
wavファイル読み込み、再生
AudioInputStreamを用いてオーディオファイルを読みこみながら、 SourceDataLineを使って再生することができます。
// Test08.java import javax.sound.sampled.*; import java.io.*; class Test08 { public static void main(String[] args_){ try{ AudioInputStream ais = AudioSystem.getAudioInputStream(new File("test07.wav")); AudioFormat frmt = ais.getFormat(); DataLine.Info info = new DataLine.Info(SourceDataLine.class,frmt); SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(frmt); line.start(); byte buf[]=new byte[1024]; int len; while( (len=ais.read(buf,0,buf.length))!=-1 ){ line.write(buf,0,len); } line.drain(); line.close(); } catch(Exception e){e.printStackTrace(System.err);} } }
readで読み込まれるデータはファイルの波形情報部です。255~0の値となります。
wavファイルを読み込み、データを変更し再生
wavファイルを読み、データを解析したうえで再生する例を載せます。
この例では読み込んだものが符号なし下駄ばき8bit(255~0)データの並びとして、
符号付き8bit(127~-127)に変換したうえで再生しています。
// Test09.java import javax.sound.sampled.*; import java.io.*; class Test09 { public static void main(String[] args_){ try{ AudioInputStream ais = AudioSystem.getAudioInputStream(new File("test07.wav")); AudioFormat frmt = ais.getFormat(); byte[] buf= new byte[44100*4]; int len; int dlen=0; while( (len=ais.read(buf,dlen,buf.length-dlen))!=-1 ){ dlen+=len; } AudioFormat frmt2= new AudioFormat(44100,8,1,true,false); for(int idx=0;idx<dlen;++idx){ // ファイルから得たAudioFormatを使う場合この値変換は不要 buf[idx]= (byte)((((int)buf[idx])&0xFF)-128); } DataLine.Info info= new DataLine.Info(Clip.class,frmt2); Clip clip= (Clip)AudioSystem.getLine(info); clip.open(frmt2,buf,0,dlen); clip.start(); Thread.sleep(100);while(clip.isRunning()) {Thread.sleep(100);} } catch(Exception e){e.printStackTrace(System.err);} } }
なお、AudioInputStreamから取得したAudioFormatで再生する場合、データの変換を 行う必要はありません。
###
2011/7/15
行番号付きソースコードがコピペ時にIE8最新版ではなぜか行番号も
ペーストされるようになってしまったので、行番号無しに変更。
昔は大丈夫だったし、今も
コピーの為のドラッグ中は行番号部は選択された形に見えない。
| 固定リンク