如何将 JSlider 设置为音频文件的持续时间? [英] How to set a JSlider to the duration of an audio file?

查看:33
本文介绍了如何将 JSlider 设置为音频文件的持续时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个事件是否可以在 JSlider 中实现?另外,可以将滑块移动到音频文件中的某个点吗?具体来说,用户可以将滑块拖动到 JSlider 中的任何一点,这会导致播放倒带"或跳过".

Is this event possible to implement in a JSlider or not? Also, can one be able to move the slider to a certain point in the audio file? To Elaborate, the user can drag the slider to any point in the JSlider which causes the playback to "rewind" or "skip".

推荐答案

在这种情况下,你谷歌一下.不,我是认真的.

In situation like this, you google. No I'm serious.

我使用了 java wav 播放器添加暂停和继续.我该怎么做在 Java 中获取声音文件的总时间? 并将它们组合成一个解决方案,允许 JSlider 显示当前播放位置并更改当前播放位置.

I used the answer from java wav player adding pause and continue. and How do I get a sound file's total time in Java? and combined them into a solution which allows a JSlider to display the current playback position AND change the current playback position.

在尝试解决此类问题时要记住的重要一点是 - 您不太可能找到完全匹配的解决方案,您将不得不调整许多想法来满足您的需求.

The important thing to remember when trying to solve problems like this is - it's unlikely you will find an exact matching solution and you're going to have to adapt a number of ideas to meet your needs.

虽然下面的可能"看起来像一个完全成熟的系统,但它只是一个演示 - 它需要大量额外的工作和管理才能使其灵活和强大 - 这是我会让你弄清楚的事情.

While the following "might" look like a fully fledge system, it's just a demonstration - it needs a lot of additional work and management to make it flexible and robust - this is something I'll leave you to figure out.

核心功能如下...

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 可以用来播放音频文件.

This basically loads a audio file, obtains the frameCount and uses it to calculate the duration in seconds. It then creates a Clip which can be used play the audio file.

从那里开始,重置只是在播放音频时监视 framePosition(我使用 Swing Timer)并更新状态.

From there, the reset is just about monitoring the framePosition while the audio is been played (I use a Swing Timer) and updating the state.

JSlider 被用户更改时,这只是将 framePosition 设置为所需的帧

When the JSlider is changed by the user, this simply sets the framePosition to the desired frame

例如...

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 设置为音频文件的持续时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆