2013-04-06 4 views
1

У меня есть аудиофайл wav. Я знаю, как играть в нее с помощью AudioImputStream в java. Я научился создавать 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

+0

Я понятия не имею, что у вас есть, но я собираюсь предположить, что вы воспроизводите аудио обратно в потоке, используя DataLine, а не клип. Оттуда его простая математика. Вы начинаете с 0%, а конец звукового файла - 100%. Найдите длину аудиофайла, а затем, когда воспроизводятся звуковые файлы, отслеживайте, насколько далеко вы находитесь в аудиофайле, и отрегулируйте слайдер соответственно от потока.Я считаю, что это будет что-то вроде currentPositionInTrack/totalLengthOfTrack * 100, надеюсь, я не ошибаюсь, но это должно дать вам процент завершен. Если вам нужна дополнительная помощь, вам нужно быть более конкретным. –

+0

Итак, проблема обновления слайдера решена. Я использовал таймер, в котором я получаю текущий кадр звуковой дорожки, конвертирую его в продолжительность и обновляю таймер каждые 30 миллисекунд. – jas

ответ

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 не реагирует на каждый вызов перерисовки, но вместо этого решает, что смежные вызовы достаточно похожи, чтобы их можно было разложить на меньшее количество рецензий. Я замечаю, что если я поставлю System.out.println (timeNow) в TimerTask, на консоль в секунду будет напечатано 33 момента времени. Я предполагаю, что скорость, по которой вы хотите, чтобы ваш JSlider обновлялся.

Я обнаружил, что если у меня есть таймер в отдельном классе (вместе с его TimerTask) и вызовите перерисовку оттуда, вероятность того, что EDT будет сворачивать рецензенты, будет меньше. Я помню один раз перед тем, как поставить Timer на JPanel, где его вызов «его собственная» перерисовка дала мне аналогичный результат «рухнувшего EDT».

Я не знаю точного механизма или теории. Так что это не самый лучший совет. Но все равно стоит выделить код таймера в свой класс. Для этого вам также придется перейти к этим классам копий JFrame и Clip.

 Смежные вопросы

  • Нет связанных вопросов^_^