精华内容
下载资源
问答
  • MFCC梅尔频率倒谱系数

    2021-01-30 14:43:56
    文章目录MFCC梅尔频率倒谱系数MFCC梅尔频率倒谱系数的原理计算MFCC的步骤1、音频信号文件读取及预加重2、信号分帧加窗3、计算帧功率谱的周期图估计4、将梅尔滤波器组应用于功率谱,将每个滤波器的能量求和5、取所有...

    MFCC梅尔频率倒谱系数原理及python实现

    MFCC梅尔频率倒谱系数的原理

    MFCC梅尔频率倒谱系数的应用:MFCC通过提取语音信号特征(识别音频信号,丢弃背景噪声、情绪信息)准确表示短时功率谱图,进一步表现语音声道形状,有助于我们准确表示声道形状发音产生的音素,被广泛的应用于以线性预测系数(LPC)、线性预测倒谱系数(LPCC)(倒谱和LPCC教程)以及隐马尔可夫模型HMM分类器主要特征类型的自动语音识别(ASR)和说话人识别。

    计算MFCC的步骤

    1. 音频信号文件读取及预加重。

    2. 信号分帧加窗。

    3. 计算帧功率谱的周期图估计

    4. 将梅尔滤波器组应用于功率谱,将每个滤波器的能量求和。

    5. 取所有滤波器组能量的对数。

    6. 取对数滤波器组能量的离散余弦变换DCT。

    7. 保持DCT系数2-13,其余部分丢弃。

      梅尔音阶

      Volkmann和Newmann提出了一个音高单位,以使相等的音高距离听起来与听众相等, 这称为梅尔音阶。 对频率执行数学运算,以将其转换为mel标度。

      梅尔音阶将感觉到的纯音的频率或音高与其实际测量的频率相关联。与低频时相比,人类在分辨低频时音调的细微变化方面要好得多。合并此比例使我们的功能与人类听到的声音更加匹配。从频率转换为梅尔标度的公式为:
      在这里插入图片描述
      从梅尔回到频率:
      在这里插入图片描述
      对语音信号进行16kHz采样。
      1125取值有时也取2595或者其他值是两个不同的度量标准。

    1、音频信号文件读取及预加重

    • 依据所选取的音频文件,采样频率一般为8000Hz和16000Hz,需大于真实信号最大频率的2倍。
    • 预加重处理其实是将语音信号通过一个高通滤波器:
      在这里插入图片描述
      预加重的目的是提升高频部分,使信号的频谱变得平坦,保持在低频到高频的整个频带中,能用同样的信噪比求频谱,避免在后边的FFT操作中出现数值问题。同时,也是为了消除发生过程中声带和嘴唇的效应,来补偿语音信号受到发音系统所抑制的高频部分,也为了突出高频的共振峰。其中其中α一般取值为0.97、0.95。

    使用librosa.get_duration读取信号的持续时间,采样librosa.load返回语音信号采样率与音频采样数组,采样率需要大于真实信号的频率的2倍才可无失真还原。

    在预加重避免在FFT操作中出现数值问题,需要对高频信息进行加强,因为一般高频能量比低频小,取系数不同加强的程度也不同。
    在这里插入图片描述

    #导入音频处理的python工具包
    import numpy as np
    import librosa
    import time
    import math
    from scipy.fftpack import fft, ifft
    #导入音频及绘图显示包
    import librosa.display
    #导入绘图工作的函数集合
    import matplotlib.pyplot as plt
    #读取音频文件,Librosa默认的采样率是22050Hz
    #如果需要读取原始采样率44100Hz,需要设定参数sr=None
    #如果需要重采样,只需要将采样率参数sr设定为你需要的值
    times= librosa.get_duration(filename='./DrinkWater.wav')#获取音频时长单位为秒
    y, sr = librosa.load('DrinkWater.wav', sr=16000,offset=0.0,duration=None)#返回音频采样数组及采样率
    print("sr=",sr)
    print("times=",times)
    #绘图
    #plt.figure()
    #显示波形图
    #librosa.display.waveplot(y, sr, x_axis='time')#画出波形的振幅线
    #plt.title("DrinkWater wave")
    PointNumbers=int(times*sr)+1#在此由于时间精确度较高,总取样点数取整后加一,保证不丢失信息量,代价是多处理一个采样点
    #在此抛出一个时间精确度的问题
    print("PointNumbers=",PointNumbers)
    x1= np.arange(0,PointNumbers,1)#采样点刻度
    x2=np.arange(0,times,1/sr)#时间刻度
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('DrinkWater.wav', fontsize=12, color='black')
    plt.plot(x1,y)
    plt.show()
    plt.figure()
    plt.xlabel("times")
    plt.ylabel("wave")
    plt.title('DrinkWater.wav', fontsize=12, color='black')
    plt.plot(x2,y)
    plt.show()
    

    在此可根据语音处理的需求设置音频读取的时间精度来确定所取的采样点的个数。
    求得:

    sr= 16000#采样频率
    times= 26.992426303854874#音频时间
    PointNumbers= 431879#采样点数
    

    注意到返回的y为长度为431879的array数组。

    array([0.60138094, 0.9744118 , 0.8517753 , ..., 0.8879393 , 0.8933856 , 0.        ], dtype=float32)#
    

    音频DrinkWater.wav的采样图(采样点刻度):
    在这里插入图片描述
    音频DrinkWater.wav的采样图(采样时间刻度):
    在这里插入图片描述
    在此由于时间精确度较高,以sr=16000求出的总采样点数PointNumbers不是整数数,可以对求出总采样点数直接取整或是取整后后加1,二者不同之处在于,取整加一后保证不丢失信息量,代价是多处理一个采样点。在图中末尾的拖尾0点就是就是这个采样点带来的效果。

    从上面的分析,在此可在采样时间的精度上进行优化,由采样率为16000可知,依据采样频率可取时间精度为千分之一来保证采样点个数为整数,而不用增加或舍去采样点。

    #预加重x=y(i)-0.97y(i-1)
    PreEmphasis=y
    PointNumbers=int(PointNumbers)#转化为整型
    for i in range(1,PointNumbers,1):#range(PointNumbers),PointNumbers需为整型
        PreEmphasis[i]=PreEmphasis[i]-0.97*PreEmphasis[i-1]
    #plt.figure()
    #显示预加重波形图
    #print("音频文件drink_water.wav预加重波形图:")
    #librosa.display.waveplot(PreEmphasis, sr)
    #plt.title("PreEmphasis RecordVower1 wave")
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('PreEmphasis DrinkWater.wav', fontsize=12, color='black')
    plt.plot(x1,PreEmphasis)
    plt.show()
    plt.figure()
    plt.xlabel("time")
    plt.ylabel("wave")
    plt.title('PreEmphasis DrinkWater.wav', fontsize=12, color='black')
    plt.plot(x2,PreEmphasis)
    plt.show()
    

    音频DrinkWater.wav的预加重采样图(采样点刻度):
    在这里插入图片描述
    音频DrinkWater.wav的预加重采样图(时间刻度):
    在这里插入图片描述
    由图可知预加重后波形的幅值减小了。

    2、信号分帧加窗

    音频信号是非平稳信号,在短时范围内(20-40 ms)可假设语音信号是统计平稳的,语音信号分帧时间范围也为(20-40 ms),选取帧长太短时,我们将没有足够的样本来获得可靠的频谱估计;选取帧长太长时,则信号在整个帧中变化太大。

    • 25 ms是标准配置,故将语音信号分成25 ms每帧,例如:16kHz信号的帧长为0.025 * 16000 = 400个样本,帧步长通常约为10毫秒(160个样本)(帧会有一些重叠)前400个样本帧从样本0开始,下一个400样本帧从样本从160开始,直到到达语音文件的末尾,如果语音文件没有分成偶数个帧,则用零填充赝本集使帧个数成偶数个。
      帧长 = f s . 0.025 ( 采样点 ) 帧移 = f s . 0.01 ( 采样点 ) \text{帧长}=f_s.0.025\left( \text{采样点} \right) \\ \text{帧移}=f_s.0.01\left( \text{采样点} \right) 帧长=fs.0.025(采样点)帧移=fs.0.01(采样点)

    • 对于每个单个帧,为每个帧提取一组12个MFCC系数。简而言之,就是符号:S(n)。装帧后,Si(n)可以确定n的范围是1-400(如果我们的帧是400个样本),i范围是帧数。当我们计算复数DFT时,我们得到Si(k)其中i表示与时域帧相对应的帧号。Pi(k)是i的功率谱。

    • 要获取帧的离散傅立叶变换:
      在这里插入图片描述
      其中h(n)是N样本长序列的分析窗口(例如汉明窗口)。


    #分帧
    LenFrame=int(sr*0.025)#每帧长(持续0.025秒)
    PatFrame=int(sr*0.001)#帧移(持续0.001秒)
    Discover=int(LenFrame-PatFrame)#每帧之间的非重叠部分
    NumFrames=(PointNumbers-LenFrame)/Discover
    #分成整数帧
    if (NumFrames-int(NumFrames))==0 :
        NumFrames=int(NumFrames)
    else:
        NumFrames=int(NumFrames)+1#帧号数
    #if (NumFrames%2)==0:
    #    NumFrames=int(NumFrames)
    #else:
    #   NumFrames=int(NumFrames)+1
    NumFillZero=(NumFrames*Discover+LenFrame)-PointNumbers#填充0的数目
    NumFrames=int(NumFrames)+1#在此表示帧数
    print("sr=",sr)
    print("times=",times)
    print("LenFrame=",LenFrame)
    print("PatFrame=",PatFrame)
    print("Discover=",Discover)
    print("NumFrames=",NumFrames)
    print("PointNumbers=",PointNumbers)
    print("NumFillZero=",NumFillZero)
    print("sumPointNumbers=",PointNumbers+NumFillZero)
    FillZeros=np.zeros(NumFillZero)#生成填充序列
    PreEmphasis1=np.concatenate((PreEmphasis,FillZeros)) #填补后的信号记为PreEmphasis1,np.concatenate()连接两个维度相同的矩阵
    #plt.figure()
    #显示预加重填充波形图
    #print("音频文件drink_water.wav预加重填充波形图:")
    #librosa.display.waveplot(PreEmphasis1, sr)
    #plt.title("PreEmphasis1 RecordVower1 wave")
    x3= np.arange(0,PointNumbers+NumFillZero,1)#填充后采样点刻度
    x4= np.arange(0,(PointNumbers+NumFillZero)/sr,1/sr)#填充后时间刻度
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('PreEmphasis1 DrinkWater.wav', fontsize=12, color='black')
    plt.plot(x3,PreEmphasis1)
    plt.show()
    plt.figure()
    plt.xlabel("times")
    plt.ylabel("wave")
    plt.title('PreEmphasis1 DrinkWater.wav', fontsize=12, color='black')
    plt.plot(x4,PreEmphasis1)
    plt.show()
    

    结果得:

    sr= 16000
    times= 26.992426303854874
    LenFrame= 400
    PatFrame= 16
    Discover= 384
    NumFrames= 1125
    PointNumbers= 431879
    NumFillZero= 137
    sumPointNumbers= 432016
    

    可知采样数据点为PointNumbers有431879个,填充零为NumFillZero有137个,此时的总数据点数为sumPointNumbers=PointNumbers+NumFillZero有432016个。

    音频DrinkWater.wav的预加重填充采样图(采样点刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样图(时间刻度):

    在这里插入图片描述

    #开始分帧
    indices=np.tile(np.arange(0,LenFrame),(NumFrames,1))+np.tile(np.arange(0,NumFrames*Discover,Discover),(LenFrame,1)).T  #相当于对所有帧的时间点进行抽取,得到NumFrames*LenFrame长度的矩阵
    indices=np.array(indices,dtype=np.int32) #将indices转化为矩阵
    Frames=PreEmphasis1[indices] #得到帧信号
    x5= np.arange(PointNumbers+NumFillZero-LenFrame,PointNumbers+NumFillZero,1)#最后一帧采样点刻度
    x6= np.arange((PointNumbers+NumFillZero-LenFrame)/sr,(PointNumbers+NumFillZero)/sr-1/sr,1/sr)#最后一帧时间刻度
    #x9=np.arange((times+NumFillZero/sr)-(LenFrame/sr),times+NumFillZero/sr,1/sr)#某帧时间刻度
    plt.figure()
    #显示最后一帧波形图
    #print("音频文件drink_water.wav预加重填充最后一帧波形图:")
    #librosa.display.waveplot(Frames[NumFrames-1], sr)
    #plt.title("PreEmphasis1 RecordVower1 LastFrames  wave")
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('PreEmphasis1 DrinkWater LastFrames  wave', fontsize=12, color='black')
    plt.plot(x5,Frames[NumFrames-1])
    plt.show()
    plt.figure()
    plt.xlabel("times")
    plt.ylabel("wave")
    plt.title('PreEmphasis1 DrinkWater LastFrames  wave', fontsize=12, color='black')
    plt.plot(x6,Frames[NumFrames-1])
    plt.show()
    x7= np.arange(0,LenFrame,1)#第一帧采样点刻度
    x8= np.arange(0,(LenFrame)/sr,1/sr)#第一帧时间刻度
    #显示第一帧波形图
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('PreEmphasis1 DrinkWater FirstFrames  wave', fontsize=12, color='black')
    plt.plot(x7,Frames[0])
    plt.show()
    plt.figure()
    plt.xlabel("times")
    plt.ylabel("wave")
    plt.title('PreEmphasis1 DrinkWater FirstFrames  wave', fontsize=12, color='black')
    plt.plot(x8,Frames[0])
    plt.show()
    #显示第二帧波形图
    x9= np.arange(LenFrame,2*LenFrame,1)#第二帧采样点刻度
    x10= np.arange(LenFrame/sr,2*LenFrame/sr,1/sr)#第二帧时间刻度
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('PreEmphasis1 DrinkWater SecondFrames  wave', fontsize=12, color='black')
    plt.plot(x9,Frames[1])
    plt.show()
    plt.figure()
    plt.xlabel("times")
    plt.ylabel("wave")
    plt.title('PreEmphasis1 DrinkWater SecondFrames  wave', fontsize=12, color='black')
    plt.plot(x10,Frames[1])
    plt.show()
    

    分帧后的Frames为一个1125*400的多维数组(1125维,每维代表一帧)。

    结果:

    音频DrinkWater.wav的预加重填充采样数据分帧后的最后一帧图(采样点刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样数据分帧后的最后一帧图(时间刻度):

    在这里插入图片描述

    可在图中26.990到26.995秒之间看到一个负数的点,这个点是第一节抛出的问题引起的,可改变下面语句参数:

    times= librosa.get_duration(filename='./DrinkWater.wav')#获取音频时长单位为秒
    y, sr = librosa.load('DrinkWater.wav', sr=16000,offset=0.0,duration=None)#返回音频采样数组及采样率
    

    将第一句中的times的精度对应采样频率保留三位小数,将第二句中duration=None改为duration=times(此times为三位小数精度的时间)使填充前最后一个点的取值不为0。

    音频DrinkWater.wav的预加重填充采样数据分帧后的第一帧图(采样点刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样数据分帧后的第一帧图(时间刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样数据分帧后的第二帧图(采样点刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样数据分帧后的第二帧图(时间刻度):

    在这里插入图片描述

    #加窗
    HanningWindow=np.hanning(LenFrame)  #调用汉明窗参数为帧长
    #a=0.46
    #myhanming=np.array([0.]*LenFrame)  #创建一个1行LenFrame列的一维零数组
    #for i in range(0,LenFrame,1):    
    #    myhanming[i]=(1-a)-a*(math.cos(2*(math.pi)*i/LenFrame))
    plt.figure()
    #显示汉明窗
    #print("显示汉明窗:")
    #librosa.display.waveplot(HanningWindow, sr)
    #plt.title("HanningWindow(librosa.display.waveplot)  wave")
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('HanningWindow  wave)', fontsize=12, color='black')
    plt.plot(x7,HanningWindow)
    plt.figure()
    plt.xlabel("time")
    plt.ylabel("wave")
    plt.title('HanningWindow  wave', fontsize=12, color='black')
    plt.plot(x8,HanningWindow)
    #print(HanningWindow)
    HanningWindows=np.tile(HanningWindow,(NumFrames,1))#将窗函数平铺成NumFrames行
    #print(HanningWindows)
    #分别对每一帧加窗
    Frames=np.multiply((np.mat(Frames)),(np.mat(HanningWindows)))
    Frames=np.array(Frames)
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('SecondFrames with HanningWindow wave', fontsize=12, color='black')
    plt.plot(x9,Frames[1])
    plt.show()
    plt.figure()
    plt.xlabel("times")
    plt.ylabel("wave")
    plt.title('SecondFrames with HanningWindow wave', fontsize=12, color='black')
    plt.plot(x10,Frames[1])
    plt.show()
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("wave")
    plt.title('LastFrames with HanningWindow wave', fontsize=12, color='black')
    plt.plot(x5,Frames[NumFrames-1])
    plt.show()
    plt.show()
    plt.figure()
    plt.xlabel("times")
    plt.ylabel("wave")
    plt.title('LastFrames with HanningWindow wave', fontsize=12, color='black')
    plt.plot(x6,Frames[NumFrames-1])
    plt.show()
    

    汉明窗公式为:
    W ( n ) = ( 1 − a ) − a ⋅ cos ⁡ ( 2 ⋅ π ⋅ n N )    1 ⩾ n ⩾ N W\left( n \right) =\left( 1-a \right) -a\cdot \cos \left( 2\cdot \pi \cdot \frac{n}{N} \right) \,\, 1\geqslant n\geqslant N W(n)=(1a)acos(2πNn)1nN

    a的取值不同对应的窗口也不同,一般情况下a = 0.46 。

    结果:

    汉明窗图(采样点刻度):

    在这里插入图片描述

    汉明窗图(时间刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样数据分帧加窗后的第二帧图(时间刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样数据分帧加窗后的第二帧图(时间刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样数据分帧加窗后的最后一帧图(采样点刻度):

    在这里插入图片描述

    音频DrinkWater.wav的预加重填充采样数据分帧加窗后的最后一帧图(时间刻度):

    在这里插入图片描述

    由加窗后的图像可知,经过加窗处理后,音频部分被抑制,第二帧加窗后体现不出信号的幅值变化,抛出一个问题。

    另选一个信号验证本程序加窗前后波形如下:

    在这里插入图片描述

    在这里插入图片描述

    得出出现上面抛出的问题的原因可能是加窗后整体帧信号的局部变化幅值较小造成的。

    3、计算帧功率谱的周期图估计

    计算每个帧的功率谱,周期图估计值根据声音的频率在不同的位置振动情况(对应人体耳蜗中振动的位置-摆动小毛发),确定帧中存在哪些频率。

    • K是DFT的长度。语音帧的基于周期图的功率谱估计Pi(K)由下式给出:
      在这里插入图片描述
      这称为功率谱的周期图估计。N为窗口长度,我们取复数傅里叶变换的绝对值,并将结果平方。

    • 计算滤波器组的梅尔间隔,取20-40(26个标准)三角形滤波器应用于周期图功率谱估计,滤波器组以26个长度为N的向量的形式出现,每个向量大多为零,但在频谱的特定部分非零。


    #帧功率谱的周期图
    #求傅里叶变换
    #x1 = np.linspace(0, 1, LenFrame)#创建0-1的等差数组 LenFrame个
    x2 = np.arange(0,LenFrame,1)#创建0-LenFrame的等差数组,步长为1
    FftFrames = np.fft.fft(Frames)#fft计算
    AbsFrames = np.abs(FftFrames)#求模
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("amplitude")
    plt.title('SecondFrames fft', fontsize=12, color='black')
    plt.plot(x9,AbsFrames[1])
    plt.show()
    #功率谱的周期图估计
    Power=(np.square(AbsFrames))/LenFrame
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("amplitude")
    plt.title('Power', fontsize=12, color='black')
    plt.plot(Power)
    plt.show()
    

    对于加窗后的矩阵Frames,它是一个1125**400的矩阵,也就是说,它有1125帧数据,且每一帧数据都有400个采样点,那么我们接下来就要对这1125帧的每一帧都要进行快速傅里叶变换,得到一个大小为1125400大小的矩阵FftFrames,其帧数还是1125帧,对每一帧的400个数据点分别取模再取平方,然后除以LenFrame为400;便得到能量谱密度Power,其大小为1125x400,对每一帧得到的能量进行相加,代表每一帧能量的总和。

    结果:

    Power的维数为(1125*400)

    显示第二帧的傅里叶变换:

    在这里插入图片描述

    显示所有帧的功率谱的周期图估计:

    在这里插入图片描述

    4、将梅尔滤波器组应用于功率谱,将每个滤波器的能量求和

    周期图频谱估计包含许多自动语音识别(ASR)不需要的信息,表现为耳蜗不能辨别两个间隔较小的信号频率之间的差异,随着频率的增加,这种影响变得更加明显,此时需要将成簇的周期图进行汇总,以了解各个频率区域中存在多少能量。

    梅尔滤波器组执行周期图能量汇总:第一个滤波器非常窄,可以指示0赫兹附近存在多少能量。随着频率的升高,我们对滤波器的关注也越来越小,滤波器也变得越来越宽。对每个位置产生多少能量,梅尔刻度可以准确地告诉我们,间隔滤光片组以及滤光片组的宽度下面给出了有关如何计算间距的信息。
    在这里插入图片描述
    梅尔滤波器组和开窗功率谱图

    • 为了计算滤波器组的能量,将每个滤波器组乘以功率谱,然后将系数相加。完成此操作后,我们剩下26个数字,这些数字可以指示每个滤波器组中的能量。

    • 实际上常常使用26-40个滤波器组。

    • 为了获得上图(a)所示的滤波器组,选择一个较低和较高的频率,较低的频率为300Hz,较高的频率为8000Hz。如果语音以8000Hz采样,则上限频率将限制为4000Hz。

    • 使用梅尔音阶公式将高频和低频转换为梅尔兹。在此,300Hz为401.25 Mels,而8000Hz为2834.99 Mels。

    • 在此示例中,做10个滤波器组,为此需要12个点。需要在401.25和2834.99之间线性间隔的10个额外点。

      结果是:

    m(i)= 401.25、622.50、843.75、1065.00、1286.25、1507.50、1728.74, 
           1949.99、217.24、239.49、2613.74、2834.99
    
    • 使用梅尔音阶公式将其转换回赫兹:
    h(i)= 300,517.33,781.90,1103.97,1496.04,1973.32,2554.33, 
           3261.62,4122.63,5170.76,6446.70,8000
    

    注意:频率的起点和终点都在我们想要的频率上。

    • 我们没有将滤波器放置在上面计算出的精确点上所需的频率分辨率,因此我们需要将这些频率四舍五入到最接近的FFT档。此过程不会影响功能的准确性。要将频率转换为FFT bin(离散线谱间隔),FFT大小和采样率如下:
    f(i)=下限((nfft + 1)* h(i)/采样率)
    

    结果如下:

    f(i)= 9、16、25、35、47、63、81、104、132、165、206、256
    

    可以看到最终的滤波器组在bin 256处结束,这对应于512点FFT大小的8kHz。

    • 创建滤波器组:第一个滤波器组将从第一个点开始,在第二个点达到峰值,然后在第三个点返回零。第二个滤波器组将从第二个点开始,在第三个点达到最大值,然后在第四个点为零,依此类推。计算公式如下:
      在这里插入图片描述
      其中M是滤波器数量,f()是M +2梅尔间隔频率列表。

    • 彼此重叠的所有10个过滤器的最终图是:
      在这里插入图片描述

    上图包含了10个过滤器的梅尔过滤器组,该滤波器组以0Hz开始,以8000Hz结束。这仅是一个指南,实际工作示例始于300Hz。

    • 滤波器的第二种方法:创建Hm矩阵,这个矩阵得定义如下所示:
      在这里插入图片描述
      发现该梅尔滤波器,在频率很小的时候,滤波器宽度很窄,随着其频率的增大,滤波器的宽度也会逐渐增大,但其幅值也会逐渐减小。
      在这里插入图片描述

    #梅尔滤波器组应用于功率谱
    fl = 0
    fh =int(sr)
    bl = 1125*np.log(1+fl/700) # 把 Hz 变成 Mel
    bh = 1125*np.log(1+fh/700)
    #梅尔频率转换
    x11 = np.arange(fl,fh,1)#创建0-LenFrame的等差数组,步长为1
    MelFrequency= 1125*np.log(1+x11/700)
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("mel-frequency")
    plt.title('mel-frequency transfornation', fontsize=12, color='black')
    plt.plot(x11,MelFrequency)
    plt.show()
    

    其在低频范围内增长速度很快,但在高频范围内,梅尔值的增长速度很慢。每一个频率值都对应着一个梅尔值。

    结果:

    梅尔频率图:

    在这里插入图片描述

    #梅尔滤波器组一
    p = 26#滤波器个数
    B = bh-bl
    y = np.linspace(0,B,p+2)# 将梅尔刻度等间隔
    #print(y)
    Fb = 700*(np.exp(y/1125)-1)# 把 Mel 变成 Hz
    #print(Fb)
    W2 = int(LenFrame )#LenFrame内对应的FFT点数
    df = sr/LenFrame
    freq = []#采样频率值
    for n in range(0,W2):
        freqs = int(n*df)
        freq.append(freqs)#采样频率值
    bank = np.zeros((p,W2))#生成一个p行W2列的全零数组
    for k in range(1,p+1):
        f1 = Fb[k-1]
        f2 = Fb[k+1]
        f0 = Fb[k]
        n1=np.floor(f1/df)#f(m-1)在频域中的谱线索引号
        n2=np.floor(f2/df)#f(m+1)在频域中的谱线索引号
        n0=np.floor(f0/df)#f(m)在频域中的谱线索引号。f(m)是从0开始,而在MATLAB中数组的索引是从1开始,所以要加1,否则会出现index=0的错误
        for i in range(1,W2):
            if i>=n1 and i<=n0:
                bank[k-1,i]=(i-n1)/(n0-n1)
            elif i>n0 and i<=n2:
                bank[k-1,i]=(n2-i)/(n2-n0)
        # print(k)
        # print(bank[k-1,:])
        plt.plot(freq,bank[k-1,:])
    plt.show()
    #将梅尔滤波器组和功率谱相乘
    #for k in range(1,p+1):
    #H=Power*(bank.T)
    #H=mat(Power)*mat((bank.T))#H(NumFrames*p)
    H=np.mat(Power)*np.mat((bank.T))#H(NumFrames*p)
    #print(Power)#Power(NumFrames*LenFrame)
    #print(bank.T)#bank(p*LenFrame)
    #print(H)
    #梅尔滤波器组二
    p2 = 26#滤波器个数
    B2 = bh-bl
    y2 = np.linspace(0,B2,p2+2)# 将梅尔刻度等间隔
    #print(y2)
    Fb2 = 700*(np.exp(y2/1125)-1)# 把 Mel 变成 Hz
    #print(Fb2)
    W22 = int(LenFrame )#LenFrame内对应的FFT点数
    df2 = sr/LenFrame
    freq2 = []#采样频率值
    for n2 in range(0,W22):
        freqs2 = int(n2*df2)
        freq2.append(freqs2)#采样频率值
    bank2 = np.zeros((p2,W22))#生成一个p行W2列的全零数组
    for k2 in range(1,p2+1):
        f12 = Fb2[k2-1]
        f22 = Fb2[k2+1]
        f02 = Fb2[k2]
        n12=np.floor(f12/df2)#f(m-1)在频域中的谱线索引号
        n2=np.floor(f22/df2)#f(m+1)在频域中的谱线索引号
        n02=np.floor(f02/df2)#f(m)在频域中的谱线索引号。f(m)是从0开始,而在MATLAB中数组的索引是从1开始,所以要加1,否则会出现index=0的错误
        for i2 in range(1,W22):
            if i2>=n12 and i2<=n02:
                bank2[k2-1,i2]=(2*(i2-n12))/((n2-n12)*(n02-n12))
            elif i2>n02 and i2<=n2:
                bank2[k2-1,i2]=(2*(n2-i2))/((n2-n12)*(n02-n12))
        # print(k2)
        # print(bank2[k2-1,:])
        plt.plot(freq2,bank2[k2-1,:])
    plt.show()
    

    结果:

    梅尔滤波器组一:

    在这里插入图片描述

    梅尔滤波器组二:

    在这里插入图片描述

    抛出问题,不同的梅尔滤波器组,不同滤波器参数及作用。

    梅尔滤波器组的作用是放大低频信息,抑制高频频信息,尽可能保留低频部分信息,低频信息的跨度小于高频部分,幅度更体现低频的放大与高频的缩小 。

    5、取所有滤波器组能量的对数

    对数运算允许我们使用倒谱均值减法,这是一种通道归一化技术,人类听力听不到线性范围的响度,有了滤波器组能量,我们就可以取它们的对数,要将声音的感知音量加倍,我们需要将成(>8)倍的能量投入其中,这意味着,如果声音很大,开始时能量的大变化听起来可能并没有那么大的不同,这种(压缩)操作使我们的对数处理功能与人类实际听到的声音更加接近。

    • 取指示滤波器能量的26个数字的对数,得到26个log滤波器组能量。

    #将梅尔滤波器组和功率谱相乘
    #将梅尔滤波器组和功率谱相乘
    H2=np.mat(Power)*np.mat((bank2.T))#H2(NumFrames*p2)
    #取所有滤波器组能量的对数
    H3=np.log(H2)#第二个滤波器
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("mfcc")
    plt.title('mfcc-filter*powe', fontsize=12, color='black')
    plt.plot(H2)
    plt.show()
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("mfcc")
    plt.title('mfcc-log(filter*powe)', fontsize=12, color='black')
    plt.plot(H3)
    plt.show()
    

    结果:

    H2、H3的维数为:1125*26

    梅尔滤波器组和功率谱相乘:

    在这里插入图片描述

    所有滤波器组能量的对数图:

    在这里插入图片描述

    6、取对数滤波器组能量的离散余弦变换DCT

    离散余弦变换具有信号谱分量丰富,能量集中,不需要对语音进行相位估算等优点,在较低的计算复杂度下获得较好的语音增强的效果

    滤波器组都是重叠的,故滤波器组的能量彼此相关性极强,DCT对能量进行去相关,这意味着可以使用对角协方差矩阵对HMM分类器中的特征进行建模。

    • .对26个对数滤波器组能量进行离散余弦变换(DCT),得到26个倒谱系数。

    • M F C C ( i , n ) = ∑ m = 1 M log ⁡ [ H ( i , m ) ] . cos ⁡ [ π . n . ( 2 m − 1 ) 2 M ] MFCC\left( i,n \right) =\sum_{m=1}^M{\log \left[ H\left( i,m \right) \right] .\cos \left[ \frac{\pi .n.\left( 2m-1 \right)}{2M} \right]} MFCC(i,n)=m=1Mlog[H(i,m)].cos[2Mπ.n.(2m1)]

      其中H为我们上边得到的矩阵H,M代表梅尔滤波器个数,i代表第几帧数据(取值为1-NumFrames),n代表第i帧的第n列(n取值范围为1-26)。


    #print(mfcc)#完成离散余弦变换
    #在Numpy库中,函数的输入x不仅可以为单独一个数,还可以是一个列表,一个Numpy数组
    #其结果为Numpy数组。也就是说Numpy中的函数不需要循环就可以实现每个元素的批量处理。
    mfcc=np.zeros(shape=(NumFrames,p2))#创建0数组
    for i3 in range(0,NumFrames-1):
        for i4 in range(0,p2-1):
            sum=0#求每帧能量总和
            for i5 in range(0,p2-1):#做离散余弦变换
                sum=sum+H3[i3,i5]*math.cos(((math.pi)*i4)*(2*i5-1)/(2*p2))
            mfcc[i3,i4]=((2/p2)**0.5)*sum
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("mfcc")
    plt.title('mfcc-DCT', fontsize=12, color='black')
    plt.plot(mfcc)
    plt.show()
    

    结果:

    得到1125*26的数组

    对数滤波器组能量的离散余弦变换DCT图:

    在这里插入图片描述

    7、保持DCT系数2-13,其余部分丢弃

    保留26个DCT系数中的12个,这是因为较高的DCT系数表示滤波器组能量的快速变化,并且事实证明,这些快速变化实际上会降低ASR性能,因此通过降低DCT系数可以得到很小的改进。

    • 仅保留26个系数中较低的12-13,产生的特征(每帧12个数字)称为“梅尔频率倒谱系数”。

    #保持DCT系数2-13,其余部分丢弃
    #mfcc=mfcc[[0,2],:] #取某几行
    #mfcc=mfcc[:,[end-12,end]] #取后13列
    mfcc=mfcc[:,[0,1,2,3,4,5,6,7,8,9,10,11,12]] #取前13列
    #mfcc3=mfcc[:,[0,1,2,3]] #取前13列
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("mfcc")
    plt.title('mfcc', fontsize=12, color='black')
    plt.plot(mfcc)
    plt.show()
    

    结果:

    得到1125*13的数组

    取前13列图:

    在这里插入图片描述

    得到1125*2的数组

    取2列图:

    在这里插入图片描述

    8、求升倒谱系数及mfcc的第一组、第二组及第三组

    因为大部分的信号数据一般集中在变换后的低频区,所以对每一帧只取前13个数据就好了。其公式表达如下:
    在这里插入图片描述

    其中L为升倒谱系数,一般取值为22,我们将其带入即可求得矩阵K,这是一个1x13大小的矩阵,这一部分的升倒谱的其实现代码如下:


    #求升倒谱取升倒谱系数为22
    L=22
    K=[0,0,0,0,0,0,0,0,0,0,0,0,0]
    for i in range(0,12,1):
        K[i]=1+(L/2)*math.sin((math.pi)*(i+1)/L)
    #print(K)
    #得到二维数组feat,这是mfcc的第一组数据,默认为三组
    feat=mfcc1
    for i3 in range(0,NumFrames-1):
        for i in range(0,12):
            feat[i3,i]= feat[i3,i]*K[i]
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("feat")
    plt.title('feat', fontsize=12, color='black')
    plt.plot(feat)
    plt.show()
    
    

    在这里插入图片描述

    包括第一组参数:
    在这里插入图片描述

    接下来就是求取MFCC的第二组,第三组参数了。第二组参数其实就是在已有的基础参数下作一阶微分操作,第三组参数在第二组参数下作一阶微分操作:

    在这里插入图片描述

    第二组参数:

    #接下来求取第二组(一阶差分系数),这也是mfcc参数的第二组参数
    dtfeat=np.array([[0]*13]*(NumFrames))  #创建一个NumFrames-1行13列的二维零数组
    #求差分
    for i3 in range(0+3,NumFrames-1-2):
        for i in range(0,12):
            dtfeat[i3,i]=feat[i3+1,i]-feat[i3-1,i]+2*feat[i3+2,i]-2*feat[i3-2,i]
    dtfeat=dtfeat/10
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("dtfeat")
    plt.title('dtfeat', fontsize=12, color='black')
    plt.plot(dtfeat)
    plt.show()
    

    在这里插入图片描述

    
    #求取二阶差分系数,mfcc参数的第三组参数
    #二阶差分系数就是对前面产生的一阶差分系数dtfeat再次进行操作
    dttfeat=np.array([[0]*13]*(NumFrames))  #创建一个NumFrames-1行13列的二维零数组
    #求差分
    for i3 in range(0+3,NumFrames-1-2):
        for i in range(0,12):
            dttfeat[i3,i]=dtfeat[i3+1,i]-dtfeat[i3-1,i]+2*dtfeat[i3+2,i]-2*dtfeat[i3-2,i]
    dttfeat=dttfeat/10#这里的10是根据数据确定的
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("dttfeat")
    plt.title('dttfeat', fontsize=12, color='black')
    plt.plot(dttfeat)
    plt.show()
    

    在这里插入图片描述

    9、将三组数据合并得到特征参数

    由于一阶求导和二阶求导的前两帧和后两帧数据都为0,于是我们就要对在mfcc_final中去除这四帧数据:

    #将三组参数拼接
    mfcc_final=(np.concatenate((feat.T,dtfeat.T,dttfeat.T))).T#1125*39 
    #填补后的信号记为PreEmphasis1,np.concatenate()连接几个个维度相同的矩阵
    plt.figure()
    plt.xlabel("frequency")
    plt.ylabel("mfcc_final")
    plt.title('mfcc_final', fontsize=12, color='black')
    plt.plot(mfcc_final)
    plt.show()
    #由于一阶求导和二阶求导的前两帧和后两帧数据都为0,于是我们就要对在mfcc_final中去除这四帧数据
    mfcc24=mfcc_final[3:NumFrames-1-2,:]
    #选取每一帧的mfcc系数的第一个数得到MFCC0
    mfcc0=mfcc24[:,1]#选取mfcc系数的第一个数,组成新的特征参数mfcc0
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("mfcc0")
    plt.title('mfcc0', fontsize=12, color='black')
    plt.plot(mfcc0)
    plt.show()
    mfcc00=(mfcc0-80)/2
    plt.figure()
    plt.xlabel("point")
    plt.ylabel("mfcc00")
    plt.title('mfcc00', fontsize=12, color='black')
    plt.plot(mfcc00)
    plt.show()
    
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    总的有1125帧数据,剪掉四帧后 ,得到1121点的数据。
    可以看到,原始信号之前是431879个采样点的数据,而现在的M F C C 0 0参数图形大致与原始信号一致,并且其点数只有1121个点,这也就说明通过此方法M F C C 0 0,我们可以提取出语音信号的特点以及走向趋势,也就是说在某个程度上我们可以用这1121个点来代替431879点的数据。

    10、验证

    matlab验证:
    Matlab调用h=melbankm(p,n,fs,fl,fh,w),输入音频为DrinkWater.wav,数据每帧长n为400,滤波器组数p为26,采样频率fs为波器最16000、最低频为0,最高频fl取0.5,窗口采用汉明窗m(三角窗取t海宁窗取n)。fs与fl为采用fs归一化的频率。(问题:在书本中fl一般取0.5,对应例题的采样频率 为8000)f(i)=上限((nfft + 1)* h(i)/采样率)。
    在这里插入图片描述

    另一段语音验证:

    采用语音RecordVower1.wav
    在这里插入图片描述

    mfcc(matlab)
    在这里插入图片描述

    mfcc(mypython)
    在这里插入图片描述


    总结

    本次任务,也驱动于初学python,注释掉的代码部分是行不通的试错代码或不是最优需改进的代码,在此未作删除留作学习python的备忘,读者可忽略或指正。

    注意:对每个小节分割线上为理论资料,分割线下为具体实现,请注意资料对应的举例说明参数仅便于理解方法,具体音频实例参数对照注释及第二小节第一个图以及代码的语义注释。

    展开全文
  • 主要为大家详细介绍了语音识别之梅尔频率倒谱系数及Python实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 加密域梅尔频率倒谱系数和脆弱的音频水印
  • 语音信号处理之(四)梅尔频率倒谱系数,语音信号处理之(四)梅尔频率倒谱系数语音信号处理之(四)梅尔频率倒谱系数语音信号处理之(四)梅尔频率倒谱系数语音信号处理之(四)梅尔频率倒谱系数语音信号处理之(四...
  • 基于梅尔频率倒谱系数的非负矩阵分解的音频哈希函数
  • 梅尔频率倒谱系数

    2019-02-20 18:29:55
     梅尔频率倒谱系数( Mel Frequency Cepstrum Coefficient, MFCC )考虑到了人类的听觉特征,先将线性频谱映射到基于听觉感知的 Mel 非线性频谱中,然后转换到倒谱上。  将普通频率转化到Mel频率的公式是:    ...

    《语音信号处理》这门课,快考试了,所以也要了解了解相关的知识点。呵呵,平时没怎么听课,现在只能抱佛脚了。顺便也总结总结,好让自己的知识架构清晰点,也和大家分享下。下面总结的是第四个知识点:MFCC。因为花的时间不多,所以可能会有不少说的不妥的地方,还望大家指正。谢谢。

     

          在任意一个Automatic speech recognition 系统中,第一步就是提取特征。换句话说,我们需要把音频信号中具有辨识性的成分提取出来,然后把其他的乱七八糟的信息扔掉,例如背景噪声啊,情绪啊等等。

          搞清语音是怎么产生的对于我们理解语音有很大帮助。人通过声道产生声音,声道的shape(形状?)决定了发出怎样的声音。声道的shape包括舌头,牙齿等。如果我们可以准确的知道这个形状,那么我们就可以对产生的音素phoneme进行准确的描述。声道的形状在语音短时功率谱的包络中显示出来。而MFCCs就是一种准确描述这个包络的一种特征。

           MFCCs(Mel Frequency Cepstral Coefficents)是一种在自动语音和说话人识别中广泛使用的特征。它是在1980年由Davis和Mermelstein搞出来的。从那时起。在语音识别领域,MFCCs在人工特征方面可谓是鹤立鸡群一枝独秀,从未被超越啊(至于说Deep Learning的特征学习那是后话了)。

           好,到这里,我们提到了一个很重要的关键词:声道的形状,然后知道它很重要,还知道它可以在语音短时功率谱的包络中显示出来。哎,那什么是功率谱?什么是包络?什么是MFCCs?它为什么有效?如何得到?下面咱们慢慢道来。

     

    一、声谱图(Spectrogram)

             我们处理的是语音信号,那么如何去描述它很重要。因为不同的描述方式放映它不同的信息。那怎样的描述方式才利于我们观测,利于我们理解呢?这里我们先来了解一个叫声谱图的东西。

           这里,这段语音被分为很多帧,每帧语音都对应于一个频谱(通过短时FFT计算),频谱表示频率与能量的关系。在实际使用中,频谱图有三种,即线性振幅谱、对数振幅谱、自功率谱(对数振幅谱中各谱线的振幅都作了对数计算,所以其纵坐标的单位是dB(分贝)。这个变换的目的是使那些振幅较低的成分相对高振幅成分得以拉高,以便观察掩盖在低幅噪声中的周期信号)。

      

           我们先将其中一帧语音的频谱通过坐标表示出来,如上图左。现在我们将左边的频谱旋转90度。得到中间的图。然后把这些幅度映射到一个灰度级表示(也可以理解为将连续的幅度量化为256个量化值?),0表示黑,255表示白色。幅度值越大,相应的区域越黑。这样就得到了最右边的图。那为什么要这样呢?为的是增加时间这个维度,这样就可以显示一段语音而不是一帧语音的频谱,而且可以直观的看到静态和动态的信息。优点稍后呈上。

             这样我们会得到一个随着时间变化的频谱图,这个就是描述语音信号的spectrogram声谱图。

          下图是一段语音的声谱图,很黑的地方就是频谱图中的峰值(共振峰formants)。

          那我们为什么要在声谱图中表示语音呢?

          首先,音素(Phones)的属性可以更好的在这里面观察出来。另外,通过观察共振峰和它们的转变可以更好的识别声音。隐马尔科夫模型(Hidden Markov Models)就是隐含地对声谱图进行建模以达到好的识别性能。还有一个作用就是它可以直观的评估TTS系统(text to speech)的好坏,直接对比合成的语音和自然的语音声谱图的匹配度即可。

     

    二、倒谱分析(Cepstrum Analysis)

           下面是一个语音的频谱图。峰值就表示语音的主要频率成分,我们把这些峰值称为共振峰(formants),而共振峰就是携带了声音的辨识属性(就是个人身份证一样)。所以它特别重要。用它就可以识别不同的声音。

            既然它那么重要,那我们就是需要把它提取出来!我们要提取的不仅仅是共振峰的位置,还得提取它们转变的过程。所以我们提取的是频谱的包络(Spectral Envelope)。这包络就是一条连接这些共振峰点的平滑曲线。

          我们可以这么理解,将原始的频谱由两部分组成:包络和频谱的细节。这里用到的是对数频谱,所以单位是dB。那现在我们需要把这两部分分离开,这样我们就可以得到包络了。

          那怎么把他们分离开呢?也就是,怎么在给定log X[k]的基础上,求得log H[k] 和 log E[k]以满足log X[k] = log H[k] + log E[k]呢?

          为了达到这个目标,我们需要Play a Mathematical Trick。这个Trick是什么呢?就是对频谱做FFT。在频谱上做傅里叶变换就相当于逆傅里叶变换Inverse FFT (IFFT)。需要注意的一点是,我们是在频谱的对数域上面处理的,这也属于Trick的一部分。这时候,在对数频谱上面做IFFT就相当于在一个伪频率(pseudo-frequency)坐标轴上面描述信号。

             由上面这个图我们可以看到,包络是主要是低频成分(这时候需要转变思维,这时候的横轴就不要看成是频率了,咱们可以看成时间),我们把它看成是一个每秒4个周期的正弦信号。这样我们在伪坐标轴上面的4Hz的地方给它一个峰值。而频谱的细节部分主要是高频。我们把它看成是一个每秒100个周期的正弦信号。这样我们在伪坐标轴上面的100Hz的地方给它一个峰值。

             把它俩叠加起来就是原来的频谱信号了。

          在实际中咱们已经知道log X[k],所以我们可以得到了x[k]。那么由图可以知道,h[k]是x[k]的低频部分,那么我们将x[k]通过一个低通滤波器就可以得到h[k]了!没错,到这里咱们就可以将它们分离开了,得到了我们想要的h[k],也就是频谱的包络。

           x[k]实际上就是倒谱Cepstrum(这个是一个新造出来的词,把频谱的单词spectrum的前面四个字母顺序倒过来就是倒谱的单词了)。而我们所关心的h[k]就是倒谱的低频部分。h[k]描述了频谱的包络,它在语音识别中被广泛用于描述特征。

          那现在总结下倒谱分析,它实际上是这样一个过程:

    1)将原语音信号经过傅里叶变换得到频谱:X[k]=H[k]E[k];

    只考虑幅度就是:|X[k] |=|H[k]||E[k] |;

    2)我们在两边取对数:log||X[k] ||= log ||H[k] ||+ log ||E[k] ||。

    3)再在两边取逆傅里叶变换得到:x[k]=h[k]+e[k]。

           这实际上有个专业的名字叫做同态信号处理。它的目的是将非线性问题转化为线性问题的处理方法。对应上面,原来的语音信号实际上是一个卷性信号(声道相当于一个线性时不变系统,声音的产生可以理解为一个激励通过这个系统),第一步通过卷积将其变成了乘性信号(时域的卷积相当于频域的乘积)。第二步通过取对数将乘性信号转化为加性信号,第三步进行逆变换,使其恢复为卷性信号。这时候,虽然前后均是时域序列,但它们所处的离散时域显然不同,所以后者称为倒谱频域。

          总结下,倒谱(cepstrum)就是一种信号的傅里叶变换经对数运算后再进行傅里叶反变换得到的谱。它的计算过程如下:

     

    三、Mel频率分析(Mel-Frequency Analysis) 

             好了,到这里,我们先看看我们刚才做了什么?给我们一段语音,我们可以得到了它的频谱包络(连接所有共振峰值点的平滑曲线)了。但是,对于人类听觉感知的实验表明,人类听觉的感知只聚焦在某些特定的区域,而不是整个频谱包络。

             而Mel频率分析就是基于人类听觉感知实验的。实验观测发现人耳就像一个滤波器组一样,它只关注某些特定的频率分量(人的听觉对频率是有选择性的)。也就说,它只让某些频率的信号通过,而压根就直接无视它不想感知的某些频率信号。但是这些滤波器在频率坐标轴上却不是统一分布的,在低频区域有很多的滤波器,他们分布比较密集,但在高频区域,滤波器的数目就变得比较少,分布很稀疏。

           人的听觉系统是一个特殊的非线性系统,它响应不同频率信号的灵敏度是不同的。在语音特征的提取上,人类听觉系统做得非常好,它不仅能提取出语义信息, 而且能提取出说话人的个人特征,这些都是现有的语音识别系统所望尘莫及的。如果在语音识别系统中能模拟人类听觉感知处理特点,就有可能提高语音的识别率。

            梅尔频率倒谱系数(Mel Frequency Cepstrum Coefficient, MFCC)考虑到了人类的听觉特征,先将线性频谱映射到基于听觉感知的Mel非线性频谱中,然后转换到倒谱上。

            将普通频率转化到Mel频率的公式是:
     
          由下图可以看到,它可以将不统一的频率转化为统一的频率,也就是统一的滤波器组。

          在Mel频域内,人对音调的感知度为线性关系。举例来说,如果两段语音的Mel频率相差两倍,则人耳听起来两者的音调也相差两倍。

     

    四、Mel频率倒谱系数(Mel-Frequency Cepstral Coefficients) 

           我们将频谱通过一组Mel滤波器就得到Mel频谱。公式表述就是:log X[k] = log (Mel-Spectrum)。这时候我们在log X[k]上进行倒谱分析:

    1)取对数:log X[k] = log H[k] + log E[k]。

    2)进行逆变换:x[k] = h[k] + e[k]。

          在Mel频谱上面获得的倒谱系数h[k]就称为Mel频率倒谱系数,简称MFCC。

             现在咱们来总结下提取MFCC特征的过程:(具体的数学过程网上太多了,这里就不想贴了)

    1)先对语音进行预加重、分帧和加窗;

    2)对每一个短时分析窗,通过FFT得到对应的频谱;

    3)将上面的频谱通过Mel滤波器组得到Mel频谱;

    4)在Mel频谱上面进行倒谱分析(取对数,做逆变换,实际逆变换一般是通过DCT离散余弦变换来实现,取DCT后的第2个到第13个系数作为MFCC系数),获得Mel频率倒谱系数MFCC,这个MFCC就是这帧语音的特征;

           这时候,语音就可以通过一系列的倒谱向量来描述了,每个向量就是每帧的MFCC特征向量。

         这样就可以通过这些倒谱向量对语音分类器进行训练和识别了。

     

    五、参考文献

    [1]这里面还有一个比较好的教程:

    http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/

    [2]本文主要参考:cmu的教程:

     http://www.speech.cs.cmu.edu/15-492/slides/03_mfcc.pdf

    [3] C library for computing Mel Frequency Cepstral Coefficients (MFCC)

    http://code.google.com/p/libmfcc/


    转自https://blog.csdn.net/zouxy09/article/details/9156785/

    展开全文
  • 正弦信号的matlab代码梅尔频率倒谱系数 梅尔频率倒谱系数 该代码按照与Matlab中相同的步骤(功能:mfcc)来计算梅尔频率倒谱系数。 该代码使用默认的40频段滤波器组,其范围大约为133 Hz至6864 Hz,如Matlab中所述。...
  • 参考文章:梅尔频率倒谱系数(MFCC) 学习笔记、声学特征(二) MFCC特征原理。   MFCC概述 在语音识别(SpeechRecognition)和话者识别(SpeakerRecognition)方面,最常用到的语音特征就是梅尔倒谱系数(Mel-...

    转载自:语音特征参数MFCC提取过程详解

    参考文章:梅尔频率倒谱系数(MFCC) 学习笔记声学特征(二) MFCC特征原理

     

    MFCC概述

    在语音识别(SpeechRecognition)和话者识别(SpeakerRecognition)方面,最常用到的语音特征就是梅尔倒谱系数(Mel-scaleFrequency Cepstral Coefficients,简称MFCC)。根据人耳听觉机理的研究发现,人耳对不同频率的声波有不同的听觉敏感度。从200Hz到5000Hz的语音信号对语音的清晰度影响对大。两个响度不等的声音作用于人耳时,则响度较高的频率成分的存在会影响到对响度较低的频率成分的感受,使其变得不易察觉,这种现象称为掩蔽效应。由于频率较低的声音在内耳蜗基底膜上行波传递的距离大于频率较高的声音,故一般来说,低音容易掩蔽高音,而高音掩蔽低音较困难。在低频处的声音掩蔽的临界带宽较高频要小。所以,人们从低频到高频这一段频带内按临界带宽的大小由密到疏安排一组带通滤波器,对输入信号进行滤波。将每个带通滤波器输出的信号能量作为信号的基本特征,对此特征经过进一步处理后就可以作为语音的输入特征。由于这种特征不依赖于信号的性质,对输入信号不做任何的假设和限制,又利用了听觉模型的研究成果。因此,这种参数比基于声道模型的LPCC相比具有更好的鲁邦性,更符合人耳的听觉特性,而且当信噪比降低时仍然具有较好的识别性能。

    梅尔倒谱系数(Mel-scale Frequency Cepstral Coefficients,简称MFCC)是在Mel标度频率域提取出来的倒谱参数,Mel标度描述了人耳频率的非线性特性,它与频率的关系可用下式近似表示:

    式中f为频率,单位为Hz。下图展示了Mel频率与线性频率的关系:

     

     

    语音特征参数MFCC提取过程

    基本流程:

    预加重

    预加重处理其实是将语音信号通过一个高通滤波器:

    式中的值介于0.9-1.0之间,我们通常取0.97。

    预加重的目的是提升高频部分,使信号的频谱变得平坦,保持在低频到高频的整个频带中,能用同样的信噪比求频谱。同时,也是为了消除发生过程中声带和嘴唇的效应,来补偿语音信号受到发音系统所抑制的高频部分,也为了突出高频的共振峰。

    分帧

    先将N个采样点集合成一个观测单位,称为帧。通常情况下N的值为256或512,涵盖的时间约为20~30ms左右。为了避免相邻两帧的变化过大,因此会让两相邻帧之间有一段重叠区域,此重叠区域包含了M个取样点,通常M的值约为N的1/2或1/3。

    通常语音识别所采用语音信号的采样频率为8KHz或16KHz,以8KHz来说,若帧长度为256个采样点,则对应的时间长度是256/8000 1000=32ms。

    加窗(Hamming Window)

    将每一帧乘以汉明窗,以增加帧左端和右端的连续性。假设分帧后的信号为S(n), n=0,1,…,N-1, N为帧的大小,那么乘上汉明窗后S'(n)=S(n)xW(n),W(n)形式如下:

    不同的a值会产生不同的汉明窗,一般情况下a取0.46。

    快速傅里叶变换

    由于信号在时域上的变换通常很难看出信号的特性,所以通常将它转换为频域上的能量分布来观察,不同的能量分布,就能代表不同语音的特性。所以在乘上汉明窗后,每帧还必须再经过快速傅里叶变换以得到在频谱上的能量分布。对分帧加窗后的各帧信号进行快速傅里叶变换得到各帧的频谱。并对语音信号的频谱取模平方得到语音信号的功率谱。

    设语音信号的DFT为:

    式中x(n)为输入的语音信号,N表示傅里叶变换的点数。

    三角带通滤波器

    将能量谱通过一组Mel尺度的三角形滤波器组,定义一个有M个滤波器的滤波器组(滤波器的个数和临界带的个数相近),采用的滤波器为三角滤波器,中心频率为 。M通常取22-26。各f(m)之间的间隔随着m值的减小而缩小,随着m值的增大而增宽,如图所示:

     

    三角滤波器的频率响应定义为:

    式中:

    三角带通滤波器有两个主要目的:

    对频谱进行平滑化,并消除谐波的作用,突显原先语音的共振峰。(因此一段语音的音调或音高,是不会呈现在MFCC 参数内,换句话说,以MFCC 为特征的语音辨识系统,并不会受到输入语音的音调不同而有所影响)此外,还可以降低运算量。

    计算每个滤波器组输出的对数能量

    经离散余弦变换(DCT)得到MFCC系数

    将上述的对数能量带入离散余弦变换,求出L阶的Mel-scale Cepstrum参数。L阶指MFCC系数阶数,通常取12-16。这里M是三角滤波器个数。倒谱(cepstrum)就是一种信号的傅里叶变换经对数运算后再进行傅里叶反变换得到的谱。

    对数能量

    此外,一帧的音量(即能量),也是语音的重要特征,而且非常容易计算。因此,通常再加上一帧的对数能量(定义:一帧内信号的平方和,再取以10为底的对数值,再乘以10)使得每一帧基本的语音特征就多了一维,包括一个对数能量和剩下的倒频谱参数。

    注:若要加入其它语音特征以测试识别率,也可以在此阶段加入,这些常用的其它语音特征包含音高、过零率以及共振峰等。

    动态查分参数的提取(包括一阶差分和二阶差分)

    标准的倒谱参数MFCC只反映了语音参数的静态特性,语音的动态特性可以用这些静态特征的差分谱来描述。实验证明:把动、静态特征结合起来才能有效提高系统的识别性能。差分参数的计算可以采用下面的公式:

    式中,dt表示第t个一阶差分;Ct表示第t个倒谱系数;Q表示倒谱系数的阶数;K表示一阶导数的时间差,可取1或2。将上式中结果再代入就可以得到二阶差分的参数。

    总结

    因此,MFCC的全部组成其实是由:

    N维MFCC参数(N/3MFCC系数+ N/3一阶差分参数+ N/3二阶差分参数)+帧能量(此项可根据需求替换)

     

    MATLAB实现方法

    注:在提取MFCC参数之前需要加载并使用VOICEBOX工具包

    实现代码:

    >[x fs]=wavread('000.wav');
    bank=melbankm(24,256,fs,0,0.4,'t');%Mel滤波器的阶数为24,fft变换的长度为256,采样频率为16000Hz
    
    %归一化mel滤波器组系数
    bank=full(bank);
    bank=bank/max(bank(:));
    for k=1:12 %归一化mel滤波器组系数
    n=0:23;
    dctcoef(k,:)=cos((2*n+1)*k*pi/(2*24));
    end
    w=1+6*sin(pi*[1:12]./12);%归一化倒谱提升窗口
    
    w=w/max(w);%预加重滤波器
    xx=double(x);
    xx=filter([1-0.9375],1,xx);%语音信号分帧
    xx=enframe(xx,256,80);%对x 256点分为一帧
    
    %计算每帧的MFCC参数
    for i=1:size(xx,1)
    y=xx(i,:);
    s=y'.*hamming(256);
    t=abs(fft(s));%fft快速傅立叶变换
    t=t.^2;
    c1=dctcoef*log(bank*t(1:129));
    c2=c1.*w';
    m(i,:)=c2';
    end
    
    %求取一阶差分系数
    dtm=zeros(size(m));
    for i=3:size(m,1)-2
    dtm(i,:)=-2*m(i-2,:)-m(i-1,:)+m(i+1,:)+2*m(i+2,:);
    end
    dtm=dtm/3;
    
    %求取二阶差分系数
    dtmm=zeros(size(dtm));
    for i=3:size(dtm,1)-2
    dtmm(i,:)=-2*dtm(i-2,:)-dtm(i-1,:)+dtm(i+1,:)+2*dtm(i+2,:);
    end
    dtmm=dtmm/3;
    
    %合并mfcc参数和一阶、二阶差分mfcc参数
    ccc=[m dtm dtmm];
    %去除首尾两帧,因为这两帧的一阶差分参数为0
    ccc=ccc(3:size(m,1)-2,:);
    ccc
    
    % subplot(2,1,1)
    % ccc_1=ccc(:,1);
    % plot(ccc_1);title('MFCC');ylabel('幅值');
    % [h,w]=size(ccc);
    % A=size(ccc);
    % subplot(212)
    % plot([1,w],A);
    % xlabel('维数');
    % ylabel('幅值');
    % title('维数与幅值的关系')

    结果:

    以上即是语音特征参数MFCC提取过程的详细解释和具体实现。

     

    展开全文
  • 梅尔频率倒谱系数(MFCC)讲解 这几天搞一搞关于MFCC的东西,看到这篇文章非常好,所以转载下。 转自:http://b...

    梅尔频率倒谱系数(MFCC)讲解

    这几天搞一搞关于MFCC的东西,看到这篇文章非常好,所以转载下。

    转自:http://blog.csdn.net/zouxy09

    在任意一个Automatic speech recognition 系统中,第一步就是提取特征。换句话说,我们需要把音频信号中具有辨识性的成分提取出来,然后把其他的乱七八糟的信息扔掉,例如背景噪声啊,情绪啊等等。

          搞清语音是怎么产生的对于我们理解语音有很大帮助。人通过声道产生声音,声道的shape(形状?)决定了发出怎样的声音。声道的shape包括舌头,牙齿等。如果我们可以准确的知道这个形状,那么我们就可以对产生的音素phoneme进行准确的描述。声道的形状在语音短时功率谱的包络中显示出来。而MFCCs就是一种准确描述这个包络的一种特征。

           MFCCs(Mel Frequency Cepstral Coefficents)是一种在自动语音和说话人识别中广泛使用的特征。它是在1980年由Davis和Mermelstein搞出来的。从那时起。在语音识别领域,MFCCs在人工特征方面可谓是鹤立鸡群,一枝独秀,从未被超越啊(至于说Deep Learning的特征学习那是后话了)。

           好,到这里,我们提到了一个很重要的关键词:声道的形状,然后知道它很重要,还知道它可以在语音短时功率谱的包络中显示出来。哎,那什么是功率谱?什么是包络?什么是MFCCs?它为什么有效?如何得到?下面咱们慢慢道来。

     

    一、声谱图(Spectrogram)

             我们处理的是语音信号,那么如何去描述它很重要。因为不同的描述方式放映它不同的信息。那怎样的描述方式才利于我们观测,利于我们理解呢?这里我们先来了解一个叫声谱图的东西。

           这里,这段语音被分为很多帧,每帧语音都对应于一个频谱(通过短时FFT计算),频谱表示频率与能量的关系。在实际使用中,频谱图有三种,即线性振幅谱、对数振幅谱、自功率谱(对数振幅谱中各谱线的振幅都作了对数计算,所以其纵坐标的单位是dB(分贝)。这个变换的目的是使那些振幅较低的成分相对高振幅成分得以拉高,以便观察掩盖在低幅噪声中的周期信号)。

      

           我们先将其中一帧语音的频谱通过坐标表示出来,如上图左。现在我们将左边的频谱旋转90度。得到中间的图。然后把这些幅度映射到一个灰度级表示(也可以理解为将连续的幅度量化为256个量化值?),0表示黑,255表示白色。幅度值越大,相应的区域越黑。这样就得到了最右边的图。那为什么要这样呢?为的是增加时间这个维度,这样就可以显示一段语音而不是一帧语音的频谱,而且可以直观的看到静态和动态的信息。优点稍后呈上。

             这样我们会得到一个随着时间变化的频谱图,这个就是描述语音信号的spectrogram声谱图。

          下图是一段语音的声谱图,很黑的地方就是频谱图中的峰值(共振峰formants)。

          那我们为什么要在声谱图中表示语音呢?

          首先,音素(Phones)的属性可以更好的在这里面观察出来。另外,通过观察共振峰和它们的转变可以更好的识别声音。隐马尔科夫模型(Hidden Markov Models)就是隐含地对声谱图进行建模以达到好的识别性能。还有一个作用就是它可以直观的评估TTS系统(text to speech)的好坏,直接对比合成的语音和自然的语音声谱图的匹配度即可。

     

    二、倒谱分析(Cepstrum Analysis)

           下面是一个语音的频谱图。峰值就表示语音的主要频率成分,我们把这些峰值称为共振峰(formants),而共振峰就是携带了声音的辨识属性(就是个人身份证一样)。所以它特别重要。用它就可以识别不同的声音。

            既然它那么重要,那我们就是需要把它提取出来!我们要提取的不仅仅是共振峰的位置,还得提取它们转变的过程。所以我们提取的是频谱的包络(Spectral Envelope)。这包络就是一条连接这些共振峰点的平滑曲线。

          我们可以这么理解,将原始的频谱由两部分组成:包络和频谱的细节。这里用到的是对数频谱,所以单位是dB。那现在我们需要把这两部分分离开,这样我们就可以得到包络了。

          那怎么把他们分离开呢?也就是,怎么在给定log X[k]的基础上,求得log H[k] 和 log E[k]以满足log X[k] = log H[k] + log E[k]呢?

          为了达到这个目标,我们需要Play a Mathematical Trick。这个Trick是什么呢?就是对频谱做FFT。在频谱上做傅里叶变换就相当于逆傅里叶变换Inverse FFT (IFFT)。需要注意的一点是,我们是在频谱的对数域上面处理的,这也属于Trick的一部分。这时候,在对数频谱上面做IFFT就相当于在一个伪频率(pseudo-frequency)坐标轴上面描述信号。

             由上面这个图我们可以看到,包络是主要是低频成分(这时候需要转变思维,这时候的横轴就不要看成是频率了,咱们可以看成时间),我们把它看成是一个每秒4个周期的正弦信号。这样我们在伪坐标轴上面的4Hz的地方给它一个峰值。而频谱的细节部分主要是高频。我们把它看成是一个每秒100个周期的正弦信号。这样我们在伪坐标轴上面的100Hz的地方给它一个峰值。

             把它俩叠加起来就是原来的频谱信号了。

          在实际中咱们已经知道log X[k],所以我们可以得到了x[k]。那么由图可以知道,h[k]是x[k]的低频部分,那么我们将x[k]通过一个低通滤波器就可以得到h[k]了!没错,到这里咱们就可以将它们分离开了,得到了我们想要的h[k],也就是频谱的包络。

           x[k]实际上就是倒谱Cepstrum(这个是一个新造出来的词,把频谱的单词spectrum的前面四个字母顺序倒过来就是倒谱的单词了)。而我们所关心的h[k]就是倒谱的低频部分。h[k]描述了频谱的包络,它在语音识别中被广泛用于描述特征。

          那现在总结下倒谱分析,它实际上是这样一个过程:

    1)将原语音信号经过傅里叶变换得到频谱:X[k]=H[k]E[k];

    只考虑幅度就是:|X[k] |=|H[k]||E[k] |;

    2)我们在两边取对数:log||X[k] ||= log ||H[k] ||+ log ||E[k] ||。

    3)再在两边取逆傅里叶变换得到:x[k]=h[k]+e[k]。

           这实际上有个专业的名字叫做同态信号处理。它的目的是将非线性问题转化为线性问题的处理方法。对应上面,原来的语音信号实际上是一个卷性信号(声道相当于一个线性时不变系统,声音的产生可以理解为一个激励通过这个系统),第一步通过卷积将其变成了乘性信号(时域的卷积相当于频域的乘积)。第二步通过取对数将乘性信号转化为加性信号,第三步进行逆变换,使其恢复为卷性信号。这时候,虽然前后均是时域序列,但它们所处的离散时域显然不同,所以后者称为倒谱频域。

          总结下,倒谱(cepstrum)就是一种信号的傅里叶变换经对数运算后再进行傅里叶反变换得到的谱。它的计算过程如下:

     

    三、Mel频率分析(Mel-Frequency Analysis) 

             好了,到这里,我们先看看我们刚才做了什么?给我们一段语音,我们可以得到了它的频谱包络(连接所有共振峰值点的平滑曲线)了。但是,对于人类听觉感知的实验表明,人类听觉的感知只聚焦在某些特定的区域,而不是整个频谱包络。

             而Mel频率分析就是基于人类听觉感知实验的。实验观测发现人耳就像一个滤波器组一样,它只关注某些特定的频率分量(人的听觉对频率是有选择性的)。也就说,它只让某些频率的信号通过,而压根就直接无视它不想感知的某些频率信号。但是这些滤波器在频率坐标轴上却不是统一分布的,在低频区域有很多的滤波器,他们分布比较密集,但在高频区域,滤波器的数目就变得比较少,分布很稀疏。

           人的听觉系统是一个特殊的非线性系统,它响应不同频率信号的灵敏度是不同的。在语音特征的提取上,人类听觉系统做得非常好,它不仅能提取出语义信息, 而且能提取出说话人的个人特征,这些都是现有的语音识别系统所望尘莫及的。如果在语音识别系统中能模拟人类听觉感知处理特点,就有可能提高语音的识别率。

            梅尔频率倒谱系数(Mel Frequency Cepstrum Coefficient, MFCC)考虑到了人类的听觉特征,先将线性频谱映射到基于听觉感知的Mel非线性频谱中,然后转换到倒谱上。

            将普通频率转化到Mel频率的公式是:
     
          由下图可以看到,它可以将不统一的频率转化为统一的频率,也就是统一的滤波器组。

          在Mel频域内,人对音调的感知度为线性关系。举例来说,如果两段语音的Mel频率相差两倍,则人耳听起来两者的音调也相差两倍。

     

    四、Mel频率倒谱系数(Mel-Frequency Cepstral Coefficients) 

           我们将频谱通过一组Mel滤波器就得到Mel频谱。公式表述就是:log X[k] = log (Mel-Spectrum)。这时候我们在log X[k]上进行倒谱分析:

    1)取对数:log X[k] = log H[k] + log E[k]。

    2)进行逆变换:x[k] = h[k] + e[k]。

          在Mel频谱上面获得的倒谱系数h[k]就称为Mel频率倒谱系数,简称MFCC。

             现在咱们来总结下提取MFCC特征的过程:(具体的数学过程网上太多了,这里就不想贴了)

    1)先对语音进行预加重、分帧和加窗;

    2)对每一个短时分析窗,通过FFT得到对应的频谱;

    3)将上面的频谱通过Mel滤波器组得到Mel频谱;

    4)在Mel频谱上面进行倒谱分析(取对数,做逆变换,实际逆变换一般是通过DCT离散余弦变换来实现,取DCT后的第2个到第13个系数作为MFCC系数),获得Mel频率倒谱系数MFCC,这个MFCC就是这帧语音的特征;

           这时候,语音就可以通过一系列的倒谱向量来描述了,每个向量就是每帧的MFCC特征向量。

         这样就可以通过这些倒谱向量对语音分类器进行训练和识别了。

     

    五、参考文献

    [1]这里面还有一个比较好的教程:

    http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/

    [2]本文主要参考:cmu的教程:

     http://www.speech.cs.cmu.edu/15-492/slides/03_mfcc.pdf

    [3] C library for computing Mel Frequency Cepstral Coefficients (MFCC)

    http://code.google.com/p/libmfcc/

      展开全文
    • 梅尔频率倒谱系数(MFCC) 学习笔记 最近学习音乐自动标注的过程中,看到了有关使用MFCC提取音频特征的内容,特地在网上找到资料,学习了一下相关内容。此笔记大部分内容摘自博文 ...
    • mfcc:根据浏览器中的麦克风输入计算MFCC(梅尔频率倒谱系数)。 (TypeScript)
    • MFCC 梅尔频率倒谱系数

      千次阅读 2017-06-04 19:39:17
      TERM: MFCC 梅尔频率倒谱系数 在任何的自动语音识别系统中,第一步一般都是提取特征,也就是识别出音频信号的组成部分,哪些部分有利于我们识别语义内容,从而舍弃掉其他不相关的信息,比如背景噪音,情绪...
    • 语音信号处理之(四)梅尔频率倒谱系数(MFCC)zouxy09@qq.comhttp://blog.csdn.net/zouxy09 这学期有《语音信号处理》这门课,快考试了,所以也要了解了解相关的知识点。呵呵,平时没怎么听课,现在只能抱佛脚了。...
    • 梅尔频率倒谱系数(MFCC) 高斯混合模型(GMM) 数据集 可以在上找到免费的ST美国英语语料库数据集(SLR45) 。 它是提供的免费的美国英语语料库,其中包含10位说话者(5位女性和5位男性)的讲话。 每个说话者大约...
    • 梅尔频率倒谱系数(Mel-Frequency Cepstral Coefficients,MFCCs) 这个词涉及到梅尔频率和倒谱,所以先分别了解这俩词的意思。 1. 倒谱(Cepstral): (这个词是频谱spectrum的前面四个字母顺序倒过来,所以和...
    • 梅尔频率倒谱系数(MFCC)的提取过程与C++代码实现 2015年07月21日 20:38:00-绿色小屋阅读数:9623标签:语音识别 MFCC更多 个人分类:数字信号处理 版权声明:本文为博主原创文章,未经博主允许不得转载。 ...
    • 梅尔频率倒谱系数(MFCC)在语音项目中尤其重要,例如在语音识别,声纹识别等中都有他的身影.具体细节可以参看博客https://www.cnblogs.com/BaroC/p/4283380.html 话不多说,直接上代码. *******开始讲解几个重要函数,...
    • 【语音识别】之梅尔频率倒谱系数(mfcc)及Python实现一、mel滤波器二、mfcc特征Python实现 语音识别系统的第一步是进行特征提取,mfcc是描述短时功率谱包络的一种特征,在语音识别系统中被广泛应用。 一、mel...

    空空如也

    空空如也

    1 2 3 4 5 ... 20
    收藏数 900
    精华内容 360
    关键字:

    梅尔频率倒谱系数