目录
1 简介
2 下载
3 事件与监听器
4 播放器
4.1 Player播放器
4.2 jlp极简播放器
4.3 jlap简易播放器
4.4 AdvancedPlayer高级播放器
1 简介
Java SE自带的API中缺少对MP3格式音频文件的支持,想要使用Java代码播放MP3需要第三方库。JLayer是一款Java语言编写的开源MP3解码器库。最早于1999年2月开始研发,但2008年停止更新,目前的最高版本为1.0.1。
JLayer的官网主页地址:
http://www.javazoom.net/javalayer/javalayer.html
JLayer在线API地址:
http://www.javazoom.net/javalayer/docs/docs1.0/index.html
说明:官网可能已经失效,可尝试从sourceforge平台下载JAR包:
https://sourceforge.net/projects/javalayer/
2 下载
下载JLayer JAR包的步骤如下:
(1)进入官网主页,在打开的页面中单击“download”超链接,操作如图1所示。
图1 单击JLayer主页的下载链接
(2)在打开的下载列表中,找到最新的1.0.1版本(实际早在2008年就停止了更新),单击该版本中的zip超链接,操作如图2所示。
图2 单击压缩包下载链接
(3)下载完压缩包后,压缩包根目录下的jl1.0.1.jar就是JLayer的JAR包,文件所在位置如图3所示。将该文件解压出来,就获得了JLayer的JAR包,可以直接导入到Java项目使用。
图3 JAR文件的位置
3 事件与监听器
javazoom.jl.player.advanced.PlaybackEvent类是播放器回放动作所触发的事件,源码中没有给出太多的解释,可以简单的理解为播放监听器所捕获的播放事件。
javazoom.jl.player.advanced.PlaybackListener类是播放监听器。这个监听器有两个方法,会在播放器开始播放时或结束播放时触发,下面分别介绍这两个方法:
(1)playbackStarted(PlaybackEvent evt) 播放器开始播放事件
为播放器添加PlaybackListener监听之后,在播放器开始播放之前会触发此方法。
(2)playbackFinished(PlaybackEvent evt)
为播放器添加PlaybackListener监听之后,在播放器结束播放之后会触发此方法。此方法可以判断音乐文件是否播放完毕。
4 播放器
4.1 Player播放器
javazoom.jl.player.Player类是JLayer提供的标准播放器类,该类的使用方法非常简单,在创建播放器对象时将MP3音频文件的文件输入流当做参数,然后执行播放器的play()方法即可播放。
实例代码如下:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
public class MP3Player {
public static void main(String[] args) {
try {
Player player = new Player(new FileInputStream("D:\\demo.mp3")); // 创建播放器
player.play(); // 开始播放
} catch (JavaLayerException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
运行代码之后就可以听到文件中声音,想要停止播放必须强制终止Java进程。
play()方法还有一个play(int frames)的重载形式,方法参数为播放的帧数,如果参数值大于音频文件的最大帧数,就会播放至结束。例如,播放音频前50帧的代码如下:
Player player = new Player(new FileInputStream("D:\\demo.mp3")); // 创建播放器
player.play(50);
4.2 jlp极简播放器
javazoom.jl.player.jlp类是一个极简播放器,仅提供了一个play()方法。虽然jlp是小写的,不符合类名规范,但它的确是个类。jlp的构造方法有一个字符串参数,用来指明音频文件的路径。
jlp的使用方法如下:
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.jlp;
public class MP3Player {
public static void main(String[] args) {
jlp j = new jlp("D:\\demo.mp3"); // 创建播放器
try {
j.play(); // 开始播放
} catch (JavaLayerException e) {
e.printStackTrace();
}
}
}
4.3 jlap简易播放器
javazoom.jl.player.advanced.jlap类也是一个简化版的播放器,但它的功能却比Player播放器强大。jlap提供了四种播放方法,如表1所示。
表1 jlap类提供的四种播放方法
方法 | 说明 |
void play(java.lang.String filename) | 播放文件地址为filename音频文件 |
static AdvancedPlayer playMp3(java.io.File mp3, int start, int end, PlaybackListener listener) | 播放mp3文件,从start帧开始播放,播放至end帧,播放器采用的播放监听为listener |
static AdvancedPlayer playMp3(java.io.File mp3, PlaybackListener listener) | 播放mp3文件,播放器采用的播放监听为listener |
static AdvancedPlayer playMp3(java.io.InputStream is, int start, int end, PlaybackListener listener) | 播放is流提供的数据,从start帧开始播放,播放至end帧,播放器采用的播放监听为listener |
例如,拿最复杂的第四个方法举例,创建jlap播放器,播放指定的音频文件,从第50帧播放至第100帧。在播放之前在控制台打印“播放开始”,播放完第100帧之后在控制台打印“播放结束”,具体代码如下:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.advanced.AdvancedPlayer;
import javazoom.jl.player.advanced.PlaybackEvent;
import javazoom.jl.player.advanced.PlaybackListener;
import javazoom.jl.player.advanced.jlap;
public class MP3Player {
public static void main(String[] args) {
try {
InputStream is = new FileInputStream("D:\\demo.mp3");// 创建音频文件的输入流对象
jlap.playMp3(is, // 创建播放器,播放音频输入流
50, // 从第50帧开始播放
100, // 播放至第100帧
new PlaybackListener() {// 触发的监听
@Override
public void playbackStarted(PlaybackEvent arg0) {// 播放开始前触发
System.out.println("播放开始");
}
@Override
public void playbackFinished(PlaybackEvent arg0) {// 播放结束后触发
System.out.println("播放结束");
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (JavaLayerException e) {
e.printStackTrace();
}
}
}
4.4 AdvancedPlayer高级播放器
javazoom.jl.player.advanced.AdvancedPlayer类是最灵活、功能最全的播放器类。该类提供了很多方法,如表2所示。
表2 AdvancedPlayer类提供的方法
方法 | 说明 |
void close() | 关闭播放器 |
protected boolean decodeFrame() | 解码(播放)一帧 |
PlaybackListener getPlayBackListener() | 获取本播放器的播放监听 |
void play() | 播放 |
boolean play(int frames) | 播放前frames帧 |
boolean play(int start, int end) | 从第start帧播放至第end帧 |
void setPlayBackListener(PlaybackListener listener) | 设置播放监听 |
protected boolean skipFrame() | 跳过一帧 |
void stop() | 停止播放 |
创建AdvancedPlayer播放器,并播放音频文件的代码如下所示:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.advanced.AdvancedPlayer;
public class MP3Player {
public static void main(String[] args) {
try {
AdvancedPlayer player = new AdvancedPlayer(new FileInputStream("D:\\demo.mp3"));
player.play();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JavaLayerException e) {
e.printStackTrace();
}
}
}
AdvancedPlayer播放器提供了decodeFrame()方法和skipFrame()方法可以让开发者主动的播放一帧或跳过一帧,这样就可以实现加速播放的效果。因为这两个方法是使用protected修饰的,所以需要通过编写子类的方式调用这两个方法。
例如,创建一个MP3Player类,继承AdvancedPlayer类。在MP3Player类中创建自定义的quickPlay ()方法,在该方法中循环读取每一帧,将帧数能被5整除的帧全部跳过,并播放剩余的侦,这样就实现了快速播放。代码如下:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.advanced.AdvancedPlayer;
public class MP3Player extends AdvancedPlayer {
public MP3Player(InputStream arg0) throws JavaLayerException {// 依然采用父类构造方法
super(arg0);
}
public void quickPlay() {// 自定义的播放方法
for (int i = 0; i < Integer.MAX_VALUE; i++) {
if (i % 5 == 0) {// 跳过所有能被5整除的帧
try {
skipFrame();// 跳过一帧
} catch (JavaLayerException e) {
e.printStackTrace();
}
} else {
try {
decodeFrame();// 播放一帧
} catch (JavaLayerException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
try {
MP3Player play = new MP3Player(new FileInputStream("D:\\demo.mp3"));
play.quickPlay();// 自定义播放
} catch (JavaLayerException e1) {
e1.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
运行之后可以听到,虽然这种方法可以加快播放速度,但因为丢帧也会出现失真的现象。