7

Java で適切で信頼性の高いデジタル サンプリング サウンドを再生するための良いレシピはありますか?

私のリクエストのリストはかなり短いです:

  • デジタル化されたサンプルを .wav ファイルなどからメモリにロードします (たとえば、jar にバンドルされたリソースから)。
  • ノンブロッキングでプレイする
  • 複数のサンプルを同時に再生し、それらが時間的に交差する場合、適切にミックスされるはずです

次のものがあるといいのですが、実際にはそれがなくても生活できます。

  • .ogg または同様の圧縮形式からの再生 (明らかに、Java で CPU を大量に消費するデコーダーを実装する必要はありません)
  • 再生中に同じサンプルを再度再生しても、特定のサンプルの前の再生を停止するべきではありませんが、2 番目のコピーが開始され、最初のコピーと適切にミックスされる必要があります。

悪名高いJava Sound APIを試してみましたが、まったく信頼性が低く、最小限の希望リストさえ満たすことができないようです。私が得る問題:

  • ALSA dmix (OpenJDK 6) を使用する Linux では、Java Sound API の初期化中に他のアプリケーションでオーディオを使用すると、Java アプリからのすべてのサウンドがエラーや警告なしで消えます。

  • Linux (OpenJDK 6) では、 を一覧表示し、それらのいずれかを使用しMixerInfoてオブジェクトを取得しようとすると、wav ファイルをロードしようとすると、次の例外がスローされます。Clip

    java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian
    

    したがって、AudioSystem.getClip(anySortOfMixer)まったく機能していないようです。のみAudioSystem.getClip()動作します。

  • を使用してサンプルレート/ビット/フォーマットが異なるファイルをロードすると、 でClip失敗しLineUnavailableExceptionます。を最初に呼び出すと、clip.openサウンド システムが特定のサウンド オプションに設定され、次にわずかに異なるサンプル レートでファイルをロードするように見えます (たとえば、最初は 44100、2 番目は 48000)。

  • Linux (OpenJDK 6) では、いくつかClipの異なる を初期化してそれらを再生しようとすると、最後にロードされたものだけが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
    

    Windows でこのコードを使用すると、すべて問題ありません。すべてのクリップが聞こえ、再生され、適切にミックスされます。Macではテストしていません。

  • サポートされているファイル形式 (で分析AudioSystem.getAudioFileTypes) は、Linux/OpenJDK6 と Windows/Oracle JDK 7 の両方で wav / au / aif を返すため、oggs や mp3 さえありません:(

  • Clip2 番目のコピーを別々の としてロードせずに、同じサウンドの 2 つのコピーを同時に作成する簡単な方法はないようですClip

それで、問題は - このすべてのものを修正して信頼性を高めるための良い解決策/回避策はありますか? 他のサウンド システム ( LWJGL OpenALpaulscode.com サウンド システムなど) に切り替えると効果がありますか? または、Java Sound API をいくつかのセーフ ガードでラップすることは可能で、適切に動作しますか?

上記のすべてをテストする小さなアプリケーションを作成しましたが、少し長いのでgistとして公開しようと思いましたが、残念ながら、現在 GitHub でいくつかのネットワークの問題が発生しています。ということで、もう少ししたら公開します。

4

1 に答える 1

2

私は Java-gaming.org に非常にシンプルで限定的なオーディオ ミキサーを投稿しました 。 -pass/27943/view.html

最初の投稿に記載されている jar にはソース コードとサンプルの使用法があり、私は javadoc コメントを作成することに力を入れています。(ダウンロードの 98% は、私が含めた単一のサンプル wav です。) また、スレッドには多くの API 情報があります。

Linuxにはまだ問題があります。しかし、私はあなたの分析に感銘を受けており、これをトラブルシューティングして修正する努力を分かち合いたいと思っています!

あなたのポイントについて:

  • 一部の Linux システムでは単一の出力しかできないという話を聞いたことを思い出します。競合が発生した場合、一部のアプリケーションは公正に動作せず、オーディオを Java に解放します。これが正確である限り、これを Java の問題と呼ぶのは難しく、むしろ Linux OS の問題でしょうか?

  • 2 番目のポイント: Linux のミキサーからのロードはまだ試していませんが、私の Web アプリ Java Theremin からこれを実行できた人がいることは知っています。そのアプリ (上記のスレッドにリンクされています) には、ユーザーがミキサーを選択できるドロップダウンが含まれています。少なくとも一部の Linux ユーザーはこれで成功しています。

  • ビッグ エンディアンの wav は使用していませんが、リトル エンディアンの wav のみを使用しています。私のミキサーを現在の状態で使用するには、Audacity などでバイトを反転する必要があります。

  • 私のシステムは並行性を処理します。PFClipData オブジェクトに wav をロードします。次に、これをさまざまな方法で再生できます。PFClipShooter (20 または 30 の同時再生を処理でき、異なるピッチでも可能) または PFClipLooper (オプションのオーバーラップ モードを使用してクリップをループします)。ループポイントを滑らかにするのに役立ちます)。すべての出力は、舞台裏で単一の SourceDataLine に集められます。

  • ogg や mp3 はまだ実装していません。16 ビット、44100fps のステレオ リトルエンディアン wav ファイルのみです。

  • これを共有してくれる人が他にいる場合は、これをオープン ソースの git プロジェクトにすることを喜んで検討します。

-- 最近、PC のデュアル ブート パーティションに Linux (Ubuntu デスクトップ) をインストールすることに成功しました。サウンド カードをインストールして、説明されている問題のいくつかを再現し、できれば修正するかどうかを確認しようとしています。Ubuntu には OpenJDK と Oracle の JDK の両方があるため、Java の実装が問題の一部であるかどうかを確認したいと考えています。進行中の作業...

于 2012-12-23T08:23:23.007 に答える