Capturing audio from soundcard!
Can anybody help me? When i compile this code no problems appears, however when i execute the program this is shown to:
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
c:\Sun\SDK\jdk\bin>java JCapture
javax.media.NotConfiguredError: setContentDescriptor cannot be called before con
figured
at com.sun.media.ProcessEngine.setContentDescriptor(ProcessEngine.java:3
42)
at com.sun.media.MediaProcessor.setContentDescriptor(MediaProcessor.java
:123)
at JCapture.doIt(JCapture.java:69)
at JCapture.main(JCapture.java:27)
Exception in thread "main" javax.media.NotConfiguredError: setContentDescriptor
cannot be called before configured
at com.sun.media.ProcessEngine.setContentDescriptor(ProcessEngine.java:3
42)
at com.sun.media.MediaProcessor.setContentDescriptor(MediaProcessor.java
:123)
at JCapture.doIt(JCapture.java:69)
at JCapture.main(JCapture.java:27)
The code is this:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Vector;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.DataSink;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Processor;
import javax.media.datasink.DataSinkEvent;
import javax.media.datasink.DataSinkListener;
import javax.media.datasink.EndOfStreamEvent;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
public class JCapture
{
CaptureDeviceInfo captureDeviceInfo = null;
DataSink dataSink = null;
public static void main(String[] args)
{
JCapture jCapture = new JCapture();
jCapture.doIt();
System.exit(0);
}
private void doIt()
{
// retrieve list of available capture devices
Vector vector = CaptureDeviceManager.getDeviceList(null);
Iterator it = vector.iterator();
while(it.hasNext())
{
CaptureDeviceInfo deviceInfo = (CaptureDeviceInfo)it.next();
if("DirectSoundCapture".equals(deviceInfo.getName()))
{
captureDeviceInfo = deviceInfo;
break;
}
}
// exit if no capture devices found
if(captureDeviceInfo == null)
{
System.err.println("No capture devices found!");
System.exit(-1);
}
try
{
// get media locator from capture device
MediaLocator mediaLocator = captureDeviceInfo.getLocator();
// create processor
Processor p = Manager.createProcessor(mediaLocator);
// configure the processor
p.configure();
// set the content type
p.setContentDescriptor(new FileTypeDescriptor(FileTypeDescriptor.WAVE));
// realise the processor
p.realize();
// get the output of processor
DataSource dataSource = p.getDataOutput();
// create medialocator with output file
MediaLocator dest = new MediaLocator("file://c:\\myFile.wav");
// create datasink passing in output source and medialocator specifying our output file
dataSink = Manager.createDataSink(dataSource,dest);
// create dataSink listener
dataSink.addDataSinkListener
(
// anonymous inner class to handle DataSinkEvents
new DataSinkListener()
{
// if end of media, close data writer
public void dataSinkUpdate(DataSinkEvent dataEvent)
{
// if capturing stopped, close DataSink
if(dataEvent instanceof EndOfStreamEvent)
{
dataSink.close();
}
}
}
);
// open the datasink
dataSink.open();
// start the datasink
dataSink.start();
// start the processor
p.start();
getConsolePress();
// stop the processor
p.stop();
// close the processor
p.close();
}
catch(Exception e)
{
e.printStackTrace();
System.exit(-1);
}
System.out.println("Finished!!");
}
public void getConsolePress() throws Exception
{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader input = new BufferedReader(isr);
String line;
System.out.println("Press x to stop capturing...");
while (!(line = input.readLine()).equals("x"))
{
System.out.println("Press x to stop capturing...");
}
return;
}
}
# 2
I compiled and ran your code and saw
the error you described, but could not fix it ..
OTOH - here is some code I was mucking
about with recently (it was adapated from an
example I found on a forum, but I cannot recall
where), it seemed to work quite well, without
ever creating a processor.
Maybe that might help?
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
public class AudioRecorder extends JFrame{
boolean stopCapture = false;
ByteArrayOutputStream byteArrayOutputStream;
AudioFormat audioFormat;
TargetDataLine targetDataLine;
AudioInputStream audioInputStream;
SourceDataLine sourceDataLine;
File file;
// AudioFileFormat.Type fileType;
/** The recorder will request enough memory for this lengh
of time of audio recording.More might be possible.*/
static int minutes = 4;
/** channels - 1 for mono, 2 for stereo. */
static int channels = 2;
/** bytes - 1 means 8 bit, 2 means 16 bit, 3 means 24 bit. */
static int bytes = 2;
/** Samples per second, sample rate in Hertz. */
static int samplerate = 44100;
/** Default size of the audio array before expansion.
Guarantees there is 'minutes' of memory for recording
'bytes' of sound depth in 'channels' at 'samplerate'. */
static int size = samplerate*channels*bytes*60*minutes;
/** Make the temp buffer, for this fraction of a second. */
static int timeperiod = 20;
/** An arbitrary-size temporary holding
buffer
enough for 3 minutes of sampling in
stereo at 16 bit, 44100Hz */
//static byte tempBuffer[];
static byte tempBuffer[] = new byte[samplerate*channels*bytes/timeperiod];
public static void main(
String args[]){
if (args.length==0) {
new AudioRecorder(null);
} else {
new AudioRecorder(args[0]);
}
}//end main
public AudioRecorder(String outputFileName){//constructor
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
setLocation(100,50);
final JButton captureBtn =
new JButton("Capture");
final JButton stopBtn =
new JButton("Stop");
final JButton playBtn =
new JButton("Save");
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(false);
captureBtn.addActionListener(
new ActionListener(){
public void actionPerformed(
ActionEvent e){
captureBtn.setEnabled(false);
stopBtn.setEnabled(true);
playBtn.setEnabled(false);
captureAudio();
}
}
);
getContentPane().add(captureBtn);
stopBtn.addActionListener(
new ActionListener(){
public void actionPerformed(
ActionEvent e){
captureBtn.setEnabled(true);
stopBtn.setEnabled(false);
playBtn.setEnabled(true);
//Terminate the capturing of
// input data from the
// microphone.
stopCapture = true;
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(stopBtn);
playBtn.addActionListener(
new ActionListener(){
public void actionPerformed(
ActionEvent e){
//Play back all of the data
// that was saved during
// capture.
saveAudio();
}//end actionPerformed
}//end ActionListener
);//end addActionListener()
getContentPane().add(playBtn);
getContentPane().setLayout(new FlowLayout());
setTitle("IMAR");
setDefaultCloseOperation(
EXIT_ON_CLOSE);
setSize(250,70);
setVisible(true);
if ( outputFileName==null ) {
JFileChooser fc = new JFileChooser();
int returnVal = fc.showSaveDialog(null);
if(returnVal == JFileChooser.APPROVE_OPTION) {
outputFileName = fc.getSelectedFile().toString();
} else {
outputFileName = "default.wav";
}
}
file = new File(outputFileName);
FileOutputStream fout;
try {
fout=new FileOutputStream(file);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
}//end constructor
//This method captures audio input
// from a microphone and saves it in
// a ByteArrayOutputStream object.
private void captureAudio(){
try{
//Get everything set up for
// capture
audioFormat = getAudioFormat();
/*AudioFormat.Encoding[] encodings =
AudioSystem.getTargetEncodings(audioFormat);
for(int ii=0; ii<encodings.length; ii++) {
System.out.println( encodings[ii] );
}*/
DataLine.Info dataLineInfo =
new DataLine.Info(
TargetDataLine.class, audioFormat);
targetDataLine = (TargetDataLine)
AudioSystem.getLine(dataLineInfo);
targetDataLine.open(audioFormat);
targetDataLine.start();
System.out.println( "AR.cA: " + targetDataLine );
audioInputStream = new
AudioInputStream(targetDataLine);
//Create a thread to capture the
// microphone data and start it
// running.It will run until
// the Stop button is clicked.
CaptureThread ct = new CaptureThread();
Thread captureThread =
new Thread(ct);
captureThread.start();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}//end catch
}//end captureAudio method
//This method plays back the audio
// data that has been saved in the
// ByteArrayOutputStream
private void saveAudio() {
try{
//Get everything set up for
// playback.
//Get the previously-saved data
// into a byte array object.
byte audioData[] =
byteArrayOutputStream.
toByteArray();
//Get an input stream on the
// byte array containing the data
InputStream byteArrayInputStream
= new ByteArrayInputStream(audioData);
AudioFormat audioFormat =
getAudioFormat();
AudioInputStream audioInputStreamTemp =
new AudioInputStream(
byteArrayInputStream,
audioFormat,
audioData.length/audioFormat.
getFrameSize());
audioInputStream =
AudioSystem.getAudioInputStream(
AudioFormat.Encoding.PCM_SIGNED,
audioInputStreamTemp );
DataLine.Info dataLineInfo =
new DataLine.Info(
SourceDataLine.class,
audioFormat);
sourceDataLine = (SourceDataLine)
AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
//Create a thread to play back
// the data and start it
// running.It will run until
// all the data has been played
// back.
Thread saveThread =
new Thread(new SaveThread());
saveThread.start();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}//end catch
}//end playAudio
//This method creates and returns an
// AudioFormat object for a given set
// of format parameters.If these
// parameters don't work well for
// you, try some of the other
// allowable parameter values, which
// are shown in comments following
// the declarations.
private AudioFormat getAudioFormat(){
float sampleRate = 44100.0F;
//8000,11025,16000,22050,44100
int sampleSizeInBits = channels*8;
//8,16
//int channels = 2;
//1,2
boolean signed = true;
//true,false
boolean bigEndian = false;
//true,false
return new AudioFormat(
sampleRate,
sampleSizeInBits,
channels,
signed,
bigEndian);
}//end getAudioFormat
//===================================//
/** Inner class to capture data from
microphone */
class CaptureThread extends Thread{
public void run(){
byteArrayOutputStream =
new ByteArrayOutputStream(size);
stopCapture = false;
try{//Loop until stopCapture is set
// by another thread that
// services the Stop button.
while(!stopCapture){
//Read data from the internal
// buffer of the data line.
int cnt = targetDataLine.read(
tempBuffer,
0,
tempBuffer.length);
if(cnt > 0){
//Save data in output stream
// object.
byteArrayOutputStream.write(
tempBuffer, 0, cnt);
}//end if
}//end while
byteArrayOutputStream.close();
}catch (Exception e) {
e.printStackTrace();
System.exit(0);
}//end catch
}//end run
}//end inner class CaptureThread
/** Inner class to play back the data
that was saved. */
class SaveThread
extends Thread {
public void run(){
try{
if (AudioSystem.isFileTypeSupported(
AudioFileFormat.Type.WAVE,
audioInputStream)) {
AudioSystem.write(audioInputStream,
AudioFileFormat.Type.WAVE, file);
}
JOptionPane.showMessageDialog(null,"Clip Saved!");
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}//end catch
}//end run
}//end inner class PlayThread
//===================================//
}//end outer class AudioCapture.java
# 5
2 notes:
That code I posted, is not mine, and although I'd
made a few tweaks to it, I had not bothered yet to
look into it more closely. It worked 'as is' for me,
and I did not have the time at that instant to go
delving into it.
On the other hand, here is an application I wrote..
http://www.physci.org/sound/audiotrace.html#download
It does not store the sound, just draws a trace on-screen.
While coding it - one of the major problems on two
of the three test machines, was detecting any sound.
As far as I recall (I could hunt down the forum
dicsussion if you are that interested) one of the
testers had to go into the config. of their computer
and enable a 'loopback' for it to work.
There was no obvious way in Java (without
resorting to JNI) to change that setting.
The early* code for it is here..
http://www.physci.org/test/oscilloscope/AudioTrace.java
* (I've improved the GUI in the version for
the public, but the code in the linked version
includes the important parts of getting
the lines.)
In any case, I think you should run that code
and check all lines to see if 'the basic' Java
can detect sound coming through the
microphone on that machine.
To do that, either compile & run the code linked
earlier, or install the built version linked first, and
go to..
View (menu)
Options (Menu Item)
in the 'Audio Trace display options' dialog..
select the 'Display all lines' checkbox and
cilck the OK button
Make sound into the microphone and check
that you can see the trace in one or more of
the lines. (At the moment, my machine shows
two lines, and all sound comes through both
of them!)
Message was edited by:
AndrewThompson64