《基于python的音頻播放器的設(shè)計與實現(xiàn)》9000字_第1頁
《基于python的音頻播放器的設(shè)計與實現(xiàn)》9000字_第2頁
《基于python的音頻播放器的設(shè)計與實現(xiàn)》9000字_第3頁
《基于python的音頻播放器的設(shè)計與實現(xiàn)》9000字_第4頁
《基于python的音頻播放器的設(shè)計與實現(xiàn)》9000字_第5頁
已閱讀5頁,還剩26頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第1章引言在人們逐漸追求精神文化的過程中,聽音樂也漸漸成為了一種比較廣泛的興趣愛好。如今在互聯(lián)網(wǎng)當(dāng)中,音頻播放器種類眾多。音樂播放器屬于多媒體軟件,可以進行各式各樣的文件播放,同時包含了多種格式內(nèi)容,例如MP3等。其通常操作過程比較簡單,而且界面較為美觀,能夠讓人真正進入到放松的音樂空間當(dāng)中。音樂播放器在本質(zhì)上其實屬于一種操作界面,其根本內(nèi)容是音頻解碼器,主要是對于不同種類的編碼后的音頻所進行的解碼。許多音樂播放器對于各類格式都比較支持,其原因是音頻播放器本身能夠?qū)τ诓煌N類的解碼器進行有效解碼,并且使所有的播放頁面達到統(tǒng)一,讓使用者對于音樂有更加深刻的感受。由于音樂播放器本身存在固定的方式進行音頻解碼,而且其原理層面僅僅是對于解碼器進行打包,所以在整體上來說,一切播放器的播放音質(zhì)都可能是完全一樣的,并沒有音質(zhì)方面的區(qū)別。不過,某些音樂播放器為了突出自身的播放水平,會以解碼器作為前提,進一步進行DSP插件的添加,滿足受眾的需求,這可以說是對于原本音樂展開扭曲或者轉(zhuǎn)換的過程,但其實僅僅是對于細節(jié)的過濾或者將音調(diào)降低等,在宣傳過程中,可能會宣傳成為音質(zhì)的美化等方式,但其實,這種方式在本身上是對于音樂的破壞,其能夠讓某些音樂變得更加好聽,但對于大部分音樂來說,卻會導(dǎo)致音質(zhì)水平的降低。因此,有必要了解到的是,作為音樂播放器本身,其所具備的操作界面或者擴展性內(nèi)容,才是真正屬于播放器本身的特色。如今許多商業(yè)播放軟件,可能有非常絢麗的界面,或者說在操作方面存在與眾不同的表現(xiàn),但通常而言并不具備拓展性,對于格式支持并不是很多。同時,在開源播放軟件方面通常能夠獲得一定程度的拓展,對于不同種類的音樂格式予以支持,不過通常而言界面比較樸素,客戶無法從中感受到充分的吸引力。國外的音樂播放器通常包括realplayer和微軟系統(tǒng)本身自帶的播放器,但是通常在國內(nèi)的使用頻率并不高,而在國內(nèi)音樂市場當(dāng)中,酷狗、網(wǎng)易云、QQ音樂等播放器占據(jù)了大量市場,而且通過一定的軟件更新和升級,無論是播放器本身的功能還是給用戶帶來的體驗方面都有了不錯的發(fā)展。如今,國內(nèi)進行了兩個主要方向的音頻研究,首先是胡守超以Python語言作為基礎(chǔ),通過音頻的捕獲和頻率分析所展開的設(shè)計,通過編程語言分析相關(guān)音頻數(shù)據(jù),并對于音頻數(shù)據(jù)內(nèi)容進行有效采集,進行音頻波譜以及頻率的有效顯示。另外也是以Python音頻數(shù)據(jù)作為基礎(chǔ),通過對于聲音文件本身格式以及播放特性的轉(zhuǎn)換,對于不同的音頻文件展開對應(yīng)分離以及合成,同時對不同音樂之間所具有的特征展開有效分析,有效改變原本聲音當(dāng)中出現(xiàn)的采樣寬度、速率以及編碼等內(nèi)容。國外使用頻率較高的專業(yè)播放器,具備多媒體解析功能以及軟件編輯功能,來自于Adobe公司所開發(fā)的相關(guān)內(nèi)容,其主要設(shè)計目標(biāo)是音頻以及視頻專業(yè)人員,通常他們使用于照相師、后期制作以及廣播等方面,軟件本身具備音頻混合、音頻編輯、音頻控制以及相關(guān)頻率的處理等功能特性。此次研究過程中,以CoolEditPro軟件本身具備的功能作為基礎(chǔ),借助其軟件運用,同時通過Python語言的結(jié)合使用,以及利用程序編輯器和專業(yè)工具包,進行音頻播放器的設(shè)計以及實現(xiàn),播放器本身能夠進行各種格式的音頻播放,并且能夠進行wava文件的波形顯示等一系列的特殊功能。第2章軟件開發(fā)環(huán)境與開發(fā)工具2.1Eclipse軟件簡介Eclipse本身屬于一種集成式的開發(fā)環(huán)境,同時具備跨平臺的作用。一開始這個平臺的作用是java開發(fā),不過到如今為止,已經(jīng)有很多人利用插件進行其他語言的開發(fā),比如c語言以及Python??梢哉f此軟件僅僅屬于一種平臺,屬于開發(fā)過程中的框架,而通過這些插件支持,相對來說使整個平臺的靈活性大大提升,對于比較固定的軟件而言,這種靈活性是非常難得的。在此平臺當(dāng)中,插件本身也是組件化的存在,作為客戶而言,在使用過程中,可以通過插件滿足相關(guān)附加功能,比方說不僅僅對于java語言有一定的支持程度,同時對其他語言而言,也能夠予以支持。另外,如今已經(jīng)存在的插件已經(jīng)可以支持多種編程語言的開發(fā),并且可以進行相關(guān)數(shù)據(jù)庫開發(fā),比如C語言、C++以及本文當(dāng)中所使用的Python語言等。同時,作為該平臺本身,存在一定的插件架構(gòu),能夠支持各類擴展功能,比如配置管理等,而并不只是對于不同種類的編程語言予以支持。作為Eclipse平臺本身,其所具備的設(shè)計理念在于所有的東西都屬于插件的一部分。作為平臺本身,其核心內(nèi)容并不是很多,而另外的功能都以核心為基礎(chǔ),同時以插件的方式進行附著。此外,其中內(nèi)核成分包含了圖形、環(huán)境插件以及java語言等基礎(chǔ)內(nèi)容。同時,作為軟件開發(fā)人員而言,通過SDK進行相應(yīng)的組建合并,能夠讓使用者更方便的進行工具下載。在合并之后可以提供具備豐富特性的開發(fā)環(huán)境,同時作為開發(fā)者而言,則能夠有效進行工具建設(shè),并且集成到平臺環(huán)境當(dāng)中。SDK本身包含了平臺自身的工具以及其他軟件當(dāng)中的系列工具內(nèi)容,這些工具主要是源代碼已經(jīng)開放的相關(guān)平臺。另外,作為項目生產(chǎn)過程中,可以通過GPL進行有效發(fā)布,而作為組件來說,則有它們本身的許可協(xié)議等內(nèi)容。2.2Python語言簡介Python屬于解釋型,且能夠面向?qū)ο蟮某绦蛘Z言,同時此程序語言屬于動態(tài)類型。從1990年開始發(fā)展到如今,此類語言已經(jīng)在系統(tǒng)管理任務(wù)當(dāng)中獲得了非常廣泛的使用,同時也在web編程當(dāng)中得到了良好的應(yīng)用效果,甚至可以說是目前受歡迎程度最廣的一項涉及語言。因為該語言本身具備可擴展以及簡潔特性,在國外通過這種語言進行科學(xué)計算的機構(gòu)數(shù)量漸漸增加,尤其是不少知名大學(xué)已經(jīng)采取此語言進行程序課程的教育。同時,許多開源科學(xué)計算過程中都提供了相應(yīng)的接口,可以進行此類語言的調(diào)用。而針對Python本身,科學(xué)擴展庫數(shù)量可以說是非常多,比如numpy以及scipy等,通過這些擴展庫能夠讓語言本身獲得數(shù)值運算等功能,或者進行數(shù)組處理和繪圖功能的實現(xiàn)。所以總體而言,該語言本身和語言擴展功能共同構(gòu)成相應(yīng)的開發(fā)環(huán)境,有利于科研人員進行數(shù)據(jù)處理,同時有利于工程技術(shù)人員進行相應(yīng)你的圖標(biāo)制作,或者進行科學(xué)程序的有效開發(fā)。另外,追溯到源頭可以得知Python設(shè)計者本身在語法方面加強了限制性,可以說是在很大程度上糾正了一些不良習(xí)慣,避免由于疏漏導(dǎo)致的程序錯誤,比如對于if語句而言,如果下一行沒有縮進的話,在這個平臺當(dāng)中的編譯是無法被通過的,這也就是眾所周知的此語言本身具備的縮進規(guī)則。此外,Python與其他許多語言,比如C++等語言存在的主要區(qū)別在于:模塊本身擁有的接線,并不是通過某些符號表達所進行的定義,在許多語言當(dāng)中模塊接線通常需要特殊字符進行隔離,但是在Python當(dāng)中,則是由首字符所在的位置進行確定的。這一點的設(shè)定引起了不少人的不滿,主要原因是由于C++等語言出現(xiàn)之后,逐漸將語法本身具有的含義不體現(xiàn)在字符的排列方面,而且認為這種區(qū)分屬于程序語言在逐步進步的過程。但是需要承認的是,Python平臺當(dāng)中的這些要求,讓整體程序的美觀度大大提升,其中包含了一些模塊的使用,尤其是if以及for等定義的強制縮進等要求,這種強制性可以說是帶來了一定的好處。而且,Python作為一種語言,本身是面對某些對象進行使用的,其中包括了模塊、字符串以及函數(shù)等,而且具備一定的繼承性和派生性等,在這個過程中,對于源代碼重復(fù)使用有一定的幫助。同時,平臺本身對于動態(tài)特性和運算符的重新載入有一定的支持度,相比較一些比較傳統(tǒng)的語言而言,在函數(shù)設(shè)計方面,該平臺并沒有提供全方位的支持,而是比較片面的作用。在具體執(zhí)行過程中,Python平臺本身會執(zhí)行后綴名為py的文件,并且將其中存在的源代碼進行編譯,使之全部成為字節(jié)碼,之后通過虛擬機進行字節(jié)碼的有效執(zhí)行。另外,平臺本身能夠通過交互模式進行運行,也就是說可以在不同系統(tǒng)當(dāng)中進行操作,而并不是僅僅局限于Windows或者某種系統(tǒng),一些主流系統(tǒng)都能夠在命令模式之下進行此平臺的環(huán)境命令,或者通過指令下達,就可以有效完成相關(guān)操作過程。2.3所用到的python工具包在整體開發(fā)進程當(dāng)中,Python平臺當(dāng)中使用了各類工具包,比如跨平臺所進行的應(yīng)用程式框架等程序pyside,其可以說是屬于平臺本身存在的綁定版本,另外還有一些工具包能夠進行波形圖的繪制,以及計算其中所存在的音頻數(shù)據(jù)等內(nèi)容,在此開發(fā)過程中得到了廣泛的應(yīng)用。同時在此次設(shè)計過程中,還需要通過Pysideuic進一步轉(zhuǎn)換相應(yīng)的ui文件,使之成為py后綴名的文件內(nèi)容。第3章軟件界面窗口的實現(xiàn)3.1QtDesigner軟件簡介QtDesigner屬于GUI的工具內(nèi)容,通過這項工具的使用,能夠使QT程序的編寫速度大大加強,另外,通過此軟件的使用,能夠產(chǎn)生所見所得的效果,避免盲目進行代碼編寫之后出現(xiàn)各類問題,在編寫過程中,可以通過QT程序產(chǎn)生界面代碼,而在增加系列功能之后,就能夠妥善完成工具編寫。具體操作步驟是通過此類程序進行頁面搭建,在搭建之后保存相應(yīng)的UI文件,之后通過命令解釋器進行文件轉(zhuǎn)換,也就是上文當(dāng)中所提到的將ui文件向py文件進行轉(zhuǎn)換。3.2軟件整體界面的繪制需要重視的是,在整體界面當(dāng)中并非僅僅包含一部分內(nèi)容,而是由上半部分、中部以及下半部分共同構(gòu)成,其中上半部分屬于播放器,包含了文件選擇、時間編輯以及播放或者停止等,同時可以在這一部分進行音量的調(diào)節(jié)以及波形的具體條件,而且也能夠進行快進和快退等操作內(nèi)容。而中部則屬于動態(tài)波形區(qū)域,可以進行相關(guān)波形的展示。下半部分則屬于靜態(tài)波形區(qū),在音頻播放的過程中也具有特定的效果,但總體功能還是集中在頁面的最上方。在具體繪制的過程中,可以在運行軟件之后,新建窗口,同時按照原本的設(shè)計路徑進行功能的添加以及繪制,分別包括時間的編輯按鈕,以及進行文件選擇,文本框的粘貼,之后則設(shè)置播放按鈕以及暫停按鈕,同時為了方便使用,還可以設(shè)置停止播放按鈕,隨后對于音量大小進行調(diào)節(jié),可以設(shè)置按鈕或者進度條等,再之后通過放大鏡作為觸發(fā)模式,針對波形的大小展開調(diào)節(jié),而后實現(xiàn)快進與快退等模式,通過時間以及進度條等觀察音樂具體的播放情況,在這些功能全部添加之后,也就完成了上半部分的界面繪制,不過還需要將整體布局設(shè)置成水平模式,從而實現(xiàn)如圖所示的構(gòu)造。之后,為了實現(xiàn)其他部分的窗口功能和內(nèi)容,可以重新建立窗口,并進行兩個部分的劃分,上半部分是播放過程中的動態(tài)波形顯示,而下半部分則是保持不變的整體波形顯示,通過這種操作也就完成了整體的頁面設(shè)計過程。圖3.2設(shè)計頁面第4章音頻解析與播放功能的實現(xiàn)4.1phonon模塊簡介隨著科學(xué)技術(shù)的發(fā)展,音頻格式也逐漸增多,如今在音頻格式領(lǐng)域已經(jīng)包含了MP3、WMA、WAV等常見格式,以及VQF和APE等不是非常常見的格式。面對如此復(fù)雜的內(nèi)容,通過調(diào)用工具包當(dāng)中的模塊就能夠?qū)τ谒幸纛l格式進行有效解析,而且可以在調(diào)用相應(yīng)模塊之后,有效實現(xiàn)各種音頻格式的播放。4.2功能具體實現(xiàn)過程音頻格式當(dāng)中包含如下幾個方面的內(nèi)容,第一是獲取源文件,之后是實現(xiàn)播放功能、暫停功能以及停止等具體功能。因為平臺本身屬于集成且開源的類型,其中包含了許多種類的API等內(nèi)容,所以只需要進行普通函數(shù)調(diào)用就能夠有效實現(xiàn)相關(guān)功能,而在此次設(shè)計過程中使用了如下內(nèi)容:MediaObject、MediaSource、MusicCategory、createPath、PlayingState、StoppedState、LoadingState、BufferingState、ErrorState。之后利用代碼以及注釋對于相關(guān)過程展開有效分析:classPlayer(QtGui.QWidget):def__init__(self,parent=None):QtGui.QWidget.__init__(self,parent)self.ui=Ui_toolBoxWidget()#實例化Ui_toolBoxWidget類self.ui.setupUi(self)#調(diào)用setupUi函數(shù)self.media=Phonon.MediaObject(self)#實例化MediaObject類self.media.setCurrentSource(Phonon.MediaSource())#設(shè)置當(dāng)前源文件self.media.setTickInterval(100)#設(shè)置音頻解析間隔self.output=Phonon.AudioOutput(Phonon.MusicCategory,self)#音頻輸出類型Phonon.createPath(self.media,self.output)#選擇默認音頻路徑self.ui.volumeSlider_music.setAudioOutput(self.output)#鏈接到音量調(diào)節(jié)功能self.ui.seekSlider_musicProgress.setMediaObject(self.media)#鏈接到進度條self.ui.lcdNumber.display("00:00")#鏈接到時間顯示self.media.stateChanged.connect(self.stateChanged)#鏈接到狀態(tài)轉(zhuǎn)換函數(shù)self.media.tick.connect(self.tick)#鏈接到顯示時間方式函數(shù)self.ui.pushButton_musicPlay.clicked.connect(self.changePlayPause)#鏈接到播放暫停函數(shù)self.ui.pushButton_musicStop.clicked.connect(self.changeStop)#鏈接到停止函數(shù)self.ui.pushButton_chooseMusicFile.clicked.connect(self.handleButtonChoose)#鏈接到文件選擇函數(shù)self.ui.timeEdit_music.timeChanged.connect(self.timeEditTimeChanged)#鏈接到時間編輯函數(shù)self.path=None#路徑初始化為空self.signal=FileChoosedSignal()#實例化FileChoosedSignal類deftimeEditTimeChanged(self,time):miliSec=(((time.hour()*60+time.minute())*60)+time.second())*1000print'miliSec',miliSecself.media.seek(miliSec)#時間編輯defgetPlayerMedia(self):returnself.media#獲取源文件defhandleButtonChoose(self):dialog=QtGui.QFileDialog(self)dialog.setFileMode(QtGui.QFileDialog.ExistingFile)ifdialog.exec_()==QtGui.QDialog.Accepted:self.path=dialog.selectedFiles()[0]self.media.setCurrentSource(Phonon.MediaSource(self.path))self.ui.lineEdit_musicFilePath.setText(self.path)dialog.deleteLater()#選擇文件deftick(self,time):displayTime=QtCore.QTime(0,(time/60000)%60,(time/1000)%60)self.ui.lcdNumber.display(displayTime.toString('mm:ss'))self.signal.TimeNowChanged.emit(time)#時間顯示方式defchangePlayPause(self):ifself.path==None:msgBox=QtGui.QMessageBox(self)msgBox.setText("pleasechooseamusicfilefirst.")msgBox.setStandardButtons(QtGui.QMessageBox.Ok)msgBox.exec_()returnifself.media.state()==Phonon.PlayingState:self.media.pause()elifself.media.state()==Phonon.StoppedState:self.media.play()self.signal.fileChoosedSignal.emit()else:self.media.play()#播放暫停defchangeStop(self):self.media.stop()#停止defstateChanged(self,newstate,oldstate):ifnewstate==Phonon.PlayingState:self.ui.pushButton_musicPlay.setIcon(QtGui.QIcon(":/Image/Image/pause.png"))elif(newstate!=Phonon.LoadingStateandnewstate!=Phonon.BufferingState):self.ui.pushButton_musicPlay.setIcon(QtGui.QIcon(":/Image/Image/play.png"))ifnewstate==Phonon.ErrorState:print('ERROR:playiswrong:%s'%self.media.errorString())#狀態(tài)轉(zhuǎn)換classFileChoosedSignal(QtCore.QObject):fileChoosedSignal=QtCore.Signal()TimeNowChanged=QtCore.Signal(int)#創(chuàng)建兩個信號圖4.2音頻區(qū)第5章波形顯示的實現(xiàn)5.1對WAV文件獲取數(shù)據(jù)波形本身是利用解析得知的數(shù)據(jù)在波形區(qū)當(dāng)中的位置進行描點,而通過描點進行集合,將會產(chǎn)生連續(xù)波形等內(nèi)容。在此次設(shè)計過程中,可以利用wava模塊對于具體數(shù)據(jù)進行解析,可以返回有關(guān)數(shù)據(jù)并進行識別。最終可以依照已經(jīng)得到的數(shù)據(jù)信息進行波形繪制。對于Python而言,模塊本身提供了相應(yīng)的接口進行使用,其能夠?qū)τ谖募?dāng)中的參數(shù)進行解析,比如頻率、寬度以及幀數(shù)等內(nèi)容。通過類似數(shù)據(jù)以及結(jié)合相關(guān)工具進行wava文件繪制。依照上述內(nèi)容可以了解到,模塊本身存在缺點,比如不支持解壓等特性,因此在此次設(shè)計過程中,僅僅能夠進行wava波形的解壓,如下可以利用代碼更好地實現(xiàn)相關(guān)內(nèi)容:第一步是進行初始化得到對應(yīng)的文件內(nèi)容。self.audio=wave.open(path,'r')#對文件進行只讀操作self.nchannels,self.sampwidth,self.framerate,self.nframes,ptype,pname=self.audio.getparams()#獲取文件各項參數(shù)然后進行讀取操作,defread(self,size):data=self.audio.readframes(size)#size為總幀數(shù)sw=self.audio.getsampwidth()#獲取采樣寬度data=numpy.frombuffer(data,dtype=numpy.dtype("i%d"%sw))#用numpy工具進行科學(xué)計算nc=self.audio.getnchannels()ifnc>1:left=data[0::nc]right=data[1::nc]sample=[left,right]else:sample=datareturnsample+#返回值也就是在波形繪制過程中的數(shù)據(jù)需求。5.2根據(jù)音頻數(shù)據(jù)繪制音樂波形通過上述模塊能夠獲得畫圖當(dāng)中的具體數(shù)據(jù)內(nèi)容,在畫圖當(dāng)中使用的工具是matplot包。而此內(nèi)容通常是在平臺代碼當(dāng)中展開,進行2D界面繪圖的有效制作,同時促進科學(xué)計算性能的有效優(yōu)化。5.2.1音頻數(shù)據(jù)全部波形在音頻數(shù)據(jù)波形當(dāng)中,能夠使完整的wav文件獲得轉(zhuǎn)換,轉(zhuǎn)換的是所有的數(shù)據(jù)內(nèi)容,而結(jié)果是一切波形。在此模塊當(dāng)中,通過五項函數(shù)進行調(diào)用,分別包括初始化繪圖、依照數(shù)據(jù)進行跟蹤區(qū)的有效刷新、依照數(shù)據(jù)對時間信息進行刷新以及展開屬性設(shè)置。如下是具體的代碼操作:deffreshLeftAndWidthFromUpperPlot(self,leftFrame,rightFrame):ifself.ax==None:Return#print(22%250)else:self.leftDot=leftFrame/self.zipRateself.rightDot=rightFrame/self.zipRatexy=#print(22%250)np.array([[self.leftDot,0.],[self.leftDot,1.],[self.rightDot,1.],[self.rightDot,0.],[self.leftDot,0.]])self.span.set_xy(xy)self.canvas.draw()#print(22%250)#根據(jù)實時數(shù)據(jù)來刷新矩形跟蹤區(qū)deffreshCurrentTimeFromUpperPlot(self,frameNow):ifhasattr(self,'vline'):self.vline.set_xdata(frameNow/self.zipRate)self.canvas.draw()#print(22%250)#根據(jù)實時數(shù)據(jù)來刷新當(dāng)前時間信息defdrawInit(self,waveData):self.clf()self.plotDataDict=self.plotDataProcess(waveData)self.ax=self.add_axes([0.1,0.1,0.8,0.8])#print(22%250)self.vline=self.ax.axvline(x=10,color='red',zorder=3)self.span=self.ax.axvspan(0,0,facecolor='g',alpha=0.5,zorder=2)self.plotFunc(self.plotDataDict)self.ax.set_xlim(0,self.dotsInScreen)self.canvas.draw()#繪圖區(qū)初始化defplotFunc(self,plotDataDict):xarray=np.arange(self.dotsInScreen)ifplotDataDict.has_key('y_mean_2'):ymax=plotDataDict['y_max']ymin=plotDataDict['y_min']#print(22%250)ymean=plotDataDict['y_mean']ymean2=plotDataDict['y_mean_2']self.fillPlot=self.ax.fill_between(xarray,ymax,y2=ymin,color='#108070',zorder=0)self.linePlot=self.ax.plot(xarray,ymean,'pink',xarray,ymean2,'y',zorder=1)else:#print(22%250)ymax=plotDataDict['y_max']ymin=plotDataDict['y_min']ymean=plotDataDict['y_mean']self.fillPlot=self.ax.fill_between(xarray,ymax,y2=ymin,zorder=0)self.linePlot=self.ax.plot(xarray,ymean,'b',zorder=1)#繪圖區(qū)屬性設(shè)置defplotDataProcess(self,waveData):ifisinstance(waveData,list):dataOne=waveData[0]#print(22%250)dataTwo=waveData[1]dataLength=len(dataOne)numchunks=self.dotsInScreenchunksize=dataLength//numchunksself.zipRate=chunksize#print(22%250)team_1=dataOne[:chunksize*numchunks].reshape((-1,chunksize))team_2=dataTwo[:chunksize*numchunks].reshape((-1,chunksize))max_1=team_1.max(axis=1)max_2=team_2.max(axis=1)#print(22%250)max_1_2=np.maximum(max_1,max_2)min_1=team_1.min(axis=1)min_2=team_2.min(axis=1)#print(22%250)min_1_2=np.minimum(min_1,min_2)mean_1=team_1.mean(axis=1)mean_2=team_2.mean(axis=1)plotDataDict=dict(y_max=max_1_2,y_min=min_1_2,y_mean=mean_1,y_mean_2=mean_2)else:#print(22%250)dataOne=waveDatadataLength=len(dataOne)numchunks=self.dotsInScreenchunksize=dataLength//numchunksself.zipRate=chunksize#print(22%250)team_1=dataOne[:chunksize*numchunks].reshape((-1,chunksize))max_1=team_1.max(axis=1)min_1=team_1.min(axis=1)mean_1=team_1.mean(axis=1)plotDataDict=dict(y_max=max_1,y_min=min_1,y_mean=mean_1)returnplotDataDict#print(22%250)利用相關(guān)函數(shù)能夠得到音頻當(dāng)中的全部波形內(nèi)容:圖5.1靜態(tài)波形區(qū)5.2.2當(dāng)前時間段波形在上述操作當(dāng)中,獲得了來自音頻的整體波形,但屬于第三個區(qū)域的靜態(tài)內(nèi)容,而如果想要讓其得到動態(tài)有效的顯示,還需要展開進一步的研究。與靜態(tài)波形相同的是,動態(tài)波形也是在wave模塊當(dāng)中所獲得的信息,并且通過軟件進行繪制。但存在區(qū)別的是,動態(tài)模型需要實時刷新,并且獲得實時數(shù)據(jù)跟蹤等內(nèi)容。在這一方面可以用到的函數(shù)數(shù)量更多,比如波形的更新、時間的同步以及繪圖初始化等操作,并且能夠進行坐標(biāo)清除和屬性設(shè)置,更進一步獲得動態(tài)的數(shù)據(jù)跟蹤,同時具備波形的縮小以及放大等功能,實現(xiàn)音樂的快速調(diào)整,對于波形進行放大以及縮小。具體程序代碼如下:defmediaTimeChanged(self,time):self.currentTime_ms=int(time)self.fresh()self.signal.freshScreenTime.emit(time)#源文件時間同步deffresh(self):#print(22%250)ifnothasattr(self,'ax'):returnifhasattr(self,'pressX')andnotself.pressX==None:self.currentTime_ms=self.media.currentTime()frameNow=self.currentTime_ms*self.framerate/1000framesInScreen=self.secondsInScreen*self.frameratedotNow=frameNow/self.zipRateself.signal.freshLowerPlotCurrentTime.emit(frameNow)ifdotNow>=self.leftDot+self.dotsInScreen*3/2ordotNow<=self.leftDot-self.dotsInScreen/2:print'or'#print(22%250)print'self.leftdot=',self.leftDotprint'dotNow=',dotNownumberOfScreens=(dotNow-self.dotsInScreen/2)//self.dotsInScreenself.leftDot=numberOfScreens*self.dotsInScreennpSlice=np.arange(self.leftDot,self.leftDot+self.dotsInScreen)self.plotFunc(npSlice)self.clearAxes()#print(22%250)ifself.leftDot+self.dotsInScreen*3/2>dotNow>self.leftDot+self.dotsInScreen/2:print'draw>>'npSlice=np.arange(self.leftDot+self.dotsInScreen,self.leftDot+2*self.dotsInScreen)self.plotFunc(npSlice)self.clearAxes()#print(22%250)self.leftDot+=self.dotsInScreenself.ax.set_xlim(dotNow-self.dotsInScreen/2,dotNow+self.dotsInScreen/2)self.vline.set_xdata(dotNow)self.signal.freshLowerPlotPanLeftAndWidth.emit(frameNow-framesInScreen/2,frameNow+framesInScreen/2)self.canvas.draw()#實時更新波形defdrawInit(self,dataDict):self.clf()#print(22%250)self.media=dataDict['media']self.waveData=dataDict['data']self.framerate=dataDict['framerate']self.zipRate=int(self.secondsInScreen*self.framerate/self.dotsInScreen)self.plotDataList=[]self.getAllPlotData(self.zipRate)ifhasattr(self,'ax'):self.ax.clear()#print(22%250)self.ax=self.add_axes([0.1,0.1,0.8,0.8])self.ax.axhline(y=0,color='0.8',zorder=2)self.vline=self.ax.axvline(x=0,color='red',zorder=3)self.leftDot=0self.npSlice=[0]npSlice=np.arange(self.leftDot,self.leftDot+self.dotsInScreen)self.plotFunc(npSlice)self.mediaTimeChanged(0)#繪圖區(qū)初始化defplotFunc(self,npSlice):ifnpSlice[0]<0:Return#print(22%250)ifnpSlice[0]>self.waveDataLength:returnelifnpSlice[-1]>self.waveDataLength:npSlice=npSlice[0:self.waveDataLength-npSlice[0]]plotDataSliceDict=self.getSlicePlotData(npSlice)ymax=plotDataSliceDict['y_max']ymin=plotDataSliceDict['y_min']fillPlot=self.ax.fill_between(npSlice,ymax,y2=ymin,color='c',zorder=0)#print(22%250)self.plotDataList.append(fillPlot)#繪圖區(qū)屬性設(shè)置defclearAxes(self):length=len(self.plotDataList)iflength>2:foriinxrange(length-3):self.plotDataList[i].remove()self.plotDataList.pop(i)#清除坐標(biāo)defgetAllPlotData(self,zipRate):waveData=self.waveDataifisinstance(waveData,list):dataOne=waveData[0]dataTwo=waveData[1]dataLength=len(dataOne)chunksize=zipRate#print(22%250)numchunks=dataLength//chunksizeteam_1=dataOne[:chunksize*numchunks].reshape((-1,chunksize))team_2=dataTwo[:chunksize*numchunks].reshape((-1,chunksize))max_1=team_1.max(axis=1)max_2=team_2.max(axis=1)max_1_2=np.maximum(max_1,max_2)min_1=team_1.min(axis=1)min_2=team_2.min(axis=1)min_1_2=np.minimum(min_1,min_2)mean_1=team_1.mean(axis=1)mean_2=team_2.mean(axis=1)plotDataDict=dict(y_max=max_1_2,y_min=min_1_2,y_mean=mean_1,y_mean_2=mean_2)self.waveDataLength=numchunkselse:#print(22%250)dataLength=len(waveData)chunksize=zipRatenumchunks=dataLength//chunksizeteam_1=waveData[:chunksize*numchunks].reshape((-1,chunksize))max_1=team_1.max(axis=1)min_1=team_1.min(axis=1)mean_1=team_1.mean(axis=1)plotDataDict=dict(y_max=max_1,y_min=min_1,y_mean=mean_1)self.waveDataLength=numchunksself.plotDataAllDict=plotDataDict#獲取當(dāng)前繪圖區(qū)的全部數(shù)據(jù)defgetSlicePlotData(self,npSlice):ymaxSlice=self.plotDataAllDict['y_max'][npSlice]yminSlice=self.plotDataAllDict['y_min'][npSlice]ymeanSlice=self.plotDataAllDict['y_mean'][npSlice]ifself.plotDataAllDict.has_key('y_mean_2'):ymean2Slice=self.plotDataAllDict['y_mean_2'][npSlice]plotDataSliceDict=dict(y_max=ymaxSlice,y_min=yminSlice,y_mean=ymeanSlice,y_mean_2=ymean2Slice)else:#print(22%250)plotDataSliceDict=dict(y_max=ymaxSlice,y_min=yminSlice,y_mean=ymeanSlice)returnplotDataSliceDict#獲取當(dāng)前繪圖區(qū)的部分數(shù)據(jù)defzoomIn(self):self.secondsInScreen/=2self.zipRate=int(self.secondsInScreen*self.framerate/self.dotsInScreen)ifself.zipRate==0:returnself.plotDataList=[]self.getAllPlotData(self.zipRate)self.currentTime_ms=self.media.currentTime()self.fresh()#print(22%250)#波形放大功能defzoomOut(self):self.secondsInScreen*=2self.zipRate=int(self.secondsInScreen*self.framerate/self.dotsInScreen)self.plotDataList=[]self.getAllPlotData(self.zipRate)self.currentTime_ms=self.media.currentTime()self.fresh()#波形縮小功能deftoNextScreen(self):print'next'self.currentTime_ms+=self.secondsInScreen*1000ifself.currentTime_ms>self.media.totalTime():self.currentTime_ms=self.media.totalTime()self.media.seek(self.currentTime_ms)#快進功能deftoPreviousScreen(self):print'next'#print(22%250)self.currentTime_ms-=self.secondsInScreen*1000ifself.currentTime_ms<0:self.currentTime_ms=0self.media.seek(self.currentTime_ms)#快退功能classfreshSignal(QtCore.QObject):freshLowerPlotPanLeftAndWidth=QtCore.Signal(int,int)freshLowerPlotCurrentTime=QtCore.Signal(int)freshTimeNowLabel=QtCore.Signal(str)#print(22%250)freshMusicTotalTimeLabel=QtCore.Signal(str)freshVisionTimeLengthLabel=QtCore.Signal(str)freshScreenTime=QtCore.Signal(int)#創(chuàng)建信號defcontextMenuEvent(self,event):actionzoomIn=QtGui.QAction('xzoomIn',self)actionzoomOut=QtGui.QAction('xzoomOut',self)actionzoomIn.triggered.connect(self.zoomIn)actionzoomOut.triggered.connect(self.zoomOut)menu=QtGui.QMenu(self)#print(22%250)menu.addAction(actionzoomIn)menu.addAction(actionzoomOut)menu.addSeparator()menu.exec_(event.globalPos())#右鍵放大縮小功能圖5.2.2動態(tài)波形區(qū)5.2.3上下波形區(qū)整合在上述內(nèi)容當(dāng)中已經(jīng)設(shè)置了動態(tài)以及靜態(tài)波形等內(nèi)容,但是如果要真正實現(xiàn)波形的完整性,還需要進行兩方面的充分整合,如下是具體的程序代碼和相關(guān)注釋內(nèi)容:classUpAndDownWaveWidget(QtGui.QWidget):def__init__(self,parent=None):super(UpAndDownWaveWidget,self).__init__(parent)self.setGeometry(100,100,1000,400)#設(shè)置幾何位置及長寬self.upperPlotWidget=upperPlotWidget.plotControlWidget(self)#實例化plotControlWidget類self.lowerPlotWidget=lowerPlotWidget.plotWidget(self)#實例化plotWidget類self.path=None#print(22%250)self.media=Nonelayout=QtGui.QVBoxLayout()layout.addWidget(self.upperPlotWidget)#垂直添加upperPlotWidget波形區(qū)layout.addWidget(self.lowerPlotWidget)#垂直添加lowerPlotWidget波形區(qū)self.setLayout(layout)#print(22%250)self.upperPlotWidget.plotWidget.figure.signal.freshLowerPlotPanLeftAndWidth.connect\(self.lowerPlotWidget.figure.freshLeftAndWidthFromUpperPlot)#鏈接到freshLeftAndWidthFromUpperPlot信號self.upperPlotWidget.plotWidget.figure.signal.freshLowerPlotCurrentTime.connect\(self.lowerPlotWidget.figure.freshCurrentTimeFromUpperPlot)#鏈接到freshCurrentTimeFromUpperPlot信號defsetMedia(self,media):self.media=media#print(22%250)defanalyzeWaveAndDrawInit(self):path=str(self.media.currentSource().url().path())path=path[1:]form=waveForm.waveform(path)waveData=form.getWaveData()dataDict=dict(data=waveData,#print(22%250)framerate=form.framerate,media=self.media)self.lowerPlotWidget.figure.drawInit(waveData)self.upperPlotWidget.plotWidget.figure.drawInit(dataDict)#解析波形并初始化圖5.2.3上下波形區(qū)整合第6章系統(tǒng)整合與測試6.1程序主界面整合對于音頻進行解析以及對于波形進行繪制之后,還需要對于所有的程序進行有效整合。具體的代碼和注釋:classWaveWidget(QtGui.QWidget):def__init__(self,parent=None):QtGui.QWidget.__init__(self,parent)self.ui=Ui_widget_waveModule()#實例化Ui_widget_waveModule類self.ui.setupUi(self)#調(diào)用setupUi函數(shù)player=Player(self)#實例化Player類self.ui.horizontalLayout_musicToolBox.addWidget(player)#添加音頻模塊upAndDownWaveWidget=UpAndDownWaveWidget(self)#實例化UpAndDownWaveWidget函數(shù)self.upAndDownWaveWidget=upAndDownWaveWidgetself.ui.horizontalLayout_plots.addWidget(upAndDownWaveWidget)#添加波形模塊upAndDownWaveWidget.setMedia(player.getPlayerMedia())#將波形與音頻同步player.signal.fileChoosedSignal.connect(upAndDownWaveWidget.analyzeWaveAndDrawInit)#鏈接到文件選擇功能player.signal.TimeNowChanged.connect\(upAndDownWaveWidget.upperPlotWidget.plotWidget.figure.mediaTimeChanged)#鏈接到時間選擇功能player.ui.pushButton_goLeft.clicked.connect(upAndDownWaveWidget.upperPlotWidget.plotWidget.figure.toPreviousScreen)#鏈接到快退功能player.ui

溫馨提示

  • 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. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論