Javasound recording not working in Eclipse

From: Charles Fox (charlesfox357_at_hotmail.com)
Date: 07/12/04


Date: 12 Jul 2004 02:12:18 -0700

I'm playing with the javasound SimpleAudioRecorder demo -- the code
below runs on windows from the command line jdk java command; but
running in Eclipse there is no audio input coming in - the line just
records a stream of zeros. Please help -- try compiling it yourself
and see if it works in Eclipse, it's only one file, you can just cut
and paste it.

import java.io.IOException;
import java.io.File;
import javax.sound.sampled.*;
public class SimpleAudioRecorder extends Thread {
        
        private TargetDataLine m_line;
        private AudioFileFormat.Type m_targetType; //data format of the
targetLine
        private AudioInputStream m_audioInputStream; //this stream will be
built on // the line
        private File m_outputFile;
        
        public static void main(String[] args) {
                /*if (args.length != 1 || args[0].equals("-h")) {
                        printUsageAndExit(); //ensure theres only one cmd line argument
                }
                String strFilename = args[0];
                File outputFile = new File(strFilename); */
                
                File outputFile = new File("test.wav");
                
                //NB frame size must be equal to: (n channels)*(bits per sample) /
                // (bits per byte = 8)
                //ie its the number of bytes to store one instant in time.
                AudioFormat audioFormat = new AudioFormat(
                                AudioFormat.Encoding.PCM_SIGNED, //format
                                8000.0F, //sample rate (44100.0F) [8000.0F]
                                8, //bits per sample (16) [8]
                                1, //n channels (2) [1]
                                1, //frame size (4) [1]
                                8000.0F, //frame rate (44100.0F) [8000.0F]
                                false); //big endian (false) [false]
                DataLine.Info info = new DataLine.Info(TargetDataLine.class,
                                audioFormat); //make info obj from desired format
                TargetDataLine targetDataLine = null; //we will make line from info,
by
                                                                                          // requesting from audiosystem.
                try {
                        targetDataLine = (TargetDataLine) AudioSystem.getLine(info); //find
                                                                                                                                                 // a
                                                                                                                                                 // suitable
                                                                                                                                                 // targetLine
                        targetDataLine.open(audioFormat); //open the line!
                } catch (Exception e) {
                        out("unable to get a recording line");
                        e.printStackTrace();
                        System.exit(1);
                }
                AudioFileFormat.Type targetType = AudioFileFormat.Type.WAVE;
                //make an instance of this class -- controls startng, stopping etc
                SimpleAudioRecorder recorder = new
SimpleAudioRecorder(targetDataLine,

                                targetType, outputFile);
                out("Press ENTER to start the recording.");
                try {
                        System.in.read(); //WAIT HERE
                } catch (IOException e) {
                        e.printStackTrace();
                }
                recorder.start(); //STARTS THE RECORDER THREAD
                out("Recording...");
                out("Press ENTER to stop the recording.");
                try {
                        System.in.read(); //WAIT HERE
                } catch (IOException e) {
                        e.printStackTrace();
                }
                recorder.stopRecording(); //STOPS RECORDER THREAD
                out("Recording stopped.");
        }
        //CONSTRUCTOR -- just sets members to its args
        public SimpleAudioRecorder(TargetDataLine line,
                        AudioFileFormat.Type targetType, File file) {
                m_line = line;
                //m_audioInputStream = new AudioInputStream(line); //make an
                // inputStream from the line (why?)
                m_targetType = targetType;
                m_outputFile = file;
        }
        public void start() {
                m_line.start(); // Starting the TargetDataLine. It now begins
bufferin
                                                // audio input.
                super.start(); // Starts this thread object -- ie calls run(). This
will
                                           // process the data on the line.
        }
        /**
         * Main working method. --- Once the thread is started, run is
called. You
         * may be surprised that here, just 'AudioSystem.write()' is called.
But
         * internally, it works like this: AudioSystem.write() contains a
loop that
         * is trying to read from the passed AudioInputStream. Since we have
a
         * special AudioInputStream that gets its data from a TargetDataLine,
         * reading from the AudioInputStream leads to reading from the
         * TargetDataLine. The data read this way is then written to the
passed
         * File. Before writing of audio data starts, a header is written
according
         * to the desired audio file type. Reading continues untill no more
data can
         * be read from the AudioInputStream. In our case, this happens if no
more
         * data can be read from the TargetDataLine. This, in turn, happens
if the
         * TargetDataLine is stopped or closed (which implies stopping).
(Also see
         * the comment above.) Then, the file is closed and
'AudioSystem.write()'
         * returns.
         */
        public void run() {
                //try {
                //AudioSystem can deal with file formats. Write the data in the
                // inputStream, of given format, into the outputFile.
                //loops forever; blocks when no data; terminates when line is
closed.
                // (EOF written to the stream?)
                //AudioSystem.write(m_audioInputStream, m_targetType, m_outputFile);
                byte[] b = new byte[1000];
                while (true) {
                        int ok = m_line.read(b, 0, 1000);
                        out("read a window");
                        //this window would now be passed to Matlab/Octave for analysis.
                        // Just print it for now.
                        for (int i = 0; i < 1000; i++) {
                                System.out.println(b[i]);
                        }
                        //NB we probalby do want to do some flushing if the buffer is
                        // getting overfull - we want timely information.
                }
                //} catch (IOException e) {
                //e.printStackTrace();
                //}
        }
        /**
         * Stops the recording. Note that stopping the thread explicitely is
not
         * necessary. Once no more data can be read from the TargetDataLine,
no more
         * data be read from our AudioInputStream. And if there is no more
data from
         * the AudioInputStream, the method 'AudioSystem.write()' (called in
'run()'
         * returns. Returning from 'AudioSystem.write()' is followed by
returning
         * from 'run()', and thus, the thread is terminated automatically.
It's not
         * a good idea to call this method just 'stop()' because stop() is a
         * (deprecated) method of the class 'Thread'. And we don't want to
override
         * this method.
         */
        public void stopRecording() {
                m_line.stop();
                m_line.close();
        }
        //some little utility methods
        private static void printUsageAndExit() {
                out("SimpleAudioRecorder: usage:");
                out("\tjava SimpleAudioRecorder -h");
                out("\tjava SimpleAudioRecorder <audiofile>");
                System.exit(0);
        }
        private static void out(String strMessage) {
                System.out.println(strMessage);
        }
}