暂停Java中的音频录制

暂停Java中的音频录制,java,audio,playback,recording,pause,Java,Audio,Playback,Recording,Pause,我正在尝试用Java为我的音频录制模块实现暂停/恢复功能。到目前为止,我在So上所发现的是,它没有给出一个明确的答案-我尝试了回答者的建议,在TargetDataLine上调用start()和stop(),以实现这一点,并且我知道stop()(来自Oracle): 停止该行。停止的行应停止I/O活动。但是,如果该行已打开并正在运行,它应保留恢复活动所需的资源。停止的行应保留其缓冲区中的所有音频数据,而不是丢弃这些数据,以便在恢复时,I/O可以在其停止的位置继续(如果可能的话) 然而,我发现,当我

我正在尝试用Java为我的音频录制模块实现暂停/恢复功能。到目前为止,我在So上所发现的是,它没有给出一个明确的答案-我尝试了回答者的建议,在
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
中寻找其他重载方法。