#本文PDF版下载python
#本文代码下载github
Wav波形绘图代码windows
#本文实例音频文件night.wav下载数组
音频文件下载 (石进-夜的钢琴曲)学习
在如今繁忙的生活中,咱们常常会听些歌来放松一下本身,咱们常常会从各类播放软件中听本身喜欢的歌,而且每每咱们会下载一部分歌曲,而如今音频的种类也至关繁多,像是Wav,Mp3,FLAC,AAC等等不少格式,最近因为须要作一个可以分析Wav格式音频的波形来取得一些数据好比获取人录音时是否说完等等用途.本周先对解析Wav并用Python绘制其波形进行了一些探索.测试
咱们先来看看wikipedia上对于wav音频格式的解释:编码
「Waveform Audio File Format(WAVE,又或者是由于扩展名而被大众所知的WAV),是微软与IBM公司所开发在我的电脑存储音频流的编码格式,在Windows平台的应用软件受到普遍的支持,地位上相似于麦金塔电脑里的AIFF.此格式属于资源交换档案格式(RIFF)的应用之一,一般会将采用脉冲编码调制的音频资存储在区块中。也是其音乐发烧友中经常使用的指定规格之一.因为此音频格式未通过压缩,因此在音质方面不会出现失真的状况,但档案的体积于是在众多音频格式中较为大.」spa
咱们能够看到上面提到了两个个关键词RIFF和脉冲编码调制.因此咱们接下来先解释一下 RIFF「资源交换档案格式」是什么.code
咱们一样的来看一下wikipedia对RIFF的解释
「 Resource Interchange File Format(简称RIFF),资源交换文件格式,是一种按照标记区块存储数据(tagged chunks)的通用文件存储格式,多用于存储音频、视频等多媒体数据.Microsoft在windows下的AVI、ANI 、WAV等都是基于RIFF实现的.
RIFF是由Microsoft和IBM于1991年,在windows 3.1中引入的,做为windows 3.1默认的多媒体文件格式。RIFF是参考Interchange File Format来的,两者主要的区别是字节序大端、小端的问题.在基于IBM的80x86系列主机下,RIFF的字节序是小端的;而在IFF原有的格式中是按照大端存储整型数据的.」
RIFF是由chunk构成的,chunk是RIFF组成的基本单位,每一个CHUNK可看做存贮了视频的一帧数据或者是音频的一帧数据,因此下面咱们来讨论一下chunk的结构是怎么样的.
CHUNK总共由三个部分组成:
结构示意图以下:
CHUNK的结构
下面是一个包含了子CHUNK的结构示意图:
包含了SUBCHUNK的结构示意图
Form Type结构示意图以下:
包含了Form Type的结构示意图
咱们先来看看百度百科对它的解释:
「PCM 脉冲编码调制是Pulse Code Modulation的缩写,脉冲编码调制是数字通讯的编码方式之一.主要过程是将话音、图像等模拟信号每隔必定时间进行取样,使其离散化,同时将抽样值按分层单位四舍五入取整量化,同时将抽样值按一组二进制码来表示抽样脉冲的幅值.」
咱们从上面的介绍能够理解为:
经过三个过程-抽样、量化和编码讲音频的模拟信号转化为数字信号.
抽样是因为模拟信号是连续的,经过必定频率对模拟信号进行取样,近似获得,以下面的图中灰色框中就是取了必定频率进行抽样的示意图:
抽样过程示意图
抽样信号离散的模拟信号,其取样的值在必定的取值范围内,由无限多种值可能性存在.为了实现以数字码表示样值,咱们采用“四舍五入”的方法把样值分级“取整”,使必定取值范围内的样值由无限多个值变为有限个值.
量化后的抽样信号在必定的取值范围内仅有有限个可取的样值,且信号正、负幅度分布的对称性使正、负样值的个数相等,正、负向的量化级对称分布
WAVE文件是由若干个CHUNK组成的.按照文件中CHUNK的出现顺序分别为:RIFF Chunk, Format Chunk, Fact Chunk, Data Chunk,其中的Fact CHUNK为非必要部分,结构具体以下图所示:
WAV文件头文件的CHUNK组成
RIFF是头CHUNK,而Format CHUNK里面记录了WAV的各类参数信息,详细参数信息以下:
而FACT CHUNK的做用是由于有些并无使用PCM格式,因此须要一个FACT CHUNK记录数据解压缩数据大小.
最后的DATA块中装的是真正的声音数据.通常按照WAVE_FORMAT_PCM的数据格式存贮,即脉冲编码调制PCM.
DATA块内的信息是根据format chunk内的信息而决定的.由量化位数/声道数/采样率共同决定,下图为四种状况下DATA区域存储信息的格式:
DATA CHUNK的格式
在python中,咱们能够直接经过许多音频的库对wav文件进行操做,好比自带的标准库wave库,还有如eyeD3,PyAudio,Audacity等等.咱们先不介绍这种方式,咱们先经过传统的文件操做以二进制的形式读取Wav文件,来分析一下它的头文件来验证一下咱们前面有关CHUNK所学的知识.经过二进制操做音频文件并取得前四个字节的代码以下:(咱们的测试音频是night.wav,已放在github中,经过个人博客园右上角的绿色图标能够连接到个人github界面,找到lab102下的w8目录便可获取该资源,或者找到本文博客园最上方资源):
#读取wav前四个字节内容 -xlxw
file = open("night.wav", "rb") s = file.read(4) print(s)
程序运行截图:
咱们能够看到最前面的字节和咱们认为的没错,是RIFF,那咱们来读取44个字节来看看其中的信息是怎么样的:
#读取wav前44个字节内容 -xlxw
file = open("night.wav", "rb") s = file.read(44) print(s)
程序运行截图:
咱们能够看到RIFF后面的字符串为WAVE的Form Type,以及fmt,data这几个FOURCC,而其余用十六进制表示的就是数据大小/数据了.因此咱们经过二进制读取的WAV文件的信息和咱们前面学习的CHUNK中的内容是一致的.
在咱们前面中的介绍能够知道wav文件的存储方式,而且可以简单的提取其中的信息了,而咱们知道wav文件最重要的就是声音信息的存贮,这一部分咱们也能够经过对CHUNK的DATA 进行分析,不过咱们在python中有更加简单的得到声音的方式,那就是利用python自带的wave库,咱们下面就来介绍一下wave库的一些方法,为后文作铺垫.
import wave
打开一个声音文件,使用方法wave.open(声音文件地址,模式)
其中声音文件地址就是wav文件位置,模式和文件读写差很少,如“wb”-只写;“rb”-只读方式 b表明以二进制模式打开.
关闭声音文件
获取wav文件的参数(以tuple形式输出),依次为(声道数,采样精度,采样率,帧数,......)
以下图为本文例子night.wav的getparams()的信息:
获得每一帧的声音数据,返回的值是二进制数据,在python中用字符串表示二进制数据,以下图,因此咱们后面要进行转化.
获得的night.wav的前10帧的数据以下图所示:
上面就基本上是wave库的经常使用方法了.下面会对此进行应用了.
咱们常常在许多声音软件,好比CoolEdit,Audition等软件中能看到声音文件的波形,因此咱们在这里利用Python以及前面介绍的wave库,辅以numpy,Matplotlib来尝试绘制night.wav文件的波形.
下面咱们来简单讲述一下绘制波形的步骤:(以night.wav为例子)
咱们来对这些步骤中的一些部分详细说一下:
由于night.wav是一个双声道的WAV 文件,咱们从上文对DATA区域格式的介绍能够知道储存形式是左声道/右声道的形式存贮数据,因此在这里咱们要对提取出的数据进行处理,这里numpy库为咱们提供了很好的解决方法,咱们主要用到了改变形状的Shape方法以及T转置方法,咱们在这里来举一个例子:
咱们建立一个数组[1,2,3,4,5,6,7,8]里面有8个元素,这时候根据咱们的分离方法,应该分为左声道[1,3,5,7]和右[2,4,6,8],咱们能够经过shape先改变矩阵的形状使数据变为两列分别为左右声道,再经过转置获得最终数据,咱们的例子能够用以下图所示理解:
将数据分为左右声道的例子
这里咱们要绘出波形,因此用matplotlib库大大减小咱们的绘图难度,咱们主要用到plt.subplot和plt.plot这两个方法,因此咱们对这两个方法进行解释.
这是用于matplotlib绘制多个子图的方法,由于咱们这里音频文件要分为两个部分(左声道/右声道)
即分红2X1的形式,因此咱们的第一个绘图和第二个绘图分别用
plt.subplot(211)和plt.subplot(212)来表示,以下图所示:
matplotlib子图
plt.plot()是用于绘制线条的方法,咱们用到了其中的三个参数
(X坐标,y坐标,颜色)
就能用plot画出最终的波形图了
用于绘制出wav文件波形的代码以下(这里咱们仍是以night.wav做为例子)
#wave data -xlxw
#import
import wave as we import numpy as np import matplotlib.pyplot as plt def wavread(path): wavfile = we.open(path,"rb") params = wavfile.getparams() framesra,frameswav= params[2],params[3] datawav = wavfile.readframes(frameswav) wavfile.close() datause = np.fromstring(datawav,dtype = np.short) datause.shape = -1,2 datause = datause.T time = np.arange(0, frameswav) * (1.0/framesra) return datause,time def main(): path = input("The Path is:") wavdata,wavtime = wavread(path) plt.title("Night.wav's Frames") plt.subplot(211) plt.plot(wavtime, wavdata[0],color = 'green') plt.subplot(212) plt.plot(wavtime, wavdata[1]) plt.show() main()
程序绘制出的波形图的截图:
night.wav声音文件的双声道波形
在本周我学到了wav文件的存贮格式以及怎么用python读取wav文件信息而且绘制出波形图.其中在绘制了波形图后,咱们能够对波形多透露出的信息进行分析,好比:
等等用途,能够用于许多方面,如声音识别,断句(音频分割)等等许多的场景.这里在之后我也会继续进行探索.