通过 Minim 访问 JavaSound SourceDataLine 不一致

发布于 2025-01-12 01:26:33 字数 2539 浏览 0 评论 0原文

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

一些上下文:

该应用程序在带有 Debian Buster 的 BeagleBone Black 上运行。这是一个 ARM 微控制器。我的 Java 应用程序以 root 用户身份将系统作为 systemd 服务启动。它以无头模式运行,但具有虚拟帧缓冲区 (xvfb),因为它是一个处理应用。我有一个连接到 BeagleBone 的 USB 集线器,其中装有 USB 转 AUX 适配器。 AUX 侧分成粉色/绿色输入/输出电缆。我将麦克风连接到粉色端,将耳塞连接到绿色端。

问题:

当使用 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 也不会为 null。我可以将其传递给其他方法,但我永远听不到任何声音。只有两个混音器出现,一个用于 USB 适配器,另一个在打开后抛出异常。

我尝试过的解决方案:

使用 aplay 播放示例文件曾经失败,但是一旦我 apt install-ed 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 类来查询混音器支持的格式。它们与我请求的格式相同,因此我不确定错误消息能否准确描述问题。我尝试过单声道、立体声、不同的缓冲区大小......以及可能的其他东西。

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

这段代码在 Windows 上运行良好,我在将其移植到 Debian 机器之前在 Windows 上进行了测试。

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

I'm a not-so-knowledgeable person in the Linux world trying to understand an audio problem I have in a project. In short, I'm trying to get an audio output through a Java library called Minim (ddf.minim). I can get an output by listening to an input and enabling "monitoring." Monitoring echoes the input to an output. I cannot however get a working output line independent of this feature.

Some context:

This application is running on a BeagleBone Black with Debian Buster. This is an ARM microcontroller. My Java application starts up with the system as a systemd service as the root user. It runs in headless mode but with a virtual frame buffer (xvfb) because it's a Processing application. I have a USB hub connected to the BeagleBone, which hosts a USB-to-AUX adapter. The AUX side splits into the pink/green input/output cables. I have a mic connected to the pink end and earbuds into the green end.

The problem:

When Minim's getLineIn() is used to get an input, no errors are seen. Enabling monitoring doesn't generate errors either. Using getLineOut() will show errors that look like this:

==== 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

Here's my code that asks for an output:

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;
    }
}

Errors don't always throw an exception, so that's why I have a null check. Interestingly, even when error messages show up, LineOut will not be null. I can pass it to other methods but I can never hear anything. Only two mixers ever show up, one for the USB adapter and one that throws an exception once opened.

Solutions I've tried:

Playing example files with aplay used to fail, but once I apt install-ed PulseAudio, they worked.

I don't have a soundcard 0, but the USB adapter shows as soundcard 1. I've changed the asound.conf to have these extra lines at the bottom:

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

I've also added these lines in the sound.properties config file under /usr/lib/jdk1.8.0_251/jre/lib after reading about Java's weak support for PulseAudio:

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

I've used the AudioSystem class to query for the supported formats of the mixer. They're the same formats I'm requesting, so I'm not confident the error message accurately describes the issue. I've tried mono, stereo, different buffer sizes... and probably other things.

I've changed my application to only seek an output, and not look for an input. The issue persists.

This code works fine on Windows, which is where I test things before porting it to the Debian machine.

I've read a lot about the general fragility of sound on Linux, and so my suspicion is that I'm doing something wrong there or Java is just not fit for outputting sound with my unique setup. Help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薄情伤 2025-01-19 01:26:33

我想通了!

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

不过,我确实还有其他的发现。

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

I figured it out!

Calling mixer.open() was causing problems. I guess Minim does this itself and expects users to leave it unopened when requesting a line.

However, I did also have other discoveries.

  • Java and/or Minim are very sensitive to re-requesting audio resources, at least on Debian. Since requesting a line-in implicitly requested both an input and output for the monitoring feature, a subsequent call to getLineOut() would fail. You can, however, call Minim.stop() to start over and get resources again.
  • The AudioPlayer just seems broken. I can't get it to request a working output, but I found that FilePlayer works fine for some reason. You can even ask for an output with getLineOut() before making a FilePlayer. Maybe you have to call setOutputMixer() (without also calling getLineOut()) before getting an AudioPlayer in order for it to work.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文