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;
}
thanks for this..
ReplyDeleteHave no idea how much this helped me - it's tricky to find an example for this sort of thing!
ReplyDeletehi am using above provided code but am getting the fallowing exception
ReplyDeletejava.lang.Error: Unresolved compilation problem:
The method getDefaultFormat() is undefined for the type AudioFormatUtil
you need to remove
DeleteAudioFormatUtil.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
hi,
ReplyDeletetell me please how do u know that line = (TargetDataLine) AudioSystem.getLine(info); points to the microphone? Why dont u use Port.Info.MICROPHONE explicitly ?
Port.Info shows only info about port. You can't record on this port :).
ReplyDeleteWhich library contains WaveData class ?
ReplyDeleteyou can create your own WaveData class and put the method "saveToFile" there
Deletehow can I learn all this stuff ,i know core java..??
ReplyDeleteHi 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!
ReplyDeleteHI, 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
ReplyDeleteMicrophoneRecorder mr = new MicrophoneRecorder( YOU NEED TO PASS OBJECT OF AudioFormat here);
ReplyDeleteI am getting error in the above line.I am not getting what object I need to pass.