2

最近、Javaオーディオクリップの音量を制御することについて質問しましたが、JMFを試すように提案されました。古いJVM(1.4)を使用していて、WAVファイルの再生にのみ関心があるため、JMFは完璧なソリューションであり、アプリケーションでオーディオクリップのロード、再生、および音量を制御するためのコードを大幅に簡素化しました。

しかし、オンデマンドでクリップを停止するのに問題があります。呼び出すのと同じくらい簡単に見えますplayer.stop()stop()、プレーヤーが再生を終了するまでブロックするようです。簡単なコード例を次に示します。

Player p = Manager.createRealizedPlayer( f.toURI().toURL() );

p.start();
System.out.println( "Player playing" );

Thread.sleep( 1000 );
System.out.println( " Clip is at time: " + p.getMediaTime().getSeconds() );

p.stop();
System.out.println( " Clip is at time: " + p.getMediaTime().getSeconds() );

これにより、次のような出力が生成されます。

Player playing
 Clip is at time: 0.8591836730000001
 Clip is at time: 3.227619047

2回目は、1回目と同じか、それより少し遅れて読むと予想していたところ。(または、0か何かにリセットされている可能性があります。)私も試しp.setStopTime( p.getMediaTime() )ました。これにより、クリップは時間どおりに停止しますが、停止する前に一瞬の歪みが再生されます。これは望ましくありません。

グーグルで回ると、他の人はこの問題を抱えていないように思います。そして、選択肢を見つけるのはちょっと難しいです。これはバッファリングの問題でしょうか、それとも他に何かが足りないのでしょうか?あなたが提供できるどんな洞察も大いに感謝されます。


詳細: JVM 1.4.2とJMF2.1.1を使用しています(変更できません)。私のすべてのWAVファイルの長さはわずか1〜10秒です。

4

2 に答える 2

2

そして確かにそれはバッファリングの問題でした。次のコードスニペットを使用して使用可能なコントロールを表示しようとしたときに、BufferControlがリストされていなかったため、これを見つけるのにしばらく時間がかかりました。

Player p = ...
Control cs[] = p.getControls();
for ( int j = 0; j < cs.length; j++ )
  System.out.println( "  Found control: " + cs[j].getClass().getCanonicalName() );

最終的に、私はこのスニペットでBufferControlを取得する際にブラインドスタブを作成し、それが機能しました。

BufferControl bc = (BufferControl) p.getControl( "javax.media.control.BufferControl" );

調査してもう少しいじった後、デフォルトのバッファ長は2秒であることがわかりました。バッファの長さを1秒に減らすことで、2.5秒以上のWAVファイルを正しく停止することができました。さらに0.5秒に短縮すると、すべての入力ファイルで最初に求めていた動作が得られました。

JMFソースを見ずに、オーディオが2秒のチャンク(2秒はバッファーの長さ)で読み取られて再生され、それらのチャンクの再生を終了する必要があるという問題が発生したと想定しています。 -何らかの理由で-停止する前に。0.5秒に短縮しても、実際には問題が解決しない場合があります(停止するように指示された後もサウンドが再生され続ける場合)が、少なくとも問題が目立たなくなるまで軽減されます。さらに、私のWAVファイルはすべて小さくてローカルなので、再生の遅延やスキップは問題になりません。

最後に、元の質問からのコードスニペットのリビジョンを次に示します。これにより、目的の動作が得られます。

Player p = Manager.createRealizedPlayer( f.toURI().toURL() );

BufferControl bc = (BufferControl) p.getControl( "javax.media.control.BufferControl" );
if ( bc != null )
  bc.setBufferLength( 500 ); // buffer length specified in milliseconds

p.start();
System.out.println( "Player playing" );

Thread.sleep( 1000 );
System.out.println( " Clip is at time: " + p.getMediaTime().getSeconds() );

p.stop();
System.out.println( " Clip is at time: " + p.getMediaTime().getSeconds() );
于 2009-11-11T17:25:15.427 に答える
0

私も短いオーディオファイルでのみこの問題を抱えていました。バッファを設定しても役に立ちませんでした。私は大胆にオーディオに沈黙を加えることになった。

私はJMFが嫌いです:)

編集:まあ、短いオーディオファイルがある場合、JMFはGainControl.setLevel()呼び出しもブロックします。問題の根本は同じだと思います。JMFはショートファイルが完了するまでリクエストをブロックします(ボリュームの設定、停止)。

于 2011-04-27T04:17:55.797 に答える