通过 Minim 访问 JavaSound SourceDataLine 不一致
我是一个对 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想通了!
调用 mixer.open() 导致出现问题。我猜 Minim 自己会这样做,并希望用户在请求线路时不打开它。
不过,我确实还有其他的发现。
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.
getLineOut()
would fail. You can, however, callMinim.stop()
to start over and get resources again.AudioPlayer
just seems broken. I can't get it to request a working output, but I found thatFilePlayer
works fine for some reason. You can even ask for an output withgetLineOut()
before making aFilePlayer
. Maybe you have to callsetOutputMixer()
(without also callinggetLineOut()
) before getting anAudioPlayer
in order for it to work.