梅尔频谱和梅尔倒谱系数:音频信号处理的关键特征
梅尔频谱和梅尔倒谱系数:音频信号处理的关键特征
在音频信号处理领域,梅尔频谱和梅尔倒谱系数(MFCCs)是两种重要的特征表示,广泛应用于语音识别、音乐分析和音频分类等任务。本文将介绍梅尔频谱和 MFCCs 的概念、计算方法及其意义,并给出完整的代码示例和可视化。
1. 概念介绍与意义
1.1 短时傅里叶变换(STFT)
短时傅里叶变换(STFT)用于将信号转换到频域,揭示信号在不同频率上的能量分布。STFT 频谱能够帮助我们理解信号的频率成分。
计算公式 :
$$
X[k, m] = \sum_{n=0}^{N-1} x[n] \cdot w[n - mR] \cdot e^{-j\frac{2\pi}{N}kn}
$$
其中,$w[n]$ 是窗函数,$R$ 是重叠步长,$N$ 是窗长度。
1.2 梅尔频谱
梅尔频谱是将音频信号的频谱转换为梅尔尺度,旨在模拟人耳对频率的感知特性。梅尔尺度是一种非线性频率尺度,基于人耳对频率变化的敏感度,特别是在低频段的感知能力更强。梅尔频谱通过应用梅尔滤波器组来计算,能够有效捕捉音频信号的频率分布。
梅尔尺度的定义
梅尔尺度的设计是为了更好地反映人耳对不同频率的感知。梅尔频率($f_m$)与线性频率($f$)之间的关系可以通过以下公式表示:
$$
f_m = 2595 \cdot \log_{10}(1 + \frac{f}{700})
$$
这个公式表明,梅尔频率是通过对线性频率进行非线性变换得到的。人耳在低频段的分辨率较高,而在高频段的分辨率较低,因此梅尔尺度在低频段的分布更密集。
梅尔滤波器组
梅尔频谱的计算依赖于梅尔滤波器组。梅尔滤波器组通常由一组重叠的三角形滤波器组成,这些滤波器的中心频率均匀分布在梅尔尺度上。每个滤波器的带宽和形状旨在模拟人耳对音频信号的响应。
计算公式 :
$$
M[m] = \sum_{k} H_m(f_k) \cdot |X[k]|^2
$$
在这个公式中:
- $M[m]$ 表示梅尔频谱在第 $m$ 个梅尔频率上的能量值。
- $H_m(f_k)$ 是第 $m$ 个梅尔滤波器在频率 $f_k$ 的响应,表示该频率对梅尔频谱的贡献。每个滤波器的响应通常是三角形的,且在梅尔尺度上均匀分布。
- $|X[k]|^2$ 是频谱的能量,表示在频率 $f_k$ 上的信号能量。
1.3 梅尔倒谱系数(MFCCs)
MFCCs 是从梅尔频谱中提取的特征,能够有效表示音频信号的主要特征,广泛用于语音识别和音频分析。MFCCs 通过对对数梅尔频谱进行离散余弦变换(DCT)计算得到。
计算公式 :
$$
L[m] = \log(M[m])
$$
$$
C[n] = \sum_{m=0}^{M-1} L[m] \cdot \cos\left(\frac{\pi n}{M} \left(m + \frac{1}{2}\right)\right)
$$
其中,$L[m]$ 是对数梅尔频谱,$C[n]$ 是第 $n$ 个 MFCC。
2. 代码示例
下面的代码示例展示了如何从音频信号计算 STFT 频谱、梅尔频谱和 MFCCs,并进行可视化。
import numpy as np
import matplotlib.pyplot as plt
import librosa
import librosa.display
# 生成示例信号(白噪声)
sample_rate = 22050 # 采样率
duration = 2.0 # 持续时间(秒)
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False) # 时间轴
# 生成白噪声信号
signal = np.random.randn(len(t)) # 生成随机信号(白噪声)
# 计算短时傅里叶变换(STFT)
n_fft = 2048 # FFT 点数
hop_length = 512 # 每次移动的样本数
stft = librosa.stft(signal, n_fft=n_fft, hop_length=hop_length)
spectrum = np.abs(stft) # 频谱取绝对值
# 计算梅尔频谱
mel_spectrogram = librosa.feature.melspectrogram(y=signal, sr=sample_rate, n_fft=n_fft, hop_length=hop_length, n_mels=128)
mel_spectrogram_db = librosa.power_to_db(mel_spectrogram, ref=np.max) # 转换为对数刻度
# 计算梅尔倒谱系数(MFCCs)
mfccs = librosa.feature.mfcc(y=signal, sr=sample_rate, n_mfcc=13)
# 创建一个包含所有可视化的图形
plt.figure(figsize=(12, 12))
# 原始信号
plt.subplot(4, 1, 1)
plt.plot(t, signal)
plt.title('Original Signal (White Noise)')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid()
# STFT 频谱
plt.subplot(4, 1, 2)
plt.imshow(spectrum, aspect='auto', origin='lower',
extent=[0, duration, 0, sample_rate / 2])
plt.title('Frequency Spectrum (STFT)')
plt.xlabel('Time (s)')
plt.ylabel('Frequency (Hz)')
plt.colorbar(format='%+2.0f dB')
plt.grid()
# 梅尔频谱
plt.subplot(4, 1, 3)
librosa.display.specshow(mel_spectrogram_db, sr=sample_rate, x_axis='time', y_axis='mel', hop_length=hop_length, fmax=8000)
plt.colorbar(format='%+2.0f dB')
plt.title('Mel Spectrogram')
plt.grid()
# MFCCs
plt.subplot(4, 1, 4)
librosa.display.specshow(mfccs, sr=sample_rate, x_axis='time')
plt.title('MFCCs')
plt.colorbar()
plt.grid()
plt.tight_layout()
plt.show()
3. 数据维度
- 原始信号的维度 :
- 输出 :
signal.shape
输出为(44100,)
- 解释 :
- 该维度表示信号的样本点数量。
- 这里的样本总数为 $(22050 , \text{Hz} \times 2 , \text{秒} = 44100)$ 。
- 这意味着信号持续时间为 2 秒,采样率为 22050 Hz。
- 频谱的维度 :
- 输出 :
spectrum.shape
输出为(1025, 86)
- 解释 :
- 1025 是通过设置
n_fft=2048
得到的频率 bins 数量(FFT 点数的一半加一)。 - 86 是时间帧数,取决于信号长度和
hop_length
的设置。 - 该维度表示在每个时间帧上,信号在不同频率上的能量分布。
- 梅尔频谱的维度 :
- 输出 :
mel_spectrogram_db.shape
输出为(128, 86)
- 解释 :
- 128 表示梅尔滤波器的数量,这通常是基于人耳对频率的感知特性选择的。
- 86 是时间帧数,和频谱的时间帧数相同。
- 该维度表示在每个时间帧上,信号在梅尔尺度上的能量分布,能够有效捕捉音频信号的频率特征。
- 梅尔倒谱系数的维度 :
- 输出 :
mfccs.shape
输出为(13, 86)
- 解释 :
- 13 表示提取的 MFCC 特征数量,通常选择前 13 个系数以捕捉音频信号的主要特征。
- 86 是时间帧数,和梅尔频谱的时间帧数相同。
- 该维度表示每个时间帧上提取的音频特征,广泛应用于语音识别和音频分析。