《基于python的音频播放器的设计与实现》9000字_第1页
《基于python的音频播放器的设计与实现》9000字_第2页
《基于python的音频播放器的设计与实现》9000字_第3页
《基于python的音频播放器的设计与实现》9000字_第4页
《基于python的音频播放器的设计与实现》9000字_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第1章引言在人们逐渐追求精神文化的过程中,听音乐也渐渐成为了一种比较广泛的兴趣爱好。如今在互联网当中,音频播放器种类众多。音乐播放器属于多媒体软件,可以进行各式各样的文件播放,同时包含了多种格式内容,例如MP3等。其通常操作过程比较简单,而且界面较为美观,能够让人真正进入到放松的音乐空间当中。音乐播放器在本质上其实属于一种操作界面,其根本内容是音频解码器,主要是对于不同种类的编码后的音频所进行的解码。许多音乐播放器对于各类格式都比较支持,其原因是音频播放器本身能够对于不同种类的解码器进行有效解码,并且使所有的播放页面达到统一,让使用者对于音乐有更加深刻的感受。由于音乐播放器本身存在固定的方式进行音频解码,而且其原理层面仅仅是对于解码器进行打包,所以在整体上来说,一切播放器的播放音质都可能是完全一样的,并没有音质方面的区别。不过,某些音乐播放器为了突出自身的播放水平,会以解码器作为前提,进一步进行DSP插件的添加,满足受众的需求,这可以说是对于原本音乐展开扭曲或者转换的过程,但其实仅仅是对于细节的过滤或者将音调降低等,在宣传过程中,可能会宣传成为音质的美化等方式,但其实,这种方式在本身上是对于音乐的破坏,其能够让某些音乐变得更加好听,但对于大部分音乐来说,却会导致音质水平的降低。因此,有必要了解到的是,作为音乐播放器本身,其所具备的操作界面或者扩展性内容,才是真正属于播放器本身的特色。如今许多商业播放软件,可能有非常绚丽的界面,或者说在操作方面存在与众不同的表现,但通常而言并不具备拓展性,对于格式支持并不是很多。同时,在开源播放软件方面通常能够获得一定程度的拓展,对于不同种类的音乐格式予以支持,不过通常而言界面比较朴素,客户无法从中感受到充分的吸引力。国外的音乐播放器通常包括realplayer和微软系统本身自带的播放器,但是通常在国内的使用频率并不高,而在国内音乐市场当中,酷狗、网易云、QQ音乐等播放器占据了大量市场,而且通过一定的软件更新和升级,无论是播放器本身的功能还是给用户带来的体验方面都有了不错的发展。如今,国内进行了两个主要方向的音频研究,首先是胡守超以Python语言作为基础,通过音频的捕获和频率分析所展开的设计,通过编程语言分析相关音频数据,并对于音频数据内容进行有效采集,进行音频波谱以及频率的有效显示。另外也是以Python音频数据作为基础,通过对于声音文件本身格式以及播放特性的转换,对于不同的音频文件展开对应分离以及合成,同时对不同音乐之间所具有的特征展开有效分析,有效改变原本声音当中出现的采样宽度、速率以及编码等内容。国外使用频率较高的专业播放器,具备多媒体解析功能以及软件编辑功能,来自于Adobe公司所开发的相关内容,其主要设计目标是音频以及视频专业人员,通常他们使用于照相师、后期制作以及广播等方面,软件本身具备音频混合、音频编辑、音频控制以及相关频率的处理等功能特性。此次研究过程中,以CoolEditPro软件本身具备的功能作为基础,借助其软件运用,同时通过Python语言的结合使用,以及利用程序编辑器和专业工具包,进行音频播放器的设计以及实现,播放器本身能够进行各种格式的音频播放,并且能够进行wava文件的波形显示等一系列的特殊功能。第2章软件开发环境与开发工具2.1Eclipse软件简介Eclipse本身属于一种集成式的开发环境,同时具备跨平台的作用。一开始这个平台的作用是java开发,不过到如今为止,已经有很多人利用插件进行其他语言的开发,比如c语言以及Python。可以说此软件仅仅属于一种平台,属于开发过程中的框架,而通过这些插件支持,相对来说使整个平台的灵活性大大提升,对于比较固定的软件而言,这种灵活性是非常难得的。在此平台当中,插件本身也是组件化的存在,作为客户而言,在使用过程中,可以通过插件满足相关附加功能,比方说不仅仅对于java语言有一定的支持程度,同时对其他语言而言,也能够予以支持。另外,如今已经存在的插件已经可以支持多种编程语言的开发,并且可以进行相关数据库开发,比如C语言、C++以及本文当中所使用的Python语言等。同时,作为该平台本身,存在一定的插件架构,能够支持各类扩展功能,比如配置管理等,而并不只是对于不同种类的编程语言予以支持。作为Eclipse平台本身,其所具备的设计理念在于所有的东西都属于插件的一部分。作为平台本身,其核心内容并不是很多,而另外的功能都以核心为基础,同时以插件的方式进行附着。此外,其中内核成分包含了图形、环境插件以及java语言等基础内容。同时,作为软件开发人员而言,通过SDK进行相应的组建合并,能够让使用者更方便的进行工具下载。在合并之后可以提供具备丰富特性的开发环境,同时作为开发者而言,则能够有效进行工具建设,并且集成到平台环境当中。SDK本身包含了平台自身的工具以及其他软件当中的系列工具内容,这些工具主要是源代码已经开放的相关平台。另外,作为项目生产过程中,可以通过GPL进行有效发布,而作为组件来说,则有它们本身的许可协议等内容。2.2Python语言简介Python属于解释型,且能够面向对象的程序语言,同时此程序语言属于动态类型。从1990年开始发展到如今,此类语言已经在系统管理任务当中获得了非常广泛的使用,同时也在web编程当中得到了良好的应用效果,甚至可以说是目前受欢迎程度最广的一项涉及语言。因为该语言本身具备可扩展以及简洁特性,在国外通过这种语言进行科学计算的机构数量渐渐增加,尤其是不少知名大学已经采取此语言进行程序课程的教育。同时,许多开源科学计算过程中都提供了相应的接口,可以进行此类语言的调用。而针对Python本身,科学扩展库数量可以说是非常多,比如numpy以及scipy等,通过这些扩展库能够让语言本身获得数值运算等功能,或者进行数组处理和绘图功能的实现。所以总体而言,该语言本身和语言扩展功能共同构成相应的开发环境,有利于科研人员进行数据处理,同时有利于工程技术人员进行相应你的图标制作,或者进行科学程序的有效开发。另外,追溯到源头可以得知Python设计者本身在语法方面加强了限制性,可以说是在很大程度上纠正了一些不良习惯,避免由于疏漏导致的程序错误,比如对于if语句而言,如果下一行没有缩进的话,在这个平台当中的编译是无法被通过的,这也就是众所周知的此语言本身具备的缩进规则。此外,Python与其他许多语言,比如C++等语言存在的主要区别在于:模块本身拥有的接线,并不是通过某些符号表达所进行的定义,在许多语言当中模块接线通常需要特殊字符进行隔离,但是在Python当中,则是由首字符所在的位置进行确定的。这一点的设定引起了不少人的不满,主要原因是由于C++等语言出现之后,逐渐将语法本身具有的含义不体现在字符的排列方面,而且认为这种区分属于程序语言在逐步进步的过程。但是需要承认的是,Python平台当中的这些要求,让整体程序的美观度大大提升,其中包含了一些模块的使用,尤其是if以及for等定义的强制缩进等要求,这种强制性可以说是带来了一定的好处。而且,Python作为一种语言,本身是面对某些对象进行使用的,其中包括了模块、字符串以及函数等,而且具备一定的继承性和派生性等,在这个过程中,对于源代码重复使用有一定的帮助。同时,平台本身对于动态特性和运算符的重新载入有一定的支持度,相比较一些比较传统的语言而言,在函数设计方面,该平台并没有提供全方位的支持,而是比较片面的作用。在具体执行过程中,Python平台本身会执行后缀名为py的文件,并且将其中存在的源代码进行编译,使之全部成为字节码,之后通过虚拟机进行字节码的有效执行。另外,平台本身能够通过交互模式进行运行,也就是说可以在不同系统当中进行操作,而并不是仅仅局限于Windows或者某种系统,一些主流系统都能够在命令模式之下进行此平台的环境命令,或者通过指令下达,就可以有效完成相关操作过程。2.3所用到的python工具包在整体开发进程当中,Python平台当中使用了各类工具包,比如跨平台所进行的应用程式框架等程序pyside,其可以说是属于平台本身存在的绑定版本,另外还有一些工具包能够进行波形图的绘制,以及计算其中所存在的音频数据等内容,在此开发过程中得到了广泛的应用。同时在此次设计过程中,还需要通过Pysideuic进一步转换相应的ui文件,使之成为py后缀名的文件内容。第3章软件界面窗口的实现3.1QtDesigner软件简介QtDesigner属于GUI的工具内容,通过这项工具的使用,能够使QT程序的编写速度大大加强,另外,通过此软件的使用,能够产生所见所得的效果,避免盲目进行代码编写之后出现各类问题,在编写过程中,可以通过QT程序产生界面代码,而在增加系列功能之后,就能够妥善完成工具编写。具体操作步骤是通过此类程序进行页面搭建,在搭建之后保存相应的UI文件,之后通过命令解释器进行文件转换,也就是上文当中所提到的将ui文件向py文件进行转换。3.2软件整体界面的绘制需要重视的是,在整体界面当中并非仅仅包含一部分内容,而是由上半部分、中部以及下半部分共同构成,其中上半部分属于播放器,包含了文件选择、时间编辑以及播放或者停止等,同时可以在这一部分进行音量的调节以及波形的具体条件,而且也能够进行快进和快退等操作内容。而中部则属于动态波形区域,可以进行相关波形的展示。下半部分则属于静态波形区,在音频播放的过程中也具有特定的效果,但总体功能还是集中在页面的最上方。在具体绘制的过程中,可以在运行软件之后,新建窗口,同时按照原本的设计路径进行功能的添加以及绘制,分别包括时间的编辑按钮,以及进行文件选择,文本框的粘贴,之后则设置播放按钮以及暂停按钮,同时为了方便使用,还可以设置停止播放按钮,随后对于音量大小进行调节,可以设置按钮或者进度条等,再之后通过放大镜作为触发模式,针对波形的大小展开调节,而后实现快进与快退等模式,通过时间以及进度条等观察音乐具体的播放情况,在这些功能全部添加之后,也就完成了上半部分的界面绘制,不过还需要将整体布局设置成水平模式,从而实现如图所示的构造。之后,为了实现其他部分的窗口功能和内容,可以重新建立窗口,并进行两个部分的划分,上半部分是播放过程中的动态波形显示,而下半部分则是保持不变的整体波形显示,通过这种操作也就完成了整体的页面设计过程。图3.2设计页面第4章音频解析与播放功能的实现4.1phonon模块简介随着科学技术的发展,音频格式也逐渐增多,如今在音频格式领域已经包含了MP3、WMA、WAV等常见格式,以及VQF和APE等不是非常常见的格式。面对如此复杂的内容,通过调用工具包当中的模块就能够对于所有音频格式进行有效解析,而且可以在调用相应模块之后,有效实现各种音频格式的播放。4.2功能具体实现过程音频格式当中包含如下几个方面的内容,第一是获取源文件,之后是实现播放功能、暂停功能以及停止等具体功能。因为平台本身属于集成且开源的类型,其中包含了许多种类的API等内容,所以只需要进行普通函数调用就能够有效实现相关功能,而在此次设计过程中使用了如下内容:MediaObject、MediaSource、MusicCategory、createPath、PlayingState、StoppedState、LoadingState、BufferingState、ErrorState。之后利用代码以及注释对于相关过程展开有效分析:classPlayer(QtGui.QWidget):def__init__(self,parent=None):QtGui.QWidget.__init__(self,parent)self.ui=Ui_toolBoxWidget()#实例化Ui_toolBoxWidget类self.ui.setupUi(self)#调用setupUi函数self.media=Phonon.MediaObject(self)#实例化MediaObject类self.media.setCurrentSource(Phonon.MediaSource())#设置当前源文件self.media.setTickInterval(100)#设置音频解析间隔self.output=Phonon.AudioOutput(Phonon.MusicCategory,self)#音频输出类型Phonon.createPath(self.media,self.output)#选择默认音频路径self.ui.volumeSlider_music.setAudioOutput(self.output)#链接到音量调节功能self.ui.seekSlider_musicProgress.setMediaObject(self.media)#链接到进度条self.ui.lcdNumber.display("00:00")#链接到时间显示self.media.stateChanged.connect(self.stateChanged)#链接到状态转换函数self.media.tick.connect(self.tick)#链接到显示时间方式函数self.ui.pushButton_musicPlay.clicked.connect(self.changePlayPause)#链接到播放暂停函数self.ui.pushButton_musicStop.clicked.connect(self.changeStop)#链接到停止函数self.ui.pushButton_chooseMusicFile.clicked.connect(self.handleButtonChoose)#链接到文件选择函数self.ui.timeEdit_music.timeChanged.connect(self.timeEditTimeChanged)#链接到时间编辑函数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())#状态转换classFileChoosedSignal(QtCore.QObject):fileChoosedSignal=QtCore.Signal()TimeNowChanged=QtCore.Signal(int)#创建两个信号图4.2音频区第5章波形显示的实现5.1对WAV文件获取数据波形本身是利用解析得知的数据在波形区当中的位置进行描点,而通过描点进行集合,将会产生连续波形等内容。在此次设计过程中,可以利用wava模块对于具体数据进行解析,可以返回有关数据并进行识别。最终可以依照已经得到的数据信息进行波形绘制。对于Python而言,模块本身提供了相应的接口进行使用,其能够对于文件当中的参数进行解析,比如频率、宽度以及帧数等内容。通过类似数据以及结合相关工具进行wava文件绘制。依照上述内容可以了解到,模块本身存在缺点,比如不支持解压等特性,因此在此次设计过程中,仅仅能够进行wava波形的解压,如下可以利用代码更好地实现相关内容:第一步是进行初始化得到对应的文件内容。self.audio=wave.open(path,'r')#对文件进行只读操作self.nchannels,self.sampwidth,self.framerate,self.nframes,ptype,pname=self.audio.getparams()#获取文件各项参数然后进行读取操作,defread(self,size):data=self.audio.readframes(size)#size为总帧数sw=self.audio.getsampwidth()#获取采样宽度data=numpy.frombuffer(data,dtype=numpy.dtype("i%d"%sw))#用numpy工具进行科学计算nc=self.audio.getnchannels()ifnc>1:left=data[0::nc]right=data[1::nc]sample=[left,right]else:sample=datareturnsample+#返回值也就是在波形绘制过程中的数据需求。5.2根据音频数据绘制音乐波形通过上述模块能够获得画图当中的具体数据内容,在画图当中使用的工具是matplot包。而此内容通常是在平台代码当中展开,进行2D界面绘图的有效制作,同时促进科学计算性能的有效优化。5.2.1音频数据全部波形在音频数据波形当中,能够使完整的wav文件获得转换,转换的是所有的数据内容,而结果是一切波形。在此模块当中,通过五项函数进行调用,分别包括初始化绘图、依照数据进行跟踪区的有效刷新、依照数据对时间信息进行刷新以及展开属性设置。如下是具体的代码操作: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)#根据实时数据来刷新矩形跟踪区deffreshCurrentTimeFromUpperPlot(self,frameNow):ifhasattr(self,'vline'):self.vline.set_xdata(frameNow/self.zipRate)self.canvas.draw()#print(22%250)#根据实时数据来刷新当前时间信息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()#绘图区初始化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)#绘图区属性设置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)利用相关函数能够得到音频当中的全部波形内容:图5.1静态波形区5.2.2当前时间段波形在上述操作当中,获得了来自音频的整体波形,但属于第三个区域的静态内容,而如果想要让其得到动态有效的显示,还需要展开进一步的研究。与静态波形相同的是,动态波形也是在wave模块当中所获得的信息,并且通过软件进行绘制。但存在区别的是,动态模型需要实时刷新,并且获得实时数据跟踪等内容。在这一方面可以用到的函数数量更多,比如波形的更新、时间的同步以及绘图初始化等操作,并且能够进行坐标清除和属性设置,更进一步获得动态的数据跟踪,同时具备波形的缩小以及放大等功能,实现音乐的快速调整,对于波形进行放大以及缩小。具体程序代码如下: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)#绘图区初始化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)#绘图区属性设置defclearAxes(self):length=len(self.plotDataList)iflength>2:foriinxrange(length-3):self.plotDataList[i].remove()self.plotDataList.pop(i)#清除坐标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#获取当前绘图区的全部数据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#获取当前绘图区的部分数据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)#创建信号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动态波形区5.2.3上下波形区整合在上述内容当中已经设置了动态以及静态波形等内容,但是如果要真正实现波形的完整性,还需要进行两方面的充分整合,如下是具体的程序代码和相关注释内容:classUpAndDownWaveWidget(QtGui.QWidget):def__init__(self,parent=None):super(UpAndDownWaveWidget,self).__init__(parent)self.setGeometry(100,100,1000,400)#设置几何位置及长宽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波形区layout.addWidget(self.lowerPlotWidget)#垂直添加lowerPlotWidget波形区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上下波形区整合第6章系统整合与测试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)#调用setupUi函数player=Player(self)#实例化Player类self.ui.horizontalLayout_musicToolBox.addWidget(player)#添加音频模块upAndDownWaveWidget=UpAndDownWaveWidget(self)#实例化UpAndDownWaveWidget函数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. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论