为什么我的 8kHz wav 文件的 mel 特征在 sr = 16kHz 和 44.1kHz 中提取不同
why my 8kHz wav file's mel feature extracted differently in sr = 16kHz and 44.1kHz
我目前正在从婴儿哭声数据集中提取梅尔特征,wav 文件的采样率为 8kHz、16 位、单声道和大约 7 秒。
当 sr = 16000 时的梅尔频谱图
当 sr = 44100 时的梅尔频谱图
但如您所见,每当我以不同的采样率 sr
提取特征时,梅尔频谱图的值都会发生变化。
我想,因为wav文件的采样率是8kHz,如果我把采样率设置到16kHz以上,赫兹的值一定是一样的。
我将 wav 文件的采样率 8kHz 转换为 44.1kHz 并再次提取它,但没有任何变化。
这是我的代码:
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
sr = 44100 # or 16000
frame_length = 0.1
frame_stride = 0.01
path = '...'
train = []
j, sr = librosa.load(path + '001.wav', sr, duration = 5.0)
input_nfft = int(round(sr*frame_length))
input_stride = int(round(sr*frame_stride))
mel = librosa.feature.melspectrogram(j, n_mels = 128, n_fft = input_nfft, hop_length=input_stride, sr = sr)
train.append(mel)
plt.figure(figsize=(10,4))
librosa.display.specshow(librosa.power_to_db(train[0], ref=np.max), y_axis='mel', sr=sr, hop_length=input_stride, x_axis='time')
plt.colorbar(format='%+2.0f dB')
plt.title('Mel-Spectrogram')
plt.tight_layout()
plt.show()
无论sr = 44100
还是16000
,y轴的值必须相同
但我不明白为什么会这样。
当您要求 librosa 创建梅尔频谱图时,您要求它执行两个步骤:
傅立叶Transform-based光谱
首先,您要求它在可能的范围上创建一个FFT-based频谱图。要了解可能的范围是什么,您必须了解 Nyquist-Shannon theorem,它(粗略地)指出当您以 sr Hz 采样信号时,您不能表示超过 sr/2 Hz(sr = 采样率)的频率.因此,以 44.1kHz 采样的信号的可能频率范围是 0 到 22.05 kHz。
librosa 生成规则线性间隔的频谱图作为中间结果。频率范围是 0 到 sr/2 赫兹。
梅尔频谱图
与常规 FT-based 频谱图相反,梅尔频谱图没有线性频率标度,而是(几乎)对数标度。为了将 FT-based 频谱图映射到对数刻度,所有可用数据都映射到特定数量的对数间隔箱。使用的 bin 数指定为 n_mels
,即梅尔波段数。
放在一起
因此对于 n_mels = 128
,如果您有一个以 44.1kHz 采样的信号,您可以表示 0 到 22.05 Hz 的范围。该范围映射到 128 个对数间隔的波段。如果您的信号以 16 kHz 采样,您可以表示 0 到 8 Hz 的范围。该范围映射到 128 个对数间隔的频带,即 0-8 kHz 的范围被分成 128 个部分,而不是 0-22.05 kHz 的范围。这一定会导致不同的结果。
解决方案
如果要确保映射到n_mels
mel波段的频率范围始终相同,无论采样率如何,必须指定关键字参数fmin
和fmax
(参见 here)。
例如:
fmin = 0.
fmax = 4000. # since your original signal is sampled at 8 kHz
mel = librosa.feature.melspectrogram(j, n_mels=128,
n_fft=input_nfft,
hop_length=input_stride,
sr=sr,
fmin=fmin,
fmax=fmax)
我目前正在从婴儿哭声数据集中提取梅尔特征,wav 文件的采样率为 8kHz、16 位、单声道和大约 7 秒。
当 sr = 16000 时的梅尔频谱图
但如您所见,每当我以不同的采样率 sr
提取特征时,梅尔频谱图的值都会发生变化。
我想,因为wav文件的采样率是8kHz,如果我把采样率设置到16kHz以上,赫兹的值一定是一样的。
我将 wav 文件的采样率 8kHz 转换为 44.1kHz 并再次提取它,但没有任何变化。
这是我的代码:
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
sr = 44100 # or 16000
frame_length = 0.1
frame_stride = 0.01
path = '...'
train = []
j, sr = librosa.load(path + '001.wav', sr, duration = 5.0)
input_nfft = int(round(sr*frame_length))
input_stride = int(round(sr*frame_stride))
mel = librosa.feature.melspectrogram(j, n_mels = 128, n_fft = input_nfft, hop_length=input_stride, sr = sr)
train.append(mel)
plt.figure(figsize=(10,4))
librosa.display.specshow(librosa.power_to_db(train[0], ref=np.max), y_axis='mel', sr=sr, hop_length=input_stride, x_axis='time')
plt.colorbar(format='%+2.0f dB')
plt.title('Mel-Spectrogram')
plt.tight_layout()
plt.show()
无论sr = 44100
还是16000
,y轴的值必须相同
但我不明白为什么会这样。
当您要求 librosa 创建梅尔频谱图时,您要求它执行两个步骤:
傅立叶Transform-based光谱
首先,您要求它在可能的范围上创建一个FFT-based频谱图。要了解可能的范围是什么,您必须了解 Nyquist-Shannon theorem,它(粗略地)指出当您以 sr Hz 采样信号时,您不能表示超过 sr/2 Hz(sr = 采样率)的频率.因此,以 44.1kHz 采样的信号的可能频率范围是 0 到 22.05 kHz。
librosa 生成规则线性间隔的频谱图作为中间结果。频率范围是 0 到 sr/2 赫兹。
梅尔频谱图
与常规 FT-based 频谱图相反,梅尔频谱图没有线性频率标度,而是(几乎)对数标度。为了将 FT-based 频谱图映射到对数刻度,所有可用数据都映射到特定数量的对数间隔箱。使用的 bin 数指定为 n_mels
,即梅尔波段数。
放在一起
因此对于 n_mels = 128
,如果您有一个以 44.1kHz 采样的信号,您可以表示 0 到 22.05 Hz 的范围。该范围映射到 128 个对数间隔的波段。如果您的信号以 16 kHz 采样,您可以表示 0 到 8 Hz 的范围。该范围映射到 128 个对数间隔的频带,即 0-8 kHz 的范围被分成 128 个部分,而不是 0-22.05 kHz 的范围。这一定会导致不同的结果。
解决方案
如果要确保映射到n_mels
mel波段的频率范围始终相同,无论采样率如何,必须指定关键字参数fmin
和fmax
(参见 here)。
例如:
fmin = 0.
fmax = 4000. # since your original signal is sampled at 8 kHz
mel = librosa.feature.melspectrogram(j, n_mels=128,
n_fft=input_nfft,
hop_length=input_stride,
sr=sr,
fmin=fmin,
fmax=fmax)