版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、<p> 基于java的mp3播放器的設(shè)計與實現(xiàn)</p><p> 摘 要:隨著計算機和多媒體技術(shù)的不斷發(fā)展以及個人計算機的普及,各種各樣的媒體文件、媒體播放器層出不窮,而MP3(MPEG Audio Layer3)格式以其體積小、音質(zhì)也有保證的特點成為使用最為廣泛的音頻格式,得到了絕大多數(shù)軟件和硬件媒體播放器的支持,同時WAV格式作為無損的音頻格式也獨樹一幟。如今,軟件市場上的媒體播放器百花齊
2、放,如:MediaPlayer,酷我音樂盒和千千靜聽等。高音質(zhì)播放和低內(nèi)存消耗是各種媒體播放器所追求的目標(biāo)。</p><p> 關(guān)鍵詞:音樂播放器 java MVC JMF Ecplise </p><p><b> 一、緒論</b></p><p> 1.1背景、目的與意義</p><p> 隨著個人電腦的普
3、及,多媒體信息的傳播和應(yīng)用已經(jīng)深入我們生活中的各個方面。其中數(shù)字音頻憑借著其占用存儲空間小,聲音質(zhì)量高的特點風(fēng)靡全球,傳統(tǒng)磁帶和CD所統(tǒng)治的半壁江山已經(jīng)成為了數(shù)字音頻的天下。 </p><p> 當(dāng)微軟Windows的局限性和缺點開始暴露出來的同時,多樣化的操作系統(tǒng)平臺如Solaris,Linux以及MacOS等操作系統(tǒng)各自擁有不俗的表現(xiàn)以及龐大的用戶群。面對繁多的操作系統(tǒng)平臺,一款具有通用性的音頻播放軟件則是
4、必不可少的。</p><p> 本音頻播放軟件采用Java語言編寫,旨在利用Java的平臺無關(guān)性特點,做出一款通用性強、占用空間少卻五臟俱全的音頻播放器。</p><p> 1.2 Java語音的特性</p><p> 首先,從面向?qū)ο蟮奶匦詠砜矗琂ava是一種完全的面向?qū)ο笤O(shè)計語言。Java的多態(tài)主要是建立在后期綁定(Late Bingding)或叫動態(tài)綁定
5、(Dynamic Binding)基礎(chǔ)之上的,這樣Java先天就具備了對對象類型的自動判斷能力。而C++是不支持動態(tài)綁定的,綁定動作發(fā)生在編譯期而不是執(zhí)行期,所以C++要實現(xiàn)多臺的效果必須要使用虛函數(shù)。此外雖然C++語言支持封裝和繼承,但多態(tài)仍然是建立在編譯時綁定的基礎(chǔ)上,必須要通過虛函數(shù)實現(xiàn)。不僅如此,C++語言的指針操作允許使用goto語句,容易產(chǎn)生歧義的多重繼承等特性也使C++不能嚴(yán)格符合面向?qū)ο蟮乃枷搿?lt;/p>&
6、lt;p> 其次,Java具有絕對的平臺無關(guān)性,其使用一種虛擬機作為中間層來屏蔽平臺差異。Java的源程序經(jīng)過編譯產(chǎn)生類文件,類文件結(jié)構(gòu)不同于傳統(tǒng)的編譯器生成的二進(jìn)制文件,必須經(jīng)過虛擬機的解釋才能運行,因此Java被認(rèn)為是一種解釋性語言。虛擬機作為中間層負(fù)責(zé)把編譯好的類文件轉(zhuǎn)換為不同平臺的指令。而對于不同的C,C++編譯器,各種數(shù)據(jù)類型所占用空間有可能不一樣,這種差異會影響程序的可移植性。</p><p>
7、; 此外,在內(nèi)存管理方面,Java在其虛擬機內(nèi)部實現(xiàn)了垃圾內(nèi)存自動回收功能,能夠自動判斷那些內(nèi)存不再被用戶使用,這樣就讓用戶在系統(tǒng)設(shè)計時從繁雜的內(nèi)存管理工作中解脫出來。C和C++語言分配的內(nèi)存空間必須由用戶在不使用的時候進(jìn)行回收,容易產(chǎn)生內(nèi)存回收不充分的問題,形成內(nèi)存漏洞。</p><p> 然而,Java也有瑕疵,由于是一種解釋型語言,編譯后的Java類文件不能直接被操作系統(tǒng)執(zhí)行,需要虛擬機的解釋,因此其效
8、率和C,C++相比有一定差距。在運行時,Java編寫的軟件需要操作系統(tǒng)中安裝有虛擬機,所以程序的發(fā)布相對繁瑣??偟恼f來,</p><p><b> Java編程語言是</b></p><p><b> ·簡單與面向?qū)ο蟮?lt;/b></p><p> ·分布式、安全與魯棒的</p>&l
9、t;p> ·解釋執(zhí)行與高性能的</p><p> ·多線程與動態(tài)執(zhí)行的</p><p><b> 二、相關(guān)技術(shù)簡介</b></p><p> 2.1 關(guān)于JMF技術(shù)</p><p> JMF(Java Media Framework),Java媒體架構(gòu),是對應(yīng)Java 2平臺標(biāo)準(zhǔn)版(
10、J2SE)的一種可選用的應(yīng)用編程接口(API)軟件包,它為音頻和視頻等媒體內(nèi)容的捕獲、回放、傳輸和編碼轉(zhuǎn)換等提供了一個統(tǒng)一的架構(gòu)。</p><p> JMF技術(shù)提供了先進(jìn)的媒體處理能力,從而擴展了Java平臺的功能。這些功能包括:媒體捕獲、壓縮、流轉(zhuǎn)、回放,以及對各種主要媒體形式和編碼的支持,如M-JPEG、H.263、MP3、RTP/RTSP (實時傳送協(xié)議和實時流轉(zhuǎn)協(xié)議)、Macromedias Flash
11、、IBM的HotMedia和Beatniks的Rich Media Format (RMF)等。JMF 2.1.1還支持廣受歡迎的媒體類型,如Quicktime、Microsofts AVI和MPEG-1等。此外,JMF軟件中包括了一個開放的媒體架構(gòu),可使開發(fā)人員靈活采用各種媒體回放、捕獲組件,或采用他們自己的定制的內(nèi)插組件。</p><p> Java Media Framework(JMF)是構(gòu)建在 Jav
12、a Sound之上的一層。JMF實際上將Java Sound用于其音頻處理。JMF支持更多音頻格式和更多回放功能,但缺少Java Sound的低層訪問。另外,標(biāo)準(zhǔn) JDK 發(fā)行版不包括JMF而包括 Java Sound。</p><p> Java Sound: </p><p> 添加音頻和MIDI支持 </p><p> 與JDK 1.3及更高版本一起提供
13、 </p><p><b> 是輕量級的 </b></p><p> 本身支持相對較少的音頻格式(AIFF、WAV和AU) </p><p> 通過Java Sound的服務(wù)供應(yīng)商接口(SPI)可以進(jìn)行擴展 </p><p><b> JMF: </b></p><p&g
14、t; 添加對音頻、視頻和其它基于時間的數(shù)據(jù)的支持 </p><p> 提供多種媒體格式的同步和控制功能 </p><p> 當(dāng)前沒有與任何JDK一起提供 </p><p> 本身支持許多音頻格式(AIFF、WAV等)以及 MPEG和其它格式 </p><p> 包含可擴展的編碼器/解碼器媒體支持 </p><p&
15、gt; 2.2 JMF常用類</p><p> JMF的常用類包括以下幾個:</p><p> 數(shù)據(jù)源(DataSource)</p><p> 媒體定位器(MediaLocator)</p><p> 播放器(Player)</p><p> 處理器(Processor)</p><
16、p> 數(shù)據(jù)池(DataSink)</p><p> 數(shù)據(jù)格式(Format)</p><p> 管理器(Manager)</p><p> 2.2.1 數(shù)據(jù)源(DataSource)</p><p> 在JMF中,DataSource對象就是數(shù)據(jù)源,它可以是從采集設(shè)備獲得的數(shù)據(jù),也可以是一個多媒體文件,也可以是從互聯(lián)網(wǎng)上下載的
17、數(shù)據(jù)流。對于DataSource對象,一旦你確定了它的位置和類型,對象中就包含了多媒體的位置信息和能夠播放該多媒體的軟件信息。當(dāng)創(chuàng)建了 DataSource對象后,可以將它送入Player對象中,而Player對象不需要關(guān)心DataSource中的多媒體是如何獲得的,以及格式是什么。</p><p> 2.2.2 媒體定位器(MediaLocator)</p><p> DataSou
18、rce通常用兩種方式來定義,媒體定位器(MediaLocator)或URL(Universal Resource Locator)。MediaLocator類似于URL,并且可以由URL來構(gòu)造,即使在沒有安裝相應(yīng)的協(xié)議處理機制的情況下,也能構(gòu)造MediaLocator(在Java,只有在系統(tǒng)上安裝了URL協(xié)議的處理機制的情況下,才能構(gòu)造一個URL)。MediaLocator用來定位采集設(shè)備、本機的媒體文件、網(wǎng)絡(luò)上的媒體文件以及網(wǎng)絡(luò)RTP
19、流。</p><p> 2.2.3 播放器(Player)</p><p> 如圖2-1所示,播放器(Player)對象將音頻、視頻數(shù)據(jù)流作為輸入,然后將數(shù)據(jù)流輸出到音箱或屏幕上,就像播放器讀取DV帶中的數(shù)據(jù),然后將音頻信號送到音箱上,視頻數(shù)據(jù)送到屏幕上一樣。</p><p> 圖2-1 處理器模型</p><p> 如圖2-2所示,
20、除了在播放器中提到了的6種狀態(tài)以外,處理器對象還包括兩種新的狀態(tài)。這兩種狀態(tài)是在Unrealized狀態(tài)之后,在Realizing 狀態(tài)之前。</p><p> Configuring:當(dāng)調(diào)用configure( )方法后,處理器對象進(jìn)入該狀態(tài)。在該狀態(tài)下處理器對象連接到數(shù)據(jù)源并獲取輸入數(shù)據(jù)的格式信息。</p><p> Configured:當(dāng)完成數(shù)據(jù)源連接,獲得輸入數(shù)據(jù)格式的信息后
21、,處理器對象就處于Configured狀態(tài)。</p><p> 圖2-2 處理器的狀態(tài)轉(zhuǎn)換圖</p><p> 2.2.4 數(shù)據(jù)池(DataSink)</p><p> 數(shù)據(jù)池(DataSink)用來讀取數(shù)據(jù)源(DataSource)的媒體數(shù)據(jù)和輸出到特定的目的地——這里的目的地不同于以上所說的如音箱或屏幕。一個特定的DataSink或把數(shù)據(jù)輸出到一個文件,或
22、通過網(wǎng)絡(luò)傳輸數(shù)據(jù),或進(jìn)行RTP廣播。像Player一樣,DataSink對象以DataSource作為參數(shù),通過管理器(Manager)來構(gòu)造。</p><p> 2.2.5 數(shù)據(jù)格式(Format)</p><p> 在JMF架構(gòu)中,數(shù)據(jù)格式(Format)對象中保存了媒體的格式(format)信息。它并不包括編碼參數(shù)和全局時間信息。只是描述了該格式的編碼名稱和數(shù)據(jù)類別。Format
23、的子類包括 AudioFormat和VideoFormat類,VideoFormat又有六個子類:H261Format、H263Format、IndexedColorFormat、JPEGFormat、RGBFormat和YUVFormat類[4]。在AudioFormat中,描述了音頻格式的屬性,如采樣頻率、每次采樣的數(shù)據(jù)位數(shù)等等。在VideoFormat中則描述了視頻數(shù)據(jù)的類型如H.263等。</p><p>
24、; 圖2-3 表示JMF對音頻格式和視頻格式的定義:</p><p> 圖2-3 JMF的媒體數(shù)據(jù)格式</p><p> 2.2.6管理器(Manager)</p><p> JMF提供了下面四種管理器(Manager):</p><p> Manager:Manager相當(dāng)于兩個類之間的接口。例如當(dāng)你需要播放一個DataSourc
25、e對象,你可以通過使用Manager對象createPlayer( )方法創(chuàng)建一個 Player對象來播放它。使用Manager對象可以創(chuàng)建Player、Processor、DataSource和DataSink對象。</p><p> PackageManager:該管理器中保存了JMF類注冊信息。</p><p> CaptureDeviceManager:該管理器中保存了截取設(shè)備
26、的注冊信息。</p><p> PlugInManager:該管理器中保存了JMF插件的注冊信息。</p><p><b> 2.3 事件模型</b></p><p> JMF利用事件報告機制來使基于JMF的程序獲知媒體系統(tǒng)當(dāng)前的狀態(tài),從而使程序能夠?qū)ο鄳?yīng)狀態(tài)的改變作出相應(yīng)的操作。在任何時候,當(dāng)一個JMF對象需要報告當(dāng)前的狀態(tài),它將發(fā)出
27、一個MediaEvent事件。MediaEvent的子類包括ControllerEvern,DataSinkEvent,GainChangeEvent,RTPEvent。</p><p> 對于任何一個能發(fā)送MediaEvent的JMF對象而言,JMF都定義了一個相應(yīng)的偵聽接口(listener interface)。為了能在某一MediaEvent事件發(fā)生時得到相應(yīng)的通知,必須實現(xiàn)適當(dāng)?shù)膫陕牻涌谝约霸趯?yīng)的類
28、體中重寫該接口中處理MediaEvent事件的方法體,并通過調(diào)用addListener方法來接收此MediaEvent事件。</p><p> JMF中的Controller對象,例如播放器(Player)和處理器(Processor),以及Control對象,例如GainControl都可以發(fā)出MediaEvent事件。(Player和Processor繼承于Controller類 </p>&
29、lt;p> 所有的Controller事件,ControllerEvent由Controller(如Player或Processor)產(chǎn)生,可分為三類:改變通知(change notification),關(guān)閉事件(closed event),狀態(tài)轉(zhuǎn)變事件(transition event):</p><p> 1.改變通知事件如RateChangeEvent,DurationUpdateEvent,F(xiàn)o
30、rmatChangeEvent表明一些Controller的屬性的改變。</p><p> 2.狀態(tài)轉(zhuǎn)變事件可以使你的程序?qū)ontroller對象的狀態(tài)轉(zhuǎn)變作出反應(yīng)。Player當(dāng)從一個狀態(tài)轉(zhuǎn)為另一狀態(tài)時都會產(chǎn)生transition events。</p><p> 3.當(dāng)Controller關(guān)閉時,它將產(chǎn)生關(guān)閉事件。</p><p> 三、系統(tǒng)架構(gòu)和功能模
31、塊分析</p><p> 3.1.MVC模式概述 </p><p> MVC架構(gòu)是“Model-View-Controller”的縮寫,即將“模型-視圖-控制”作為應(yīng)用程序構(gòu)成的三要素。Event(事件)導(dǎo)致Controller改變Model或View,或者同時改變兩者。只要Controller改變了Models的數(shù)據(jù)或者屬性,所有以來的View都會自動更新。類似的,只要Control
32、ler改變了View,View會從潛在的Model中獲取數(shù)據(jù)來刷新自己。相應(yīng)地,本軟件也同樣使用MVC思想指導(dǎo)設(shè)計,做到模塊細(xì)化,分工明確,模塊間邏輯順序清晰的三大目標(biāo)。</p><p><b> 流程如圖3-1所示</b></p><p> 圖3-1 框架流程圖</p><p><b> 3.2系統(tǒng)目標(biāo)</b>&l
33、t;/p><p> 對于音頻播放器,必須給用戶提供最簡單的操作和最完善的功能。至少應(yīng)該能夠?qū)σ纛l文件進(jìn)行播放、暫停、停止、音量和進(jìn)度拖放操作等。除了最基本的操作以外,優(yōu)秀的播放器還提供了許多附加的功能來突出顯示該媒體播放器的特色,例如本播放器的歌詞實時顯示。在這樣的情況下,對播放器的設(shè)計目標(biāo)要求有如下功能的實現(xiàn):</p><p> 用戶界面窗口的控制功能:播放器主窗口控制、播放列表窗口的控
34、制和歌詞顯示窗口的控制;</p><p> 媒體文件的播放控制功能:開始播放、暫停播放、停止播放和拖動播放等;</p><p> 媒體文件的管理功能:添加歌曲、添加目錄,刪除歌曲、清空列表、保存列表和裝載列表;</p><p> 音頻文件信息顯示功能:將音頻文件的基本信息呈現(xiàn)給用戶,同時用戶自己可以設(shè)置一些信息。</p><p> 3
35、.3系統(tǒng)功能模塊概要設(shè)計</p><p> 本軟件同樣采用MVC的設(shè)計模式,做到控制,信息與視圖的相互分離,同時相互間有聯(lián)系緊密,互相調(diào)用,互為條件與依賴。故將系統(tǒng)分為五大模塊進(jìn)行構(gòu)建,分別是</p><p><b> 用戶界面模塊</b></p><p><b> 播放控制模塊</b></p><
36、;p><b> 播放信息模塊</b></p><p><b> 播放列表控制模塊</b></p><p><b> 歌詞控制模塊</b></p><p> 其相互關(guān)系如圖3-2所示:</p><p> 用戶請求事件
37、 用戶請求事件</p><p> 視圖信息更新 視圖信息更新</p><p> 更新信息 信息 更新 讀取 讀取 更新</p><p> 圖3-2 相互關(guān)系圖&l
38、t;/p><p> 3.3.1 用戶界面模塊</p><p> 為了實現(xiàn)軟件產(chǎn)品界面的友好性和簡潔性,同時又要保證功能的完整性,播放器的控制窗口的設(shè)計顯得更是不同一般的重要。首先,給出該界面的組件組成。</p><p> 于一個小小的窗口,要擺放這么多的控件,如果隨便地放在窗口上的話,將會使窗口十分混亂,影響使用,所以要對其擺放位置進(jìn)行合理的規(guī)劃。這些控件被按照
39、功能分成了3組,它們分別是控制面板、播放列表面板和LRC面板。這樣一來,就可以實現(xiàn)軟件產(chǎn)品界面的友好性與簡潔性,條理分明,在保證軟件產(chǎn)品功能完整性的同時,方便了用戶的使用。各面板關(guān)系如圖3-3:</p><p> 圖3-3 面板關(guān)系圖</p><p> 3.3.2 播放信息模塊</p><p> 放信息模塊由播放信息,播放列表,歌曲信息節(jié)點三個層次嵌套而成,
40、如3-4所示:</p><p> 圖3-4 信息模塊關(guān)系圖</p><p> 3.4音頻文件播放邏輯</p><p> 3.4.1 對音頻文件的傳遞</p><p> 音頻文件的傳送主要是用在播放列表處理的過程中,當(dāng)播放器的用戶想利用本播放器來播放一個音頻文件時,首先要做的就是將該音頻文件所在磁盤上的地址傳到播放列表模塊中,由播放列
41、表將信息傳遞給播放信息模塊進(jìn)行數(shù)據(jù)更新。當(dāng)要播放該文件時,就從播放信息模塊中提取當(dāng)前索引所指向該文件地址并將地址傳送到播放控制模塊,然后賦值給管理器Manager的新創(chuàng)建的媒體定位器對象(MediaLocator),Manager創(chuàng)建播放器(Player)后,剩下的工作都交給Player進(jìn)行音頻文件的播放。</p><p> 3.4.2 對歌詞文件的傳遞</p><p> 詞的實時顯
42、示作為本播放器的重要功能,LRC歌詞文件的處理流程也就顯得至關(guān)重要,因為LRC歌詞可能處于不同位置,所以其地址和數(shù)據(jù)處理流程要比音頻文件的處理流程要復(fù)雜得多。</p><p> 先,也是將音頻文件所在磁盤上的地址傳到播放列表中,當(dāng)要播放該文件時,就從播放列表中提取該文件地址并將地址傳送到播放控制窗口,并將音頻文件擴展名改為LRC,以獲得一個與MP3文件相同路徑的LRC歌詞文件的地址,將音頻文件名和LRC文件名傳
43、遞到播放信息模塊;在播放信息模塊中先讀取音頻文件的TAG信息,然后將音頻文件末尾的內(nèi)容傳遞給歌詞處理模塊,檢查該音頻文件是否內(nèi)嵌了歌詞,如果內(nèi)嵌歌詞存在則分離出時間信息和歌詞文本并返回;如果不存在內(nèi)嵌歌詞,則檢查同路徑下LRC歌詞文件是否存在,如果存在則將其傳遞給歌詞處理模塊進(jìn)行歌詞處理,分離出時間信息和歌詞文本并返回;如果不存在則嘗試自動關(guān)聯(lián)歌詞文件夾中是否存在該歌詞。如果存在,則將其傳遞給歌詞控制模塊進(jìn)行時間信息和歌詞文本的分離,然
44、后返回播放控制模塊;如果此時返回的歌詞存在,則將其傳遞給歌詞顯示窗口進(jìn)行顯示,并使用時間信息進(jìn)行控制。如果上述3處都沒有歌詞,則可以使用歌詞右鍵菜單中的關(guān)聯(lián)歌詞功能按鈕手動關(guān)聯(lián)LRC歌詞文件。</p><p> 3.4.3 播放控制流程</p><p> 器Player從建立之初到消亡,各有一系列已經(jīng)在JMF中編寫好的方法可以調(diào)用。</p><p> 軟件也
45、自定義了一系列方法來實現(xiàn)播放,暫停,停止,時間拖拽,播放邏輯如圖3-5所示:</p><p> 圖3-5 播放邏輯圖</p><p> 四、系統(tǒng)詳細(xì)設(shè)計與實現(xiàn)</p><p> 4.1開發(fā)平臺及環(huán)境</p><p> 系統(tǒng)采用的開發(fā)平臺是IBM公司的Eclipse3.2平臺。Eclipse是一個開放源代碼的,基于Java的可擴展開發(fā)平
46、臺,也同時是目前非常流行的跨平臺的自由集成開發(fā)環(huán)境(IDE)。Eclipse本身非常小,其設(shè)計思想是“一切皆為插件”,其他功能都是基于插件的形式與Eclipse無縫結(jié)合,協(xié)同工作,如Eclipse的圖形開發(fā)環(huán)境(SWT/JFace),Java開發(fā)環(huán)境插件(JDT),多國語言包,等。在Eclipse啟動后,要真正用到某個插件是,該插件才會被動態(tài)載入內(nèi)存,不再被使用的插件會在適當(dāng)?shù)臅r候被清出內(nèi)存,本系統(tǒng)使用到的典型插件的例子就是用于開發(fā)圖形
47、界面的VisualEditor</p><p> 4.2用戶界面模塊詳細(xì)設(shè)計與實現(xiàn)</p><p> 戶界面的主要有三大任務(wù),即</p><p> 受被改變的信息,顯示/更新界面信息</p><p> 聽用戶/播放器的事件</p><p> 改變的信息傳遞給其他控制模塊</p><p>
48、; 重要的任務(wù)無意識監(jiān)聽用戶/播放器的事件并作出相應(yīng)的反應(yīng)。</p><p> 4.3播放控制模塊詳細(xì)設(shè)計與實現(xiàn)</p><p> 放功能是媒體播放器所有控制功能中最重要的一個功能,沒有了它,播放器不能播放,也就不能稱之為播放器了。在本播放器系統(tǒng)中,當(dāng)點擊播放會有兩種狀態(tài)轉(zhuǎn)換:第一種是從停止?fàn)顟B(tài)轉(zhuǎn)換到播放狀態(tài);第二種是從暫停狀態(tài)轉(zhuǎn)換到播放狀態(tài)。播放命令由播放按鈕點擊產(chǎn)生單機事件形成播
49、放命令</p><p> 當(dāng)播放器接收到播放命令后,會依次執(zhí)行下面的過程:</p><p> 1:查播放器的當(dāng)前狀態(tài)是否是暫停狀態(tài),即判斷暫停狀態(tài)布爾型變量isPaused的值。如果是暫停狀態(tài),那么讓Player繼續(xù)播放,計時器Timer開始計時,并置isPaused值為False后,退出播放控制過程;如果不是暫停狀態(tài),則執(zhí)行第2步;</p><p> 2:查
50、播放列表中是否有媒體文件,如果沒有則調(diào)用ListController添加歌曲過程進(jìn)行添加,然后再次執(zhí)行本過程進(jìn)行播放;如果播放列表中有文件則執(zhí)行第3步;</p><p> 3:查播放列表索引,判斷是否選中了播放列表的一首歌曲來進(jìn)行播放,如果沒有選擇,則選擇播放列表中的第一首后執(zhí)行第4步,如果已經(jīng)選擇了要播放的歌曲則直接執(zhí)行第4步;</p><p> 4:斷要播放的歌曲在播放列表中的位置
51、,如果是第一首則將上一首按鈕置為無效,否則置為有效;如果是最后一首,則將下一首按鈕置為無效,否則置為有效;</p><p> 5:查播放模式中是否是單曲循環(huán),如果是則將上一首和下一首都置為無效,否則置為有效,</p><p> 6:取選擇的歌曲的播放地址,使用Player控件進(jìn)行播放,并調(diào)用歌詞顯示函數(shù)顯示歌詞;</p><p> 建播放器核心代碼如下:<
52、;/p><p> player = Manager.createRealizedPlayer(new MediaLocator(</p><p> "file:"+mp3state.getCurrentlist().getCurrentsonginfo().getAbsolutepath()));</p><p> 用播放狀態(tài)的當(dāng)前播放文件創(chuàng)建
53、一個分配好資源處于就緒狀態(tài)的播放器</p><p> mp3state.getCurrentlist().getCurrentsonginfo().setTotalTime((player.getDuration().getSeconds() / 10E6) / 3.29);</p><p> 用Player獲取播放時間后賦值給播放狀態(tài)中的當(dāng)前列表的當(dāng)前播放文件節(jié)點的總時間屬性 pl
54、ayer.start();//播放器開始播放</p><p> 4.4播放信息模塊詳細(xì)設(shè)計與實現(xiàn)</p><p> ?。?)播放信息模塊:</p><p> 播放信息模塊主要負(fù)責(zé)記錄播放器的各種狀態(tài),并提供get/set函數(shù)進(jìn)讀取、設(shè)置,由于播放信息模塊包含著播放列表模塊,因此播放信息模塊中包含著對播放列表的操作,當(dāng)ListController播放列表控制模塊要
55、對播放列表進(jìn)行操作時,需要間接調(diào)用播放信息模塊的函數(shù)。</p><p><b> 主要變量如下:</b></p><p> private JPanel contentPanel = null;</p><p> private JSlider volumnSlider = null;</p><p> priv
56、ate JCheckBox muteCheckBox = null;</p><p> private JPanel headPanel = null;</p><p> private JLabel nameLabel = null;</p><p> private JLabel playLabel = null;</p><p>
57、 private JLabel totalTimeLabel = null;</p><p> private JPanel visualPanel = null;</p><p> private JSlider processSlider = null;</p><p> private JButton playlistButton = null;<
58、;/p><p> private JButton stopButton = null;</p><p> private JButton playButton = null;</p><p> private JButton previousButton = null;</p><p> private JButton nextButto
59、n = null;</p><p> private JButton cutButton = null;</p><p> private JButton mergeButton = null;</p><p> private JButton aboutButton = null;</p><p> private JFrame p
60、layListFrame = null; </p><p> private JPanel jContentPane = null;</p><p> private List playList = null;</p><p> private JButton addButton = null;</p><p> private JB
61、utton removeButton = null;</p><p> private JButton exitButton = null;</p><p> private JFrame cutFrame = null; </p><p> private JPanel jContentPane1 = null;</p><p>
62、private JFrame mergeFrame = null; </p><p> private JPanel jContentPane2 = null;</p><p> private HashMap songMap = new HashMap();</p><p> private Mp3TVShow mp3TVShow = new Mp3TV
63、Show();</p><p> private PlayerCTL playerCTL = new PlayerCTL(); </p><p> private boolean progressSliderDrag = false;</p><p> private int plstate = Mp3Enum.PLSTATE_HIDE;</p>
64、<p> private int playBtnState = Mp3Enum.INIT;</p><p> private int cutFrameState = Mp3Enum.CUTFRAME_HIDE;</p><p> private int mergeFrameState = Mp3Enum.MERGEFRAME_HIDE;</p><p&
65、gt; private JSlider startSlider = null;</p><p> private JSlider endSlider = null;</p><p> private JLabel jLabel = null;</p><p> private JLabel jLabel1 = null;</p><p&g
66、t; private JTextField cutFilePath = null;</p><p> private JButton cutPathButton = null;</p><p> private JButton cutExecButton = null;</p><p> private JButton addMergeButton = nu
67、ll;</p><p> private JButton removeMergeButton = null;</p><p> private List mergeList = null;</p><p> private JTextField mergedFilePath = null;</p><p> private JButt
68、on mergePathButton = null;</p><p> private JButton mergeExecButton = null;</p><p> private JDialog warningDialog = null; </p><p> private JPanel jContentPane3 = null;</p>
69、<p> private JLabel jLabel2 = null;</p><p> private JButton sureButton = null;</p><p> private ScrollThread scrollThread = null;</p><p> private WindowDragControl windowDra
70、gControl = new WindowDragControl(this);</p><p> private JCheckBox circleCheckBox = null;</p><p> private JCheckBox shuffleCheckBox = null;</p><p> 于播放信息中包含播放列表,播放列表中又包含歌曲節(jié)點,層層嵌套
71、所以下面介紹播放列表和歌曲節(jié)點的內(nèi)容及操作</p><p> (2)播放列表模塊:</p><p> 列表可以看作是一個容器,每一個播放列表的對象都存放著許多歌曲節(jié)點,它主要負(fù)責(zé)對歌曲及誒單的操作,如添加文件,刪除列表項,清空列表等 </p><p> ?。?)歌曲信息節(jié)點模塊:</p><p> 構(gòu)造中讀取3字節(jié)的標(biāo)簽“TAG”,30
72、字節(jié)的MP3標(biāo)題信息,30字節(jié)的演唱者信息,30字節(jié)的專輯信息,4字節(jié)的年代信息,30字節(jié)的備注信息和1個字節(jié)的音樂風(fēng)格序列,共128字節(jié)的MP3歌曲信息</p><p> 歌曲節(jié)點的核心代碼主要是構(gòu)造函數(shù)的代碼,如下</p><p> SongInfo(File f) {//獲取文件對象以構(gòu)造歌曲節(jié)點</p><p> // TODO 自動生成構(gòu)造函數(shù)存根&
73、lt;/p><p> filename=f.getName();//文件名</p><p> absolutepath=f.getAbsolutePath();//文件路徑</p><p> Date d = new Date(f.lastModified());//日期</p><p> lastmodifiedy=d.getYear(
74、)+1900;//年</p><p> lastmodifiedm=d.getMonth()+1;//月</p><p> lastmodifiedd=d.getDate();//日</p><p> try {format=AudioSystem.getAudioFileFormat(f);//格式</p><p> tempp
75、layer=Manager.createPlayer(new MediaLocator("file:"+f.getAbsolutePath()));</p><p> totaltime=tempplayer.getMediaTime().getSeconds();</p><p> //創(chuàng)建一個未分配系統(tǒng)資源的播放器以便獲取播放總時間</p><
76、;p> tempplayer.close();</p><p> formatinfo=format.toString();</p><p> } catch{…..}</p><p> if(f.getName().endsWith(".mp3")||f.getName().endsWith(".MP3"))&
77、lt;/p><p> { //若為mp3文件,則讀取TAG獲取信息try {</p><p> FileInputStream fin = new FileInputStream(f);</p><p> byte[] data=new byte[128];</p><p> fin.read(data)
78、;</p><p> getmp3info(data);//通過讀取的128個字節(jié)信息獲取歌曲信息</p><p> } catch {…..}</p><p><b> }}</b></p><p> 4.5播放列表控制模塊詳細(xì)設(shè)計與實現(xiàn)</p><p> 播放列表主要負(fù)責(zé)對列表的操作
79、,如新建列表,刪除列表,載入列表,保存列表</p><p><b> 打開函數(shù)文件</b></p><p> 打開文件時,要調(diào)用系統(tǒng)的文件選擇器,新建一個JFileChooser的對象并進(jìn)行一定的過濾,只能打開.wav和.mp3格式的文件,若用戶沒有取消選擇,則將文件或文件組添加到當(dāng)前列表</p><p><b> 保存/裝載列
80、表函數(shù)</b></p><p> 當(dāng)一對象創(chuàng)建之后,只要需要,他會一直存在下去,擔(dān)當(dāng)應(yīng)用程序結(jié)束,所有的對象都會走向消亡。有些應(yīng)用場景下,如果能夠?qū)ο蟮臓顟B(tài)保存下來,并在下一次應(yīng)用程序啟動是重新啟動被保存的信息是非常有必要的,利用Java的I/O操作可以實現(xiàn)。</p><p> 序列化(即將播放列表保存)</p><p> 1:要一個輸出目的,因
81、此需要創(chuàng)建一個OutputStream對象。</p><p> 2:OutputStream封裝到一個ObjectOutputStream對象內(nèi)。ObjectOutputStream是一個專門用于對象序列化的類</p><p> 3:用ObjectOutputStream提供的writeObject()方法即可將對象序列化,轉(zhuǎn)換成字節(jié)序列,并將其發(fā)送到OutputStream所指代的媒
82、介中。</p><p><b> 代碼如下</b></p><p> private static File file=new File("save\\”+filename);</p><p> ObjectOutputStream out = new ObjectOutputStream(new FileOutputStrea
83、m(file));</p><p> out.writeObject(this.getListofSonglist());</p><p> out.close();</p><p> 同樣,反序列化代碼原理相同,在此不再一一贅述。</p><p> 4.6 歌詞控制模塊詳細(xì)設(shè)計與實現(xiàn)</p><p> 歌
84、詞控制模塊主要負(fù)責(zé)歌詞的加載,撤銷,歌詞的識別,以及重新繪制歌詞面板等</p><p> 讀取LRC文件成功后翻譯為兩個鏈表,一個是時間鏈表,一個是歌詞鏈表,二者一一對應(yīng),在后面的時間線程中每隔一秒檢查一次歌詞時間匹配</p><p><b> 代碼如下:</b></p><p> double ct = player.getMediaT
85、ime().getSeconds();//當(dāng)前時間</p><p> double nt = 0;//讀取LRC標(biāo)示時間</p><p> while (true) {</p><p><b> try {</b></p><p> s = in.nextLine();//讀取下一行</p><
86、;p> } catch (NoSuchElementException e) {</p><p><b> break;</b></p><p><b> }</b></p><p> nt = 60 * Integer.parseInt(s.substring(1, 3))//分</p>
87、<p> + Integer.parseInt(s.substring(4, 6))//秒</p><p> + Integer.parseInt(s.substring(7, 9)) / 100.0;</p><p><b> }</b></p><p> 大綱視圖如圖4-1:</p><p&g
88、t; 圖4-1 大綱邏輯圖</p><p> 五、系統(tǒng)運行環(huán)境及效果</p><p> 5.1 系統(tǒng)運行環(huán)境</p><p> 本軟件運行需要Java Runtime Enrironment1.6.0的虛擬機運行環(huán)境以及JavaMediaFramework2_1_1的安裝支持</p><p> 5.2 系統(tǒng)運行效果</p&
89、gt;<p> 圖5-1 程序主界面圖</p><p><b> 六、總結(jié)</b></p><p> 面對軟件市場上的各種各樣的媒體播放器,要設(shè)計一個非常優(yōu)秀的并非常有競爭力的音頻播放器,并不是一件容易的事。但筆者還是設(shè)計實現(xiàn)了一個自制的帶歌詞實時顯示的音頻播放器,這不僅僅讓我學(xué)到了很多有關(guān)多媒體方面的知識,還讓我了解到了如何去設(shè)計,以及如何實現(xiàn)播
90、放器的各種功能。通過設(shè)計此系統(tǒng),我學(xué)到了不少有用的知識,這些將對我今后的學(xué)習(xí)與工作有很大的幫助。</p><p> 首先,通過此播放器系統(tǒng)的設(shè)計,我對于設(shè)計開發(fā)一個軟件系統(tǒng)的工作流程有了進(jìn)一步的認(rèn)識,明白了軟件開發(fā)過程中各個階段的基本任務(wù),以及各個階段之間的聯(lián)系,明確了軟件開發(fā)中形成的文檔資料的重要性。</p><p> 第二,通過此播放器系統(tǒng)的設(shè)計,我基本上掌握了怎樣使用Eclips
91、e,JMF來編寫多媒體應(yīng)用程序。</p><p> 當(dāng)然,由于這是我第一次進(jìn)行多媒體系統(tǒng)的開發(fā)工作,所開發(fā)出來的系統(tǒng)不可避免地存在著一些不足,我會在今后的學(xué)習(xí)工作中逐步加以改進(jìn)。在這個軟件的編制過程中,我參看了大量的書籍與資料,但由于能力水平有限,在程序中肯定有較多不完善的地方。總體來說,通過本學(xué)期的畢業(yè)設(shè)計,我在帶歌詞實時顯示的音頻播放器系統(tǒng)的開發(fā)、Eclipse,Java及JMF編程等方面有了一定的進(jìn)步,為
92、以后從事更大型的軟件設(shè)計奠定了堅實的基礎(chǔ)。</p><p><b> 參考文獻(xiàn)</b></p><p> [1] 青島東合信息技術(shù)有限公司.JavaSE程序設(shè)計高級教程.北京:電子工業(yè)出版社,2010,237~292</p><p> [2](美)??藸?Java編程思想.北京:機械工業(yè)出版社,2007,50~100</p>
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 基于java的mp3播放器設(shè)計與實現(xiàn)
- 基于java的MP3播放器設(shè)計與實現(xiàn).doc
- 基于安卓android的mp3播放器的設(shè)計與實現(xiàn)-軟件工程畢業(yè)論文
- 基于linux的mp3播放器設(shè)計與實現(xiàn)
- 基于單片機的mp3播放器設(shè)計【畢業(yè)論文】
- 畢業(yè)設(shè)計---mp3播放器的設(shè)計與實現(xiàn)
- 畢業(yè)設(shè)計---mp3播放器的設(shè)計與實現(xiàn)
- 基于mp3播放器的設(shè)計
- 基于安卓android的mp3播放器畢業(yè)論文
- 基于android的MP3播放器的設(shè)計與實現(xiàn)論文.doc
- 基于arm的mp3播放器設(shè)計與實現(xiàn)
- 畢業(yè)論文(設(shè)計)基于stm32的mp3播放器設(shè)計
- 畢業(yè)設(shè)計---mp3播放器的設(shè)計與實現(xiàn)
- 畢業(yè)設(shè)計---mp3播放器的設(shè)計與實現(xiàn)
- 基于android的mp3播放器的設(shè)計與實現(xiàn)
- 畢業(yè)設(shè)計---MP3播放器的設(shè)計與實現(xiàn).doc
- 基于DSP的MP3播放器的設(shè)計與實現(xiàn).pdf
- 基于dsp的mp3播放器設(shè)計
- 基于android的mp3音樂播放器設(shè)計畢業(yè)設(shè)計論文
- mp3播放器設(shè)計設(shè)計
評論
0/150
提交評論