How to use middle of AudioInputStream to record to file for x seconds, and continue stream?

I have a Java desktop program (Sphinx4) that continuously listens on a microphone for a keyword. I then want it to record to a file (WAVE, bigEndian) with the audio following the keyword and send it off to an external web api for processing. The good news is that I have the keyword working properly and I created a method that starts recording to a file at the time I need it too, but I am unable to stop the output when it’s in the middle of its audio inputstream without cutting off the entire stream.

I can output the file successfully using:

AudioSystem.write(inputStream, AudioFileFormat.Type.WAVE, new File(“test3.wav”));

However that is thread blocking and would continue forever (seeing as this is continuous listening). After looking at this for hours, I was hoping someone would have a simple solution that hopefully I’d missed.

At first, I thought all I needed to do was treat it like a normal inputstream, but without setting meta information the file is unplayable:

        byte[] buffer = new byte[1024];
        FileOutputStream out = new FileOutputStream("test.wav");
        while ((read = inputStream.read(buffer)) != -1) {
            out.write(buffer, 0, read);             
        }
        out.close();

Basically, my plan was to add a boolean variable in the while loop to detect when to stop and then close it out, and while it did create a file, it was unplayable.

The audio stream is initiated with the following:

    AudioFormat format =
        new AudioFormat(sampleRate, sampleSize, 1, signed, bigEndian);
    try {
        line = AudioSystem.getTargetDataLine(format);
        line.open();
    } catch (LineUnavailableException e) {
        throw new IllegalStateException(e);
    }
    inputStream = new AudioInputStream(line);

So what can I do to get an audio file in the middle of the stream and record for “x” seconds?

2
Leave a Reply

avatar
2 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Jason Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jason
Guest

After trying various methods, I finally found the solution. My goal was to record an audio file from the AudioInputStream, yet calling “close()” on it basically broke the entire application because various other classes needed the inputstream as well. Closing and starting a new stream just wasn’t practical in my use case. I decided to look into cloning an inputstream and it was exactly what I needed. In summary, all that was really needed was to create a ByteArrayOutputStream from the AudioInputStream then write out the bytes for as long as necessary. Once done, close out the ByteArrayOutputStream and do… Read more »

Jason
Guest

Call this new Timer().schedule(new TimerTask() { @Override public void run() { inputStream.close(); this.cancel(); } }, TIME_TO_RECORD,20000); before calling AudioSystem.write(inputStream, AudioFileFormat.Type.WAVE, new File("test3.wav")); This basically closes the input stream after a period of time. You might need to adjust the delay time based on the need.