How to save a WAV file using "AudioSystem" and "AudioInputStream"of JavaSound?

I'm on Processing 2.0.3 and tried to make a sound effect program which is not using real-time buffering and saves buffer (AudioInputStream) as .wav file after effecting, but my program doesn't work and gets the error :"Unhandled exception type IOException".

I couldn't a solution for this. Please advise me on how to save an AudioInputStream instans as .wav file.


import javax.sound.sampled.*;
import java.io.*;

void setup(){}
void draw(){}
void mousePressed(){
         byte[] pcm_data= new byte[44100*2];
         double L1      = 44100.0/440.0;
         double L2      = 44100.0/455.0;
         for(int i=0;i<pcm_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(pcm_data)
                   ,frmt
                   ,pcm_data.length);

         AudioSystem.write(
                    ais
                   ,AudioFileFormat.Type.WAVE
                   ,new File("test.wav"));
}

I read the article: http://forum.processing.org/one/topic/exception-type-ioexception.html ,and tried to write "try{---}catch (IOException e) {System.err.println(e);}", but the program didn't output .wav file and any error messages.

I searched some processing libraries for sound (examples:minim, Ess). But those are suitable for real-time playing, effecting and recording, so I use the JavaSound library directly. I suppose those libraries don't have save methods for non real-time array lists(?). If you know how to save non real-time buffer array list as .wav using minim or Ess, please advise me...

Thanks in advance for your help. I'm Japanese, so please, no flames about my bad English.

Answers

  • edited October 2014 Answer ✓

    I guess by now you already found the solution... Just in case:

    import javax.sound.sampled.*;
    import java.io.*;
    
    void setup() {}
    void draw() {}
    void mousePressed() {
      byte[] pcm_data = new byte[44100*2];
      double L1 = 44100.0/240.0;
      double L2 = 44100.0/245.0;
      for (int i=0; i<pcm_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, true);
      AudioInputStream ais = new AudioInputStream(
        new ByteArrayInputStream(pcm_data), frmt, 
        pcm_data.length / frmt.getFrameSize()
      );
    
      try {
        AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new 
          File(sketchPath + "/test.wav")
        );
      } 
      catch(Exception e) {
        e.printStackTrace();
      }
    }
    

    I changed 3 things: BigEndian (last argument in AudioFormat), divided the pcm_data.length by the frame size, and set an absolute path for the file.

  • Dear hamoid,

    Thanks for answering. And the code you fixed is working!

  • edited November 2014

    ... and set an absolute path for the file.

    It's more organized saving to "/data/" subfolder. So rather than new File(sketchPath + "/test.wav"),
    this 1 points straight to "/data/": dataFile("test.wav"). :-c

    Also, Processing already imports from lotsa "java.io" libraries already.
    So import java.io.*; is usually redundant! :-j

  • import java.io.*; is not redundant in this case.

Sign In or Register to comment.