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);
}
}
Michael Amling - 14 Jul 2004 03:50 GMT
> byte[] b = new byte[1000];
> while (true) {
> int ok = m_line.read(b, 0, 1000);
The variable "ok" has a useful value, but you ignore it. If ok<=0,
doesn't that mean end-of-file? Any time ok<1000, you may print up to a
thousand spurious zeros.
> out("read a window");
> //this window would now be passed to Matlab/Octave for analysis.
[quoted text clipped - 3 lines]
> }
> }
At minimum, you should change this to
...
int ok=m_line.read(b, 0, 1000);
if (ok>0) {
out("read a window");
for (int i=0; i<ok; i++) {
System.out.println(b[i]);
}
} else {
// close, break, or something
}
...
--Mike Amling