如何将 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 设置为音频文件的持续时间?的主要内容,如果未能解决你的问题,请参考以下文章

JSlider 问题音频播放器

MP3/wav 音频文件的持续时间

如何反转 AAC 音频文件?

如何获取音频文件的持续时间?

如何使用 swift 仅在已知持续时间内流式传输音频

Mediaplayer 应该只播放音频文件的最后几秒钟