java – 使用Clip对象播放多个声音片段
作者:互联网
我正在开发一个包含大量JButton对象的程序,我希望每个对象都有自己的.wav文件.此外,我希望声音以某种方式工作,使得它们可以与其他按钮的声音重叠,但它不能与自身重叠(在播放声音时单击按钮将重新启动声音).
我尝试使用一个Clip对象,但我无法完成上面所说的内容.结果,我使用每个按钮声明一个新的Clip对象,但我觉得这对我的问题来说是一个相当低效的解决方案.
我怎样才能以最有效的方式完成我在第一段中所说的内容?
解决方法:
有几种方法可以实现这一点,但基本思路是,您希望将LineListener注册到Clip并监视LineEvent.Type.STOP事件并重新启用该按钮
例如.这将查找给定目录中的所有.wav文件,并为每个文件创建一个按钮.单击时,按钮(或更重要的是,基础操作)被禁用并播放音频.当它停止时,重新启用Action(和扩展按钮).
无论如何,Sound API可以同时播放多个声音
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
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 {
public TestPane() {
File[] musicFiles = new File("a directory somewhere").listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().toLowerCase().endsWith(".wav");
}
});
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
for (File music : musicFiles) {
try {
JButton btn = new JButton(new AudioAction(music.getName(), music.toURI().toURL()));
add(btn, gbc);
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
}
}
public class AudioAction extends AbstractAction {
private URL audio;
public AudioAction(String name, URL audioSource) {
super(name);
this.audio = audioSource;
}
public URL getAudioSource() {
return audio;
}
@Override
public void actionPerformed(ActionEvent e) {
setEnabled(false);
try (InputStream is = getAudioSource().openStream()) {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(is);
Clip play = AudioSystem.getClip();
play.addLineListener(new LineListener() {
@Override
public void update(LineEvent event) {
System.out.println(event.getFramePosition());
if (event.getType().equals(LineEvent.Type.STOP)) {
setEnabled(true);
}
}
});
play.open(audioInputStream);
play.start();
} catch (IOException | LineUnavailableException | UnsupportedAudioFileException exp) {
exp.printStackTrace();
}
}
}
}
nb:我尝试使用Clip#drain(在后台线程中),但它只适用于第一个剪辑,后续剪辑基本上跳过了方法,因此我选择了LineListener
现在有了更好的资源管理
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
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 {
public TestPane() {
File[] musicFiles = new File("...").listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().toLowerCase().endsWith(".wav");
}
});
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
for (File music : musicFiles) {
try {
JButton btn = new JButton(new AudioAction(music.getName(), music.toURI().toURL()));
add(btn, gbc);
} catch (MalformedURLException exp) {
exp.printStackTrace();
}
}
}
}
public class AudioAction extends AbstractAction {
private AudioPlayer player;
public AudioAction(String name, URL audioSource) {
super(name);
player = new AudioPlayer(audioSource);
}
@Override
public void actionPerformed(ActionEvent e) {
if (player.isPlaying()) {
player.stop();
} else {
try {
player.play();
} catch (IOException | LineUnavailableException | UnsupportedAudioFileException ex) {
ex.printStackTrace();
}
}
}
}
public class AudioPlayer {
private Clip clip;
private URL url;
public AudioPlayer(URL url) {
this.url = url;
}
public boolean isPlaying() {
return clip != null && clip.isRunning();
}
protected void open() throws IOException, LineUnavailableException, UnsupportedAudioFileException {
clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(url.openStream()));
}
public void play() throws IOException, LineUnavailableException, UnsupportedAudioFileException {
if (clip == null || !clip.isRunning()) {
open();
clip.setFramePosition(0);
clip.start();
}
}
public void stop() {
if (clip != null && clip.isRunning()) {
clip.stop();
clip.flush();
dispose();
}
}
public void dispose() {
try {
clip.close();
} finally {
clip = null;
}
}
}
}
标签:javasound,clip,java,audio,swing 来源: https://codeday.me/bug/20190919/1812555.html