Java Clip 播放音频
Java Clip 播放音频
·
Clip 是 Java 音频 API 中用于简化音频播放的类。它是 DataLine 接口的实现,属于 javax.sound.sampled 包。Clip 类提供了一种简便的方式来处理音频播放,通常用于短音频片段的播放,如音效或简短的音乐片段。
| 音频格式 | 支持情况 |
|---|---|
| *.wav | (JDK 原生支持) |
| *.pcm | (JDK 原生支持) |
| *.au | (JDK 原生支持) |
| *.aiff | (JDK 原生支持) |
| *.mp3 | mp3spi.jar |
| *.flac | jflac-codec.jar |
FloatControl.Type 是 Java Sound API 中的一个内部类,定义了 FloatControl 可以支持的控制类型。 FloatControl 提供了一种方式来控制以浮点数表示的参数,这些参数通常是音频系统的某些方面。常见的控制类型包括音量控制、平衡控制、增益控制等。
| FloatControl.Type | 类型 |
|---|---|
| MASTER_GAIN | 主增益控制。调整整个音频系统的增益(音量)。 |
| AUX_SEND | 辅助发送电平控制。调整发送到辅助总线的电平。 |
| AUX_RETURN | 辅助返回电平控制。调整从辅助总线返回的电平。 |
| REVERB_SEND | 混响发送电平控制。调整发送到混响效果器的电平。 |
| PAN | 声道平衡控制。调整立体声左右声道的平衡。 |
| BALANCE | 声道平衡控制。类似于 PAN 控制,调整音频信号在左右声道之间的平衡。 |
| SAMPLE_RATE | 采样率控制。调整音频流的采样率。 |
1 依赖
<!-- 如果需要解码播放mp3文件则引入这个jar包 -->
<dependency>
<groupId>com.googlecode.soundlibs</groupId>
<artifactId>mp3spi</artifactId>
<version>1.9.5.4</version>
</dependency>
<!-- 如果需要解码播放flac文件则引入这个jar包 -->
<dependency>
<groupId>org.jflac</groupId>
<artifactId>jflac-codec</artifactId>
<version>1.5.2</version>
</dependency>
2 接口
package com.xu.music;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import javax.sound.sampled.AudioInputStream;
import java.io.File;
import java.net.URL;
/**
* Java 音频播放
*
* @author hyacinth
* @date 2019年10月31日19:06:39
*/
public interface Player {
/**
* Java Music 加载音频
*
* @param url 音频文件url
* @throws Exception 异常
* @date 2019年10月31日19:06:39
*/
void load(URL url) throws Exception;
/**
* Java Music 加载音频
*
* @param file 音频文件
* @throws Exception 异常
* @date 2019年10月31日19:06:39
*/
void load(File file) throws Exception;
/**
* Java Music 加载音频
*
* @param path 文件路径
* @throws Exception 异常
* @date 2019年10月31日19:06:39
*/
void load(String path) throws Exception;
/**
* Java Music 加载音频
*
* @param stream 音频文件输入流
* @throws Exception 异常
* @date 2019年10月31日19:06:39
*/
void load(AudioInputStream stream) throws Exception;
/**
* Java Music 加载音频
*
* @param encoding Encoding
* @param stream AudioInputStream
* @throws Exception 异常
* @date 2019年10月31日19:06:39
*/
void load(Encoding encoding, AudioInputStream stream) throws Exception;
/**
* Java Music 加载音频
*
* @param format AudioFormat
* @param stream AudioInputStream
* @throws Exception 异常
* @date 2019年10月31日19:06:39
*/
void load(AudioFormat format, AudioInputStream stream) throws Exception;
/**
* Java Music 暂停播放
*
* @date 2019年10月31日19:06:39
*/
void pause();
/**
* Java Music 继续播放
*
* @param duration 音频位置
* @date 2019年10月31日19:06:39
*/
void resume(long duration);
/**
* Java Music 开始播放
*
* @throws Exception 异常
* @date 2019年10月31日19:06:39
*/
void play() throws Exception;
/**
* Java Music 结束播放
*
* @date 2019年10月31日19:06:39
*/
void stop();
/**
* Java Music 设置音量
*
* @param volume 音量
* @date 2019年10月31日19:06:39
*/
void volume(float volume);
}
3 实现
package com.xu.music;
import cn.hutool.core.text.CharSequenceUtil;
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import java.io.File;
import java.net.URL;
/**
* Java 音频播放
*
* @author hyacinth
* @date 2019年10月31日19:06:39
*/
public class ClipPlayer implements Player {
/**
* Clip
*/
private Clip clip;
/**
* FloatControl
*/
private FloatControl control = null;
/**
* 播放位置
*/
private volatile long position = 0;
/**
* 暂停
*/
private volatile boolean paused = false;
private ClipPlayer() {
}
public static ClipPlayer createPlayer() {
return ClipPlayer.SingletonHolder.player;
}
private static class SingletonHolder {
private static final ClipPlayer player = new ClipPlayer();
}
@Override
public void load(URL url) throws Exception {
load(AudioSystem.getAudioInputStream(url));
}
@Override
public void load(File file) throws Exception {
String name = file.getName();
if (CharSequenceUtil.endWithIgnoreCase(name, ".mp3")) {
AudioInputStream stream = new MpegAudioFileReader().getAudioInputStream(file);
AudioFormat format = stream.getFormat();
format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate(), 16, format.getChannels(),
format.getChannels() * 2, format.getSampleRate(), false);
stream = AudioSystem.getAudioInputStream(format, stream);
load(stream);
return;
}
if (CharSequenceUtil.endWithIgnoreCase(name, ".flac")) {
AudioInputStream stream = AudioSystem.getAudioInputStream(file);
AudioFormat format = stream.getFormat();
format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate(), 16, format.getChannels(),
format.getChannels() * 2, format.getSampleRate(), false);
stream = AudioSystem.getAudioInputStream(format, stream);
load(stream);
return;
}
load(AudioSystem.getAudioInputStream(file));
}
@Override
public void load(String path) throws Exception {
load(new File(path));
}
@Override
public void load(AudioInputStream stream) throws Exception {
DataLine.Info info = new DataLine.Info(Clip.class, stream.getFormat(), AudioSystem.NOT_SPECIFIED);
this.clip = (Clip) AudioSystem.getLine(info);
this.clip.addLineListener(event -> {
System.out.println(event.getType() + "\t" + event.getFramePosition());
});
this.clip.open(stream);
if (this.clip.isControlSupported(FloatControl.Type.MASTER_GAIN)) {
control = (FloatControl) this.clip.getControl(FloatControl.Type.MASTER_GAIN);
}
}
@Override
public void load(AudioFormat.Encoding encoding, AudioInputStream stream) throws Exception {
load(AudioSystem.getAudioInputStream(encoding, stream));
}
@Override
public void load(AudioFormat format, AudioInputStream stream) throws Exception {
load(AudioSystem.getAudioInputStream(format, stream));
}
@Override
public void pause() {
if (this.clip != null && this.clip.isRunning()) {
paused = true;
position = this.clip.getMicrosecondPosition();
this.clip.stop();
}
}
@Override
public void resume(long duration) {
if (this.clip != null && paused) {
paused = false;
this.position = (0 == duration) ? position : duration;
this.clip.setMicrosecondPosition(position);
this.clip.start();
}
}
@Override
public void play() {
if (this.clip != null) {
this.clip.start();
this.clip.drain();
}
}
@Override
public void stop() {
if (this.clip != null) {
this.clip.stop();
this.clip.close();
}
}
@Override
public void volume(float volume) {
if (null == control) {
return;
}
if (volume < control.getMinimum() || volume > control.getMaximum()) {
return;
}
control.setValue(volume);
}
}
4 测试
package com.xu.music.player.player;
/**
* Java 音频播放
*
* @author hyacinth
* @date 2019年10月31日19:06:39
*/
public class Test {
public static void main(String[] args) throws Exception {
ClipPlayer player = ClipPlayer.createPlayer();
player.load("D:\\Kugou\\梦涵 - 加减乘除.mp3");
player.play();
Thread.sleep(5000);
player.pause();
Thread.sleep(5000);
player.resume(0);
Thread.sleep(5000);
player.stop();
}
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)