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;  
   }  

12 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
  4. Port.Info shows only info about port. You can't record on this port :).

    ReplyDelete
  5. Which library contains WaveData class ?

    ReplyDelete
    Replies
    1. you can create your own WaveData class and put the method "saveToFile" there

      Delete
  6. how can I learn all this stuff ,i know core java..??

    ReplyDelete
  7. Hi guys, can you tell me something about quality of your recordings using this code? I wonder that low quality of my recordings cause bad sound card but i want to check your opinions. Thanks a lot!

    ReplyDelete
  8. HI, If i want to record audio and video together at same time how can i achieve it. If i use javacv ffmpegframerecorder it will record to another file and with above code i will save audio to another file then i need to merge it. Is there any option available to record and save video with audio in single step.not recording both in separate files. Thanks for your answer

    ReplyDelete
  9. MicrophoneRecorder mr = new MicrophoneRecorder( YOU NEED TO PASS OBJECT OF AudioFormat here);
    I am getting error in the above line.I am not getting what object I need to pass.

    ReplyDelete

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