为什么我的8kHz wav文件的mel特征在sr = 16kHz和44.1kHz下提取出来的结果不同?

2024-04-19 23:49:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在从我的婴儿哭声数据集提取mel特征,wav文件的采样率是8kHz,16位,单声道和大约7秒。在

sr=16000时的Mel spectrogramsr=44100时的Mel spectrogram

但正如您所见,每当我以不同的采样率提取特征sr,mel谱图的值就会改变。 我想既然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()  

y轴的值必须相同,无论sr = 4410016000 但我不明白为什么会这样。在


Tags: 文件importinputtrainplt特征framelength
1条回答
网友
1楼 · 发布于 2024-04-19 23:49:01

当您要求librosa创建mel谱图时,您要求它执行两个步骤:

基于傅里叶变换的频谱

首先,你要求它在可能的范围内创建一个基于FFT的频谱图。要理解可能的范围是什么,您必须理解Nyquist-Shannon theorem,它(大致)说明当您在sr赫兹采样信号时,您不能表示超过sr/2hz(sr=采样率)的频率。所以44.1kHz采样信号的可能频率范围是0到22.05kHz。在

librosa产生一个规则的线性间隔谱图作为中间结果。频率范围为0至sr/2 Hz。在

Mel谱图

与常规的基于FT的谱图相反,mel谱图没有线性频率标度,而是(几乎)对数标度。为了将基于FT的谱图映射到对数标度,所有可用的数据都映射到特定数量的对数间隔的容器中。使用的存储单元数指定为n_mels,即mel波段的数量。在

把它放在一起

所以对于n_mels = 128,如果你有一个以44.1kHz采样的信号,你可以代表0到22.05Hz的范围。这个范围被映射到128个对数间隔的频带上。如果您的信号采样频率为16 kHz,则可以表示0到8 Hz的范围。这个范围被映射到128个对数间隔的频带上,即0-8khz的范围被分成128个部分,而不是0-22.05khz的范围。这必然导致不同的结果。在

解决方案

如果要确保映射到n_melsmel波段的频率范围始终相同,而不考虑采样率,则必须指定关键字参数fmin和{}(请参见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)            

相关问题 更多 >