« △Javaで波形データ作成再生サンプル:メモ | トップページ | △フォルマント合成・時間差差分加算式 »

JavaでPCMファイル波形データ読み書き:メモ

メモです。Javaで波形データ作成再生サンプル:メモの続きです。

 ファイル出力

波形データからAudioInputStreamを作成し、AudioSystem.write()メソッドで ファイルに出力することができます。

次のコードは前の記事 Javaで波形データ作成再生サンプル:メモで作成した「うなり」 サウンドをwavファイルに落とすものです。

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

|

« △Javaで波形データ作成再生サンプル:メモ | トップページ | △フォルマント合成・時間差差分加算式 »

トラックバック


この記事へのトラックバック一覧です: JavaでPCMファイル波形データ読み書き:メモ:

« △Javaで波形データ作成再生サンプル:メモ | トップページ | △フォルマント合成・時間差差分加算式 »