使用java中的线程同时录制来自两个不同麦克风的音频

时间:2014-08-21 11:52:35

标签: java multithreading audio

我想构建一个同时记录来自两个USB麦克风声音的应用程序,并将每个录音存储在不同的文件中。到目前为止,我已经设法构建应用程序,只适合一个麦克风,它工作正常。其结构如下:

  • 阅读配置文件

  • 找到所有支持录制的混音器

  • 根据配置文件

  • 选择所需的混音器
  • 将所需混音器的音频录制到字节数组

  • 将字节数组写入文件

应用程序中出现的前3个步骤是否需要一个或两个麦克风,但我想同时开始录制两个麦克风,并开始在一个单独的线程上写入每个字节数组,因为它有点时间消费和干扰音频录制过程,这是一个循环内部。这是我到目前为止所尝试的:

    recorder.readConfig(configFile);
    recorder.showAvailableMixers();
    recorder.selectMixer();
    while (true) {
        final byte[] audioBytes = recorder.recordAudio(recorder.firstMixer);
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    final byte[] audioBytes2 = recorder.recordAudio(recorder.secondMixer);
                    recorder.writeToDisk(audioBytes2);
                } catch (InterruptedException | LineUnavailableException | IOException ex) {
                    Logger.getLogger(ContinuousAudioRecording.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }.start();
        recorder.writeToDisk(audioBytes);
    }

这是一个有点简化的版本,因为它不使用另一个线程写入磁盘。我介绍了1s睡眠,因为我写的文件的名称严格依赖于当前时间,所以我想避免覆盖。我在这里写的程序介绍了两个录音之间的主要延迟,我期待它们录制几乎相同的声音(差异为1秒)。

你能告诉我我做错了什么或者我该如何解决这个问题?我是新手使用线程,我花了一整天时间寻找教程和示例,但我还没有找到一个解决我的程序的复杂性。谢谢!

编辑25.08:我已经设法通过创建另一个记录器对象来解决问题,并在另一个线程上再次执行相同的操作。它不漂亮,绝对不是最佳的,但它是一种解决方法。我还改变了写入磁盘的方法,现在它也依赖于用于录制的麦克风。如果您希望改进它或使用类似的东西,您可以在下面找到我的新代码。希望它能帮助将来的某个人。

    final ContinuousAudioRecording recorder = new ContinuousAudioRecording();
    recorder.setConfigPath(ContinuousAudioRecording.class.getResource("config.prop").toString().replace("file:", ""));
    recorder.readConfig(new File(recorder.getConfigPath()));
    recorder.showAvailableMixers();
    recorder.selectMixer();
    final ContinuousAudioRecording recorder2 = new ContinuousAudioRecording();
    recorder2.setConfigPath(ContinuousAudioRecording.class.getResource("config.prop").toString().replace("file:", ""));
    recorder2.readConfig(new File(recorder.getConfigPath()));
    recorder2.showAvailableMixers();
    recorder2.selectMixer();
    while (true) {
        new Thread(){
            @Override
            public void run(){
                try {
                    final byte[] _audioBytes = recorder.recordAudio(recorder.firstMixer);
                    new Thread(){
                        @Override
                        public void run(){
                            try {
                                recorder.writeToDisk(_audioBytes,recorder.firstMixer.getMixerInfo().getName().replace(" ", ""));
                            } catch (IOException ex) {
                                Logger.getLogger(ContinuousAudioRecording.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }.start();
                } catch (LineUnavailableException | IOException ex) {
                    Logger.getLogger(ContinuousAudioRecording.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                try {
                    final byte[] _audioBytes2 = recorder2.recordAudio(recorder.secondMixer);
                    new Thread(){
                        @Override
                        public void run(){
                            try {
                                recorder2.writeToDisk(_audioBytes2,recorder2.secondMixer.getMixerInfo().getName().replace(" ", ""));
                            } catch (IOException ex) {
                                Logger.getLogger(ContinuousAudioRecording.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }.start();
                } catch (LineUnavailableException | IOException ex) {
                    Logger.getLogger(ContinuousAudioRecording.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }.start();
        Thread.sleep((recorder.recordingLength+1)*1000);
    }
} 

我已添加最后一次睡眠,以便新录制将在上一次录制结束后开始。我还在录音之间又给了它一秒钟,因为它需要一段时间才能执行所有这些指令(不是一整秒,而只是为了确保)。否则,它会尝试打开之前未关闭的TargetDataLine,并导致异常。

0 个答案:

没有答案