2009-02-17 52 views
6

我正在使用以下代碼使用java聲音API播放聲音文件。我該如何等待java聲音剪輯才能完成播放?

Clip clip = AudioSystem.getClip(); 
    AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream); 
    clip.open(inputStream); 
    clip.start(); 

該方法調用Clip.start()方法立即返回,系統在後臺線程中播放聲音文件。我希望我的方法暫停,直到播放完成。

有什麼好方法可以做到嗎?

編輯:對於大家感興趣的我最終解決方案的基礎上,從開放的答案,我用下面的代碼:

private final BlockingQueue<URL> queue = new ArrayBlockingQueue<URL>(1); 

public void playSoundStream(InputStream stream) { 
    Clip clip = AudioSystem.getClip(); 
    AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream); 
    clip.open(inputStream); 
    clip.start(); 
    LineListener listener = new LineListener() { 
     public void update(LineEvent event) { 
       if (event.getType() != Type.STOP) { 
        return; 
       } 

       try { 
        queue.take(); 
       } catch (InterruptedException e) { 
        //ignore this 
       } 
     } 
    }; 
clip.addLineListener(listener); 
} 

回答

4

聲音片段是一種或線路,因此支持線聽衆。

如果使用addLineListener,則應在播放開始和停止時獲取事件;如果你不在循環中,當剪輯結束時應該停下來。但是,與任何事件一樣,在播放和停止的實際結束之前可能會有滯後。

使方法等待稍微棘手。您可以忙於等待(不是一個好主意),也可以使用其他同步機制。我認爲有一種模式(不確定)等待長時間的操作來完成一個完成事件,但這是一個普遍的問題,你可能想單獨發佈到SO。

6

你可以把這個代碼,而不是:

假設你CLIP1是玩,你想之後,要播放的CLIP2,您可以:

clip1.start(); 
while(clip1.getMicrosecondLength() != clip1.getMicrosecondPosition()) 
{ 
} 
clip2.loop(some int here); 

和,使這項工作不延遲你的主要任務(我這樣說是因爲while循環使得工作等待clip1完成,不管下一步工作是什麼......),你可以在你希望發生的地方創建一個新線程,把代碼放在run()方法中... GOOD LUCK!

+0

這工作就像一個簡單的文本到語音應用程序,我正在對一個魅力。 – progyammer 2016-09-23 08:53:12

0

由於JDK8的,Clip的監聽器是一種越野車的(即可能發生的是它激發了Type.STOP兩次音頻(.start())的單再現。

因此我會使用類似:

Clip[] myBunchOfClipsToPlaySequentially=new Clip[A_BUNCH]; 
// 
// [load actual clips...] 
// [...] 
// 
for(Clip c: myBunchOfClipsToPlaySequentially) 
    while(c.getFramePosition()<c.getFrameLength()) 
     Thread.yield(); // Note that if we simply put a NO-OP instead (like a 
         // semicolon or a {}), we make our CPU 
         // cry). Thread.yield() allows for almost 0% CPU consumption. 

此外,你可以看看新AudioClip類JFX8提供(有一些漂亮的方法亂動)

0

我使用了一個等待/通知來實現這只是FO。你的參考。

 final Clip clip = AudioSystem.getClip(mixerInfo); 
     clip.addLineListener(new LineListener(){ 

      @Override 
      public void update(LineEvent e) { 
       if (e.getType()==LineEvent.Type.STOP){ 
        synchronized(clip){ 
         clip.notifyAll(); 
        } 
        System.err.println("STOP!"); 
       } 

      } 

     }); 
     clip.open(as); 
     clip.start(); 
     while (true){ 
      synchronized(clip){ 
       clip.wait(); 
      } 
      if (!clip.isRunning()){ 
       break; 
      } 
     } 
     clip.drain(); 
     clip.stop(); 
     clip.close(); 
1

我更喜歡用Java 8是這樣的:

CountDownLatch syncLatch = new CountDownLatch(1); 

try (AudioInputStream stream = AudioSystem.getAudioInputStream(inStream)) { 
    Clip clip = AudioSystem.getClip(); 

    // Listener which allow method return once sound is completed 
    clip.addLineListener(e -> { 
    if (e.getType() == LineEvent.Type.STOP) { 
     syncLatch.countDown(); 
    } 
    }); 

    clip.open(stream); 
    clip.start(); 
} 

syncLatch.await();