昌攀 陈姚节 葛程 方志
摘要:本文论述了采用Java语言开发一种基于C/S架构的音乐播放器,利用JMF(Java Media Framework)实现播放功能。该播放器除实现普通播放器的功能外,其亮点在于可以自动或手动下载歌词并保存,并且可以自动进行歌词同步。该播放器设计界面简洁,功能强大,并且占用内存小,执行速度快。
关键词:音乐;JMF;播放器
中图分类号:TS954 文献标志码:A 文章编号:1674-9324(2014)49-0072-03
随着因特网在我国的普及,随之而来的是各式各样的播放器软件。尽管未来的音乐播放器将具备各种丰富多彩的功能,但作为一款多媒体软件,音频应用才是最基本的,也是最能决定获取用户数量的因素。 基于上述分析,音质高、外形美观、小巧且功能强大是未来播放器发展的主流趋势。Java MP3音乐播放器的播放歌曲的功能是通过JMF这个jar包里面的MediaPlayer来实现,它的play和stop方法分别实现播放和暂停功能,该播放器由歌曲控制模块、歌曲列表模块和歌词显示模块三部分组成。该播放器采用客户端/服务端(C/S)设计模式,利用“千千静听”歌词服务器作服务端,以Myeclipse 10.0作为开发环境。
一、播放器界面的实现效果
该界面清晰明了,采用Java的界面编辑技术,控件简约,所消耗的系统资源较少,运行高效快速。值得改进的地方是:可以在歌词的背景处加上背景图片,功能不是很齐全,等等。
二、播放器的基本功能
结合音乐播放器所要实现的内容,我们列出用户操作的模块,其中每个模块对应一个功能。播放器的功能应当实现市面上比较常见播放器的所有功能,并且在界面上应当操作简单,还应添加一些比较特殊的功能,比如歌词下载。经过分析后确定该播放器应具备的功能如图2所示。
三、关键技术以及改进方法
该论文所描述的播放器采用多线程来进行控制,一个主页面是一个线程,播放歌曲是一个线程。主线程就是主页面所处的线程,它动态的对歌曲名称、播放时间、播放进度和歌词显示来进行更新。播放歌曲的线程是一个位于主线程里的一个进程,控制这个进程的开始和结束来影响主线程里数据的读写和显示,所以对于线程的控制是必要的。
1.播放功能模块以及界面的设计。歌曲控制面板视图如图3所示。播放、暂停和停止都依赖于主线程中的三个控制boolean变量,一个是play,另一个是pause,第三个是stop。初始值:stop=true,play=false,pause=false。
播放、暂停、停止功能的具体实现。当play和pause都为false的时候,此时只能通过双击控制实现,双击之后会启动一个歌曲播放的进程,用来控制歌曲的具体播放动作。当歌曲的状态是暂停时,就可以继续点击暂停按钮,达到播放的效果。此时,无需重新新建一个线程,只需让原来暂停的线程重新启动,同时需要改变变量stop和play。当然,还需要考虑到主线程,当play的状态为true时,主线程才能跑的顺利。停止只有在stop为false时起作用,与pause和play无关,即无论歌曲是暂停还是播放,都可以选择停止。首先就是把musicprocess线程停止,然后就需要把stop的状态改为true,还有需要把play的状态改为false,这样做的作用是控制主线程不要一直run,然后还需要把歌曲的播放时间设置为0:00,这样就基本实现了歌曲的停止功能。
2.基本操作模块的实现。①上一曲和下一曲的实现也是通过按钮来实现的。当歌曲播放状态为停止,亦及stop状态为true时,是不能进行上下一曲操作的。但是,当歌曲处于暂停或者播放状态,这个操作都是可以完成的。特别需要注意边界的问题,最重要的还是实现了自动滚动条定位的功能。首先判断歌曲播放的状态,不是停止状态,才会导致上下一曲功能生效,然后就是进行边界判断,边界判断之后,就需要原来播放歌曲的musicprocess线程停止掉,新建一个musicprocess线程,来播放新的歌曲,线程启动后,play的状态同样得设置为true,这样做是为了避免前面提到的,当初始播放状态为暂停时,点击上下一曲歌曲还是暂停的情况。同时在主线程里面,需要将时间与歌曲总时间设置完成,并且需要将进度条也设置为初始位置,歌曲名称也需要设置成新的歌曲名称。下载歌词、解析歌词、同步歌词,这其实都是连贯动作,下载前需要判断是否存在歌词,存在就不会再下载了。②快进、快退算的上是一个播放器的核心功能,快进、快退需要涉及到一个计算过程及歌曲播放时间和进度条之间的关系,还关联到歌词同步的问题。根据进度条的拉动距离和总的拉动距离之间的比例乘以总共的歌曲播放时间,就能算出歌曲应该播放的时间,这样就能设置出歌曲播放的时间,实现快进和快退的功能。其核心的代码如下:
3.歌曲操作模块的实现。①新增歌曲:该论文所描述的播放器新增歌曲功能除了能通过Java自带的文件选择器来进行歌曲添加操作,还有一种比较酷炫的是单个或者批量拖拽增加,以及拖动文件进入到歌曲列表就能够完成新增功能。拖拽文件原理:给歌曲播放列表设置一个接口的实现类,这个接口里面的拖拽其实和文件选择器的原理类似,这个实现类里面也做了文件筛选和文件格式过滤功能。②删除歌曲:删除歌曲功能与新增歌曲类似,也是有两种途径:一种是从程序控制面板中删除按钮,另一种是在歌曲列表中的右键事件里的删除按钮,删除的原理就是从歌曲面板中和存储歌曲绝对路径的数组中删除被选中的歌曲。但是与增加不同的是,在删除歌曲的时候,要考虑被删除的歌曲是否正在播放,已经被删除的歌曲是否是最后一首歌曲,如果不是,就自动播放下一首歌曲,如果是最后一首,就自动播放上一首歌曲。
4.歌词功能模块。①歌词下载功能的实现依赖网络上的资源。歌词下载,首先就是要选择好一个歌词服务器——“千千静听”歌词服务器。由于网络环境是不支持中文的,所以“千千静听”服务器也做了必要的处理和转换,它是利用歌手和歌曲名称来转码,转化为UNICODE编码,进行歌词的下载,由于页面编码采用的是UTF-8,所以下载时必须以UTF-8的编码来进行文件的读取。②解析歌词:采用正则表达式匹配前面的内容来判断每一行的具体内容。本播放器采用的是一个字符串存储歌曲名、一个字符串存储歌手、一个字符串存储专辑名,用一个以时间为value的Map来存储歌词,这样就成功的解析了歌词。下面给出具体的正则表达式:
歌曲信息:str.startsWith("ti:")
歌手信息:str.startsWith("ar:")
专辑信息:str.startsWith("al:")
歌词信息:\\[(\\d{2}:\\d{2}\\.\\d{2})\\]
③歌词显示:歌词显示利用的技术就是java里面的画笔技术,利用画笔来绘画歌词。具体的绘画技术利用的是Java绘画中效果比较好的双缓冲技术。先是把所有歌词预画到歌词显示面板,然后再逐行显示当前播放的歌词。当然,也要考虑到不存在歌词文件的问题,由于歌词文件不存在,所以得在主线程使用一个变量标示是否存在歌词,不存在歌词,就直接显示“未找到相应的歌词文件”。值得注意的是歌词显示的比率算法,歌词显示的比率是调节显示歌词的比率,即调节歌词显示的主键模糊度,具体的算法代码如下表。 ④歌曲同步:词曲同步的最初设想是开启两个线程:一个歌曲播放线程,另一个是歌词显示线程,然后把两个线程同步,最后把歌词显示放在主线程中,这样可以减少程序占用的资源,并且在词曲同步的控制上面也可以提供很多方便。
四、测试结果
经过测试,本论文中的播放器是一款小型、灵巧的播放器,更加适合多数人的意愿。而该音乐播放器占用内存小、开启速度快,很符合现在人们比较快的生活方式。
参考文献:
[1][美]Nicholas C.Zakas.JavaScript高级程序设计[M].第3版.李松峰,曹力,译.北京:人民邮电出版社, 2012.
[2][美]Freeman.E.Head First设计模式[M].OReilly Taiwan公司,译.北京:中国电力出版社,2007.
[3]Chien-Hung Liu. Data flow analysis and testing of JSP-based Web applications[J].Information and Software Technology,2006,4812.
[4]Gary G.Yen,Brian Ivers.Job shop scheduling optimization through multiple independent particle swarms[J].International Journal of Intelligent Computing and Cybernetics,2009,(21).