【问题标题】:Java Sound API: Attempt to Do Live Microphone Input Monitoring is SlowJava Sound API:尝试进行实时麦克风输入监控很慢
【发布时间】:2016-12-13 02:12:01
【问题描述】:

我认为我的 Java Sound API 存在性能(延迟)问题。

音频监视器

以下代码确实对我有用。它正确打开了麦克风,并通过我的扬声器实时输出音频输入(即监控)。但我担心的是播放的速度……从我对着麦克风说话到通过扬声器播放的时间晚了半秒。

如何提高性能?如何降低延迟?

private void initForLiveMonitor() {

    AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);

    try {

        //Speaker
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
        SourceDataLine sourceLine = (SourceDataLine) AudioSystem.getLine(info);
        sourceLine.open();

        //Microphone
        info = new DataLine.Info(TargetDataLine.class, format);
        TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
        targetLine.open();

        Thread monitorThread = new Thread() {
            @Override
            public void run() {
                targetLine.start();
                sourceLine.start();

                byte[] data = new byte[targetLine.getBufferSize() / 5];
                int readBytes;

                while (true) {
                    readBytes = targetLine.read(data, 0, data.length);
                    sourceLine.write(data, 0, readBytes);
                }
            }
        };

        System.out.println( "Start LIVE Monitor for 15 seconds" );
        monitorThread.start();

        Thread.sleep(15000);
        targetLine.stop();
        targetLine.close();
        System.out.println( "End LIVE Monitor" );

    }
    catch(LineUnavailableException lue) { lue.printStackTrace(); }
    catch(InterruptedException ie) { ie.printStackTrace(); }


}

附加说明

  • 使用此代码,播放流畅(无爆音或抖动),仅延迟半秒。
  • 我也知道我的电脑和 USB 音频接口能够通过电脑处理实时监控,因为当我与 Logic Pro X 进行并排比较时,延迟最小——我认为没有延迟完全没有。
  • 我尝试减小/增大 byte[] 大小并没有解决问题。

我的结论是,这是我遇到的 Java 代码问题。提前致谢。

【问题讨论】:

  • 这似乎归结为targetLine.getBufferSize() 的大小。那是多少字节?
  • @AndrewThompson targetLine.getBufferSize() 方法返回 88200 字节。我已经使用了byte[] 的除数,几乎没有什么变化。当我将 byte[] 显式降低到 4 个字节时,它确实有所帮助,但我仍然感觉到四分之一秒的延迟(超过半秒的延迟)。
  • 您设置的 byte[] 大小与 DataLine 中的缓冲区无关。您需要在 open() 方法中包含大小来设置 DataLine 缓冲区大小,例如.open(大小)。每帧 4 字节的 88200 字节和每秒 44100 帧占半秒延迟。缩短太多可能会导致丢失,但我很确定您可以设置具有更少延迟的安全值。请参阅下面的答案。
  • 使用 JackAudio 或 ALSA API 进行实时采集和回放。

标签: java audio real-time javasound low-latency


【解决方案1】:

涉及的缓冲区不止一个!

当您打开 SourceDataLine 和 TargetDataLine 时,我建议您使用指定缓冲区大小的表单。但是不知道推荐什么尺码。我还没有玩够这个,不知道安全管道麦克风输入的最佳尺寸是多少——我的经验更多的是实时合成。

无论如何,如何:定义 data[] 的长度并在您的行打开方法中使用相同的长度。尝试像 1024 或倍数这样的数字(同时确保字节数可以除以每帧字节数,根据您使用的格式,每帧字节数看起来是 4)。

int bufferLen = 1024 * 4;  // experiment with buffer size here

byte[] data = new byte[bufferLen];
sourceLine.open(bufferLen);
targetLine.open(bufferLen); 

另外,也许你的 run() 中的代码最好放在其他地方,以免在管道启动之前添加到所需的处理中。数组 data[] 和 int readBytes 可以是实例变量并准备好滚动,而不是在 run() 中使用,这可能会增加延迟。

无论如何,这些都是我会尝试的。

【讨论】:

  • “数组 data[] 和 int readBytes 可以是实例变量,可以随时滚动,而不是在 run() 中进行处理,这可能会增加延迟。”这些是大土豆中的小薯条;如果他说他尝试了不同的缓冲区大小,那么就是这样! - “涉及不止一个缓冲区!”:在哪里??我想知道具体在哪里?这会影响他的表现
  • API 明确谈到为 DataLines 设置缓冲区大小。 docs.oracle.com/javase/8/docs/api/javax/sound/sampled/… TargetDataLine 也有一个。
  • 谢谢菲尔。是的,延迟确实随着为两个 open() 方法设置 bufferSize 而下降。我估计现在延迟已经改善到十分之一秒(最好是四分之一秒)。并且尝试使用缓冲区大小 1024 * 2 不会导致失真问题。去任何低于会导致声音问题的地方。
  • 很高兴这对您有所帮助。顺便说一句,我不排除为不同的行设置不同的缓冲区大小可能会带来更多改进的可能性。可能值得设置边缘情况并测试不同缓冲区的独立大小设置。正如我所说,我自己没有这样做。不同的生产线/阶段可能有不同的公差。
猜你喜欢
  • 2011-04-11
  • 1970-01-01
  • 2023-01-31
  • 1970-01-01
  • 2015-01-27
  • 1970-01-01
  • 1970-01-01
  • 2020-03-09
  • 2021-07-01
相关资源
最近更新 更多