Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用音频文件作为进度条更新jslider_Java_Audio_Jslider - Fatal编程技术网

Java 如何使用音频文件作为进度条更新jslider

Java 如何使用音频文件作为进度条更新jslider,java,audio,jslider,Java,Audio,Jslider,我有一个wav音频文件。我知道如何在java中使用AudioInputStream播放它。我学会了创建jslider。现在我必须使用滑块作为音频的进度条,例如音频播放,所以滑块向前移动。如果用户更改滑块的位置,音频文件必须从该位置播放 我是java新手,在帖子中可能会有一些错误。请忽略它们 所以,当滑块得到更新时,我一直在更新音轨。我尝试将changeListner添加到slider,但无法使其工作 这是密码 import java.io.File; import java.util.Timer

我有一个wav音频文件。我知道如何在java中使用AudioInputStream播放它。我学会了创建jslider。现在我必须使用滑块作为音频的进度条,例如音频播放,所以滑块向前移动。如果用户更改滑块的位置,音频文件必须从该位置播放

我是java新手,在帖子中可能会有一些错误。请忽略它们

所以,当滑块得到更新时,我一直在更新音轨。我尝试将changeListner添加到slider,但无法使其工作

这是密码

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);
}


}
}

从而解决了滑块的更新问题。我使用了一个计时器,在这个计时器中,我获取音频曲目的当前帧,将其转换为持续时间,并每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.setFramePositionint frames

运行代码时我观察到的情况如下:JSlider确实会更新,但仅每秒更新一次或稍快一点

我不知道这是否是答案,但也许值得考虑。有时,重新绘制的调用会被折叠。可能是EDT没有对每个重绘调用做出反应,而是决定相邻调用足够相似,可以折叠成更少的重绘。我注意到,如果我在TimerTask中放入System.out.printlntimeNow,控制台上每秒会打印大约33个timeNow,我假设这是您希望JSlider更新的速率

我发现,如果我在一个单独的类中有一个计时器及其TimerTask,并从那里调用一个重新绘制,那么EDT崩溃重新绘制的可能性会更小。我记得有一次在JPanel上安装计时器之前,让它调用自己的重新绘制给了我类似的崩溃EDT结果


我不知道这背后的确切机制或理论。所以这可能不是最好的建议。但是,将计时器代码分离到它自己的类中还是值得的。为此,您还必须将JFrame和剪辑的副本传递给本课程。

您至少尝试过什么吗?如果是这样,请在此处发布您的代码,以便对其进行改进。我们不会为你做所有的工作。我不知道你到目前为止有什么,但我假设你正在使用数据线而不是剪辑在线程中播放音频。从这里开始,它就是简单的数学。从0%开始,声音文件的结尾是100%。找到音频文件的长度,然后在音频文件播放时跟踪您进入音频文件的距离,并相应地从线程调整滑块。我相信它会像currentPositionInTrack/TotalEngthoftrack*100一样,希望我没有错,但这会给你完成百分比。如果你需要更多的帮助,你必须更加具体。因此,更新滑块的问题就解决了。我使用了一个计时器,在这个计时器中,我可以获得当前的音轨帧,将其转换为持续时间,并每30毫秒更新一次计时器。但我仍然无法在滑块的更新中更新音轨。