快速音频输入/输出

时间:2009-05-11 03:15:09

标签: audio javasound low-latency

这就是我想要做的事情:

我想让用户给我的程序一些声音数据(通过麦克风输入),然后保持250ms,然后通过扬声器将其输出。

我已经使用Java Sound API完成了这项工作。问题是它有点慢。从发出声音到再次从扬声器听到声音的时间至少需要1-2秒,我甚至还没有尝试实现延迟逻辑。理论上应该没有延迟,但有。我知道你必须等待声卡填满其缓冲区或其他任何东西,样本大小和采样率与此有关。

我的问题是:我应该继续沿着Java路径尝试这样做吗?如果可能的话,我希望将延迟降低到100毫秒。有没有人有使用Java的ASIO驱动程序的经验?据说它更快......

另外,我是一个.NET家伙。这对.NET来说有意义吗?那么C ++呢?我正在寻找在这里使用的正确技术,也许是如何使用您建议的技术平台读/写音频输入/输出流的一个很好的例子。谢谢你的帮助!

5 个答案:

答案 0 :(得分:3)

我过去曾使用过JavaSound,发现它非常不稳定(并且它在VM发布之间不断变化)。如果您喜欢C#,请使用它,只需使用DirectX API即可。这是一个使用DirectSound和C#做你想做的事情的例子。您可以使用效果插件执行250毫秒回声。

http://blogs.microsoft.co.il/blogs/tamir/archive/2008/12/25/capturing-and-streaming-sound-by-using-directsound-with-c.aspx

答案 1 :(得分:3)

您可能需要查看专为低延迟声音处理而设计的音频API JACK。此外,谷歌提出了关于将JACK与Java一起使用的nifty presentation [PDF]。

  

理论上应该没有延迟,但有。

嗯,零延迟是不可能的。你可以期待的最好的是一个不明显的延迟(就人类的感知而言)。如果您描述阅读和阅读的基本算法,它可能会有所帮助。写出声音数据,这样人们就可以发现可能的问题。

使用像Java这样的垃圾收集语言的一个潜在问题是GC会定期运行,在一段任意时间内中断处理。但是,如果在正常使用情况下> 100毫秒,我会感到惊讶。如果GC出现问题,大多数JVM都会提供您可以尝试的备用收集算法。

答案 2 :(得分:3)

如果您选择沿着C / C ++路径前进,我强烈建议您使用PortAudio(http://portaudio.com/)。它适用于多个平台上的几乎所有内容,它可以让您对声音驱动程序进行低级控制,而无需实际处理周围的各种声音驱动程序技术。

我在多个项目中使用过PortAudio,使用起来非常愉快。许可证是宽容的。

答案 3 :(得分:1)

如果低延迟是您的目标,那么您就无法击败C.

libsoundio是一个用于实时音频输入和输出的低级C库。它甚至带有一个example program,可以完全按照您的要求进行操作 - 将麦克风输入连接到扬声器输出。

答案 4 :(得分:0)

使用 JavaSound 可以实现100-150毫秒的端到端延迟。<​​/ p>

  1. 延迟的主要原因是捕获和回放行的缓冲区大小。打开行时设置大小:

    • 捕获:TargetDataLine#open(AudioFormat format, int bufferSize)
    • 播放:SourceDataLine#open(AudioFormat format, int bufferSize)
  2. 如果缓冲区太大会导致延迟时间过长,但如果缓冲区太小则会导致恶意播放。因此,您需要为应用程序需求和计算能力找到平衡点。

    调用DataLine#getBufferSize时,可以使用#open(AudioFormat format)检查默认缓冲区大小。默认大小将根据AudioFormat而变化,并且似乎适用于高延迟,无间断的播放应用(例如互联网流媒体)。如果您正在开发低延迟应用程序,则默认缓冲区大小太大而且应该更改。

    在我使用16位PCM AudioFormat的测试中,1024字节的缓冲区大小非常接近低延迟的理想状态。

    1. 音频延迟的第二个且经常被忽视的原因是在捕获或回放线程中完成的任何其他活动。例如,将消息记录到控制台可能会引入10毫秒的延迟。把它关掉。