版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、用Java實(shí)現(xiàn)音頻播放桌面PC的性能日益提高,Java虛擬機(jī)的優(yōu)化技術(shù)也不斷獲得突破,這一切使得用Java處理實(shí)時(shí)信號(hào)成為可能。本文將通過設(shè)計(jì)和構(gòu)造一個(gè)支持實(shí)時(shí)MP3 WA爭(zhēng)口 Ogg音頻格式解碼/回放的Java音樂播放器,闡述用JavaSound API編寫音頻處理程序的思路和一般過程。JavaSound是一個(gè)小巧的低層 API,支持?jǐn)?shù)字音頻和 MIDI數(shù)據(jù)的記錄/回放。在JDK 1.3.0之前,JavaSound是一個(gè)標(biāo)準(zhǔn)的Java擴(kuò)展API,但從Java 2的1.3.0版開始,JavaSound就被包含到JDK之中。由于Java有著跨平臺(tái)(操作系統(tǒng)、硬件平臺(tái))的特點(diǎn),基于JavaSoun
2、d的音頻處理程序(包括本文的程序)能夠在任何實(shí)現(xiàn)了 Java 1.3+的系統(tǒng)上運(yùn)行,無需加裝任何支持軟件。一、JavaSound的體系結(jié)構(gòu)當(dāng)前JDK的JavaSound API隨同Java媒體框架(JMF, Java Media Framework )一起發(fā)布,主頁在,適合 JDK1.1 以及更高的版本。除了 JDK實(shí)現(xiàn)的 JavaSound API之外,還有一個(gè)源代碼開放的JavaSound實(shí)現(xiàn)是Tritonus,主頁在/ 。圖一描述了 JavaSound API的體系結(jié)構(gòu),虛線表示 Sun的JavaSound標(biāo)準(zhǔn)定義的API調(diào)用。上面一根虛線表示
3、我們編寫音頻處理程序要調(diào)用的API, JavaSound API包含在javax.sound.sampled 和javax.sound.midi包中。兩根虛線之間的部分就是JavaSound API的具體實(shí)現(xiàn)。書樂播.1游恣IIriteniet耆樂:;:工放:工:編輯二I r 基于 J avaS ound 啟的應(yīng)用軟件JavaSound API就象上面一根虛線表示的API具有統(tǒng)一標(biāo)準(zhǔn)一樣,在所有的JavaSound實(shí)現(xiàn)中,圖一下面一根虛線表示的SPI (服務(wù)提供者接口,Service Provider Interface )也是統(tǒng)一的。SPI的作用是以插件(Plug-In )的形式提供自定義的
4、擴(kuò)展模塊,我們只要提供與SPI兼容的插件擴(kuò)展模塊,就可以在不改變API的情況下擴(kuò)展音頻處理程序的能力。SPI包含在java.sound.sampled.spi 和javax.sound.midi.spi 包中。對(duì)于來自各種音頻輸入端口的信號(hào),TargetDataLine 之前,利用混頻器控 獲得數(shù)字化的音頻輸入流。TargetDataLine麥克侃 CD Line In.揚(yáng)聲噩耳機(jī) Lme Out .端口端口Mixer混頻器Mixer混頻器TargetDataLineSourceDataLine例如,假設(shè)有一個(gè)只能播放 WAV文件的程序,我們只要增加一個(gè)支持MP3文件解碼的插件模塊,就可以在不
5、改動(dòng)播放程序的任何一行代碼的前提下,為這個(gè)播放程序添加播放MP3的能力。作者:出處:uncj責(zé)任編輯:方舟2003-06-23 14:10 本文將通過設(shè)計(jì)和構(gòu)造一個(gè)支持實(shí)時(shí)MP3 WAX和Ogg音頻格式解碼/回放的Java音樂播放器,闡述用JavaSound API編寫音頻處理程序的思路和一般過程、JavaSound混頻原理圖二闡述了 JavaSound的混頻器原理。在處理輸入音頻的應(yīng)用中, 例如麥克風(fēng)、CD播放器、磁帶播放器,等等,我們可以在它們到達(dá) 制輸入混頻,最后在程序中通過輸入到應(yīng)用軟件從應(yīng)用軟件ffilj lEl圖二:JavaSound混頻器類似地,在處理輸出音頻的應(yīng)用中,混頻器用來
6、對(duì)一系列來自SourceDataLine的數(shù)據(jù)進(jìn)行混頻處理,經(jīng)處理后的信號(hào)可輸出到各種輸出端口,例如揚(yáng)聲器、耳機(jī)等。SourceDataLine是一個(gè)可寫入音頻信號(hào)數(shù)字流的設(shè)備,例如,我們可以從一個(gè) WAV文件讀取內(nèi)容寫入到 SourceDataLine,然后再通過揚(yáng)聲器輸出。輸入到混頻器的信號(hào)可以來源于剪輯。剪輯(Clip )是一個(gè)包含一段完整音頻數(shù)據(jù)流的設(shè)備,或者說,剪輯就是一個(gè)緩沖在內(nèi)存中的完整音頻數(shù)據(jù)流。在一些要求反復(fù)播放音樂片段的場(chǎng)合,例如游戲的背景音 樂,剪輯是很有用的。圖三描述了 JavaSound API中一些常用的類、接口及其關(guān)系,所有圖三顯示的類、接口都通過Line這個(gè)基本
7、接口統(tǒng)一起來。Line接口用來關(guān)閉/打開設(shè)備、注冊(cè)事件監(jiān)聽器,以及提供一些用來調(diào)整聲音效果 的對(duì)象,例如調(diào)整音量大小的對(duì)象。AudioSystem在JavaSound體系中起著一個(gè)工廠(Factory)類的作用,提供了一系列的靜態(tài)方法,我們通過這些靜態(tài)方法來獲取JavaSound系統(tǒng)默認(rèn)配置的資源(所謂靜態(tài)方法,就是可以在不創(chuàng)建AudioSystem實(shí)例的情況下直接調(diào)用的方法)。圖三:常用的 JavaSound類順便說明一下,在當(dāng)前(JDK1.4 )實(shí)現(xiàn)的JavaSound的默認(rèn)配置中,輸入聲音來自本地聲卡的麥克風(fēng), 輸出聲音到本地聲卡的揚(yáng)聲器。應(yīng)當(dāng)說當(dāng)前實(shí)現(xiàn)的JavaSound對(duì)端口和混頻器
8、的支持還不完善,但對(duì)于包括本文音樂播放器在內(nèi)的許多應(yīng)用來說,默認(rèn)實(shí)現(xiàn)的JavaSound配置已經(jīng)足夠了。三、音頻數(shù)據(jù)與存儲(chǔ)格式取樣得到的音頻數(shù)據(jù)也就是從TargetDataLine 輸入或從SourceDataLine輸出的數(shù)據(jù),必須符合音頻格式的標(biāo)準(zhǔn)。音頻數(shù)據(jù)的格式選項(xiàng)由 AudioFormat類封裝,主要選項(xiàng)包括:編碼方式,可以是PCMPulse Code Modulation ,脈沖編碼調(diào)制)、MP3等;通道數(shù)量;取樣率;幀速率;等等。音頻數(shù)據(jù)可以用多種格式保存到磁盤上。在JavaSound參考實(shí)現(xiàn)中,直接支持的文件格式包括WAV(Windows)、AIFF (主要用于 Apple的Ma
9、cintosh )以及AU (主要用于 UNIX),音頻文件的格式由AudioFileFormat 類指定。并非所有音頻數(shù)據(jù)格式都可以保存到任意音頻文件格式(或從音頻文件回放),具體由平臺(tái)和操作系統(tǒng)的類型決定。為簡(jiǎn)單計(jì),本文的播放器只考慮包含PCM Mono或 Stereo數(shù)據(jù)的WAV文件,這是當(dāng)前流行的音頻數(shù)據(jù)/文件格式組合,常用于 CD音質(zhì)的音頻數(shù)據(jù)。壓縮的音頻數(shù)據(jù)(例如MP3和 Ogg Vorbis )通常有各自特殊的存儲(chǔ)格式(如.MP3和.OGG,通常不以 WAV/AIFF/AU格式存儲(chǔ)。作者:出處:uncj責(zé)任編輯:方舟2003-06-23 14:10 本文將通過設(shè)計(jì)和構(gòu)造一個(gè)支持實(shí)
10、時(shí)MP3 WAX和Ogg音頻格式解碼/回放的Java音樂播放器,闡述用JavaSound API編寫音頻處理程序的思路和一般過程四、設(shè)計(jì)音樂播放器我們要編寫的音樂播放器(圖四)由表一所示的幾個(gè)類構(gòu)成。鑒于構(gòu)造用戶界面往往需要大量的代碼,且這些代碼通常可以用IDE自動(dòng)生成,所以下文只對(duì)一些關(guān)鍵的 GUI元素略作介紹,不再給出完整的代碼。圖四:播放器的用戶界面播放器的用戶界面主要由一個(gè)帶菜單的JFrame框架、一個(gè)名稱為filenamesList 的JList和幾個(gè)JButton構(gòu)成??蚣苡幸粋€(gè)私有的TestBase成員,其實(shí)例在 GUIInit() 方法的末尾通過 pBase = newTest
11、Base()語句初始化。表一表5類的名稱4說明4應(yīng)用程序鮭叢創(chuàng)建并顯示GUL 4UsklstFrroe播赦器的GUI.讀取YKW文件,掃詮特定的目錄查找 可播放的文件,在GUI的列表中顯示出這些文件.借助 瞰鵝類的幫助管理GUL卩包含與蘆音播啟有關(guān)的所有代碼邏輯.它用一個(gè)專用的線 程來播議產(chǎn)苜,因此在播啟產(chǎn)1苜的同時(shí),用戶仍可使用 GUI 例如點(diǎn)擊各種控制心顯示關(guān)于對(duì)話框 2用戶界面中的按鈕用類似下面的代碼創(chuàng)建,其中addBttnlconText()是一個(gè)私有方法,它把一個(gè)圖標(biāo)放到按鈕的文字標(biāo)簽之上。Java程序的用戶界面和 Windows界面風(fēng)格迥異,建議讀者使用Java開發(fā)工具自帶的圖標(biāo),
12、或者從 Java圖標(biāo)庫下載(例如)。JButton playBttn = new JButto n();addBtt nlco nText(playBtt n,播放 ”,Play24.gif);playBttn.addActionListener(new java.awt.event.ActionListener() public void actio nPerformed(Actio nEve nt e) playClick(e););當(dāng)用戶點(diǎn)擊一個(gè)按鈕,與該按鈕對(duì)應(yīng)的xxxClick()事件句柄函數(shù)開始執(zhí)行。播放器共有5個(gè)按鈕,相應(yīng)的事件句柄也有 5個(gè):playClick(播放”按鈕),s
13、topClick (停止”按鈕),pauseClick (暫?!卑粹o),prevClick (后退”按鈕),nextClick (前進(jìn)”按鈕)。例如,點(diǎn)擊播放”按鈕時(shí),playClick() 句柄首先獲得JList中選中的文件,然后調(diào)用 TestBase實(shí)例中的playFile()輔助方法播放文件。playClick()句柄的代碼如下所示,注意它把音樂文件及其所在目 錄連接起來的方法是操作系統(tǒng)中立的。void playClick(Acti on Eve nt e) String fileToPlay = (String) filenamesList.getSelectedValue();if
14、(fileToPlay != n ull) pBase.playFile(searchDir + System.getProperty(file.separator) + fileToPlay);stopClick() 和 pauseClick() 方法分別調(diào)用 TestBase 中的 stop()和 pause()方法。prevClick() 和 nextClick()句柄的任務(wù)稍微復(fù)雜一點(diǎn)。 首先,它們要調(diào)用TestBase中的stop()方法中止當(dāng)前的播放動(dòng)作, 然后選中JList中當(dāng)前項(xiàng)目的前一項(xiàng)或后一項(xiàng),最后調(diào)用playClick()播放新選中的音樂文件,如下所示。void prev
15、Click(Act ion Eve nt e) pBase.stop();file namesList.setSelectedl ndex(file namesList.getSelectedl ndex() -1);playClick(e);void n extClick(Acti on Eve nt e) pBase.stop();file namesList.setSelectedl ndex(file namesList.getSelectedl ndex()+1)% curPlayListLe ngth);playClick(e);五、播放音樂TestBase類包含主要的播放邏輯。例
16、如,當(dāng)用戶點(diǎn)擊播放”按鈕,TestBase類中的play()方法開始執(zhí)行。public void play() if (!stopped) | (paused) retur n;if (playerThread = n ull) playerThread = new Thread(this);playerThread.start();try Thread.sleep(500); catch (Exceptio n ex) synchroni zed(s yn ch) stopped = false;syn ch. notifyAII();play()方法首先確認(rèn)播放器當(dāng)前已被終止播放,而不是暫
17、停播放。然后它檢查這是不是第一次調(diào)用play():如果是,則創(chuàng)建一個(gè) playerThread線程。我們用一個(gè)獨(dú)立的線程負(fù)責(zé)音樂播放,這樣,無論播放器正在讀取文件、解碼,還是正在把音頻數(shù)據(jù)輸岀到揚(yáng)聲器,用戶界面總是可操作的。啟動(dòng)線程之后,play()方法鎖定靜態(tài)synch同步對(duì)象,將stopped標(biāo)記設(shè)置為false,然后通知正在 等待的線程(playerThread線程在開始播放音樂文件之前,會(huì)等待靜態(tài)synch對(duì)象上的提醒通知)。playerThread線程啟動(dòng)后,它的run()方法開始運(yùn)行。這個(gè)線程一直執(zhí)行 while循環(huán),直到threadExit 標(biāo)記變成true為止。在while循環(huán)
18、中,線程首先等待“開始播放”的信號(hào)(當(dāng)用戶點(diǎn)擊“播放”按鈕時(shí))然后播放音樂。表二列岀了描述播放器狀態(tài)的各個(gè)標(biāo)記及其含義。public void run() while (! threadExit) waitforSig nal();if (! stopped)playMusic();表二pVWWi標(biāo)記名稱說明宀程序運(yùn)行結(jié)束,線程應(yīng)當(dāng)盡快終止.p播敢器處于停止?fàn)顟B(tài);沒有正在播糕的文件.小卿加.羊播詼器處于暫停狀態(tài);勳點(diǎn)擊夷屋:按鈕從當(dāng)前位宣開始繼 續(xù)播畝.q正在播歟煤體文件.卩playMusic()方法利用JavaSound API播放當(dāng)前選中的文件。首先要通過AudioSystem類獲得一個(gè)A
19、udioInputstream。然后,利用 AudioInputstream 的getFormat()獲知音頻數(shù)據(jù)的格式。在此基礎(chǔ)上,我 們?cè)噲D通過getLine()方法獲得一個(gè)支持該種格式的SourceDataLine。如果要播放的是 WAV文件,現(xiàn)在我們已經(jīng)有了非壓縮的 PCM格式的音頻數(shù)據(jù),可以用line對(duì)象開始播放音頻。ais= AudioSystem.getAudiolnputStream(new File(fileToPlay);Jif (ais != n ull) baseFormat = ais.getFormat();line = getL in e(baseFormat);
20、如果音頻數(shù)據(jù)是壓縮格式的,如 MP3或Ogg,必須先進(jìn)行一次轉(zhuǎn)換把 MP3/Ogg解碼成PCM解碼主要包括三個(gè)步驟:1、創(chuàng)建一個(gè)解壓縮結(jié)果的定制 AudioFormat ( PCM編碼),但保留和原壓縮流一樣的取樣率、通道信 息等。2、創(chuàng)建一個(gè) AudioInputStream 把原來的 AudioInputStream 轉(zhuǎn)換成新的 AudioFormat 格式。3、獲得一個(gè)處理解碼后格式的SourceDataLine 。如下所示:AudioFormat decodedFormat = new AudioFormat(AudioFormat.E ncod in g.PCM_SIGNED,bas
21、eFormat.getSampleRate(),16,baseFormat.getCha nn els(),baseFormat.getCha nn els() * 2,baseFormat.getSampleRate(),false);ais = AudioSystem.getAudioI nputStream(decodedFormat, ais);line = getL in e(decodedFormat);getLine()方法的返回值是一個(gè)與參數(shù)中指定的AudioFormat兼容的SourceDataLine。如果不能獲得兼容的SourceDataLine ,getLine() 返
22、回null。在getLine() 方法中,我們首先創(chuàng)建和填充一個(gè) DataLine.Info 結(jié)構(gòu),調(diào)用 AudioSystem.getLine() 方法,將 info 結(jié)構(gòu)傳遞給 AudioSystem 類工廠。private SourceDataL ine getL in e(AudioFormat audioFormat) SourceDataL ine res = n ull;DataLi ne.l nfo info = new DataLi ne.l nfo(SourceDataLi ne.class,audioFormat);try res = (SourceDataLine) A
23、udioSystem.getLine(info);res.ope n( audioFormat);catch (Excepti on e) return res;準(zhǔn)備好AudioInputStream 和SourceDataLine 之后,playMusic()剩余的任務(wù)已經(jīng)很簡(jiǎn)單:用一個(gè)循環(huán)從 AudioInputStream 讀取數(shù)據(jù),然后寫入到SourceDataL in Bytes = 0;while (inBytes != -1) & (!stopped) & (!threadExit) try in Bytes = ais.read(audioData, 0, BUFFER_SIZE); _catch (IOExcepti on e) e.pri ntStackTra
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 備戰(zhàn)2025年中考語文課內(nèi)文言文(統(tǒng)編版)20《與朱元思書》三年中考真題+模擬題(學(xué)生版+解析)
- 股東平等原則與對(duì)賭協(xié)議書(2篇)
- 南京工業(yè)大學(xué)浦江學(xué)院《稅法二》2022-2023學(xué)年第一學(xué)期期末試卷
- 殯儀館施工組織設(shè)計(jì)
- 方爺爺和圓奶奶說課稿
- 肚子里的故事說課稿
- 《中 國(guó)美食》說課稿
- 《液體的壓強(qiáng)》說課稿
- 南京工業(yè)大學(xué)浦江學(xué)院《公共事業(yè)管理》2023-2024學(xué)年第一學(xué)期期末試卷
- 八年級(jí)第六單元《三峽》說課稿
- 冶金企業(yè)的冶煉生產(chǎn)計(jì)劃三篇
- 課題論文:推動(dòng)發(fā)展培育新質(zhì)生產(chǎn)力
- 12G614-1 砌體填充墻結(jié)構(gòu)構(gòu)造
- 燃?xì)饨?jīng)營(yíng)安全重大隱患判定標(biāo)準(zhǔn)課件
- 小學(xué)一年級(jí)數(shù)學(xué)兩位數(shù)加減一位數(shù)競(jìng)賽監(jiān)控模擬題
- CHT 8023-2011 機(jī)載激光雷達(dá)數(shù)據(jù)處理技術(shù)規(guī)范(正式版)
- 檢驗(yàn)科進(jìn)修匯報(bào)課件
- 年產(chǎn)10萬套新能源車電池托盤和儲(chǔ)能箱體項(xiàng)目可行性研究報(bào)告
- 低壓電工基礎(chǔ)知識(shí)培訓(xùn)
- MOOC 葡萄酒文化與鑒賞-西北工業(yè)大學(xué) 中國(guó)大學(xué)慕課答案
- 交警進(jìn)校園宣傳安全
評(píng)論
0/150
提交評(píng)論