如果一段音频数据,其格式、长度等信息已明确,那么可以采用以下方法直接播放声音。
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.locks.LockSupport;
void main() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
try (
var byteArrayInputStream = new ByteArrayInputStream(Files.readAllBytes(Path.of("AudioFile.wav")));
var audioInputStream = AudioSystem.getAudioInputStream(byteArrayInputStream);
var clip = AudioSystem.getClip()
) {
final var mainThread = Thread.currentThread();
clip.addLineListener(
event -> {
if ( event.getType() == LineEvent.Type.STOP ) LockSupport.unpark(mainThread);
}
);
clip.open(audioInputStream);
clip.start();
LockSupport.park();
}
}
也可以使用更加简写的方式:
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.locks.LockSupport;
void main() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
try (
var audioInputStream = AudioSystem.getAudioInputStream(new File("AudioFile.wav"));
var clip = AudioSystem.getClip()
) {
final var mainThread = Thread.currentThread();
clip.addLineListener(
event -> {
if ( event.getType() == LineEvent.Type.STOP ) LockSupport.unpark(mainThread);
}
);
clip.open(audioInputStream);
clip.start();
LockSupport.park();
}
}
注意的是,JVM将会通过另外启动一个后台守护(Daemon)的Platform Thread(平台线程)来播放声音。也就是说,如果完全不去阻塞主线程的执行的话,可能就会导致声音完全来不及播放,主线程就先结束执行,程序就退出了。
所以,可以通过J.U.C.包下的锁类型(因为不会pin住载体线程),配合着事件监听,来控制音频的播放。