2013-04-06 55 views
1

我有一個wav音頻文件。我知道如何在java中使用AudioImputStream播放它。我學會了創建一個jslider。現在,我必須將滑塊用作音頻的進度條,例如音頻播放,因此滑塊向前移動。如果用戶改變滑塊的位置,則音頻文件必須從該位置播放。如何用音頻文件更新jslider作爲進度條

我是新來的java,可能會有一些錯誤,我可能不會在帖子中。請忽略它們

所以我被困在更新音軌時滑塊得到更新。我嘗試添加changeListner滑塊,但我無法讓它工作。

下面的代碼

import java.io.File; 
import java.util.Timer; 
import java.util.TimerTask; 

import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.Clip; 
import javax.sound.sampled.DataLine; 
import javax.swing.JFrame; 
import javax.swing.JSlider; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 


public class audio { 

public static void main(String args[]) 
{ 

try { 
final JFrame f=new JFrame(); 
File yourFile; 
AudioInputStream stream; 
AudioFormat format; 
DataLine.Info info; 
final Clip clip; 
yourFile = new File(fileName); 

stream = AudioSystem.getAudioInputStream(yourFile); 
format = stream.getFormat(); 
final long frames =stream.getFrameLength(); 
final double durationInSeconds = (frames+0.0)/format.getFrameRate(); 
final JSlider slider=new JSlider(0,(int) Math.round(durationInSeconds),0); 
info = new DataLine.Info(Clip.class, format); 
clip = (Clip) AudioSystem.getLine(info); 
clip.open(stream); 
clip.start(); 

f.add(slider); 
f.pack(); 
f.setLocationRelativeTo(null); 
f.setVisible(true); 
TimerTask timerTask=new TimerTask(){ 

@Override 
public void run() { 
// TODO Auto-generated method stub 
{ 
double timeNow=(durationInSeconds*clip.getFramePosition())/frames; 
slider.setValue((int)Math.round(timeNow)); 
f.repaint(); 
} 

} 
}; 
Timer timer = new Timer("MyTimer");//create a new Timer 

timer.scheduleAtFixedRate(timerTask, 30, 30);//this line starts the timer at the same time its executed 


} 

catch (Exception e) { 
System.out.println(e); 
} 


} 
} 
+0

你有沒有試過至少有的東西?如果是這樣,請在此發佈代碼,以便可以改進。我們不會爲你做所有的**工作。 – D180 2013-04-06 20:16:17

+0

我不知道你到目前爲止有什麼,但我會假設你使用DataLine而不是Clip來在線程中播放音頻。從那裏它簡單的數學。你從0%開始,聲音文件的結尾是100%。查找音頻文件的長度,然後在音頻文件播放時跟蹤您所在音頻文件的距離,並相應地從線程調整滑塊。我相信它會是currentPositionInTrack/totalLengthOfTrack * 100之類的東西,希望我沒有錯,但是應該給你完成的比例。如果你需要更多的幫助,你必須更具體。 – 2013-04-06 20:28:23

+0

因此解決了更新滑塊的問題。我使用了一個定時器,在該定時器中,我獲取當前音軌的幀,將其轉換爲持續時間並每30毫秒更新一次定時器。 – jas 2013-04-06 21:29:45

回答

0

所以更新滑塊的問題就解決了。我使用了一個定時器,在該定時器中,我獲取當前音軌的幀,將其轉換爲持續時間並每30毫秒更新一次定時器。

但我仍然堅持如何更新滑塊的更新軌道。

我不明白你爲什麼要手動更新曲目:如果你已經可以獲得音軌的當前幀,它必須更新。所以,解決你可能會面臨的問題:

如果滑塊沒有更新正確,我發現從組件刪除它,然後更新它,然後重新添加它的工作:

@Override 
public void run() { 
// TODO Auto-generated method stub 
{ 
f.remove(slider); 
double timeNow=(durationInSeconds*clip.getFramePosition())/frames; 
slider.setValue((int)Math.round(timeNow)); 
f.add(slider); 
f.repaint(); 
} 

如果你想手動更新您的剪輯,使用clip.setFramePosition(int frames)

0

什麼我觀察,當我運行代碼如下:JSlider的該會更新,但只有每秒一次(或稍快)。

我不知道這是否是答案,但也許值得考慮。有時調用重畫是「摺疊」。 EDT可能是這樣的情況,即對每次重繪呼叫都沒有反應,而是決定相鄰的呼叫足夠相似以致它們可以摺疊成更少的重繪。我注意到,如果我在TimerTask中放置一個System.out.println(timeNow),則每秒鐘會在控制檯上打印大約33個timeNow,我認爲這是您希望JSlider更新的速率。

我發現,如果我有一個單獨的類中的計時器(以及它的TimerTask),並從那裏調用重繪,那麼EDT崩潰重繪的可能性會更小。我記得在JPanel上放置一個定時器之前,曾經稱之爲「自己的」重繪給了我一個類似的「崩潰的EDT」結果。

我不知道背後的確切機制或理論。所以這可能不是最好的建議。但是將計時器代碼分離出來可能還是值得的。要做到這一點,你還必須傳遞給這個類的JFrame和Clip副本。