我编写了这两个类来测试我如何使用Java Sound API:
enum SoundEffect
:枚举封装了我使用过的所有声音。
Class SoundEffectDemo
:在Swing应用程序中测试SoundEffect枚举
当我点击SoundEffectDemo(CALLING,RING,BUSY)的任何按钮时,声音开始播放。当我点击“停止声音”按钮时,声音停止。 但是当我第二次点击SoundEffectDemo(CALLING,RING,BUSY)的任何按钮时,没有任何声音。
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
public enum SoundEffect {
BUSY("resources/phone-busy.wav"),
CALLING("resources/phone-calling.wav"),
DISCONNECT("resources/phone-disconnect.wav"),
RING("resources/telephone-ring.wav");
// Each sound effect has its own clip, loaded with its own sound file.
private Clip clip;
private URL url;
private AudioInputStream audioInputStream;
// Constructor to construct each element of the enum with its own sound file.
SoundEffect(String soundFileName) {
try {
// Use URL (instead of File) to read from disk and JAR.
this.url = this.getClass().getClassLoader().getResource(soundFileName);
// Set up an audio input stream piped from the sound file.
this.audioInputStream = AudioSystem.getAudioInputStream(url);
// Get a clip resource.
clip = AudioSystem.getClip();
// Open audio clip and load samples from the audio input stream.
clip.open(audioInputStream);
clip.addLineListener( new LineListener() {
public void update(LineEvent evt) {
if (evt.getType() == LineEvent.Type.STOP) {
evt.getLine().close();
}
}
});
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
// Play or Re-play the sound effect from the beginning, by rewinding.
public void play() {
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void stop(){
clip.stop(); // Stop the player if it is still running
}
// Optional static method to pre-load all the sound files.
static void init() {
values(); // calls the constructor for all the elements
}
public boolean isActive(){
return clip.isActive();
}
public boolean isOpen() {
return clip.isOpen();
}
public void setFramePosition() {
clip.setFramePosition(0);
}
}
import java.awt.*;
import java.awt.event.*;
import javax.sound.sampled.LineEvent;
import javax.swing.*;
// Testing the SoundEffect enum in a Swing application
@SuppressWarnings("serial")
public class SoundEffectDemo extends JFrame {
// Constructor
public SoundEffectDemo() {
// Pre-load all the sound files
// Set up UI components
Container cp = this.getContentPane();
cp.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
JButton btnSound1 = new JButton("CALLING");
btnSound1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SoundEffect.CALLING.play();
}
});
cp.add(btnSound1);
JButton btnSound2 = new JButton("RING");
btnSound2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SoundEffect.RING.play();
}
});
cp.add(btnSound2);
JButton btnSound3 = new JButton("BUSY");
btnSound3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SoundEffect.BUSY.play();
}
});
cp.add(btnSound3);
JButton btnSound4 = new JButton("Stop Sound ");
btnSound4.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(SoundEffect value : SoundEffect.values()){
if(value.isActive()){
value.stop();
}
}
}
});
cp.add(btnSound4);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Test SoundEffct");
this.pack();
this.setVisible(true);
}
public static void main(String[] args) {
new SoundEffectDemo();
}
}
答案 0 :(得分:1)
clip.addLineListener( new LineListener() {
public void update(LineEvent evt) {
if (evt.getType() == LineEvent.Type.STOP) {
evt.getLine().close();
}
}
});
这可能不是您想要做的事情,在收到停止事件时关闭该行。关闭剪辑后,您需要重新打开它才能再次播放。
鉴于你正在做的事情,你可能根本就不需要关闭这条线。呼叫关闭表示您已完成此操作。
请参阅Line#close
和AutoCloseable#close
。
针对您的停止活动的更合适的临时行动将是drain
或flush
。然后,如果要“重置”它,可能将帧位置设置为0.
因此请删除对close
的调用并执行类似
public void stop() {
clip.stop();
clip.flush();
clip.setFramePosition(0);
}
作为旁注,我注意到你没有在Event Dispatch Thread上启动你的Swing应用程序。你应该总是initialize your GUI with a call to invokeLater
,例如:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new SoundEffectDemo();
}
});
}
使用Swing进行线程安全很重要,因为不这样做会导致难以诊断的细微错误。
答案 1 :(得分:0)
通过重新播放java中的音频,你的意思并不是很清楚。
您的代码不相关,因为从它的外观看,您已将所有内容放在一个代码块中,这使得难以阅读。你错过了几个括号。但回到你的问题。我已经组建了一个简单的课程,可以满足您的要求。
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
public class PlaybackWAV {
private final int BUFFER_SIZE = 128000;
private AudioInputStream audioStream;
private AudioFormat audioFormat;
private SourceDataLine sourceLine;
private boolean running = false;
/**
* @param filename
* the name of the file that is going to be played
*/
public synchronized void playSound(final String filename) {
new Thread(new Runnable() {
public void run() {
try {
InputStream audioSrc = this.getClass().getResourceAsStream(filename);
// add buffer for mark/reset support
InputStream bufferedIn = new BufferedInputStream(audioSrc);
audioStream = AudioSystem.getAudioInputStream(bufferedIn);
audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(
SourceDataLine.class, audioFormat);
sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open(audioFormat);
sourceLine.start();
running = true;
while (running) {
int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
try {
nBytesRead = audioStream.read(abData, 0,
abData.length);
} catch (IOException e) {
e.printStackTrace();
}
if (nBytesRead >= 0) {
sourceLine.write(abData, 0, nBytesRead);
}
}
if (running)
audioStream.reset();
}
sourceLine.drain();
sourceLine.close();
} catch (Exception e) {
System.err
.printf("Exception occured while trying to playback file '%s'. (%s)%n",
filename, e.getLocalizedMessage());
e.printStackTrace();
}
}
}).start();
}
public void stopSound() {
this.running = false;
if (sourceLine != null) {
sourceLine.stop();
sourceLine.drain();
sourceLine.close();
}
}
}
这个类有两种方法,playSound启动一个新的线程并在你的类文件夹中播放一个特定的声音,而stopSound显然会停止当前播放的任何声音。这是一个简单的片段,它将创建三个按钮来播放您示例中的三个声音。
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Snippet extends JFrame {
public Snippet(){
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
JPanel panel = new JPanel(new FlowLayout());
this.getContentPane().add(panel);
final PlaybackWAV player = new PlaybackWAV();
JButton play1 = new JButton("CALLING");
panel.add(play1);
JButton play2 = new JButton("RING");
panel.add(play2);
JButton play3 = new JButton("BUSY");
panel.add(play3);
JButton play4 = new JButton("STOP");
panel.add(play4);
this.pack();
play1.setAction(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
player.stopSound();
player.playSound("resources/phone-calling.wav");
}
});
play2.setAction(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
player.stopSound();
player.playSound("resources/telephone-ring.wav");
}
});
play3.setAction(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
player.stopSound();
player.playSound("resources/phone-busy.wav");
}
});
play4.setAction(new AbstractAction(){
@Override
public void actionPerformed(ActionEvent arg0) {
player.stopSound();
}
});
}
public static void main(String[] args){
Snippet snippet = new Snippet();
snippet.setVisible(true);
}
}
快乐的编码!
修改强>
道歉,我忘了调用'mark'方法,因此重置方法无法正常工作。这是新代码:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
public class PlaybackWAV {
private final int BUFFER_SIZE = 128000;
private AudioInputStream audioStream;
private AudioFormat audioFormat;
private SourceDataLine sourceLine;
private boolean running = false;
/**
* @param filename
* the name of the file that is going to be played
*/
public synchronized void playSound(final String filename) {
new Thread(new Runnable() {
public void run() {
try {
InputStream audioSrc = this.getClass().getResourceAsStream(filename);
// add buffer for mark/reset support
InputStream bufferedIn = new BufferedInputStream(audioSrc);
audioStream = AudioSystem.getAudioInputStream(bufferedIn);
audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(
SourceDataLine.class, audioFormat);
sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open(audioFormat);
sourceLine.start();
running = true;
while (running) {
audioStream.mark(BUFFER_SIZE);
int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
try {
nBytesRead = audioStream.read(abData, 0,
abData.length);
} catch (IOException e) {
e.printStackTrace();
}
if (nBytesRead >= 0) {
sourceLine.write(abData, 0, nBytesRead);
}
}
if (running)
audioStream.reset();
}
sourceLine.drain();
sourceLine.close();
} catch (Exception e) {
System.err
.printf("Exception occured while trying to playback file '%s'. (%s)%n",
filename, e.getLocalizedMessage());
e.printStackTrace();
}
}
}).start();
}
public void stopSound() {
this.running = false;
if (sourceLine != null) {
sourceLine.stop();
sourceLine.drain();
sourceLine.close();
}
}
}