3

コード

import javax.sound.sampled.*;
import java.io.*;

public class Tester {
static Thread th;


public static void main(String[] args) {
    startNewThread();   
   while( th.isAlive() == true) {
       System.out.println("sound thread is working");
   }
}

public static void startNewThread() {
   Runnable r = new Runnable() {
       public void run() {
           startPlaying();
       }
   };
   th =new Thread(r);
   th.start();
} 
public static void startPlaying() {
   try {            
        AudioInputStream ais = AudioSystem.getAudioInputStream(new File("d:/UnderTest/wavtester.wav"));
        Clip clip = AudioSystem.getClip();
        clip.open(ais);
        clip.loop(-1); // keep playing the sound                  
   } catch(Exception exc) {
       System.out.println(exc);
     }       
 }
}

このコードは出力サウンド スレッドを動作させますが、何も再生しません。このコードでは、サウンドを再生するための別のスレッドを開始しました。プログラムは、サウンド スレッドがジョブを終了するまで終了しないでください。ただし、一連のサウンド スレッドの動作を出力した後、プログラムは終了します。

これの理由は何ですか(プログラムが終了し、サウンドが再生されないため)

4

3 に答える 3

6

問題は、Wave ファイルを再生するバックグラウンドデーモンスレッドClipを既に起動していることです。

したがって、コードの実行フローは次のようになります。

  • メイン スレッドがセカンダリ (役に立たない) スレッドを起動する
  • セカンダリ スレッドはデーモン スレッドを起動します (サウンドを再生します)。
  • その間、セカンダリスレッドが生きている間、メインスレッドは何かを印刷し続けます
  • セカンダリ スレッドが再生スレッドの起動を完了すると終了するため、セカンダリ スレッドはアクティブな状態ではなくなります。
  • メイン スレッドは、セカンダリ スレッドがアクティブでないことを認識し、同様に終了します。
  • 再生スレッドはデーモン スレッドであるため、JVM は終了します (残っているスレッドはデーモン スレッドだけであるため)。

最終的な結果はまさにあなたが見ているものです。セカンダリ スレッドが再生スレッドを起動している間にメイン スレッドによって一部のテキストが出力され、再生スレッドが再生を開始するとブームが発生し、JVM が終了します。JVM が終了する前に、ヘッドホンから (サウンドの再生が開始されると) 「カチッ」という音が聞こえる場合もあります。

最も簡単な解決策は、サウンドの再生中にセカンダリ スレッド (つまり、非デーモン スレッド) をスリープ状態にすることです。

...
  clip.open(ais);
  clip.loop(-1);
  Thread.sleep(amountToSleep);
...

注意すべき重要な点の 1 つ: 約 1 年前、その Java API を使用していたときに、メソッドgetMicrosecondLength()にバグがあることに気付きました。私は Windows と Linux の両方でコーディングを行っていましたが、一方のプラットフォームでは正しい値を取得できましたが、もう一方のプラットフォームではまったく同じ方法で長さがミリ秒単位で返されました。

音の実際の長さを取得する最も信頼できる方法は、getFrameLength()メソッドを使用し、そこから長さを計算することであることがわかりました。

当時私が書いたコードは、このノートにはありませんでした。後で別の PC で確認し、見つかった場合は完全な例を投稿します (Sun JVM を使用する Windows と、OpenJDK または Sun を使用する Linux の両方で確実に動作します)。

于 2011-07-29T10:28:15.987 に答える
0
import javax.sound.sampled.*;
import java.io.*;
import javax.swing.*;

public class Tester {
static Thread th;


public static void main(String[] args) throws Exception {
     Clip clip = AudioSystem.getClip();
     AudioInputStream ais = AudioSystem.getAudioInputStream(new File("d:/UnderTest/wavtester.wav"));
     clip.open(ais);
     clip.loop(0);
     // Calculate totalFrames
     long totalFrames = (long)(clip.getFrameLength() * clip.getFormat().getFrameRate());
     Thread.sleep( ( totalFrames* 1000 )); // pause the thread till the sound plays

     System.out.println(clip.getFrameLength());
     System.out.println(clip.getFormat().getFrameRate());           
 }
}
于 2011-07-29T11:11:55.110 に答える
0
while(clip.isRunning()){} 

優れている

于 2011-09-30T00:25:47.457 に答える