梅尔倒频谱

在讯号处理中，梅尔倒频谱（Mel-Frequency Cepstrum, MFC）系一个可用来代表短期音讯的频谱，其原理基于用非线性的梅尔刻度（mel scale）表示的对数频谱及其线性余弦转换（linear cosine transform）上。

梅尔频率倒谱系数（Mel-Frequency Cepstral Coefficients, MFCC）是一组用来建立梅尔倒频谱的关键系数。由音乐讯号当中的片段，可以得到一组足以代表此音乐讯号之倒频谱（Cepstrum），而梅尔倒频谱系数即是从这个倒频谱中推得的倒频谱（也就是频谱的频谱）。与一般的倒频谱不同，梅尔倒频谱最大的特色在于，于梅尔倒频谱上的频带是均匀分布于梅尔刻度上的，也就是说，这样的频带相较于一般所看到、线性的倒频谱表示方法，和人类非线性的听觉系统更为接近。例如：在音讯压缩的技术中，便常常使用梅尔倒频谱来处理。

梅尔倒频谱系数通常是用以下方法得到的：

- 将一讯号进行傅立叶转换
- 利用三角窗函数（triangular overlapping window），将频谱映射（mapping）至梅尔刻度
- 取对数
- 取离散余弦转换
- MFCC是转换后的频谱

取得梅尔倒频谱的方法众多，上述只是其中一种。

另外，ETSI在2000年左右有定义一套专为移动电话设计的梅尔倒频谱系数算法。

## 历史

一般认为Paul Mermelstein 是主要致力于发展梅尔倒频谱的人，然而 Mermelstein 本人却将主要的概念功劳归给 Bridle 和 Brown for the idea:

Bridle 和 Brown 运用了一组十九个、由余弦转换导出的频谱型的系数，转换的输入值是讯号在一组在频带上有非均匀间隔分布的带通滤波器后的输出。

滤波器的间隔是呈现对数分布的；因此，一般称之为梅尔式的导频谱系数

通常此两组起源都会被人当作参照使用。

另外，许多作者包括Mermelstein都认为，梅尔倒频谱中这样以频谱为基准的余弦转换函式，非常接近早期用于语音表征和辨认、对对数化频谱进型的主成分分析；关于这部分相关的资讯，可参考Pols和它同事的研究。

## 系数推导

- 对该信号做傅立叶变换

$$X[k]=FT{x[n]}$$

- 根据下面公式算出Ym

$Y[m]=\log \left( \sum_{k=f_{m-1}}^{f_{m+1}} \left| X[k] \right|^2 B_m[k] \right)$

其中$B_m[k]$是梅尔频率倒频谱的遮罩

$$B_m[k]= \begin{cases} 0 & \mbox{for } k<f_{m-1} \mbox{ and } k>f_{m+1}\\ \cfrac {k-f_{m-1}}{f_m-f_{m-1}} & \mbox{for } f_{m-1} \leq k \leq f_m \\ \cfrac {f_{m+1}-k}{f_{m+1}-f_m} & \mbox{for } f_m \leq k \leq f_{m+1} \end{cases}$$

3.对Ym做IDCT得$c_x[n]$，因为Ym是偶函数,故用IDCT(反离散余弦变换)取代IDFT(反离散傅立叶变换)

$c_x[n]= \frac{1}{M} \sum_{m=1}^{M} Y[m]cos \left( \cfrac{\pi n(m-1/2)}{M} \right)$

## 优势

梅尔倒频谱主要是为了解决传统倒频谱在数学计算上的缺陷，并使其特征更适用于声学与语音辨识。

### 相位产生的无限多解问题

一般倒频谱的核心运算是对 $X(F)$ 取对数，而 $\log(X(F)) = \log|X(F)| + j\arg(X(F))$，其中虚部的相角 $\arg(X(F))$ 本质上是一个周期函数，任何相位值加上 $2\pi$ 的整数倍都代表同一个复数，导致虚部$j\arg(X(F))$产生无限多组解，造成相位计算上的模糊与困难。

相对地，梅尔频率倒频谱在计算 $Y[m]$ 时，是把 $|X[k]|^2$ 这个一定为非负实数的量，透过三角形滤波器 $B_m[k]$ 在某个频带范围内加权后加总，所以 $\sum_k |X[k]|^2 B_m[k]$ 永远是一个确定的非负实数，对它取对数自然只会得到唯一实数值，不存在多解问题，使得梅尔倒频谱的计算更加干净、稳定且更容易实作。

### 数值趋近负无限大

在实际讯号中，频谱 $|X(F)|$ 在某些频率点上很可能因为讯号本身的特性或是因为噪声造成的相消干涉，而出现非常接近零甚至等于零的情况。一旦 $|X(F)| \to 0$，$\log|X(F)|$ 就会趋近于负无限大，这在数值计算上会造成严重的不稳定或让后续的反傅立叶转换无法收敛或产生极端的尖峰值。

梅尔倒频谱的做法是先把整个频带范围内的能量 $|X[k]|^2$ 用滤波器 $B_m[k]$ 做加权加总，而不是针对单一频率点取对数。由于这个加总是横跨一段频带的多个频率成分，即便其中某几个 $|X[k]|$ 恰好接近零，整个频带内其他频率成分的能量几乎不可能同时也都接近零，因此 $\sum_k |X[k]|^2 B_m[k]$ 整体变成零的几率被大幅降低，$\log$ 运算趋近于 $-\infty$ 的风险也就跟着大幅减少，整体数值稳定性自然提升许多。

### 人类听觉感知

人耳对频率的敏感度并非线性，在低频范围（例如几百到一千多 Hz）人耳的频率分辨率很高，能分辨很细微的频率差异，但在高频范围，即使频率差异很大，人耳感受到的差异却相对小。

梅尔频率倒频谱使用了频率以等比级数增加的遮罩，在低频区间排列得较密、带宽较窄，在高频区间则排列得较疏、带宽较宽，模拟人耳对不同频率的解析能力。因此，当讯号经过这组滤波器处理后再取对数、做离散余弦转换，所得到的特征会更贴近人耳实际感受到的差异。对于语音辨识这类模拟人类如何分辨声音的应用，这种贴近听觉感知的特征自然比一般倒频谱更有意义。

### 运算复杂度

一般的复数倒频谱在最后一步，是将已经取过对数的复数频谱 $\hat{X}(F)$ 透过反离散时间傅立叶转换（IFT）转回时域得到 $\hat{x}[n]$，由于此 IFT 是复数运算，计算量相对较大。

而梅尔频率倒频谱在计算出每个滤波器频带对应的实数对数能量 $Y[m]$ 之后，使用离散余弦转换（DCT）将 $Y[m]$ 转换成最终的系数，运算上不需要处理虚部，且可以利用与快速傅立叶转换（FFT）类似但更精简的快速算法来计算，因此相较于需要处理复数资料的 IFT，DCT 的运算量明显较小。再加上梅尔倒频谱整体所需计算的资料量本身就比一般倒频谱（理论上是无限长序列）小得多，使得梅尔频率倒频谱在计算效率上具有相当明显的优势。

## 应用

梅尔倒频谱系数通常可以用于作为语音识别系统中的特征质观察，例如：可以自动辨认一个人透过电话说的数字。梅尔倒频谱系数通常也可以作为声纹识别（Speaker Recognition），也就是、用来辨识某段语音讯号的发话者是谁的技术。除此之外，也延伸出语音情绪辨识等方向。

梅尔倒频谱系数在近年来于音乐分类（music genre classification）相关应用的领域也逐渐崭露头角，例如寻找一段音乐的相似程度等。

### 语音辨识

梅尔频率倒谱系数MFCC和感知线性预测PLP：不同于LPC等通过对人的发声机理的研究而得到的声学特征，Mel倒谱系数MFCC和感知线性预测PLP是受人的听觉系统研究成果推动而导出的声学特征。对人的听觉机理的研究发现，当两个频率相近的音调同时发出时，人只能听到一个音调。临界带宽指的就是这样一种令人的主观感觉发生突变的带宽边界，当两个音调的频率差小于临界带宽时，人就会把两个音调听成一个，这称之为屏蔽效应。Mel刻度是对这一临界带宽的度量方法之一。

MFCC的计算首先用FFT将时域信号转化成频域，之后对其对数能量谱用依照Mel刻度分布的三角滤波器组进行卷积，最后对各个滤波器的输出构成的向量进行离散余弦变换DCT，取前N个系数。PLP仍用德宾法去计算LPC参数，但在计算自相关参数时用的也是对听觉激励的对数能量谱进行DCT的方法。

## 噪声

### 根源

梅尔倒频谱系数在理想的安静环境下表现优异，但其本质上并非相当稳定，在实际计算过程中极易受到外加的加性噪声影响。这种脆弱性主要源自于算法中的取对数步骤。当语音讯号处于低能量区段（例如句尾、气音或停顿处）时，即使是微弱的背景噪声，也会在对数运算后被不成比例地放大，导致最终算出的倒频谱系数产生剧烈波动，进而大幅降低语音辨识或声纹比对系统的准确率。

### 特征正规化

为了对抗噪声与录音设备带来的变异，通常必须在萃取出的 MFCC 特征上进行正规化（Normalization）处理。最广泛使用的技术是倒频谱均值减法（Cepstral Mean Subtraction, CMS）与倒频谱变异数正规化（Cepstral Variance Normalization, CVN），两者常合并称为 CMVN。CMS 的做法是计算一段语音中所有 MFCC 向量的平均值，并将每个特征向量扣除该平均值；这能有效消除由麦克风特性或传输通道所造成的静态线性滤波效应（回响或通道失真）。而 CVN 则是将特征的变异数缩放至单位变异数，以减少不同发话者音量大小与动态范围变化的干扰。

### 算法改良

除了后期的正规化，许多研究者也致力于从 MFCC 的基础算法着手，使其设计得更加顽强。其中一种做法是导入对数能量底限。由于当频带能量趋近于零时，对数运算会产生极大的负值，因此在进行离散余弦转换（DCT）之前，算法会强制规定一个能量的下限值。一旦滤波器计算出的能量低于此范围，便会被提升并锁定在这个底限值上。这种机制确保了诸如背景白噪音等低能量项，不会在对数化后主导整个系数的结果。

此外，为了进一步平滑噪声造成的频谱峰值剧烈变化，也会套用倒频谱提升（Cepstral Liftering）技术，对计算出的 MFCC 乘上一个正弦窗函数，借此压抑高阶系数中不稳定的噪声成分，同时突显对语音辨识最有帮助的中低阶系数。

## 程式码实作范例

以下是使用 Python实作提取梅尔倒频谱系数（MFCC）的范例：

<image>

```python
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from scipy.fftpack import dct

# 參數設定
fs        = 8000
frame_ms  = 25
N         = int(fs * frame_ms / 1000)
NFFT      = 512
n_filters = 20
n_ceps    = 13

# 產生模擬訊號（包含三個頻率成分）
n  = np.arange(N)
f0 = 150 
f1, f2 = 1200, 2400

x = (1.0 * np.sin(2 * np.pi * f0 * n / fs)
     + 0.6 * np.sin(2 * np.pi * f1 * n / fs)
     + 0.3 * np.sin(2 * np.pi * f2 * n / fs))

# 加上 Hamming 窗函數
window = np.hamming(N)
x_w = x * window

# 快速傅立葉轉換 (FFT) 與功率頻譜計算
X = np.fft.rfft(x_w, NFFT)
freqs = np.fft.rfftfreq(NFFT, d=1 / fs)
power_X = np.abs(X) ** 2

# 定義 Hz 與 Mel 刻度之間的轉換函數
def hz_to_mel(f):
    return 2595.0 * np.log10(1.0 + f / 700.0)

def mel_to_hz(m):
    return 700.0 * (10 ** (m / 2595.0) - 1.0)

# 計算梅爾濾波器組的中心頻率與邊界
low_mel  = hz_to_mel(0)
high_mel = hz_to_mel(fs / 2)

mel_points = np.linspace(low_mel, high_mel, n_filters + 2)
hz_points  = mel_to_hz(mel_points)
bin_points = np.floor((NFFT + 1) * hz_points / fs).astype(int)

# 建立梅爾三角形濾波器組
filters = np.zeros((n_filters, len(freqs)))

for m in range(1, n_filters + 1):
    f_left, f_center, f_right = bin_points[m - 1], bin_points[m], bin_points[m + 1]

    for k in range(f_left, f_center):
        if f_center != f_left:
            filters[m - 1, k] = (k - f_left) / (f_center - f_left)

    for k in range(f_center, f_right):
        if f_right != f_center:
            filters[m - 1, k] = (f_right - k) / (f_right - f_center)

# 濾波器加權與能量計算
filter_energy = filters @ power_X
filter_energy = np.where(filter_energy == 0, np.finfo(float).eps, filter_energy) # 避免 log(0)
log_energy = np.log(filter_energy)          # Y[m]

# 離散餘弦轉換 (DCT) 取得 MFCC
mfcc = dct(log_energy, type=2, norm="ortho")[:n_ceps]
```