Java课程设计音乐播放器解读.docx

上传人:b****6 文档编号:16362035 上传时间:2023-07-12 格式:DOCX 页数:40 大小:2.28MB
下载 相关 举报
Java课程设计音乐播放器解读.docx_第1页
第1页 / 共40页
Java课程设计音乐播放器解读.docx_第2页
第2页 / 共40页
Java课程设计音乐播放器解读.docx_第3页
第3页 / 共40页
Java课程设计音乐播放器解读.docx_第4页
第4页 / 共40页
Java课程设计音乐播放器解读.docx_第5页
第5页 / 共40页
Java课程设计音乐播放器解读.docx_第6页
第6页 / 共40页
Java课程设计音乐播放器解读.docx_第7页
第7页 / 共40页
Java课程设计音乐播放器解读.docx_第8页
第8页 / 共40页
Java课程设计音乐播放器解读.docx_第9页
第9页 / 共40页
Java课程设计音乐播放器解读.docx_第10页
第10页 / 共40页
Java课程设计音乐播放器解读.docx_第11页
第11页 / 共40页
Java课程设计音乐播放器解读.docx_第12页
第12页 / 共40页
Java课程设计音乐播放器解读.docx_第13页
第13页 / 共40页
Java课程设计音乐播放器解读.docx_第14页
第14页 / 共40页
Java课程设计音乐播放器解读.docx_第15页
第15页 / 共40页
Java课程设计音乐播放器解读.docx_第16页
第16页 / 共40页
Java课程设计音乐播放器解读.docx_第17页
第17页 / 共40页
Java课程设计音乐播放器解读.docx_第18页
第18页 / 共40页
Java课程设计音乐播放器解读.docx_第19页
第19页 / 共40页
Java课程设计音乐播放器解读.docx_第20页
第20页 / 共40页
亲,该文档总共40页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

Java课程设计音乐播放器解读.docx

《Java课程设计音乐播放器解读.docx》由会员分享,可在线阅读,更多相关《Java课程设计音乐播放器解读.docx(40页珍藏版)》请在冰点文库上搜索。

Java课程设计音乐播放器解读.docx

Java课程设计音乐播放器解读

程序设计课程设计

综合实验

 

音乐播放器

 

班级:

指导老师:

组员:

 

2014年12月2日

目录

1程序功能描述3

2开发环境描述3

3开发技术介绍3

4详细设计4

4.1功能模块划分4

4.2用户界面设计5

4.2.1歌曲列表面板5

4.2.2播放控制面板8

4.2.3搜索及展示面板8

4.3播放功能实现9

4.3.1播放歌曲9

4.3.2暂停及继续播放11

4.3.3音量控制12

4.3.4播放模式12

4.3.5时间进度条13

4.4歌词展示实现14

4.4.1加载歌词文件14

4.4.2解析歌词文件14

4.4.3展示歌词15

4.5搜索网络歌曲资源16

4.5.1获取HTML文本16

4.5.2解析HTML文本18

4.5.3抓取数据描述20

4.6网络歌曲资源处理20

4.6.1歌曲资源的载体20

4.6.2歌曲资源的操作24

4.7程序内置的游戏26

4.7.1204826

4.7.2贪吃蛇27

4.7.3五子棋27

5程序运行28

6实验小结30

1程序功能描述

音乐播放器是一种用于播放各种音乐文件的多媒体播放软件。

我们以酷狗音乐播放器的操作界面为原型,设计一个实现播放、搜索、下载歌曲的Java音乐播放器。

此音乐播放器支持音乐格式较少,只有MID、WMA、MP3。

最后,为音乐播放器置入一些游戏,增强播放器的娱乐性。

 

2开发环境描述

IDE:

Eclipse(Luna)、netbeans

JDK:

1.8

图片处理:

Photoshop

 

3开发技术介绍

1)JavaSound:

JavaSoundAPI是JavaSE平台提供底层的处理声音接口。

使用JavaSoundAPI可以实现各种基于声音的应用,例如声音录制、音乐播放、音乐编辑等。

同时其还提供了第三方的扩展接口(SPI),实现各种音乐格式的解码与转码。

 

2)JavaZoom:

为了支持MP3的播放,必须为JavaSound扩展MP3的SPI支持库。

开源项目JavaZoom正是提供了一个兼容JavaSound的纯Java解码器。

引用:

jl1.0.1.jar、mp3spi1.9.5.jar、tritonus_share.jar

 

3)Jaudiotagger:

开源项目Jaudiotagger提供一个Java类库用于编辑音频文件的tag信息(附有此音频的歌手、标题、专辑、音轨长度等的信息)。

引用:

jaudiotagger-2.0.3.jar

 

4)Jsoup:

Jsoup是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。

它提供了一套非常省力的API。

引用:

jsoup-1.8.1.jar

 

5)Substance:

Swing自带提供了几种lookandfeel类,然而要设计一个非常精美的GUI界面,却相当麻烦。

使用javasubstance可以很简单地实现。

Substance里面有很多现成的非常漂亮的皮肤。

引用:

substance.jar

 

4详细设计

4.1功能模块划分

按结构化设计方法,划分出四个功能模块:

歌曲列表、播放控制、搜索及音乐库。

此四个模块正好对应酷狗用户界面的四部分。

酷狗音乐播放器如下:

Figure4.1.1Kugou

 

程序构建的包

main:

主入口

ui、ui.tool:

用户界面及其使用的一些工具类

song:

包含有歌曲、歌词信息的类

player:

播放相关的类

search:

搜索相关的类

 

程序结构图如下:

Figure4.1.2程序结构图

 

4.2用户界面设计

窗体(Frame):

窗体初始大小为975*670;内容面板(ContentPane)由播放面板(PlayPanel)、歌曲列表面板(PlayListPanel)、搜索面板(SearchPanel)、展示面板(ShowPanel)构成,内容面板的布局采用的是BoxLayout+Box,PlayListPanel和SearchPanel对应都绑定了一个工具条(ButtonToolBar)

程序引用了外包Substance设计观感

4.2.1歌曲列表面板

PlayListPanel由一个工具条(ButtonToolBarextendsJToolBar)、JPanel构成,其中JPanel采用CardLayout布局,JPanel加入了3个歌曲列表面板(SongListPanelextendsJScrollPanel)、1个应用面板(JScrollPanel)利用工具条的按钮切换显示面板

Figure4.2.11歌曲目录

歌曲列表面板(SongListPanel)-列表的实现:

利用JTree实现二级目录。

顾名思义,JTree是树状元件,它由众多节点构成,其中JTree需要一个根节点(root)。

关于节点,我们用可派生节点DefaultMutableTreeNode类(implementsTreeNode)即这种节点可以做“树干”也可以做“叶子”

 

1)利用一个节点构建一个JTree,该节点为根节点,即一级节点

其实我们要实现的歌曲列表是3级节点:

根节点、歌曲目录、歌曲文件,这里我们需要隐藏点根节点:

tree.setRootVisible(false);否则我们将看到3层目录

 

2)根节点加入节点歌曲目录节点(rootNode.add(aNode))

第2级节点为歌曲目录,可派生歌曲节点:

节点(TreeNode)的其中一个构造器是接受Object对象userObject

JTree是以节点的toString方法返回的字符串显示节点,而节点的toString是由UserObjcet的toString决定,所以用String来构建歌曲目录节点即可

 

3)歌曲目录节点应该有一个计算当前歌曲数目并在目录中显示的方法

目录节点计算其的子节点数,并更新到目录名

 

4)歌曲目录节点加入歌曲文件节点

加入方法与上面一样。

这里每个歌曲(File)是一个节点,不可派生子节点

上面说到每个节点在JTree显示的字符串,都是由该节点的UserObject.toString()决定,File的toString返回的是该文件的路径,

这里我们重写DefaultMutableTreeNode的toString让它返回歌曲名,所以构造了SongNode类(extendsDefaultMutableTreeNode)

 

5)弹出菜单

再做下面各种操作前,需要一个使用载体,我们利用弹出菜单来实现

Figure4.2.12弹出菜单

6)移除歌曲目录

因为用户只能选中第2、3级节点,这里需要判断当前选中的是第几级节点:

获取选中的路径TreePathpath=tree.getSelectionPath()(如果path==null可以不往下执行),通过path.getPathCount()来判断,第3级节点是返回值是3。

如果是第3级节点,需获得它的上级节点(即歌曲目录)

获取末端组件DefaultMutableTreeNodenode=(DefaultMutableTreeNode)path.getLastPathComponent()

获取上级节点DefaultMutableTreeNodeaList=node.getParent()

如果是第2级节点,可直接获取选中路径的末端组件

aList=(DefaultMutableTreeNode)path.getLastPathComponent();

这样保证都从歌曲目录节点操作,

再按以下次序进行判断:

1.如果当前目录是默认目录,不移除,可以通过当前节点在根节点的位置判断root.getIndex(aList)

2.如果当前目录含有歌曲,进行提示是否移除,可以获取该目录节点的子节点数目(getChildCount)或者该节点是否为“叶子”(isLeaf)

3.如果当前目录播放着歌曲,终止播放,这里后面再叙述。

4.最后移除,aList.removeFromParent();

 

7)清空歌曲目录

与移除目录类似,最后清空使用的方法aList.removeAllChildren();

 

8)删除歌曲

可以参考移除目录的实现,需要注意的是,要保证当前选中的节点是第3级节点,即歌曲文件,是第2级节点就不往下操作,删除方法同样是aSong.removeFromParent()

9)获取音频文件

通过JFileChooser打开个对话框,获取外部文件,并给其安装过滤器。

过滤器过滤出的格式为mid,mp3,wav

选择文件分为两种模式,1获取多个音频文件,2获取一个文件夹。

需设置JFileChooser的选择模式setFileSelectionMode(intparam)

关于第2种模式,获取了文件夹后,也要给文件夹进行过滤操作(直接判断或者安装过滤器)这里的过滤器是抽象类FileFilter,这里定义了一个AFilter(extendsFileFilter)

最后将这些files加入目录节点即可

 

10)鼠标右击选中当前节点

给JTree注册MouseListener.,先判断是否鼠标右击,再取与点击点坐标最近的节点tree.getPathForLocation(intx,inty)

应用面板(AppPanel)的实现:

应用面板用JScrollPane,加入多个按钮,一个按钮对应着Expandsion包附加的小游戏程序(Expandsion包导出游戏程序后,被删除)

 

以上,歌曲列表面板界面基本实现,注意每次对JTree操作后,请更新JTree的状态,tree.updateUI(),否则有可能出现Bug。

在我们实现歌曲播放面板操作功能时,与歌曲列表面板进行交互,会再往列表面板添加功能。

 

4.2.2播放控制面板

PlayPanel由于JavaSwing布局复杂,我们可以用Eclipse的WindowBuilder或者netbeans的Matisse可视化构建

PlayPanel由以下组件构成

标签:

歌曲名(songNameLabel)当前播放进度时间(currentTimeCountLabel)

当前播放歌曲总时间(audioTotalTimeLabel)

按钮:

上一首(backPlay)下一首(frontPlay)播放(Play)静音(voiceControl)

下载(download)标记(mark)分享(share)

这里用到的按钮,都用到图片;为简化代码,构建一个IconButton来定义上面的按钮

其它:

组合框(JComboBox)mode控制播放模式

滑块条(JSlider)voiceAdjust控制音量

进度条(TimeProgressBar)这里用到的进度条timerProgressBar由于要计时,所以也构建一个TimeProgressBar

Figure4.2.21播放控制面板

 

4.2.3搜索及展示面板

SearchPanel/ShowPanel的布局可以参考PlayListPanel,这里说下折叠面板效果的实现(下图选中的按钮)

折叠:

SearchPanel/ShowPanel均设不可见,再设置Frame的大小和刷新。

展开:

给Frame注册窗体状态监听器,如果用户按了最大化按钮,会产生一个事件给监听器,这里判断当前窗体的新状态是否为最大化,然后与折叠操作类似。

(也可以不用“最大化”按钮判断,可以设置一个新按钮作事件源)

Figure4.2.31搜索及展示面板

 

4.3播放功能实现

播放面板功能主要由BasicPlayer、HigherPlayer、TimeProgressBar,BasicPlayer实现的是底层操作(播放、暂停、继续播放、终止、获取音频总时间等)。

HigherPlayer(extendsBasicPlayer)处理面板间的交互,面板与BasicPlayer的交互。

TimeProgressBar绑定了一个Timer,作计时功能。

4.3.1播放歌曲

为实现播放功能,我们这里用了JavaSoundAPI,它可以实现各种基于声音的应用。

JavaSoundAPI的输入/输出相当于IO流,TargetDataLine/SourceDataLine接口对应输入/输出设备,要得到这个设备的对象,需要设备信息:

它是输入还是输出设备,它处理的音频数据格式-即编码格式,不是“WAV/MP3”等文件格式

AudioSystem在此过程中起着工厂类的作用

这里先关注SourceDataLine如何实现播放功能:

BasicPlayer中关于播放的属性

privateAudioInputStreamaudioInputStream;

publicSourceDataLinesourceDataLine;

publicURLaudio;

publicThreadplayThread;

1)获取audioURL

回到SongListPanel,在JTree已注册的MouseListener里增加响应mouseClicked的处理,进行判断,选取第3级节点。

HigherPlayer在load方法里获取这节点的userObect(即File),再转成URL,这里在HigherPlayer,议保存这个节点,因为节点很容易获取它所在的列表节点。

2)从指定的URL获取音频输入流及音频编码格式

先获取音频输入流AudioSystem.getAudioInputStream(audio),再获取其音频编码格式audioInputStream.getFormat()

Javax.Sound默认支持的编码格式有PCM_SIGNED、PCM_UNSIGNED、ALAW、ULAW,对于这些编码格式我们都不这么了解,只知道WAV与MID采用的是PCM_SIGNED

当要播放MP3档时,这里会报异常,因为Javax.Sound并不支持MPEG1L3编码(MP3采用此格式编码)

3)将MPEG1L3编码转换成PCM_SIGNED

首先要扩展Javax.Sound的解码能力,之后再进行转码。

Javax.Sound除了有实现声音处理的API外,同时它以SPI(服务提供接口)为基础,实现各种音乐格式的解码与转码,SPI以插件形式扩展了音频处理的能力,SPI随程序启动而被启动。

即我们只要给程序引入MP3的SPI支持库,这里用到的第3方支持库是JavaZoom,

获取其中的jl1.0.jar、mp3spil1.9.5.jar、tritonus_share.jar

因为程序解码能力扩展,所以上面不再报异常,接着往下转码

//MPEG1L3转PCM_SIGNED

if(audioFormat.getEncoding()!

=AudioFormat.Encoding.PCM_SIGNED){

audioFormat=newAudioFormat(AudioFormat.Encoding.PCM_SIGNED,

audioFormat.getSampleRate(),16,

audioFormat.getChannels(),

audioFormat.getChannels()*2,

audioFormat.getSampleRate(),false);

audioInputStream=AudioSystem.getAudioInputStream(audioFormat,

audioInputStream);

}

这里将audioFormataudioInputStream分别转换成PCM_SIGNED,对于此转码方法,我们作了搬运工

4)获取输出设备信息及对象

//根据上面的音频格式获取输出设备信息

DataLine.Infoinfo=newInfo(SourceDataLine.class,audioFormat);

//获取输出设备对象

sourceDataLine=(SourceDataLine)AudioSystem.getLine(info);

这里sourceDataLineextendsLine

5)打开输出数据管道并进行IO操作

打开输出管道sourceDataLine.open();

允许此管道执行数据I/OsourceDataLine.start();

到这里,我们从输入流读入数据,再将数据写入输出管道(输出管道会先进入混频器,再进入到端口,这里我们不管混频器,只要知道数据输入到扬声器)

最后,我们应该设置一个独立线程(playThread)启动播放过程,否则主线程会在播放结束前阻塞。

 

4.3.2暂停及继续播放

为BasicPlayer加入属性:

publicbooleanIsPause=true;//是否为暂停状态

publicbooleanNeedContinue;//当播放同一首歌曲是否继续播放状态

1)暂停

这里IsPause初始为true,是为了后面Play按钮控制使用的

上面我们用到了playTread线程启动播放,那么“暂停”只要让此线程进入阻塞状态即可,“继续播放”则是唤醒线程。

playTread线程执行过程需要占有锁旗标,只要让它释放此锁旗标就达到暂停效果

这个锁旗标(Oject)我们设为BasicPlayer这个对象本身。

(其实随便一个对象也可以)

记住wait(),notify()要在同步块中使用,synchronized(BasicPlayer.this){},否则报异常

在音频数据的I/O读写循环中,设置一个控制标记(IsPause),true时,进入暂停:

BasicPlayer.this.wait();NeedContinue=true;

 

这里不需要设置IsPause为false,我们play按钮是如下判断,当前状态是暂停,则播放,当前是播放(即不是暂停),则暂停。

 

2)继续播放

当用户点击相同的歌曲,或者暂停后,再点击play按钮时,继续播放:

方法与暂停播放相对

3)终止当前歌曲播放和播放新选中歌曲功能

BasicPlayer增加属性:

publicbooleanIsComplete;

终止当前播放:

即是销毁当前播放线程

如果当前歌曲播放完成,即线程run完,线程自动销毁

如果当前歌曲播放中,播放新歌曲,我们手工销毁当前播放线程,并初始化IsPause、NeedContinue、IsComplete,之后启动新线程播放新歌曲。

我们需要在HigherPlayer里记录当前播放的歌曲与加载的歌曲,判断两者是否是同一首歌曲。

如果这里用stop也有可能会产生Bug,不安全,我们想要终止当前线程,不一定要销毁,有点强暴,我们让线程执行完就可以,加入新标记booleanIsEnd,True时,完成这个线程(return)。

这样播放新歌曲时,过渡平滑些

4)Play按钮状态

上面说到的方法:

都是用于播放面板Play按钮的功能操作

点击Play按钮的5种状态:

1.载入歌曲为null时,没什么都不做

2.当前没播放歌曲,播放载入歌曲

3.当前播放着歌曲,让它暂停

4.当前播放歌曲已暂停,如果加载歌曲没变,让它继续播放

5.不管当前播放歌曲是否暂停,如果加载歌曲与播放歌曲不同,终止当前播放歌曲线程,播放载入歌曲

 

4.3.3音量控制

输出设备对象sourceDataLine有获取各种控制的方法

获取当前输出设备对象的浮点控制器对象,类型为总音量控制sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN);

然后通过floatVoiceControl.setValue()/getValue(),设置/获取当前音量(db)音量大概范围为-80F~6F默认为0F

通过一个滑块组件(JSlider)设置其值

 

4.3.4播放模式

1)上一首/下一首

获取当前歌曲节点的位置(通过其父节点获取的),再指向上一个/下一个,然后加载此歌曲节点,手工触发play按钮

2)单曲播放、循环等模式

因为是播放完,之后进行播放模式操作,给BasicPlayer增加属性booleanIsComplete,判断当前是否播放完。

因为线程播放期间,一直阻塞,所以在线程最后设置IsComplte=true;

组合框获取当前模式的值,进行判断。

在当前歌曲播完后,这里可以先触发一下play按钮,成暂停状态,设置IsPause为true,等待下次播放,随后进行播放模式操作选择,这个与节点所在的位置有关。

 

4.3.5时间进度条

要想实现进度条,需要得到当前播放歌曲的播放时长,再通过一个计时器,设置进度条的值。

1)获取歌曲播放时长

每个音频文件都要个文件头记录音频信息(作者、采样率、时长等),引用外包jaudiotagger.jar解析音频,步骤如下:

获取音频文件

//AudioFileIO是org.jaudiotagger.audio包的类

AudioFilefile=newAudioFileIO.read(newFile(URI));

获取音频文件头

AudioHeaderaudioHeader=file.getAudioHeader();

获取音频总长度

inttimelength=audioHeader.getTrackLength();

这里的timelength是秒计,之后将timelength转成“0:

00”格式即可。

需要更新播放面板(PlayPanel)的当前歌曲总时间标签(audioTotalTimeLabel)

2)计时及更新进度条

这里构建了一个TimeProgressBar(extendsJProgressBar),其中绑定了一个计时器Timer

当播放歌曲前,更新初始化TimeProgressBar的状态(TimeProgressBar的两个最值为0,timelength),重置Timer,启动Timer。

暂停歌曲时,Timer阻塞。

继续播放时,Timer唤醒。

Timer对应有个线程,执行一次(或定期重复执行)它的任务Task。

Timer.schedule(TimerTasktask,longdelay,longperiod)。

给Timer安排一个任务,从指定延迟时间(delay)后执行task,之后按间隔时间(period这里是1s)执行。

每次执行Task,更新TimeProgressBar的值和当前播放进度时间标签currentTimeCountLabel,当计时时间等于当前歌曲播放时长时,终止Timer,放弃所有任务,Timer.cancel(),当本次任务会执行完。

暂停/继续播放时,可以参考歌曲的处理,来处理Timer,Timer也共享IsPause,最后也是阻塞/唤醒计时线程。

4.4歌词展示实现

4.4.1加载歌词文件

加载歌词文件的方式,我们

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2