2

ClipJavaのインスタンスで奇妙な動作が見られます。

私が取り組んでいるクラスの目的はClip、同じサウンドサンプルを含むインスタンスの数をカウントすることです(によってインデックスが付けられURIます)。アプリケーションがクリップの再生を要求し、同じソースからのクリップがすでに3つ以上再生されている場合、次の手順が実行されます。

  • PAN現在再生中のクリップをとの加重和で並べ替えframePositionます。
  • 停止して再開するクリップとして、値が最も高いクリップを選択します。
  • クリップを再開します(次の方法)。

void restart(Clip clip, float gain, float pan) {
    clip.stop();
    clip.flush();
    pan = Math.max(-1f, Math.min(pan, 1f));
    ((FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN))
                        .setValue(gain);
    ((FloatControl) clip.getControl(FloatControl.Type.PAN))
                        .setValue(pan);
    clip.setFramePosition(0);
    clip.start();
}

このメソッドがすばやく連続して何度も呼び出されると(たとえば、1ミリ秒以内に20回)、奇妙な動作が発生します。

  • クリップが再生されます
  • クリップは、START再生が開始されたことを通知するイベントを発生させます
  • クリップがSTOPイベントを発生させることはありません。
  • 以降の呼び出しは効果がstopありstartません(ただし、例外をスローしないでください)。
  • getFramePosition0は、クリップが(最後に)聞こえた場合でも、常にを返します。

これを引き起こしている可能性のあるアイデアはありますか?

私はそれがスレッドの問題ではないと思います(少なくとも私のコードでは)。1つのスレッドだけが私のクラスのパブリックメソッドを呼び出しています(そしてそれらはすべてsynchronizedとにかくです)


このバグに関連している可能性があります。

4

1 に答える 1

1

の呼び出しDataLine.startDataLine.stopは、内部ののミキサーですでに同期されています。DataLineAbstractDataLine

コールスタックのどこか(/の下implStart()/ 、おそらくネイティブ/内)で少なくとも1つの非同期呼び出しが行われ、その結果、競合状態が発生しているのではないかと強く思います。implStop()DataLinenStartnstop

synchronized呼び出されるネイティブ実装についてのより深い知識がなければ、または他のJava構造を使用してこの種の問題を回避することは不可能です。

実行可能な即時の回避策は、古いクリップを巻き戻す代わりに、古いクリップを閉じて新しいインスタンスを開くことです。最適ではありませんが、より詳細な調査が行われるまではうまくいく可能性があります。

前述のより詳細な調査を実行できるようにするには、使用しているプラ​​ットフォームと、インスタンスの実際の(実装)クラス名の確認を知る必要がClipありMixerます。

アップデート

並行して、イントロスペクションを使用して設定してcom.sun.media.sound.Printer.trace = trueください(またはで独自の実装を提供してくださいcom.sun.media.sound.PrinterCLASSPATH

基本的に、スレッドセーフではない方法でいくつかの揮発性変数(特に重要な)にアクセスするスレッドをDirectClip.open()生成します。これにより、メインの再生ループがハングする可能性があります。doIO

明らかなハング時にスレッドダンプPrinterを強制し、再生スレッドの状態/スタックトレースを検査する(またはデバッガーを使用する)ことで、これを(トレースと組み合わせて)確認(または確認)できます。

などのアクセスが問題ではないdoIOことが判明した場合でも、ネイティブ実装を掘り下げ続けることは依然としてやるべきことです。などのアクセス問題であることが判明した場合も、簡単な修正はありません(イントロスペクションを使用して、定期的に取得して信号を送信して、-が原因で停止した場合に備えて確認することができます)。doIODirectClip.threaddoIO

于 2010-06-29T20:27:26.320 に答える