暂停Java中的音频录制
我正在尝试用Java为我的音频录制模块实现暂停/恢复功能。到目前为止,我在So上所发现的是,它没有给出一个明确的答案-我尝试了回答者的建议,在暂停Java中的音频录制,java,audio,playback,recording,pause,Java,Audio,Playback,Recording,Pause,我正在尝试用Java为我的音频录制模块实现暂停/恢复功能。到目前为止,我在So上所发现的是,它没有给出一个明确的答案-我尝试了回答者的建议,在TargetDataLine上调用start()和stop(),以实现这一点,并且我知道stop()(来自Oracle): 停止该行。停止的行应停止I/O活动。但是,如果该行已打开并正在运行,它应保留恢复活动所需的资源。停止的行应保留其缓冲区中的所有音频数据,而不是丢弃这些数据,以便在恢复时,I/O可以在其停止的位置继续(如果可能的话) 然而,我发现,当我
TargetDataLine
上调用start()
和stop()
,以实现这一点,并且我知道stop()
(来自Oracle):
停止该行。停止的行应停止I/O活动。但是,如果该行已打开并正在运行,它应保留恢复活动所需的资源。停止的行应保留其缓冲区中的所有音频数据,而不是丢弃这些数据,以便在恢复时,I/O可以在其停止的位置继续(如果可能的话)
然而,我发现,当我在TargetDataLine
上调用stop,然后休眠五秒钟,然后调用start()
重新打开它时,录音就再也不会恢复了。代码如下:
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();
}
}
这段代码中值得关注的部分是main()
和startRecording()
、pauseRecording()
和resumererecording()
函数中的测试,尽管为了完整性,我已经完整地包含了这段代码
有人能告诉我为什么会这样吗?任何帮助都将不胜感激。我想API并没有提供任何直接的方法来做到这一点。尝试在现有文件的末尾追加。检查
AudioSystem
中的其他重载write()
方法。你需要重新运行你的记录线程
,在你的代码中,它只执行了一次。我自己也得出了这个结论。我认为写几个.wav文件并连接它们可能是一种方法。关于重新运行我的记录线程
,我为什么需要这样做?就我所知,由于pauseRecording()
,实际上并没有停止线程,而是停止了数据线-再说一次,我对线程处理不是很有经验,所以不确定退出条件是什么?您的recordThread
在AudioSystem.write()后立即完成
返回,无论您调用暂停录制()/resumereRecording()/stopRecording()
。我明白了。在这种情况下,我认为问题在于无论出于何种原因,停止数据线都会导致AudioSystem.write()
返回,从而终止recordThread
。你能想出解决这个问题的办法吗?如果我再次运行recordThread
它会继续写入同一个.wav文件吗?如果我再次运行recordThread它会继续写入同一个.wav文件吗?
在这种情况下,我想,它会删除旧文件并创建一个新文件。因此,我建议您在AudioSystem
中寻找其他重载方法。