Java用于音频处理,是否实用?

21

Java是否是实时音频处理的C / C++替代方案?

我正在考虑一个应用程序,其中包含约100个音轨(最多),每个音轨上都同时发生延迟线(30s @ 48khz)、滤波(512点FIR?)和其他DSP类型的操作。

这些操作将被转换并以浮点数执行。

系统可能是一台四核3GHz、4GB RAM运行Ubuntu的计算机。

我看过有关Java速度比过去快得多,接近C / C++的文章,并且现在也有实时扩展。这是现实吗?它需要硬核编码和调优才能实现C某些人所规定的50%-100%的性能吗?

我真的很想知道这是否可能,还有任何注意事项。


Java 用于实时音频最终变得实用了吗? - mattbh
1
我没有进一步追求它。选择了C++,因为这是更安全的路线。 - JeffV
9个回答

21

对于音频应用程序,你通常只有非常小的代码部分需要花费大量时间。

在Java中,您可以始终使用JNI(Java Native Interface),并将计算密集型代码移动到C模块中(或者使用SSE汇编语言,如果您真的需要更高的性能)。因此,我建议使用Java并让您的代码正常运行。如果最终您发现无法满足性能目标,则可以使用JNI。

90%的代码很可能是粘合代码和应用程序内容。但请记住,这样会失去一些跨平台功能。如果您可以接受,JNI将始终为您提供原生代码性能的机会。


11

Java在许多音频应用中表现良好。与其他一些帖子的观点相反,我发现使用Java音频非常愉快。将可用的API和资源与可怕、几乎没有文档的CoreAudio相比较,你会成为信徒。Java音频存在一些延迟问题,但对于许多应用程序来说这是无关紧要的,并且缺少编解码器。还有很多人从未花时间编写良好的音频播放引擎(提示:永远不要关闭SourceDataLine,而是向其写入零),随后将问题归咎于Java。从API的角度来看,Java音频非常简单直接,易于使用,并且在jsresources.org上有大量指导。


1
jsresources.org是一个非常好的资源网站,有很多代码示例。不错的发现。 - ug_

5
我认为延迟将是您面临的主要问题 - 在现代操作系统中,即使在C/C++中,维护延迟也非常困难,而Java肯定会加重这个问题(垃圾收集器)。 “实时”音频处理的一般设计是让您的处理线程在实时调度(Linux内核上的SCHED_FIFO,在其他操作系统上具有相当作用)下运行,并且这些线程不应该阻塞。这意味着没有系统调用,没有malloc,当然也没有IO等...甚至分页也是一个问题(从磁盘获取页面到内存可能需要几毫秒),因此您应该锁定某些页面以确保它们永远不会被交换出去。
您可能能够在Java中执行这些操作,但Java使其更加复杂,而不是更容易。如果您想的话,可以考虑混合设计,其中核心部分将使用C,而其余部分(GUI等)将使用Java。

5
当然,为什么不呢?
关键问题(与语言无关,这是来自排队理论的)是:
- 您需要处理的最大吞吐量是多少(您已指定100 x 48kHz,是单声道还是立体声,在该频率下相当于多少位?) - 您的Java例程是否可以平均跟上此速率? - 最大允许延迟是多少?
如果您的程序可以平均跟上吞吐量,并且有足够的延迟空间,则应该能够使用输入和输出队列,程序中仅关键时间部分是将数据放入输入队列并从输出队列中取出数据并将其发送到DAC /扬声器/其他设备的部分。
延迟线的计算负载较低,您只需要足够的内存(+内存带宽)...实际上,您可能只需要使用输入/输出队列即可,即立即开始将数据放入输入队列,并在30秒后开始从输出队列中取出数据。如果没有,那么您的程序就太慢了...
FIRs更昂贵,除非您有其他丑陋的操作,否则这可能会成为瓶颈(并且您想要优化)。

3

你的问题中没有提到是否需要播放这些处理后的样本,或者是否有其他用途(例如将它们编码成文件)。我会更担心Java音频引擎的状态,而不是JVM处理样本的速度。

我曾经对javax.sound.sampled进行过深入的研究,并且感到非常失望。它与等效的框架如OpenAL或Mac/iPhone的Core Audio相比毫不相伯仲(我在同样强度的水平上都使用过这些框架)。javax.sound.sampled需要你将样本推入一个未知持续时间的不透明缓冲区中,这使得同步几乎不可能。它的文档也很差(很难找到流式传输长度不确定的音频示例,而不是内存中的片段的简单示例),还有未实现的方法(DataLine.getLevel()……甚至连非实现都没有记录),最后,我相信Sun在多年前已解雇了最后一位JavaSound工程师。

如果必须使用Java引擎进行声音混合和输出,我可能会首选尝试使用JOAL绑定到OpenAL,因为我至少知道该引擎目前受支持并且能够实现非常低的延迟。尽管我认为从长远来看,尼尔斯是正确的,你最终会使用JNI调用本地音频API。


3
是的,Java非常适合音频应用。您可以使用Java并通过Asio访问音频层,在Windows平台上实现非常低的延迟(64个采样的延迟几乎为零),这意味着您将在视频/电影中实现口型同步。由于没有Asio来“捷径”OS X和“Java在顶部”的组合,Mac上的延迟更高,但仍然可以接受。对于Linux,我了解得更少。请参见soundpimp.com,其中有一个Java和Asio完美协作的实际(世界首创)示例。还可以查看NRK Radio&tv Android应用程序,其中包含一个sw mp3解码器(来自Java)。您可以使用Java完成大多数音频任务,如果需要更多时间要求,则可以使用本机层。

2

不错的链接,我一定会使用它,甚至还有一个 Android 版本!https://github.com/philburk/jsyn/tree/master/android/com/jsyn/devices/android - ejectamenta

-1
为什么不花一天时间编写一个简单的Java应用程序,进行最少量的处理,并验证其性能是否足够呢?

7
@mP,这有点违背提问和回答网站的初衷,不是吗? - JeffV

-2

来自http://www.jsresources.org/faq_performance.html#java_slow

让我们收集一些永恒的智慧:

  • 地球是平的。

  • 还有,不要忘记:Java很慢。

正如几个应用程序所证明的那样(请参见链接部分),Java足以构建音频编辑器、多轨录音系统和MIDI处理软件。试试吧!


你是不正确的。当你使用JasioHost时,你只能降到64个采样或者你的ASIO驱动程序允许的最少采样数。你说错了,这是过去的事情了。我发起了那个项目,所以我知道我在说什么。192kHz,24位,64个采样延迟。你还需要什么? - carl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接