2012-04-17 72 views
1

我想在我的Java應用程序中播放mp3。用戶有能力點擊按鈕並改變聲音。以延遲結束的Java線程

聲音和切換工作...但是當用戶試圖切換聲音時,新的歌曲開始在舊的播放器上播放約一秒鐘,然後在舊的播放器停止播放。我正在嘗試使用線程來處理一切。

我的MP3類:

import java.applet.*; 
import javazoom.jl.player.Player; 
import java.io.*; 
import java.io.FileInputStream; 
import java.net.*; 

public class mp3 extends Thread implements Runnable{ 

    private Player sound; 
    private InputStream path; 
    public mp3(String file_name) { 
     path = mp3.class.getClassLoader().getResourceAsStream(file_name); 
    } 
    public void run(){ 
     try { 
      Player sound=new Player(path); 
      sound.play(); 
     } catch(Exception e) {System.out.println(e);} 
    } 
} 

這就是我試圖在我的主遊戲運行代碼。 MP3對象被稱爲歌曲。

當應用程序初始化,下面的代碼運行:

song = new mp3("default.mp3"); 
song.start(); 

有人試圖去改變它,下面的代碼運行:

song.stop(); 
song = new mp3(t+".mp3"); 
song.start(); 

其中T是文件名的參數。

我很確定這個問題依賴於MP3對象的運行功能。我對線程完全陌生,所以我希望得到一些幫助。

同樣,從「停止」被調用的時間和實際停止播放的時間延遲約爲1秒。所以也許在那裏等一下?

謝謝!

編輯:我使用的代碼基於離這裏現在:

http://introcs.cs.princeton.edu/java/faq/mp3/MP3.java.html

我創建了一個播放和定義關閉功能如下:

public void close() { if (player != null) player.close(); } 

    // play the MP3 file to the sound card 
    public void play() { 
     try { 
      FileInputStream fis  = new FileInputStream(filename); 
      BufferedInputStream bis = new BufferedInputStream(fis); 
      player = new Player(bis); 
     } catch (Exception e) { 
      System.out.println("Problem playing file " + filename); 
      System.out.println(e); 
     } 

     // run in new thread to play in background 
     new Thread() { 
      public void run() { 
       try { player.play(); } 
       catch (Exception e) { System.out.println(e); } 
      } 
     }.start(); 

我的問題是關閉功能...播放器對象始終爲空,並且關閉功能不會執行..即使播放函數初始化它。爲什麼它是空的?

+1

'Thread.stop()'是不推薦使用的方法,不應使用。 – Gray 2012-04-17 05:09:25

+0

['Clip'](http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/Clip.html)或['BigClip'](http: //stackoverflow.com/a/9470886/418556)。 – 2012-04-17 08:33:46

+0

可以擴展Thread或實現Runnable。沒有必要這樣做。關閉線程很可能不是立即停止聲音的正確方法。 Javazoom的播放器應該提供一些方法。如果沒有,那麼這是他們的對象的缺陷。另外,Player的每個實例可能都應該在自己的線程中,而不是試圖重用。 – 2012-04-18 04:41:53

回答

1

編輯:

在你的編輯,如果將多個線程訪問player領域,那麼它應該作出volatile。沒有看到如何定義player,否則很難猜測問題。


我認爲你需要確保該Player已經完成了先前的MP3在你開始下之前。展望javadocs for Player我看到:

`player.isComplete()` 

引述:

返回true,如果所有可用的MPEG音頻幀已被解碼,否則爲false

如果要停止之前的當新聲音開始時,您應該在舊播放器上使用close()

關閉此播放器。任何音頻當前正在播放的是立即停止

聲音對我說,你需要關閉當前運行Player對象(如果有的話),並開始一個新的Player對象打新的聲音。如果你這樣做是在多線程,那麼你就需要做一些事情,如:

  1. 鎖定某些final Object lock對象
  2. 如果你想目前的聲音來完成,檢查當前Player對象(如果有的話)已完成與sleep
  3. close()當前Player對象和循環創建一個新的Player如果你想殺死電流聲
  4. 呼叫play()下一個MP3,
  5. 解鎖鎖定對象。

據我所知,play()方法不會等待要播放的聲音,但在加載聲音到音頻緩衝區後立即返回。我不確定如果音頻文件很大,會發生什麼情況。

+0

感謝您的迴應。我試圖創建一個函數,當我需要改變聲音時調用sound.close。但是,更改聲音文件後,似乎可以防止再次使用該聲音。我得到一個空指針異常。 close()某種析構函數? – 2012-04-17 05:32:30

+0

它可能是@Katherine。是的,看着這個文檔你可能需要創建一個新的'Player'對象。我已經改變了我的答案,以彌補這一點。 – Gray 2012-04-17 13:36:25