通过 Minim 访问 JavaSound SourceDataLine 不一致

Inconsistent Access to JavaSound SourceDataLine Through Minim

我在 Linux 世界中是一个不太了解的人,试图了解我在项目中遇到的音频问题。简而言之,我正在尝试通过名为 Minim (ddf.minim) 的 Java 库获取音频输出。我可以通过监听输入并启用“监控”来获得输出。监控将输入回显到输出。但是,我无法获得独立于此功能的工作输出线。

一些上下文:

此应用程序 运行 在装有 Debian Buster 的 BeagleBone Black 上运行。这是一个 ARM 微控制器。我的 Java 应用程序作为 root 用户作为 systemd 服务启动。它以无头模式运行,但具有虚拟帧缓冲区 (xvfb),因为它是一个 Processing 应用程序。我有一个连接到 BeagleBone 的 USB 集线器,它装有一个 USB 转 AUX 适配器。 AUX 端分成 pink/green input/output 电缆。我有一个麦克风连接到粉红色端,耳塞连接到绿色端。

问题:

当使用 Minim 的 getLineIn() 获取输入时,没有看到任何错误。启用监控也不会产生错误。使用 getLineOut() 将显示如下所示的错误:

==== JavaSound Minim Error ====
==== Couldn't open the line: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
==== JavaSound Minim Error ====
==== Unable to return a SourceDataLine: unsupported format - PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian

这是我要求输出的代码:

Mixer.Info mixers[] = AudioSystem.getMixerInfo();
for(Mixer.Info info : mixers)
{
    try
    {
        mixer = AudioSystem.getMixer(info);
        if(!mixer.isOpen())
        {
            mixer.open();
        }
        M.setOutputMixer(mixer);
        LineOut = M.getLineOut();
    }
    catch(Exception e)
    {
        mixer = null; //This mixer can't be used.
        continue;
    }
    if(mixer != null && LineOut != null)
    {
        break;
    }
}

错误并不总是抛出异常,所以这就是我进行空值检查的原因。有趣的是,即使出现错误消息,LineOut 也不会为空。我可以将它传递给其他方法,但我永远听不到任何声音。只有两个混音器出现,一个用于 USB 适配器,另一个在打开后抛出异常。

我尝试过的解决方案:

使用 aplay 播放示例文件曾经失败,但一旦我安装了 PulseAudio,它们就可以工作了。

我没有声卡 0,但 USB 适配器显示为声卡 1。我已将 asound.conf 更改为在底部添加这些额外的行:

defaults.pcm.card 1
defaults.ctl.card 1

在阅读了 Java 对 PulseAudio 的弱支持后,我还在 /usr/lib/jdk1.8.0_251/jre/lib 下的 sound.properties 配置文件中添加了这些行:

javax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.Port=com.sun.media.sound.PortMixerProvider
javax.sound.sampled.SourceDataLine=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.TargetDataLine=com.sun.media.sound.DirectAudioDeviceProvider

我已经使用 AudioSystem class 来查询混音器支持的格式。它们与我请求的格式相同,因此我不确定错误消息是否准确描述了问题。我试过单声道、立体声、不同的缓冲区大小……可能还有其他东西。

我已将我的应用程序更改为仅查找输出,而不查找输入。问题仍然存在。

这段代码在 Windows 上运行良好,这是我在将它移植到 Debian 机器之前测试的地方。

我在 Linux 上读了很多关于声音普遍脆弱的文章,所以我怀疑我做错了什么或者 Java 不适合输出声音用我独特的设置。帮忙?

我想通了!

调用 mixer.open() 时出现问题。我想 Minim 自己会这样做,并希望用户在请求线路时不要打开它。

不过,我也有其他发现。

  • Java and/or Minim 对 re-requesting 音频资源非常敏感,至少在 Debian 上是这样。由于请求 line-in 隐式请求了监视功能的输入和输出,因此对 getLineOut() 的后续调用将失败。但是,您可以调用 Minim.stop() 重新开始并再次获取资源。
  • AudioPlayer 似乎坏了。我无法让它请求工作输出,但我发现 FilePlayer 出于某种原因工作正常。您甚至可以在 FilePlayer 之前使用 getLineOut() 请求输出。也许你必须在获得 AudioPlayer 之前调用 setOutputMixer()(而不是调用 getLineOut())才能使其工作。