正弦波Mel尺度频谱图疑问:频率对应与条带位置解析
关于Mel频谱图的疑问
我生成了频率为100Hz的正弦波,通过计算FFT验证了频率的正确性。随后计算了melspectrogram,但无法理解其输出含义:
- 输出中何处能看到100Hz?
- 黄色条带为何位于第25区域?
- 若将频率改为200Hz,
melspectrogram的黄色条带为何位于第50区域?
测试代码
# In[4]: import numpy as np import matplotlib.pyplot as plt import scipy.fft import librosa def generate_sine_wave(freq, sample_rate, duration)-> tuple[np.ndarray, np.ndarray]: x = np.linspace(0, duration, int(sample_rate * duration), endpoint=False) frequencies = x * freq # 2pi because np.sin takes radians y = np.sin(2 * np.pi * frequencies) return x, y sample_rate = 1024 freq = 100 x, y = generate_sine_wave(freq, sample_rate, 2) plt.figure(figsize=(10, 4)) plt.plot(x, y) plt.grid(True) fft = scipy.fft.fft(y) fft = fft[0 : len(fft) // 2] fft = np.abs(fft) xs = np.linspace(0, sample_rate // 2, len(fft)) plt.figure(figsize=(15, 4)) plt.plot(xs, fft) plt.grid(True) melsp = librosa.feature.melspectrogram(sr=sample_rate, y=y) melsp = melsp.T plt.matshow(melsp) plt.title('melspectrogram') max = np.max(melsp) print('melsp.shape =', melsp.shape) print('melsp max =', max)
测试结果图
正弦波波形图
![正弦波波形图]
FFT频谱图
![FFT频谱图]
100Hz Mel频谱图
![100Hz Mel频谱图]
200Hz Mel频谱图
![200Hz Mel频谱图]
解答
1. 如何在Mel频谱图中定位100Hz?
Mel频谱图的*纵轴(默认未转置前的行)*对应Mel刻度,而非线性的Hz刻度。要找到100Hz的位置,你可以通过Librosa提供的工具将Hz转换为Mel频段:
# 获取默认Mel滤波器组的中心频率 mel_freqs = librosa.mel_frequencies(n_mels=128, fmin=0, fmax=sample_rate//2) # 查找最接近100Hz的频段索引 target_idx = np.argmin(np.abs(mel_freqs - 100)) print(f"100Hz对应的Mel频段索引: {target_idx}")
默认n_mels=128时,100Hz对应的就是第25个左右的频段(索引从0开始为24),也就是你图中黄色条带的位置。
2. 黄色条带位置的原因
黄色条带代表该频段能量峰值,对应正弦波频率所在的Mel频段:
- Mel刻度是非线性的,它模拟人耳感知特性:低频段Mel间隔对应更小的Hz范围,高频段则对应更大范围。但0-1000Hz区间内,Mel与Hz近似线性(转换公式:
mel = 2595 * log10(1 + hz/700)),因此100Hz对应第25区域,200Hz对应第50区域,呈现近似线性的对应关系。 - 你代码中执行了
melsp = melsp.T转置操作,将原本的Mel频段纵轴转为横轴,所以黄色条带的横轴位置就是对应频率的Mel频段索引。
额外说明
默认librosa.feature.melspectrogram输出形状为(n_mels, 时间帧数),转置后变为(时间帧数, n_mels),因此matshow画图时,横轴对应Mel频段,纵轴对应时间帧,能量最高的黄色条带自然落在目标频率对应的Mel频段位置。
内容的提问来源于stack exchange,提问作者codeDom
相关产品推荐
相关产品推荐

