使用 Linux PulseAudio 时无法关闭 Java 音频 Clip

标签 java linux audio openjdk pulseaudio

我试图在 Java 应用程序中播放声音,但该应用程序实际上从未终止,因为即使在尝试 close 之后,PulseAudio Eventloop 线程仍在运行。 Clip用于播放声音的实例:

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

final class AudioClipTest {

    public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        try (AudioInputStream instream = AudioSystem.getAudioInputStream(new File("resources/test-sound.wav"))){
            final AudioFormat format = instream.getFormat();
            final Clip clip = (Clip) AudioSystem.getLine(new DataLine.Info(Clip.class, format));
            clip.addLineListener(new LineListener() {
                @Override
                public void update(final LineEvent event) {
                    if (event.getType() == LineEvent.Type.STOP) {
                        System.out.println("Finished playing audio.");
                        event.getLine().close();
                        // FIXME: This line is never reached on Linux with
                        // PulseAudio
                        System.out.println("Closed audio data line.");
                    }
                }
            });
            clip.open(instream);
            clip.start();
        }
    }

}

在我的Linux机器上,上面的main方法播放相关的声音,打印

Finished playing audio.

然后挂起,而在 Windows 机器上打印

Finished playing audio.

Closed audio data line.

并正确退出。

在 Linux 机器上使用的实际 Clip 实现是 org.classpath.icedtea.pulseaudio.PulseAudioClip 而在 Windows 上它是 com.sun.media。声音.DirectAudioDevice.DirectClip; 这是怎么回事? — PulseAudioClip.close() 没有返回的是什么?


发行版: Linux Mint 18.1内核: 4.4.0-92-generic x86_64OpenJDK: 8u131-b11-2ubuntu1.16.04.3PulseAudio: 1:8.0-ubuntu3.3

分布: Windows 10 Pro版本: 1703操作系统构建: 15063.540 x64Oracle JDK: 1.8.0_144-b01DirectX:版本 12

最佳答案

解决此问题的一种可能方法是使用 Alsa(用户空间)API 来使用 Java 播放音频。 alsa 用户空间 API 将重定向到 PulseAudio(或其他 API/混音器),因此您仍应获得正确的音频。

编辑 $JAVA_HOME/jre/lib/sound.properties 并注释掉与 org.classpath.icedtea.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

此外,请针对您的发行版的 openjdk 包提交错误。 PulseAudio/Java 绑定(bind)多年来一直不受支持,应该删除。

关于使用 Linux PulseAudio 时无法关闭 Java 音频 Clip,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45847635/

相关文章:

kmalloc() 可以返回无效内存吗?

audio - C++ 特定的声音输出?

iphone - 如何确定录音源

java - 如何创建仅传递请求路径的规则 - urlrewritefilter

java - 如何获取方法继承信息?

linux - 旧的 ARM32 二进制文件可以在 AARCH64 内核上运行吗?

c++ - mmap分配的是页面还是页面的一部分?

http - 通过 http 请求控制的 shoutcast 流

java - 在 Eclipse 插件中使用 Xalan

java - PrintWriter 等待 flush()