Radek
Radek

Reputation: 1413

java audio recording

I have a piece of software that records a 5 sec interval of sound and then it sends it for processing. It runs in a infinite loop and looks as follows:

while (true) {
    System.out.println("recording..");
    recorder.start();
    Thread.sleep(5000);
    recorder.stop();
    Thread.sleep(300);
    System.out.println("recording finished");

    data = toolkit.readInputStream(recorder.getInputStream());

    pkt = create(data);

    outport.send(pkt);
}

In the above code I had to add a line Thread.sleep(300); after the finish of recording because otherwise recorder.getInputStream() returns null. Why is it happening? Is there a way to change it so there won't bee a need for a delay?

The recorder code:

    public class SoundRecorder implements Runnable{


        final int bufSize = 16384;

        AudioInputStream audioInputStream;
        String errStr;
        double duration, seconds;
        File file;

     public void start() {
                errStr = null;
                thread = new Thread(this);
                thread.setName("Capture");
                thread.start();
            }

            public void stop() {
                thread = null;
            }

 private void shutDown(String message) {
            if ((errStr = message) != null && thread != null) {
                thread = null;
                System.err.println(errStr);

            }
        }


      public void run() {

                duration = 0;
                audioInputStream = null;


                // define the required attributes for our line,
                // and make sure a compatible line is supported.

                AudioFormat format = getFormat();
                DataLine.Info info = new DataLine.Info(TargetDataLine.class,
                        format);

                if (!AudioSystem.isLineSupported(info)) {
                    shutDown("Line matching " + info + " not supported.");
                    return;
                }

                // get and open the target data line for capture.

                try {
                    line = (TargetDataLine) AudioSystem.getLine(info);
                    line.open(format, line.getBufferSize());
                } catch (LineUnavailableException ex) {
                    shutDown("Unable to open the line: " + ex);
                    return;
                } catch (SecurityException ex) {
                    shutDown(ex.toString());

                    return;
                } catch (Exception ex) {
                    shutDown(ex.toString());
                    return;
                }

                // play back the captured audio data
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int frameSizeInBytes = format.getFrameSize();
                int bufferLengthInFrames = line.getBufferSize() / 8;
                int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
                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 (IOException ex) {
                    ex.printStackTrace();
                }

                // load bytes into the audio input stream for playback

                byte audioBytes[] = out.toByteArray();
                ByteArrayInputStream bais = new ByteArrayInputStream(audioBytes);
                audioInputStream = new AudioInputStream(bais, format, audioBytes.length / frameSizeInBytes);

                long milliseconds = (long) ((audioInputStream.getFrameLength() * 1000) / format.getFrameRate());
                duration = milliseconds / 1000.0;



                try {
                    audioInputStream.reset();
                } catch (Exception ex) {
                    ex.printStackTrace();
                    return;
                }


            }

    public AudioInputStream getInputStream() {
            return audioInputStream;
        }

    public AudioFormat getFormat() {

            AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
            float rate = 44100.0F;
            int sampleSize = 16;
            boolean bigEndian = true;
            int channels = 2;

            return new AudioFormat(encoding, rate, sampleSize,
                    channels, (sampleSize / 8) * channels, rate, bigEndian);

        }
    }

Upvotes: 1

Views: 1978

Answers (1)

user296828
user296828

Reputation:

You're telling your thread running in the background to stop, and the code, as it's written, has some clean up work to do on exit. Therefore you have to wait for the thread to finish before being able to use some of the functionality.

What you could do is change the stop function to something like:

public void stop() {
    Thread t = thread;
    thread = null;// this will cause your thread to exit
    t.join();//this will wait for the thread to exit before returning.
}

Upvotes: 2

Related Questions