滤波器组FBanks特征 & 梅尔频率倒谱系数MFCC基于librosa, torchaudio


滤波器组(Filter Banks, FBanks)特征 & 梅尔频率倒谱系数(Mel Frequency Cepstral Coefficients, MFCC) 基于librosa, torchaudio

  • 说明:FBanks & MFCC作为特征被广泛应用于语音识别领域。本文将使用librosatorchaudio分别实现。计算流程如下图所示(此处暂不涉及PLP)。如有错误,欢迎指正。
  • 目的:尽可能简单地理解与使用MFCC,以快速上手语音识别任务。
    请添加图片描述

1. 准备工作:导入librosa,torchaudio等包及数据

  • 本人使用版本说明
    ∘ \qquad\qquad\circ python==3.8.9
    ∘ \qquad\qquad\circ librosa==0.9.2
    ∘ \qquad\qquad\circ torch==1.10.1+cu113
    ∘ \qquad\qquad\circ torchaudio==0.10.1+cu113
    ∘ \qquad\qquad\circ scipy==1.8.0
  • 示例音频数据
    ∘ \qquad\qquad\circ 下载地址: Lab41-SRI-VOiCES-src-sp0307-ch127535-sg0042.wav
    ∘ \qquad\qquad\circ 采样频率: 16k
  • 参数说明
    ∘ \qquad\qquad\circ sample_rate (sr): 采样频率,即每秒采样点数,单位为赫兹(Hz)。
import torch
import torchaudio
from torch import Tensor
import numpy as np
import librosa
from librosa.display import specshow
from matplotlib import pyplot as plt
from scipy.fftpack import dct
wave_pt, sample_rate_pt = torchaudio.load('Lab41-SRI-VOiCES-src-sp0307-ch127535-sg0042.wav')
# librosa的默认采样频率是22050,设None即可读取原始sr
wave_librosa, sample_rate_librosa = librosa.load('Lab41-SRI-VOiCES-src-sp0307-ch127535-sg0042.wav', sr=None)

print('torchaudio版: ', wave_pt.shape, '|', sample_rate_pt)
print('librosa版: ', wave_librosa.shape, '|', sample_rate_librosa)
torchaudio版:  torch.Size([1, 54400]) | 16000
librosa版:  (54400,) | 16000
time_axis = torch.arange(0, wave_pt.shape[1]) / sample_rate_pt
plt.figure(figsize=(15, 10))
plt.subplot(2, 1, 1)
plt.plot(time_axis, wave_pt.squeeze(), 'red')
plt.title('origin wave_pt')
plt.ylabel('Amplitude')
plt.xlabel('Time(s)')
plt.subplot(2, 1, 2)
plt.plot(time_axis, wave_librosa, 'blue')
plt.title('origin wave_librosa')
plt.ylabel('Amplitude')
plt.xlabel('Time(s)')
plt.show()

请添加图片描述

2. 预处理

2.1 分帧 (Framing)

  • 说明:大多数情况下,对整个信号进行傅里叶变换是没有意义的,因为我们会随着时间的推移丢失信号的频率轮廓。假定信号在短时间( 20 m s ∼ 40 m s 20ms \sim 40ms 20ms40ms)内是稳定的,并将这段时间的信号设为1帧,相邻的帧之间有50%±10%的重叠。通常帧长为 25 m s 25ms 25ms,帧移为 10 m s 10ms 10ms

  • 参数
    ∘ \qquad\qquad\circ frame_size: 0.025
    ∘ \qquad\qquad\circ frame_stride: 0.01

2.2 加窗(Window)

  • 说明:分帧的相当于对信号加了矩形窗,相应的频域会存在严重的频谱泄露,为了减少频谱泄露,对每帧信号加其他形式的窗。

∘ \qquad\qquad\circ 汉明窗(Hamming):
⋄ \qquad\qquad\qquad\diamond 公式:
w ham  [ n ] = 0.54 − 0.46 cos ⁡ ( 2 π n N − 1 ) \mathrm{w}_{\text {ham }}[n]=0.54-0.46 \cos \left(\frac{2 \pi n}{N}-1\right) wham [n]=0.540.46cos(N2πn1)
⋄ \qquad\qquad\qquad\diamond 图形:
请添加图片描述

∘ \qquad\qquad\circ 汉宁窗(Hanning):
⋄ \qquad\qquad\qquad\diamond 公式:
W h a n [ n ] = 0.5 [ 1 − cos ⁡ ( 2 π n N − 1 ) ] \mathrm{W}_{h a n}[n]=0.5\left[1-\cos \left(\frac{2 \pi n}{N}-1\right)\right] Whan[n]=0.5[1cos(N2πn1)]
⋄ \qquad\qquad\qquad\diamond 图形:
请添加图片描述

3. 短时傅立叶变换(Short Time Fourier Transform, STFT)

  • 说明:为了分离不同频率的信号,傅里叶变换的意义:任何连续测量的时序或信号,都可以表示为不同频率的正弦波信号的无限叠加。
    请添加图片描述

  • 计算公式

∘ \qquad\qquad\circ 欧拉公式: e j ω n = cos ⁡ ( ω n ) + j sin ⁡ ( ω n ) \mathrm{e}^{\mathrm{j} \omega \mathrm{n}}=\cos (\omega \mathrm{n})+\mathrm{j} \sin (\omega \mathrm{n}) ejωn=cos(ωn)+jsin(ωn)

∘ \qquad\qquad\circ 离散傅里叶变换(Discrete Fourier Transform, DFT)第 k k k个点的计算方式:
X [ k ] = ∑ n = 0 N − 1 x [ n ] e − j 2 π k n K = ∑ n = 0 N − 1 x [ n ] e − j w n \mathrm{X}[k]=\sum_{n=0}^{N-1} x[n] \mathrm{e}^{-\frac{j 2 \pi k n}{K}}=\sum_{n=0}^{N-1} x[n] \mathrm{e}^{-j w n} X[k]=n=0N1x[n]eKj2πkn=n=0N1x[n]ejwn
⋄ \qquad\qquad\qquad\diamond ω = 2 π k K ∈ [ 0 , 2 π ] \omega=\frac{2\pi k}{K} \in [0, 2\pi] ω=K2πk[0,2π]为角频率;
⋄ \qquad\qquad\qquad\diamond x [ n ] x[n] x[n]是时域波形第 n n n个采样点;
⋄ \qquad\qquad\qquad\diamond X [ k ] X[k] X[k]是傅里叶频谱第 k k k个点;
⋄ \qquad\qquad\qquad\diamond N N N是采样的点数, K K K是DFT的大小,其中 K ≥ N K \ge N KN

∘ \qquad\qquad\circ 利用欧拉公式: e − j 2 π k n K = cos ⁡ ( 2 π k n K ) − j sin ⁡ ( 2 π k n K ) \mathrm{e}^{-\frac{j 2 \pi k n}{K}}=\cos \left(\frac{2 \pi k n}{K}\right)-\mathrm{j} \sin \left(\frac{2 \pi k n}{K}\right) eKj2πkn=cos(K2πkn)jsin(K2πkn) \qquad\qquad\qquad 则: X [ k ] = X r e a l [ k ] − j X i m a g [ k ] \mathrm{X}[k]=\mathrm{X}_{\mathrm{real}}[k]-\mathrm{j} \mathrm{X}_{\mathrm{imag}}[k] X[k]=Xreal[k]jXimag[k] X real  [ k ] = ∑ n = 0 N − 1 x [ n ] cos ⁡ ( 2 π k n K ) \mathrm{X}_{\text {real }}[k]=\sum_{n=0}^{N-1} x[n] \cos \left(\frac{2 \pi k n}{K}\right) Xreal [k]=n=0N1x[n]cos(K2πkn) X imag  [ k ] = ∑ n = 0 N − 1 x [ n ] sin ⁡ ( 2 π k n K ) \quad \mathrm{X}_{\text {imag }}[k]=\sum_{n=0}^{N-1} x[n] \sin \left(\frac{2 \pi k n}{K}\right) Ximag [k]=n=0N1x[n]sin(K2πkn)

∘ \qquad\qquad\circ 振幅频谱(Magnitude Spectrum): X magnitude  [ k ] = ( X real  [ k ] 2 + X imag  [ k ] 2 ) \mathrm{X}_{\text {magnitude }}[k]=\sqrt{\left(\mathrm{X}_{\text {real }}[k]^{2}+\mathrm{X}_{\text {imag }}[k]^{2}\right)} Xmagnitude [k]=(Xreal [k]2+Ximag [k]2)
∘ \qquad\qquad\circ 能量频谱(Power Spectrum): X power  [ k ] = X real  [ k ] 2 + X imag  [ k ] 2 \mathrm{X}_{\text {power }}[k]=\mathrm{X}_{\text {real }}[k]^{2}+\mathrm{X}_{\text {imag }}[k]^{2} Xpower [k]=Xreal [k]2+Ximag [k]2
∘ \qquad\qquad\circ 分贝(Decibel): N d B [ k ] = 10 lg ⁡ X power  [ k ] r e f N_{\mathrm{dB}}[k]=10 \lg \frac{\mathrm{X}_{\text {power }}[k]}{ref} NdB[k]=10lgrefXpower [k]

  • 代码torch.stftlibrosa.stft

∘ \qquad\qquad\circ 参数说明:
⋄ \qquad\qquad\qquad\diamond n_fft: FFT窗口长度,则对应的分帧时间为 n f f t s a m p l e _ r a t e \frac{n_{fft}}{sample\_rate} sample_ratenfft秒,默认为2048。
⋄ \qquad\qquad\qquad\diamond hop_length: 帧移,如果未指定,则默认 w i n l e n g t h / / 4 win_{length} // 4 winlength//4
⋄ \qquad\qquad\qquad\diamond win_length: 每一帧音频都由窗函数加窗,窗长 w i n l e n g t h win_{length} winlength,且 w i n l e n g t h < = n f f t win_{length}<=n_{fft} winlength<=nfft,用零填充以匹配 n f f t n_{fft} nfft,默认 w i n l e n g t h = n f f t win_{length}=n_{fft} winlength=nfft
⋄ \qquad\qquad\qquad\diamond window: 窗函数,类型为string, tuple, number, function, shape=(n_fft,)的向量,默认为'hann'
⋄ \qquad\qquad\qquad\diamond center: 如果为True,则假定输出复数矩阵D具有居中的帧,如果False,则假定D具有左对齐的帧,默认False

∘ \qquad\qquad\circ 输出:
⋄ \qquad\qquad\qquad\diamond D: 复数矩阵,shape = ( n c h a n n e l s , 1 + n f f t 2 , n f r a m e ) =(n_{channels}, 1+\frac{n_{fft}}{2}, n_{frame}) =(nchannels,1+2nfft,nframe), n f r a m e = i n t ( 1 + ( y . s h a p e [ − 1 ] − w i n l e n g t h ) / / h o p l e n g t h ) n_{frame} = int(1 + (y.shape[-1] - win_{length}) // hop_{length}) nframe=int(1+(y.shape[1]winlength)//hoplength)

d_pt = torch.stft(
    wave_pt,
    n_fft=2048,
    hop_length=None,
    win_length=None,
    window=torch.hann_window(window_length=2048),
    center=False,
    pad_mode="constant",
    return_complex=True
)

d_librosa = librosa.stft(
    wave_librosa,
    n_fft=2048,
    hop_length=None,
    win_length=None,
    window="hann",
    center=False,
    dtype=None,
    pad_mode="constant"
)
print('torch版复数矩阵: ', d_pt.shape)
print('librosa版复数矩阵: ', d_librosa.shape)
torch版复数矩阵:  torch.Size([1, 1025, 103])
librosa版复数矩阵:  (1025, 103)
def power_to_db(power_spec, ref=1.0, amin=1e-10, top_db=80.0) -> Tensor:
    """定义torch版的功率谱转到分贝"""
    log_spec = 10.0 * torch.log10(torch.clip(power_spec, min=amin))
    log_spec -= 10.0 * torch.log10(torch.tensor(np.maximum(amin, ref), device=power_spec.device))
    log_spec = torch.maximum(log_spec, log_spec.max() - top_db)
    return log_spec


magnitude_pt = torch.abs(d_pt)
power_pt = torch.pow(magnitude_pt, 2)
db_pt = power_to_db(power_pt, 1.0)

magnitude_librosa = np.abs(d_librosa)
power_librosa = np.power(magnitude_librosa, 2)
db_librosa = librosa.power_to_db(power_librosa, ref=1)

print('torch版能量谱|分贝: ', power_pt.shape, '|', db_pt.shape)
print('librosa版能量谱|分贝: ', power_librosa.shape, '|', db_librosa.shape)
torch版能量谱|分贝:  torch.Size([1, 1025, 103]) | torch.Size([1, 1025, 103])
librosa版能量谱|分贝:  (1025, 103) | (1025, 103)
def plot_db_spectrum(spectrum_db, title=None, y_label="freq_bin"):
    """绘制db谱图"""
    fig, axs = plt.subplots(1, 1)
    axs.set_title(title or "Spectrum (db)")
    axs.set_ylabel(y_label)
    axs.set_xlabel("frame")
    im = axs.imshow(spectrum_db, origin="lower", aspect="auto")
    fig.colorbar(im, ax=axs, format='%+2.0f dB')
    plt.show(block=False)


print('能量谱: ')
plot_db_spectrum(db_pt[0], title='spectrum_db_pt')
plot_db_spectrum(db_librosa, title='spectrum_db_librosa')
print('librosa自带画图:')
librosa.display.specshow(db_librosa, sr=sample_rate_librosa,
                         y_axis='linear', x_axis='time')
能量谱:

请添加图片描述
请添加图片描述

librosa自带画图:

请添加图片描述

4 梅尔滤波器组 (Mel Filter Banks)

4.1 Mel频率

  • 定义:1Mel为1kHz 音调感知程度的 1/1000。
  • 目的:模拟人耳对不同频率语音的感知。人类对不同频率语音有不同的感知能力:1kHz 以下,与频率成线性关系;1kHz 以上,与频率成对数关系。
  • 公式 Mel ⁡ ( f ) = 2595 lg ⁡ ( 1 + f 700 ) \operatorname{Mel}(f)=2595 \lg (1+\frac{f}{700}) Mel(f)=2595lg(1+700f)

4.2 Mel Filter Banks

  • 定义:定义一个有 M M M个三角滤波器的滤波器组(滤波器的个数和临界带的个数相近), M M M通常取22-40,26是标准,示例图取 n m e l s = 40 n_{mels} = 40 nmels=40。滤波器组中的每个滤波器都是三角形的,中心频率为 f ( m ) f(m) f(m) ,中心频率处的响应为1,并向0线性减小,直到达到两个相邻滤波器的中心频率,其中响应为0。第1个滤波器组将从第1个点开始,在第2个点达到峰值,然后在第3个点返回零;第2个滤波器组将从第2个点开始,在第3个点达到最大值,然后在第4个点为零,以此类推。各 f ( m ) f(m) f(m)之间的间隔随着 m m m值的增大而增宽,如图所示:
    请添加图片描述

  • 公式 H m ( k ) = { 0 k < f ( m − 1 ) k − f ( m − 1 ) f ( m ) − f ( m − 1 ) f ( m − 1 ) ≤ k ≤ f ( m ) f ( m + 1 ) − k f ( m + 1 ) − f ( m ) f ( m ) ≤ k ≤ f ( m + 1 ) 0 k > f ( m + 1 ) H_{m}(k)=\left\{\begin{array}{cl} 0 & k<f(m-1) \\ \frac{k-f(m-1)}{f(m)-f(m-1)} & f(m-1) \leq k \leq f(m) \\ \frac{f(m+1)-k}{f(m+1)-f(m)} & f(m) \leq k \leq f(m+1) \\ 0 & k>f(m+1) \end{array}\right. Hm(k)=0f(m)f(m1)kf(m1)f(m+1)f(m)f(m+1)k0k<f(m1)f(m1)kf(m)f(m)kf(m+1)k>f(m+1)
    ∘ \qquad\qquad\circ 其中, m m m是滤波器组数;
    ∘ \qquad\qquad\circ f ( ⋅ ) f(\cdot) f() m + 2 m+2 m+2个经过 M e l Mel Mel尺度变换的 M e l Mel Mel频率;

  • 代码参数(torchaudio.functional.melscale_fbanks & librosa.filters.mel)
    ∘ \qquad\qquad\circ n_fft(librosa):FFT窗口长度;
    ∘ \qquad\qquad\circ n_freqs(pt):要滤波的频率数量;
    ∘ \qquad\qquad\circ n_mels:Mel滤波器组个数;
    ∘ \qquad\qquad\circ f_min:最小截止频率(Hz);
    ∘ \qquad\qquad\circ f_max:最大截止频率(Hz);
    ∘ \qquad\qquad\circ norm:如果是slaney,将三角形的mel权重除以mel带的宽度(面积归一化)。默认为None

4.3 FilterBanks特征

  • 公式 F i l t e r B a n k s ( k ) = X power  ( k ) ⋅ H m ( k ) FilterBanks(k) = \mathrm{X}_{\text {power }}(k) \cdot H_{m}(k) FilterBanks(k)=Xpower (k)Hm(k)
  • 直接计算代码参数(torchaudio.transforms.MelSpectrogram&librosa.feature.melspectrogram)
    ∘ \qquad\qquad\circ sample_rate, n_fftn_mels, hop_length, win_length, window等同上。
n_fft = 2048
n_mels = 40
sample_rate = 16000

mel_filters_pt = torchaudio.functional.melscale_fbanks(
    int(n_fft // 2 + 1),
    n_mels=n_mels,
    f_min=0.0,
    f_max=sample_rate / 2.0,
    sample_rate=sample_rate,
    norm="slaney",
)

mel_filters_librosa = librosa.filters.mel(
    sr=sample_rate,
    n_fft=n_fft,
    n_mels=n_mels,
    fmin=0.0,
    fmax=sample_rate / 2.0,
    norm="slaney",
    htk=True,
).T

print('torch版滤波器组: ', mel_filters_pt.shape)
print('librosa版滤波器组: ', mel_filters_librosa.shape)
torch版滤波器组:  torch.Size([1025, 40])
librosa版滤波器组:  (1025, 40)
print('Mel滤波器组:')
plot_db_spectrum(power_to_db(mel_filters_pt), title='spectrum_db_pt')
plot_db_spectrum(librosa.power_to_db(mel_filters_librosa), title='spectrum_db_librosa')
Mel滤波器组:

请添加图片描述
请添加图片描述

filter_banks_pt = torch.mm(power_pt[0].T, mel_filters_pt).T
filter_banks_librosa = np.matmul(power_librosa.T, mel_filters_librosa).T
print('torch版FilterBanks特征: ', filter_banks_pt.shape)
print('librosa版FilterBanks特征: ', filter_banks_librosa.shape)
torch版FilterBanks特征:  torch.Size([40, 103])
librosa版FilterBanks特征:  (40, 103)
print('FilterBanks特征: ')
plot_db_spectrum(power_to_db(filter_banks_pt), title='spectrum_db_pt')
plot_db_spectrum(librosa.power_to_db(filter_banks_librosa), title='spectrum_db_librosa')
FilterBanks特征:

请添加图片描述
请添加图片描述

MelSpectrogram = torchaudio.transforms.MelSpectrogram(
    sample_rate=sample_rate,
    n_fft=2048,
    n_mels=40,
    hop_length=512,
    win_length=None,
    window_fn=torch.hann_window
)
mel_spec_pt = MelSpectrogram(wave_pt)

mel_spec_librosa = librosa.feature.melspectrogram(
    y=wave_librosa,
    sr=sample_rate,
    n_fft=2048,
    n_mels=40,
    hop_length=512,
    win_length=None,
    window="hann",
)
print('torch版直接API计算的FilterBanks特征: ', mel_spec_pt.shape)
print('librosa版直接API计算的FilterBanks特征: ', mel_spec_librosa.shape)
torch版直接API计算的FilterBanks特征:  torch.Size([1, 40, 107])
librosa版直接API计算的FilterBanks特征:  (40, 107)
print('直接API计算FilterBanks特征: ')
plot_db_spectrum(power_to_db(mel_spec_pt[0]), title='spectrum_db_pt')
plot_db_spectrum(librosa.power_to_db(mel_spec_librosa), title='spectrum_db_librosa')
直接API计算FilterBanks特征:

请添加图片描述
请添加图片描述

5. 梅尔频率倒谱系数(Mel-frequency Cepstral Coefficients, MFCC)

  • 说明:FilterBanks系数之间是高度相关的,对某些任务会出现问题,利用离散余弦变换(Discrete Cosine Transform, DCT)可以将FilterBanks系数去相关并且可以压缩信息。对于自动语音识别(ASR)任务,一般保留 2 ∼ 13 2\sim 13 213个系数,其余丢掉的原因是由于FilterBanks系数的快速变化,表征了声音细微的细节,对ASR任务意义不大。
  • DCT公式 C ( n ) = ∑ m = 0 N − 1 s ( m ) cos ⁡ ( π n ( m − 0.5 ) M ) , n = 1 , 2 , . . . , L C(n)=\sum\limits_{m=0}^{N-1}{s( m)\cos( \frac{\pi n( m-0.5)}{M} )},n=1,2,...,L C(n)=m=0N1s(m)cos(Mπn(m0.5)),n=1,2,...,L
    ∘ \qquad\qquad\circ L L L阶指MFCC系数阶数,通常取 2 ∼ 13 2\sim13 213
    ∘ \qquad\qquad\circ M M M是Mel滤波器个数。
  • 代码参数(torchaudio.functional.create_dct&librosa使用的是scipy下的dct):
    ∘ \qquad\qquad\circ n_mfcc:MFCC系数阶数。
  • 直接计算MFCC代码参数(torchaudio.transforms.MFCC&librosa.feature.mfcc):
    ∘ \qquad\qquad\circ n_mfcc:MFCC系数阶数;其他参数同FilterBanks参数。
n_fft = 2048
win_length = None
hop_length = 512
n_mels = 40
n_mfcc = 12
dct_pt = torchaudio.functional.create_dct(n_mfcc=n_mfcc, n_mels=n_mels, norm=None)
mfcc_pt = torch.mm(power_to_db(filter_banks_pt.T), dct_pt).T

mfcc_librosa = dct(x=librosa.power_to_db(filter_banks_librosa), axis=-2)[..., :n_mfcc, :]

print('torch版的MFCC特征: ', mfcc_pt.shape)
print('librosa版的MFCC特征: ', mfcc_librosa.shape)
torch版的MFCC特征:  torch.Size([12, 103])
librosa版的MFCC特征:  (12, 103)
print('MFCC特征:')
plot_db_spectrum(power_to_db(mfcc_pt), title='spectrum_db_pt')
plot_db_spectrum(librosa.power_to_db(mfcc_librosa), title='spectrum_db_librosa')
MFCC特征:

请添加图片描述
请添加图片描述

mfcc_transform = torchaudio.transforms.MFCC(
    sample_rate=sample_rate,
    n_mfcc=n_mfcc,
    melkwargs={
        "n_fft": n_fft,
        "n_mels": n_mels,
        "hop_length": hop_length,
        "mel_scale": "htk",
    },
)
mfcc_api_pt = mfcc_transform(wave_pt)

mfcc_api_librosa = librosa.feature.mfcc(
    y=wave_librosa,
    sr=sample_rate,
    n_mfcc=n_mfcc,
    dct_type=2,
    norm="ortho",
    # --- mel kwargs --- #
    n_fft=n_fft,
    n_mels=n_mels,
    hop_length=hop_length,
    htk=True,
)

print('torch版直接API计算的MFCC特征: ', mfcc_api_pt.shape)
print('librosa版直接API计算的MFCC特征: ', mfcc_api_librosa.shape)
torch版直接API计算的MFCC特征:  torch.Size([1, 12, 107])
librosa版直接API计算的MFCC特征:  (12, 107)
print('直接API计算MFCC特征: ')
plot_db_spectrum(power_to_db(mfcc_api_pt[0]), title='mfcc_db_pt')
plot_db_spectrum(librosa.power_to_db(mfcc_api_librosa), title='mfcc_db_librosa')
直接API计算MFCC特征:

请添加图片描述
请添加图片描述

6. 参考

  1. Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What’s In-Between
  2. Mel Frequency Cepstral Coefficient (MFCC) tutorial
  3. Torchaudio Documentation
  4. librosa api
  5. librosa语音信号处理
  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是在Matlab中提取翻转频率谱系数(MFCC)的示例代码: ```matlab % 读取音频文件 [y, Fs] = audioread(&#39;example.wav&#39;); % 预处理:对信号进行预加重,使用高通滤波器 preemph = [1, -0.97]; y = filter(preemph, 1, y); % 帧分割:将信号分为若干个帧 frame_size = 0.025; % 帧长(单位:秒) frame_shift = 0.01; % 帧移(单位:秒) frame_length = frame_size * Fs; % 帧长(单位:采样点) frame_step = frame_shift * Fs; % 帧移(单位:采样点) num_frames = floor((length(y) - frame_length) / frame_step) + 1; frames = zeros(frame_length, num_frames); for i = 1:num_frames start_idx = (i-1) * frame_step + 1; frames(:, i) = y(start_idx : start_idx + frame_length - 1); end % 加窗:对每个帧进行汉明窗加窗 window = hamming(frame_length); frames = bsxfun(@times, frames, window); % 快速傅里叶变换:对每个帧进行FFT计算 NFFT = 512; fft_frames = fft(frames, NFFT, 1); % 能量谱:计算每个帧的能量谱 power_frames = abs(fft_frames).^2 / NFFT; % 滤波器组:计算滤波器组的系数 num_filters = 20; mel_low_freq = 0; % 滤波器组的最低频率 mel_high_freq = 2595 * log10(1 + (Fs/2) / 700); % 滤波器组的最高频率 mel_points = linspace(mel_low_freq, mel_high_freq, num_filters + 2); hz_points = 700 * (10.^(mel_points / 2595) - 1); bin = floor((NFFT + 1) * hz_points / Fs); fbank = zeros(num_filters, NFFT / 2 + 1); for m = 1:num_filters f_m_minus = bin(m); f_m = bin(m+1); f_m_plus = bin(m+2); for k = f_m_minus:f_m fbank(m, k+1) = (k - bin(m)) / (bin(m+1) - bin(m)); end for k = f_m:f_m_plus fbank(m, k+1) = (bin(m+2) - k) / (bin(m+2) - bin(m+1)); end end % 翻转频率谱系数:计算每个帧的MFCC num_ceps = 12; mfcc = zeros(num_ceps, num_frames); for i = 1:num_frames % 将能量谱乘以滤波器组的系数,得到每个滤波器的输出能量 filter_energies = fbank * power_frames(:, i); % 取对数,得到滤波器组的对数输出能量 log_filter_energies = log(filter_energies + eps); % 对上面的对数输出能量进行离散余弦变换(DCT) mfcc(:, i) = dct(log_filter_energies); % 取前 num_ceps 个系数作为MFCC mfcc(:, i) = mfcc(1:num_ceps, i); end % 翻转MFCC:对每个MFCC向量进行翻转 rfcc = flipud(mfcc); ``` 以上代码中,翻转MFCC的操作是通过 `flipud` 函数实现的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值