2014-06-10 126 views
-3

有人能幫我理解下面的代碼爲什麼不起作用嗎?Java剪輯不能正常工作

我通過調用方法start()開始剪輯。此方法爲剪輯運行創建一個新的線程。但是,不,它似乎沒有發揮任何作用。

的代碼沒有任何錯誤編譯...

public class Audio 
{ 
    private Clip clip; 

    private Thread thread; 

    public Audio (String audioFile) 
    { 
     AudioInputStream audioStream = null; 

     URL audioURL = this.getClass().getClassLoader().getResource(audioFile); 

     // Obtain audio input stream from the audio file and load the information 
     // into main memory using the URL path retrieved from above. 
     try { audioStream = AudioSystem.getAudioInputStream(audioURL); } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      System.exit(1); 
     } 

     try 
     { 
      // Retrieve the object of class Clip from the Data Line. 
      this.clip = AudioSystem.getClip(); 

      // Load the audio input stream into memory for future play-back. 
      this.clip.open(audioStream); 
     } 
     catch (LineUnavailableException e) 
     { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 

    public void start() 
    { 
     Runnable r = new Runnable() { 
      public void run() 
      { 
       loop(); 
      } 
     }; 
     thread = new Thread(r); 
     thread.start(); 
    } 

    public void loop() 
    {  
     // Rewind the media to the beginning of the clip. 
     this.clip.setFramePosition(0); 

     // Continuously play the clip. 
     this.clip.loop(Clip.LOOP_CONTINUOUSLY); 

     try 
     { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) 
     { 
      e.printStackTrace(); 
     } 
    } 

UPDATE

我發現這個問題!問題是因爲音頻文件。我使用了不同的音頻文件,並且可以用上面的代碼來聽到聲音。

這真的很煩人,代碼編譯沒有任何錯誤或警告。我通過獲取音頻格式來檢測問題,然後將其傳遞給DataLine.Info類。然後,從數據線中檢索剪輯。

因此,通過基本上而不是領夾:

this.clip = AudioSystem.getClip(); 

我會用得到的片段:

AudioFormat format = audioStream.getFormat(); 
DataLine.Info info = new DataLine.Info(Clip.class, format); 
this.clip = (Clip) AudioSystem.getLine(info); 

當我與這個編譯的Java拋出以下錯誤:

No line matching interface Clip supporting format PCM_SIGNED 48000.0 Hz, 24 bit

所以,我更換了音頻文件,它工作!

+0

這是什麼?小程序嗎? –

+0

API顯示了繼承的啓動方法,你有沒有嘗試過(如this.clip.start)? – SleuthEye

+0

如果你在一個線程中全部嘗試,會發生什麼情況? – popgalop

回答

1

clip.loop是一個非阻塞呼叫。也就是說,一旦你調用了它(它做了它所做的),它就會返回,這意味着你的線程將退出,除非有另一個非守護進程線程在運行,否則JVM將退出。

我以爲你可能會使用Clip#drain來阻止它直到剪輯完成,但從技術上講,剪輯將無法完成...在正常意義上。

相反,我建立了我自己的循環...

public void start() { 
    Runnable r = new Runnable() { 
    public void run() { 
     while (true) { 
      clip.setFramePosition(0); 
      clip.start(); 
      clip.drain(); 
     } 
    } 
    }; 
    thread = new Thread(r); 
    thread.start(); 
} 

現在,這可能是一個問題,因爲Thread是一個非守護線程和永遠不會結束......取而代之的while (true) {你應該建立某種volitle標誌,你設置爲false,幫助終止循環...

例如...

import java.io.IOException; 
import java.net.URL; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.LineUnavailableException; 

public class Audio { 

    private Clip clip; 

    private Thread thread; 
    private volatile boolean keepPlaying = true; 

    public static void main(String[] args) { 
     Audio audio = new Audio("Kalimba.wav"); 
     audio.start(); 

     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException ex) { 
     } 
     audio.stop(); 
    } 

    public Audio(String audioFile) { 
     AudioInputStream audioStream = null; 

     URL audioURL = this.getClass().getClassLoader().getResource(audioFile); 

     // Obtain audio input stream from the audio file and load the information 
     // into main memory using the URL path retrieved from above. 
     try { 
      audioStream = AudioSystem.getAudioInputStream(audioURL); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 

     try { 
      // Retrieve the object of class Clip from the Data Line. 
      this.clip = AudioSystem.getClip(); 

      // Load the audio input stream into memory for future play-back. 
      this.clip.open(audioStream); 
     } catch (LineUnavailableException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 

    public void stop() { 
     if (thread != null) { 

      keepPlaying = false; 
      clip.stop(); 
      thread.interrupt(); 

     } 
    } 

    public void start() { 
     Runnable r = new Runnable() { 
      public void run() { 
       while (keepPlaying) { 
        clip.setFramePosition(0); 
        clip.start(); 
        clip.drain(); 
       } 
      } 
     }; 
     thread = new Thread(r); 
     thread.start(); 
    } 
} 

更新

上面的例子(恕我直言)有一些錯誤,它可以用一個簡單的對象監視器修復。

因此,而不是一個volatile標誌和while循環,我們可以使用Clip#loop功能,並且只需使用Object#waitObject#notify代替,例如

import java.io.IOException; 
import java.net.URL; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.LineUnavailableException; 

public class Audio { 

    private Clip clip; 

    private Thread thread; 
    private final Object loopLock = new Object(); 

    public static void main(String[] args) { 
     Audio audio = new Audio("Music.wav"); 
     audio.start(); 

     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException ex) { 
     } 
     audio.stop(); 
    } 

    public Audio(String audioFile) { 
     AudioInputStream audioStream = null; 

     URL audioURL = this.getClass().getClassLoader().getResource(audioFile); 

     // Obtain audio input stream from the audio file and load the information 
     // into main memory using the URL path retrieved from above. 
     try { 
      audioStream = AudioSystem.getAudioInputStream(audioURL); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 

     try { 
      // Retrieve the object of class Clip from the Data Line. 
      this.clip = AudioSystem.getClip(); 

      // Load the audio input stream into memory for future play-back. 
      this.clip.open(audioStream); 
     } catch (LineUnavailableException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 

    public void stop() { 
     synchronized (loopLock) { 
      loopLock.notifyAll(); 
     } 
    } 

    public void start() { 
     Runnable r = new Runnable() { 
      public void run() { 
       clip.setFramePosition(0); 
       clip.loop(Clip.LOOP_CONTINUOUSLY); 
       synchronized (loopLock) { 
        try { 
         loopLock.wait(); 
        } catch (InterruptedException ex) { 
        } 
       } 
       clip.stop(); 
      } 
     }; 
     thread = new Thread(r); 
     thread.start(); 
    } 
} 
+0

MadProgrammer,謝謝你的回覆。我知道clip.loop()啓動一個守護進程線程。這就是爲什麼我放這個命令的原因:Thread.sleep(5000);在調用clip.loop()後立即使非守護線程保持活動狀態。 –

+0

我試過你建立一個while循環並使用clip.drain()的建議。但是,這也沒有用。我開始懷疑這是一個環境問題。我在MacBook Pro上使用Eclipse IDE。這有什麼區別嗎?你能想到其他我可以嘗試的東西嗎? –

+0

如果聲音在播放,我看不到任何理由爲什麼上面的代碼會失敗(所有這一切都不是絕對「最好」的解決方案) – MadProgrammer