如何让我的 Java 应用程序在 Linux 中播放好音频?

Posted

技术标签:

【中文标题】如何让我的 Java 应用程序在 Linux 中播放好音频?【英文标题】:How can I make my Java application with audio play nice in Linux? 【发布时间】:2009-12-21 17:39:40 【问题描述】:

我有一个 Java 应用程序,其 UI 严重依赖音频。在 Windows 和 OS X 上,一切正常;但是,在 Linux 上,应用程序需要对声音设备的独占访问权限,抛出 LineUnavailableException 并且听不到声音。我正在使用 Kubuntu 9.10。

这意味着在程序运行时没有其他应用程序可以播放音频,并且在程序启动时甚至不能持有音频设备。这自然是不能接受的。

这是我用来播放音频的代码:

AudioInputStream audioInputStream = Audiosystem.getAudioInputStream(file);

Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);

clip.start();

this.wait((clip.getMicrosecondLength() / 1000) + 100);

clip.stop();

我做错了吗?在 Linux 中使用 Java 播放音频会失败吗?

【问题讨论】:

请说明 Linux 发行版和版本。 @jsight:在我看来,“Kubuntu 9.10”从一开始就在那里。 【参考方案1】:

我担心 Linux 中的音频本身就是一个失败的原因。但在这种情况下,它确实是known Java Bug。您应该尝试找出您正在使用的声音架构。我认为 Ubuntu 的默认值是 PulseAudio/ALSA。不过我不确定 Kubuntu。

有a known workaround(不过我自己从未尝试过)。

您正在运行的其他一些应用程序也有可能专门使用声卡,因此请务必使用不同的应用程序进行测试(即与其他应用程序配合得很好的应用程序)。

【讨论】:

【参考方案2】:

通过一些调整,我能够使用 OpenJDK 在 GNU/Linux (Ubuntu 10.10) 上播放音频。我相信 LineUnavailableException 是 PulseAudio 中的一个错误,并已在 10.10 中修复。

我需要指定格式(Windows 上不需要)。

AudioInputStream audioIn = AudioSystem.getAudioInputStream(in);

// needed for working on GNU/Linux (openjdk) 
AudioFormat format = audioIn.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip clip = (Clip)AudioSystem.getLine(info);
// 
// on windows, 
//Clip clip = AudioSystem.getClip();
// 

请注意,对 Clip.getMicrosecondLength() 的调用会返回 毫秒

【讨论】:

【参考方案3】:

Java 声音对于高精度或低延迟的任务来说很糟糕,而且在 Linux 上几乎完全无法正常工作。在您投入更多时间之前立即放弃船舶。 在 Java Sound 之后,我尝试了 OpenAL,它在 Linux 上也不是很好。 目前我正在使用 FMOD,不幸的是它是闭源的。

要采用的开源方式可能是 PortAudio。尝试与 SIP Communicator 开发人员交谈。

我也尝试过 RtAudio,但发现它的 ALSA 实现存在错误。

【讨论】:

【参考方案4】:

通过 shell 发送 mplayer 命令。最简单的解决方案。

【讨论】:

【参考方案5】:

我从互联网的某个地方得到这个代码,声音大部分时间都会出现,偶尔不会出现

import java.util.*;
import java.text.*;
import java.io.*;

import java.net.*;
import javax.sound.sampled.*;
public class Sound2

    public static
    void main (String name[])
    
        playSound ( "somesound.wav" );
    
    public static
    void playSound (String filename)
    

        int BUFFER_SIZE = 128000;
         //File soundFile = null;
         AudioInputStream audioStream = null;
         AudioFormat audioFormat = null;
         SourceDataLine sourceLine = null;
        try 
        
            audioStream = 
            AudioSystem.getAudioInputStream
            (
                new
                BufferedInputStream 
                (
                    new FileInputStream ( filename )
                )
            //soundFileStream
            );
         
        catch (Exception e)
        
            e.printStackTrace();
            System.exit(1);
        

        audioFormat = audioStream.getFormat();

        DataLine.Info info = new DataLine.Info
        (
            SourceDataLine.class, 
            audioFormat
        );
        try 
        
            sourceLine = (SourceDataLine) AudioSystem.getLine(info);
            sourceLine.open(audioFormat);
         
        catch (LineUnavailableException e) 
        
            e.printStackTrace();
            System.exit(1);
         
        catch (Exception e) 
        
            e.printStackTrace();
            System.exit(1);
        

        sourceLine.start();

        int nBytesRead = 0;
        byte[] abData = new byte[BUFFER_SIZE];
        while (nBytesRead != -1) 
        
            try 
            
                nBytesRead = 
                audioStream.read(abData, 0, abData.length);
             
            catch (IOException e) 
            
                e.printStackTrace();
            
            if (nBytesRead >= 0) 
            
                @SuppressWarnings("unused")
                int nBytesWritten = 
                sourceLine.write(abData, 0, nBytesRead);
            
        

        sourceLine.drain();
        sourceLine.close();
    

【讨论】:

以上是关于如何让我的 Java 应用程序在 Linux 中播放好音频?的主要内容,如果未能解决你的问题,请参考以下文章

如何让我的客户端应用程序名称显示在 java 的 zos 上?

如何让我的 React Native 应用出现在 android 的分享列表中

如何让我的 Python 模块在 Linux 系统范围内可用?

如何在开始时停止让我的应用程序崩溃

如何让我的 Facebook 应用程序公开

如何让我的简单 Java Web 服务正常工作?