Mel滤波器组的设计与实现(基于MATLAB和Python)

Mel滤波器组的设计与实现(基于MATLAB和Python)

1、Mel滤波器组介绍

在语音的频谱范围内设置若干带通滤波器 H m ( k ) , 0 m < M M 为滤波器的个数。每个滤波器具有三角形滤波特性,其中心频率为 f ( m ) ,在Mel频率范围内,这些滤波器是等带宽的。每个带通滤波器的传递函数为

H m ( k ) = { (1) 0   k < f ( m 1 ) (2) k f ( m 1 ) f ( m ) f ( m 1 )   f ( m 1 ) k f ( m )   (3) f ( m + 1 ) k f ( m + 1 ) f ( m )   f ( m ) < k f ( m + 1 ) (4) 0   k > f ( m + 1 )

f ( m ) 可以用下面的方法加以定义:
f ( m ) = ( N f s ) F m e l 1 ( F m e l ( f l ) + m F m e l ( f h ) F m e l ( f l ) M + 1 )

式中, f l 为滤波器频率范围的最低频率; f h 为滤波器频率范围的最高频率; N 为DFT(或FFT)时的长度; f s 为采样频率; F m e l 函数为
F m e l = 1125 ln ( 1 + f / 700 )

F m e l 的逆函数 F m e l 1

F m e l 1 ( b ) = 700 ( e b / 1125 1 )

2、Mel滤波器组的设计

我们设置采样率 f s = 8000 H z ,滤波器频率范围的最低频率 f l = 0 ,滤波器频率范围的最高频率 f h = f s / 2 = 8000 / 2 = 4000 ;设置滤波器个数 M = 24 ,FFT的长度 N = 256 。根据每个带通滤波器的传递函数可以计算出每个Mel滤波器的值,再由设置的滤波器个数可以形成一个Mel滤波器组。注意每个带通滤波器的传递函数值是在Mel频率域上计算的,计算完后再转到频率域上。

3、MATLAB实现

程序:

fs=8000;
fl=0; fh=fs/2;
bl=1125*log(1+fl/700);%将频率转换为Mel频率
bh=1125*log(1+fh/700);
p=24;%滤波器个数
nfft=256;%FFT点数
B=bh-bl;
y=linspace(0,B,p+2);%产生0到B之间p+2个数
Fb=700*(exp(y/1125)-1);%将Mel频率转换为频率
W2=nfft/2+1;%fs/2内对应的FFT点数
df=fs/nfft;
freq=(0:W2-1)*df;%采样频率值
bank=zeros(24,W2);%生成一个24行W2列的全零数组
for k=2:p+1%why从2开始?因为k-1
    f1=Fb(k-1); f2=Fb(k+1); f0=Fb(k);
    n1=floor(f1/df)+1;%f(m-1)在频域中的谱线索引号
    n2=floor(f2/df)+1;%f(m+1)在频域中的谱线索引号
    n0=floor(f0/df)+1;%f(m)在频域中的谱线索引号。f(m)是从0开始,而在MATLAB中数组的索引是从1开始,所以要加1,否则会出现index=0的错误
    for i=1 : W2
        if i>=n1 & i<=n0
            bank(k-1,i)=(i-n1)/(n0-n1);
        elseif i>n0 & i<=n2
            bank(k-1,i)=(n2-i)/(n2-n0);
        end
    end
    plot(freq,bank(k-1,:),'r','linewidth',2); hold on
end
grid; 

结果:
这里写图片描述

4、Python实现

程序:

import numpy as np 
import pylab as plt

fs = 8000
fl = 0
fh = fs/2
bl = 1125*np.log(1+fl/700) # 把 Hz 变成 Mel
bh = 1125*np.log(1+fh/700)
p = 24
NFFT=256
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(NFFT / 2 + 1)
df = fs/NFFT
freq = []#采样频率值
for n in range(0,W2):
    freqs = int(n*df)
    freq.append(freqs)
bank = np.zeros((24,W2))
for k in range(1,p+1):
    f1 = Fb[k-1]
    f2 = Fb[k+1]
    f0 = Fb[k]
    n1=np.floor(f1/df)
    n2=np.floor(f2/df)
    n0=np.floor(f0/df)
    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,:],'r')
plt.show()

结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_39516859/article/details/80815369
今日推荐