python音频分析(一)绘制wav的时域频域图

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)

在这里插入图片描述

发布了8 篇原创文章 · 获赞 1 · 访问量 3259

猜你喜欢

转载自blog.csdn.net/sinat_30165411/article/details/102253584
今日推荐