Java中可靠的声音API,用于简单的数字样本回放

Gre*_*Cat 7 java openal alsa lwjgl javasound

是否有一个很好的方法可以在Java中获得体面,可靠的数字采样声音播放?

我的请求列表非常简短:

  • 将数字化样本加载到内存中(例如,来自jar中捆绑的资源),例如.wav文件
  • 以非阻塞的方式播放它们
  • 当我同时播放几个样本并且它们在时间上交叉时,它们应该正确混合

拥有以下内容会很高兴,但实际上我可以没有它:

  • 从.ogg或类似的压缩格式播放(显然没有在Java中实现CPU饥饿的解码器)
  • 在播放时仍然播放相同的样本不应该停止先前播放给定的样本,但是第二个副本应该开始并与第一个正确混合

我已经尝试了臭名昭着的Java Sound API,但发现它完全不可靠,似乎无法满足我的最小愿望清单.我得到的问题:

  • 在使用ALSA dmix(OpenJDK 6)的Linux上,在初始化Java Sound API时让任何其他应用程序使用音频只会使Java应用程序中的所有声音消失而不会出现任何错误/警告.

  • 在Linux(OpenJDK 6)上,列出MixerInfos并尝试Clip使用其中任何一个获取对象时,在尝试加载wav文件时会引发以下异常:

    java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian
    
    Run Code Online (Sandbox Code Playgroud)

    因此,AudioSystem.getClip(anySortOfMixer)似乎根本不起作用.只有AudioSystem.getClip()作品.

  • 使用不同的采样率/位/格式加载文件Clip失败LineUnavailableException.似乎第一次调用clip.open将声音系统设置为特定声音选项,在调用后加载具有略微不同采样率的文件(例如,第一个是44100,第二个是48000)

  • 在Linux(OpenJDK 6)上初始化几个不同的Clips并尝试播放它们只会使最后加载Clip声音 - 没有给出错误/警告,但只有play在最后Clip加载时才使用任何声音 - 所有其他声音都是静音的:

    Clip loadSound(String name) {
        URL url = this.getClass().getResource("/" + name + ".wav");
        Clip clip = AudioSystem.getClip();
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        clip.open(ais);
        return clip;
    }
    
    void playSound(Clip) {
        if (clip.isRunning())
            clip.stop();
        clip.setFramePosition(0);
        clip.start();
    }
    ...
    Clip c1 = loadSound("foo");
    Clip c2 = loadSound("bar");
    ...
    playSound(c1); // silence
    ...
    playSound(c2); // audible
    
    Run Code Online (Sandbox Code Playgroud)

    在Windows上使用此代码一切都很好 - 所有剪辑都可以听到,播放和混合正常.尚未在Mac上测试过.

  • 支持的文件格式(分析AudioSystem.getAudioFileTypes)在Linux/OpenJDK6和Windows/Oracle JDK 7上返回wav/au/aif,所以没有oggs甚至mp3s :(

  • 似乎没有简单的方法可以同时制作相同Clip声音的两个副本,而无需将第二个副本作为一个独特的副本加载Clip.

所以,问题是 - 是否有一个很好的解决方案/解决方法来补救所有这些东西并使其更可靠?会切换到其他一些音响系统(如LWJGL OpenALpaulscode.com音响系统)有帮助吗?或者是否可以将Java Sound API包装在一些安全防护装置中并且它可以正常工作?

我做了一个测试上述所有内容的应用程序,但它有点长,所以我想我会把它作为一个要点发布,但不幸的是,GitHub现在正在解决一些网络问题.所以,我想,我稍后会发布它.

Phi*_*ner 2

我在 Java-gaming.org 上发布了一个相当简单、有限的音频混合器,欢迎您在以下网址查看: http ://www.java-gaming.org/topics/simple-audio-mixer-2nd -pass/27943/view.html

第一篇文章中列出的 jar 具有源代码和示例用法,我投入了一些精力来制作 javadoc 注释。(98% 的下载是我包含的单个示例 wav。)此外,线程上还有很多 api 信息。

Linux 仍然存在问题。但您的分析给我留下了深刻的印象,并且想知道是否可以分享尝试排除故障并解决此问题的努力!

关于你的观点:

  • 我记得听说在某些 Linux 系统中,单个输出是可能的,并且某些应用程序不公平,并且在存在争用时将音频释放到 Java。如果这是准确的,那么很难将其称为 Java 问题,而可能是 Linux 操作系统问题?

  • 第二点:我还没有尝试从 Linux 中的 Mixer 加载,但我知道有些人已经能够通过我的 Web 应用程序 Java Theremin 来做到这一点。在该应用程序(在上面的线程中链接)中,我包含一个下拉列表,允许用户选择混音器。至少有一些 Linux 用户在这方面取得了成功。

  • 我没有使用过 Big-Endian wavs,只使用过 Little Endian wavs。你必须在 Audacity 或类似的东西中翻转字节才能使用我目前的混音器。

  • 我的系统确实处理并发。将 wav 加载到 PFClipData 对象中。然后,您可以通过多种不同的方式进行播放,通过 PFClipShooter(可以处理并发播放 - 20 或 30,并且也可以以不同的音高)或 PFClipLooper(将使用结尾的可选重叠模式循环播放剪辑)帮助平滑循环点)。所有输出都在幕后汇集到单个 SourceDataLine 中。

  • 我还没有实现 ogg 或 mp3,只是 16 位、44100fps 立体声小端 wav 文件。

  • 如果有其他人愿意分享的话,我很乐意考虑将其作为一个开源 git 项目。

--我最近在我的 PC 上的双引导分区中成功安装了 Linux(Ubuntu 桌面),并且即将安装声卡,看看我是否重新创建并希望修复所描述的一些问题。Ubuntu 同时具有 OpenJDK 和 Oracle 的 JDK,因此我希望看看 Java 实现是否是问题的一部分。工作正在进行中...