Java Sound Capture from Microphone working code

Sound  Capture / Record from Microphone and Save : working java source code example
 import java.io.ByteArrayInputStream;  
 import java.io.ByteArrayOutputStream;  
 import java.io.IOException;  
 import javax.sound.sampled.AudioFormat;  
 import javax.sound.sampled.AudioInputStream;  
 import javax.sound.sampled.AudioSystem;  
 import javax.sound.sampled.DataLine;  
 import javax.sound.sampled.TargetDataLine;  
 /**  
  * Reads data from the input channel and writes to the output stream  
  */  
 public class MicrophoneRecorder implements Runnable {  
   // record microphone && generate stream/byte array  
   private AudioInputStream audioInputStream;  
   private AudioFormat format;  
   public TargetDataLine line;  
   public Thread thread;  
   private double duration;  
   public MicrophoneRecorder(AudioFormat format) {  
     super();  
     this.format = format;  
   }  
   public void start() {  
     thread = new Thread(this);  
     thread.setName("Capture");  
     thread.start();  
   }  
   public void stop() {  
     thread = null;  
   }  
   @Override  
   public void run() {  
     duration = 0;  
     line = getTargetDataLineForRecord();  
     final ByteArrayOutputStream out = new ByteArrayOutputStream();  
     final int frameSizeInBytes = format.getFrameSize();  
     final int bufferLengthInFrames = line.getBufferSize() / 8;  
     final int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;  
     final byte[] data = new byte[bufferLengthInBytes];  
     int numBytesRead;  
     line.start();  
     while (thread != null) {  
       if ((numBytesRead = line.read(data, 0, bufferLengthInBytes)) == -1) {  
         break;  
       }  
       out.write(data, 0, numBytesRead);  
     }  
     // we reached the end of the stream. stop and close the line.  
     line.stop();  
     line.close();  
     line = null;  
     // stop and close the output stream  
     try {  
       out.flush();  
       out.close();  
     } catch (final IOException ex) {  
       ex.printStackTrace();  
     }  
     // load bytes into the audio input stream for playback  
     final byte audioBytes[] = out.toByteArray();  
     final ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes);  
     audioInputStream = new AudioInputStream(bais, format, 
                audioBytes.length / frameSizeInBytes);  
     final long milliseconds = (long) ((audioInputStream.getFrameLength()  
                     * 1000) / format.getFrameRate());  
     duration = milliseconds / 1000.0;  
     System.out.println(duration);  
     try {  
       audioInputStream.reset();  
       System.out.println("resetting...");  
     } catch (final Exception ex) {  
       ex.printStackTrace();  
       return;  
     }  
   }  
   private TargetDataLine getTargetDataLineForRecord() {  
     TargetDataLine line;  
     final DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);  
     if (!AudioSystem.isLineSupported(info)) {  
       return null;  
     }  
     // get and open the target data line for capture.  
     try {  
       line = (TargetDataLine) AudioSystem.getLine(info);  
       line.open(format, line.getBufferSize());  
     } catch (final Exception ex) {  
       return null;  
     }  
     return line;  
   }  
   public AudioInputStream getAudioInputStream() {  
     return audioInputStream;  
   }  
   public AudioFormat getFormat() {  
     return format;  
   }  
   public void setFormat(AudioFormat format) {  
     this.format = format;  
   }  
   public Thread getThread() {  
     return thread;  
   }  
   public double getDuration() {  
     return duration;  
   }  
 }  

Testing Code :
Its better to use gui rather than console to record sound (due to thread start/stop problem)
Here is my console test application for sound record and save:

 public class Testss {  
   public static void main(String[] args) throws Exception {  
     //MicrophoneRecorder mr = new MicrophoneRecorder(AudioFormatUtil.getDefaultFormat());  
     MicrophoneRecorder mr = new MicrophoneRecorder( YOU NEED TO PASS OBJECT OF AudioFormat here); 
     mr.start();  
     Thread.sleep(2000);  
     mr.stop();  
     //save  
     WaveData wd = new WaveData();  
     Thread.sleep(3000);  
     wd.saveToFile("~tmp", Type.WAVE, mr.getAudioInputStream());  
   }  
 }  

Code for saving AudioInputStream in WaveData Class : (Full Code Next Time)
   public boolean saveToFile(String name, AudioFileFormat.Type fileType,  
                AudioInputStream audioInputStream) {  
     System.out.println("Saving...");  
     if (null == name || null == fileType || audioInputStream == null) {  
       return false;  
     }  
     File myFile = new File( name+"." + fileType.getExtension());  
     // reset to the beginnning of the captured data  
     try {  
       audioInputStream.reset();  
     } catch (Exception e) {  
       return false;  
     }  
     int i = 0;  
     while (myFile.exists()) {  
       String temp = "" + i + myFile.getName();  
       myFile = new File(temp);  
     }  
     try {  
       AudioSystem.write(audioInputStream, fileType, myFile);  
     } catch (Exception ex) {  
       return false;  
     }  
     System.out.println("Saved " + myFile.getAbsolutePath());  
     return true;  
   }  

5 comments:

  1. Have no idea how much this helped me - it's tricky to find an example for this sort of thing!

    ReplyDelete
  2. hi am using above provided code but am getting the fallowing exception
    java.lang.Error: Unresolved compilation problem:
    The method getDefaultFormat() is undefined for the type AudioFormatUtil

    ReplyDelete
    Replies
    1. you need to remove

      AudioFormatUtil.getDefaultFormat()

      and pass an object of AudioFormat in place of "AudioFormatUtil.getDefaultFormat()" from the line below

      MicrophoneRecorder mr = new MicrophoneRecorder(AudioFormatUtil.getDefaultFormat());


      Please refer to this for detail about AudioFormat :
      http://docs.oracle.com/javase/1.4.2/docs/api/javax/sound/sampled/AudioFormat.html

      Delete
  3. hi,
    tell me please how do u know that line = (TargetDataLine) AudioSystem.getLine(info); points to the microphone? Why dont u use Port.Info.MICROPHONE explicitly ?

    ReplyDelete

Your Comment and Question will help to make this blog better...