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最新版ではなぜか行番号も
ペーストされるようになってしまったので、行番号無しに変更。
昔は大丈夫だったし、今も
コピーの為のドラッグ中は行番号部は選択された形に見えない。
| 固定リンク

