我试图在 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_64; OpenJDK: 8u131-b11-2ubuntu1.16.04.3; PulseAudio: 1:8.0-ubuntu3.3
‡分布: Windows 10 Pro; 版本: 1703; 操作系统构建: 15063.540 x64; Oracle JDK: 1.8.0_144-b01; DirectX:版本 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/