I am trying to implement a pause/resume functionality for my audio recording module in Java. So far all I have found on SO is this, which does not give a definitive answer - I have tried the answerer's suggestion of calling start()
and stop()
on the TargetDataLine
to achieve this, and am aware that stop()
(from Oracle):
"Stops the line. A stopped line should cease I/O activity. If the line is open and running, however, it should retain the resources required to resume activity. A stopped line should retain any audio data in its buffer instead of discarding it, so that upon resumption the I/O can continue where it left off, if possible."
However I am finding that when I call stop on my TargetDataLine
, then sleep for five seconds and call start()
to reopen it, the recording never resumes. Here is the code:
import java.io.*;
import java.util.Timer;
import java.util.TimerTask;
import javax.sound.sampled.*;
import javax.sound.sampled.AudioFileFormat.Type;
public class AudioRecorder
{
static TargetDataLine targetLine = null;
static final long maxRecordingTime = 3600000; // One hour in milliseconds
static Thread recordThread;
public static void main(String[] args)
{
try
{
// Initialise audio format settings and setup data line matching format specification
initialiseAudioSettings();
}
catch (LineUnavailableException e)
{
e.printStackTrace();
}
// TEST
startRecording();
try
{
System.out.println("Sleeping for 5s...");
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("About to pause recording...");
pauseRecording();
try
{
System.out.println("Sleeping for 5s...");
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("About to resume recording...");
resumeRecording();
try
{
System.out.println("Sleeping for 5s...");
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("About to stop recording...");
stopRecording();
System.out.println("Recording stopped...(in theory)");
// /TEST
}
private static void initialiseAudioSettings() throws LineUnavailableException
{
// Define audio format as:
// Encoding: Linear PCM
// Sample Rate: 44.1 kHz
// Bit Depth: 16-bit
// Channel Format: Stereo
// Data Storage: Signed & Big-Endian
final AudioFormat audioFormat = new AudioFormat(44100, 16, 2, true, true);
// Store format metadata in an Info variable
final DataLine.Info audioFormatInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
if (!AudioSystem.isLineSupported(Port.Info.MICROPHONE))
{
throw new LineUnavailableException("No microphone has been detected. Please reconnect the microphone and try again.");
} else
{
System.out.println("Microphone detected. Querying target data line...");
}
// Use metadata to ascertain whether audio format is supported by default input device
if (AudioSystem.isLineSupported(audioFormatInfo) == false)
{
throw new LineUnavailableException("The default input device does not support the specified audio output format");
}
// Get a line matching the specified audio format
targetLine = (TargetDataLine)AudioSystem.getLine(audioFormatInfo);
// Instruct the system to allocate resources to the targetLine and switch it on
targetLine.open();
// Prepare line for audio input
targetLine.start();
}
private static void startRecording()
{
TimerTask scheduleRecordingEnd = new TimerTask()
{
public void run()
{
stopRecording();
}
};
Timer recordingTimer = new Timer("Recording Timer");
recordingTimer.schedule(scheduleRecordingEnd, maxRecordingTime);
// Setup recording thread
recordThread = new Thread(new Runnable()
{
@Override
public void run()
{
{
// Route audio input stream to target data line
AudioInputStream audioInputStream = new AudioInputStream(targetLine);
// Instantiate output filepath & filename
File outputFile = new File("C:/temp/test.wav");
// Write input audio to output .wav file
try
{
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, outputFile);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
});
// Start recording
recordThread.start();
}
private static void pauseRecording()
{
targetLine.stop();
}
private static void resumeRecording()
{
targetLine.start();
}
private static void stopRecording()
{
// Cease all I/O functions of the line
targetLine.stop();
// Close the line, deallocating system resources and deleting metadata
targetLine.close();
System.out.println("Stopping recording...");
recordThread.stop();
}
}
The parts of this code that should be of interest are the tests in main()
and the startRecording()
, pauseRecording()
and resumeRecording()
functions, although I have included the code in its entirety for completeness.
Could anyone point me in the right direction as to why this might be happening? Any help would be much appreciated.