目录

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所示。

java音乐播放器进度条实现 java 音乐播放器_后端

 图1  单击JLayer主页的下载链接

(2)在打开的下载列表中,找到最新的1.0.1版本(实际早在2008年就停止了更新),单击该版本中的zip超链接,操作如图2所示。

java音乐播放器进度条实现 java 音乐播放器_java音乐播放器进度条实现_02

 图2  单击压缩包下载链接

(3)下载完压缩包后,压缩包根目录下的jl1.0.1.jar就是JLayer的JAR包,文件所在位置如图3所示。将该文件解压出来,就获得了JLayer的JAR包,可以直接导入到Java项目使用。

java音乐播放器进度条实现 java 音乐播放器_后端_03

图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();
		}
	}
}

        运行之后可以听到,虽然这种方法可以加快播放速度,但因为丢帧也会出现失真的现象。