如何将 JSlider 设置为音频文件的持续时间?
Posted
技术标签:
【中文标题】如何将 JSlider 设置为音频文件的持续时间?【英文标题】:How to set a JSlider to the duration of an audio file? 【发布时间】:2018-03-29 03:12:09 【问题描述】:这个事件是否可以在 JSlider 中实现?另外,可以将滑块移动到音频文件中的某个点吗?详细来说,用户可以将滑块拖动到 JSlider 中的任何点,这会导致播放“倒带”或“跳过”。
【问题讨论】:
play sound with jslider to monitor the length of the streaming sound/music的可能重复 【参考方案1】:在这种情况下,你谷歌。不,我是认真的。
我使用java wav player adding pause and continue. 和How do I get a sound file's total time in Java? 的答案并将它们组合成一个解决方案,该解决方案允许JSlider
显示当前播放位置并更改当前播放位置。
在尝试解决此类问题时要记住的重要一点是 - 您不太可能找到完全匹配的解决方案,并且您将不得不调整许多想法以满足您的需求。
虽然以下“可能”看起来像一个完全成熟的系统,但它只是一个演示 - 它需要大量额外的工作和管理才能使其灵活和健壮 - 这是我会让你弄清楚的事情。
核心功能如下...
AudioInputStream ais = null;
try
File file = new File(...);
ais = Audiosystem.getAudioInputStream(file);
format = ais.getFormat();
frameCount = ais.getFrameLength();
duration = ((double) frameCount) / format.getFrameRate();
clip = AudioSystem.getClip();
clip.open(ais);
catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex)
ex.printStackTrace();
这基本上是加载一个音频文件,获取frameCount
并使用它来计算持续时间(以秒为单位)。然后它会创建一个Clip
,可以用来播放音频文件。
从那里开始,重置只是在播放音频时监视framePosition
(我使用Swing Timer
)并更新状态。
当用户更改JSlider
时,只需将framePosition
设置为所需的帧
例如...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineEvent.Type;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Test
public static void main(String[] args)
new Test();
public Test()
EventQueue.invokeLater(new Runnable()
@Override
public void run()
try
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex)
ex.printStackTrace();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
);
public class TestPane extends JPanel
private JSlider slider = new JSlider(0, 100);
private long frameCount;
private double duration;
private AudioFormat format;
private Clip clip;
private JLabel currentFrame;
private JLabel currentDuration;
private boolean playing = false;
private Timer playTimer;
private boolean ignoreStateChange = false;
public TestPane()
AudioInputStream ais = null;
try
File file = new File(System.getProperty("user.home") + "/Library/Application Support/Steam/Steam.AppBundle/Steam/Contents/MacOS/friends/voice_hang_up.wav");
ais = AudioSystem.getAudioInputStream(file);
format = ais.getFormat();
frameCount = ais.getFrameLength();
duration = ((double) frameCount) / format.getFrameRate();
clip = AudioSystem.getClip();
clip.open(ais);
catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex)
ex.printStackTrace();
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
setLayout(new GridBagLayout());
add(slider, gbc);
slider.setValue(0);
add(new JLabel("Total Frames: " + frameCount), gbc);
add(new JLabel("Total Duration: " + duration), gbc);
currentFrame = new JLabel("Current frame: 0");
currentDuration = new JLabel("Current duration: 0");
add(currentFrame, gbc);
add(currentDuration, gbc);
JButton action = new JButton("Play");
action.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
if (!playing)
int frame = getDesiredFrame();
if (frame >= frameCount)
frame = 0;
clip.setFramePosition(frame);
clip.start();
action.setText("Stop");
playing = true;
playTimer.start();
else
clip.stop();
action.setText("Play");
playing = false;
playTimer.stop();
);
clip.addLineListener(new LineListener()
@Override
public void update(LineEvent event)
if (event.getType().equals(Type.STOP)
|| event.getType().equals(Type.CLOSE))
action.setText("Play");
playing = false;
playTimer.stop();
updateState();
);
add(action, gbc);
playTimer = new Timer(100, new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
updateState();
);
Timer delayedUpdate = new Timer(250, new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
int frame = getDesiredFrame();
clip.setFramePosition(frame);
double time = getCurrentTime();
currentFrame.setText("Current frame: " + frame);
currentDuration.setText("Current duration: " + time);
);
delayedUpdate.setRepeats(false);
slider.addChangeListener(new ChangeListener()
@Override
public void stateChanged(ChangeEvent e)
if (ignoreStateChange)
return;
delayedUpdate.restart();
);
public void updateState()
ignoreStateChange = true;
int frame = clip.getFramePosition();
int progress = (int) (((double) frame / (double) frameCount) * 100);
slider.setValue(progress);
currentFrame.setText("Current frame: " + getDesiredFrame());
currentDuration.setText("Current duration: " + getCurrentTime());
ignoreStateChange = false;
public double getCurrentTime()
int currentFrame = clip.getFramePosition();
double time = (double) currentFrame / format.getFrameRate();
return time;
public int getDesiredFrame()
int progress = slider.getValue();
double frame = ((double) frameCount * ((double) progress / 100.0));
return (int) frame;
【讨论】:
以上是关于如何将 JSlider 设置为音频文件的持续时间?的主要内容,如果未能解决你的问题,请参考以下文章