python音频分析(一)绘制wav的时域频域图
一.引入
时域图:x轴为时间,y轴为振幅
频域图:x轴为频率,y轴为振幅
(上述频域图为线性振幅谱,还另有对数振幅谱、自功率谱,y轴不是单纯振幅)
时域与频域的直观关系见下图
二.画时域图
1.读入wav文件
(pyaudio.PyAudio)
2.波形数据转换为数组
(numpy.frombuffer )
3.构建横坐标
(numpy.arange)
4.画图
(matplotlib)
import wave
import pyaudio
import pylab
import numpy as np
import matplotlib.pyplot as plt
def get_framerate(wavefile):
'''
输入文件路径,获取帧率
'''
wf=wave.open(wavfile,"rb")#打开wav
p = pyaudio.PyAudio()#创建PyAudio对象
params = wf.getparams()#参数获取
nchannels, sampwidth, framerate, nframes = params[:4]
return framerate
def get_nframes(wavefile):
'''
输入文件路径,获取帧数
'''
wf=wave.open(wavfile,"rb")#打开wav
p = pyaudio.PyAudio()#创建PyAudio对象
params = wf.getparams()#参数获取
nchannels, sampwidth, framerate, nframes = params[:4]
return nframes
def get_wavedata(wavfile):
'''
输入文件路径,获取处理好的 N-2 左右声部数组
'''
#####1.读入wave文件
wf=wave.open(wavfile,"rb")#打开wav
p = pyaudio.PyAudio()#创建PyAudio对象
params = wf.getparams()#参数获取
nchannels, sampwidth, framerate, nframes = params[:4]
stream = p.open(format=p.get_format_from_width(sampwidth),
channels=nchannels,
rate=framerate,
output=True)#创建输出流
#读取完整的帧数据到str_data中,这是一个string类型的数据
str_data = wf.readframes(nframes)
wf.close()#关闭wave
#####2.将波形数据转换为数组
# N-1 一维数组,右声道接着左声道
wave_data = numpy.frombuffer(str_data, dtype=numpy.short)
#2-N N维数组
wave_data.shape = -1,2
#将数组转置为 N-2 目标数组
wave_data = wave_data.T
return wave_data
def plot_timedomain(wavfile):
'''
画出时域图
'''
wave_data=get_wavedata(wavfile) #获取处理好的wave数据
framerate=get_framerate(wavfile) #获取帧率
nframes=get_nframes(wavfile) #获取帧数
#####3.构建横坐标
time = numpy.arange(0,nframes)*(1.0/framerate)
#####4.画图
pylab.figure(figsize=(40,10))
pylab.subplot(211)
pylab.plot(time, wave_data[0]) #第一幅图:左声道
pylab.subplot(212)
pylab.plot(time, wave_data[1], c="g") #第二幅图:右声道
pylab.xlabel("time (seconds)")
pylab.show()
return None
plot_timedomain(wavfile=wavfile)
三.画频域图
1.取出所需部分进行傅里叶变换,并得到幅值*
(numppy.fft.rfft)
2.计算出作为x轴的频率列
( np.linspace)
3.画图
(matplotlib)
def plot_freqdomain(start,fft_size,wavfile):
'''
画出频域图
'''
waveData=get_wavedata(wavfile) #获取wave数据
framerate=get_framerate(wavfile) #获取帧率数据
#### 1.取出所需部分进行傅里叶变换,并得到幅值
# rfft,对称保留一半,结果为 fft_size/2-1 维复数数组
fft_y1 = np.fft.rfft(waveData[0][start:start+fft_size-1])/fft_size #左声部
fft_y2 = np.fft.rfft(waveData[1][start:start+fft_size-1])/fft_size #右声部
#### 2.计算频域图x值
#最小值为0Hz,最大值一般设为采样频率的一半
freqs = np.linspace(0, framerate/2, fft_size/2)
#### 3.画图
plt.figure(figsize=(20,10))
pylab.subplot(211)
plt.plot(freqs, np.abs(fft_y1))
pylab.xlabel("frequence(Hz)")
pylab.subplot(212)
plt.plot(freqs, np.abs(fft_y2),c='g')
pylab.xlabel("frequence(Hz)")
plt.show()
plot_freqdomain(10000,4000,wavfile)