2012-11-24 58 views
0

我已經瀏覽了互聯網上播放wav文件的方式,但是我發現它們不會在單獨的線程中播放,因此會導致程序停止播放,直到歌曲完成,這對遊戲無效。但是,當我嘗試在單獨的線程上播放所有內容時,它會滯後。有沒有人有這方面的修復?如何播放沒有滯後的wav文件?

注:我也是畫在不斷的背景:

public class DrawThread extends Thread { 

    JFrame j; 

    public DrawThread(JFrame frame) { 
     j = frame; 
    } 

    public void run() { 
     while (!(isInterrupted())) { 
      if (j.isDisplayable() && j.isActive() && j.isEnabled()) 
      j.update(j.getGraphics()); 
     } 
    } 

} 

和更新只是調用paint是:

public void paint(Graphics g) { 
      Graphics2D bg = (Graphics2D) g; 
    bg.setBackground(Color.black); 
    int w = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); 
    int h = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); 
    if (time < 500) { 
     x[time] = r.nextInt(w) + 150; 
     y[time] = h; 
     z[time] = r.nextInt(w) + 150; 
     time++; 
    } 
    for (int i = 0; i < time; i++) { 
     y[i] -= forward; 
     x[i] -= right; 
     if (y[i] < 1) { 
      x[i] = r.nextInt(400) - 200; 
      y[i] = 300; 
      z[i] = r.nextInt(400) - 200; 
     } else if (y[i] > 300) { 
      x[i] = r.nextInt(400) - 200; 
      y[i] = 1; 
      z[i] = r.nextInt(400) - 200; 
     } 
     if (x[i] > 200) 
      x[i] = -200; 
     else if (x[i] < -200) 
      x[i] = 200; 
     bg.setColor(color); 
     bg.drawLine(
       getWidth()/2 + (int) Math.round(x[i] * 200/y[i]), 
       getHeight()/2 + (int) Math.round(z[i] * 200/y[i]), 
       getWidth() 
         /2 
         + (int) Math.round((x[i] + right) * 200 
           /Math.abs(y[i] + forward)), 
       getHeight() 
         /2 
         + (int) Math.round((z[i]) * 200 
           /Math.abs(y[i] + forward))); 
    } 
} 

編輯:添加我使用的音樂播放器類(我已經切換到BigClip):

import java.io.File; 
import java.util.Collection; 
import java.util.HashMap; 

import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 

import org.crystalix.util.SoundListener; 

public class MSHandler { 
public static boolean pause = false; 
public static boolean stop = false; 
private static HashMap<String, BigClip> clips = new HashMap<String, BigClip>(); 

public static void stopAll() { 
    Collection<BigClip> c = clips.values(); 
    for (BigClip b : c) { 
     System.out.println("Stopping "+b.toString()); 
     b.stop(); 
     System.out.println("Stopped "+b.toString()); 
    } 
} 

public static void playMusic(File file) { 
    try { 
     AudioInputStream audioIn = AudioSystem.getAudioInputStream(file); 
     BigClip clip = new BigClip(); 
     clip.open(audioIn); 
     clip.addLineListener(new SoundListener()); 
     clip.loop(1); 
     clip.start(); 
     clips.put(file.getName(), clip); 
    } catch (Exception e) { 
     System.err.println("Sound could not be started!"); 
     e.printStackTrace(System.err); 
    } 
} 
} 
+0

1)'j.update(j.getGraphics());'不要那樣做。這很可能導致許多其他問題。 2)爲了更快地獲得更好的幫助,請發佈[SSCCE](http://sscce.org/)。 3)使用'Clip'作爲聲音,如[Java Sound tag Wiki](http://stackoverflow.com/tags/javasound/info)所示。 –

+0

你會如何建議我儘可能經常畫畫?這是我能找到的重複繪製的唯一方法,因爲它默認不會這樣做。此外,該文件是音樂,沒有聲音,所以剪輯不起作用,因爲它太大。我實際上使用剪輯,它失敗了。 –

+0

*「您會如何嘗試儘可能頻繁地繪畫?」*使用直接與視頻卡連接的語言。 *「..它太大了,我實際上使用了Clip並且失敗了」*在這種情況下,請使用['BigClip'](http://stackoverflow.com/a/5668510/418556)。 –

回答

0

你沒有顯示你用於wav文件的代碼playbac ķ。這使得診斷可能發生錯誤的過程有點困難!

1)該wav應該只是在自己的線程。如果你做得正確,它不會阻止其他任何事情。 Java聲音教程並沒有特別指出這一點。所以:把調用wav播放的代碼放在它自己的可運行模式中,你應該沒問題。 2)你可以在你想播放之前「打開」wav。然後,當你最終告訴它時,它應該立即「開始」。

另一個注意事項:如果播放wav文件的代碼已經在內存中,則運行速度會更快。所以,有時第一次wav播放只是在稍微猶豫後纔開始。但可以通過播放零音量的另一個聲音來將聲音重放代碼存入內存來對抗這種情況。我經常在有聲的節目開始時這樣做。

如果您使用了太多的cpus以致JVM沒有時間處理聲音,那麼在後臺進行連續繪製只是一個問題。如果那是問題,我真的很驚訝。如果是這樣,您可能會聽到的聲音回放有很多點擊。

+0

我把問題中播放wav文件的代碼。我遇到的問題是聲音切斷並在某些點跳躍,然後平滑,然後再次開始跳躍。 –

+0

切入和切出通常是由於沒有足夠快地將音頻數據饋送到輸出線以跟上播放速度。嘗試使用您的wav文件的SourceDataLine,而不是需要大量RAM的BigClip。也許BigClip,如果在錯誤的情況下使用觸發器頁面交換?也把播放放在它自己的線程中。我還沒有看到你在做什麼。我會嘗試自行運行聲音,以確保它已正確設置,然後開始添加圖形並查看它何時發生故障。你的圖形可能只是消耗太多的CPU以允許併發聲音。 –

+0

是Andrew的BigClip嗎?如果是這樣,它使用SourceDataLine並啓動一個新的線程。 –