Saturday, May 25, 2013

Sound recording


The SoundRecording program is able to record external sound and save the sound file in your current working folder. The main API used in the SoundRecoding program is JMF (Java Media Framework). You need to download and install JMF from www.sun.com.  After installing JMF in your computer system, in order  to record external sound and save it, you have to check whether your computer has proper audio capture card installed and you have a microphone.

Sound recording or audio recorder in Java

SoundRecording source code:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.Vector;
import javax.media.*;
import javax.media.control.TrackControl;
import javax.media.datasink.*;
import javax.media.format.*;
import javax.media.protocol.*;
import java.net.*;

class SoundRecording extends JFrame implements ActionListener{
  JButton btCap;
Recorder rd;
SoundRecording() throws AWTException{

btCap=new JButton("Start Recording");
btCap.addActionListener(this);
add(btCap,BorderLayout.CENTER);
setTitle("Audio Recorder");
setPreferredSize(new Dimension(300,80));
setResizable(false);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();

}

public void actionPerformed(ActionEvent e){
try{
if(btCap.getText().equals("Start Recording")){
setMess(btCap, "Stop Recording");
setState(ICONIFIED);
rd=new Recorder();
rd.start();
}
else if(btCap.getText().equals("Stop Recording")){
rd.stopCapture();
setMess(btCap, "Start Recording");
}

}catch(Exception ee){}
}


public void setMess(JButton btCap, String mess){
btCap.setText(mess);

}

class Recorder extends Thread{
StateHelper sh;
public void run(){
//declare processor p
Processor p=null;
//Find device that supports the specified audio format
CaptureDeviceManager cdm=new CaptureDeviceManager();
AudioFormat af=new AudioFormat("linear", 44100, 16, 2);
Vector cds=cdm.getDeviceList(af);
CaptureDeviceInfo cdi=null;
if(cds.size()>0){ //found the device
cdi=(CaptureDeviceInfo)cds.firstElement();
}
else //the device for the auto format is not found
System.exit(-1);
try {
p =Manager.createProcessor(cdi.getLocator()); //create process object for the device
sh =new StateHelper(p); //create state helper object
} catch (IOException e) {System.exit(-1);
} catch (NoProcessorException e) {System.exit(-1);}

// Configure the processor
if (!sh.configure(10000))
System.exit(-1);
// Set the output file content type
p.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.WAVE));
// Get the track control objects
TrackControl track[] = p.getTrackControls();
boolean ableToEncode= false;
//search for a possible format and set it to the audio track for encoding
for (int i = 0; i < track.length; i++) {
try {
track[i].setFormat(new AudioFormat(AudioFormat.IMA4_MS));
ableToEncode = true;
} catch (Exception e) {
// cannot convert to ima4
track[i].setEnabled(false);
}
}
if (!ableToEncode) {
sh.close();
System.exit(-1);
}
//realize the process
if (!sh.realize(10000))
System.exit(-1);
// get the output of the processor
DataSource source = p.getDataOutput();
//create MediaLocator object to point to the output file locaiton
String aFileName=System.currentTimeMillis()+".wav";
File fout=new File(aFileName);
MediaLocator oml=null;
try{
oml=new MediaLocator(fout.toURI().toURL());
}catch(MalformedURLException e){}
// create a datasink and open it so writing data is possible
DataSink filewriter = null;
try {
filewriter = Manager.createDataSink(source, oml);
filewriter.open();
} catch (NoDataSinkException e) {System.exit(-1);
} catch (IOException e) {System.exit(-1);
} catch (SecurityException e) {System.exit(-1);}
// now start the processor and filewriter
try {
p.start();
filewriter.start();
} catch (IOException e) {
System.exit(-1);
}
//wait for end of media stream
//in every 5 seconds there is a check to see whether the end of stream is met
sh.waitToEndOfMedia(5000);
sh.close();
filewriter.close();
}
public void stopCapture(){
sh.turnOffRecording(); //stop the recording
}

}

public class StateHelper implements ControllerListener {
Process p= null;
boolean configured = false;
boolean realized = false;
boolean prefetched = false;
boolean eom = false;
boolean failed = false;
boolean closed = false;
public StateHelper(Processor pr) {
p= pr;
p.addControllerListener(this); //register the processor with the ControllerListener
//so each state of the processor can be detemined with the ControllerUpdate method
}

public boolean configure(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
p.configure();
while (!configured && !failed) { //wait for the finish of the processor configuration
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {}
if (System.currentTimeMillis() - startTime > timeOutMillis) //no wait any more
break;
}

}
return configured;
}
public boolean realize(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
p.realize(); //realize the processor
while (!realized && !failed) { //wait for the finish of processor realization
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {}
if (System.currentTimeMillis() - startTime > timeOutMillis) //no wait any more
break;
}
}
return realized;
}

public boolean prefetch(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
p.prefetch(); // prefetch the processor
while (!prefetched && !failed) { //wait for the finish of processor prefetch
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}
if (System.currentTimeMillis() - startTime > timeOutMillis) //no wait any more
break;
}
}
return prefetched && !failed;
}
public boolean waitToEndOfMedia(int timeOutMillis) {  //continue recording until end of media
long startTime = System.currentTimeMillis();
eom = false;
synchronized (this) {
while (!eom && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {
}

}
}
return eom && !failed;
}

public void turnOffRecording(){ //forcing end of media recording
eom=true;
}

public void close() { //close the processor and wait 100 millliseconds for the process to finish the close
synchronized (this) {
p.close();
while (!closed) {
try {
wait(100);
} catch (InterruptedException ie) {}
}
}
p.removeControllerListener(this);
}

public synchronized void controllerUpdate(ControllerEvent ce) { //handle update events of the processor
if (ce instanceof RealizeCompleteEvent) {
realized = true;
} else if (ce instanceof ConfigureCompleteEvent) {
configured = true;
} else if (ce instanceof PrefetchCompleteEvent) {
prefetched = true;
} else if (ce instanceof EndOfMediaEvent) {
eom = true;
} else if (ce instanceof ControllerErrorEvent) {
failed = true;
} else if (ce instanceof ControllerClosedEvent) {
closed = true;
} else {
return;
}
notifyAll();
}

}

public static void main(String args[])  throws Exception{
   
new SoundRecording();
 
}


}

From the code above, before the audio capturing process can be performed, it is important to find a device that supports a specified audio format. To create an audio format object, you will use the AudioFormat class. The constructor of the AudioFormat class accepts three values: encoding, sample rate, and the number of bits per sample. You can get a list of supported devices by using the getDeviceList method of the CaptureDeviceManager class. This method accepts the specified audio format object as its argument. Once the audio capturing device is available, you can create a processor object to process data from this device by using the createProcessor method of  the Manager class. Before you can use the process object to set the content type of the audio output file or specify the track format of the audio output file, you have to ensure that the process is configured properly. Thank to the StateHelper class that helps us to configure and realize the processor. After the processor is configured successfully, it must be realized so that you can get the output audio data from it. The output audio data is stored in a DataSource object. To write the data to the output file, you need to create a DataSink object. When creating a DataSink to act as a file writer, you need to provide two values to its constructor: DataSource object and the MediaLocator object that points to output file path. After opening the file writer, call its start method to start the data writing process. You will wait a few seconds or minutes to complete this process.

No comments:

Post a Comment