result=librosa.feature.mfcc(signal, 16000, n_mfcc=13, n_fft=2048, hop_length=400)
result.shape()
信号长 1 秒,采样率为 16000,我计算出 13 MFCC,跳数为 400。输出尺寸为(13,41)
。为什么我得到 41 帧,不是应该是 (time*sr/hop_length)=40
吗?
最佳答案
TL;DR 答案
是的,这是正确的。
长答案
您使用时间序列作为输入(信号
),这意味着librosa首先使用 melspectrogram 函数计算梅尔频谱图。它需要一堆参数,其中您已经指定了一个 (n_fft
)。需要注意的是,melspectrogram 还提供了两个参数 center
和 pad_mode
,默认值为 True
和 "reflect"
分别。
来自文档:
pad_mode: string: If center=True, the padding mode to use at the edges of the signal. By default, STFT uses reflection padding.
center: boolean: If True, the signal y is padded so that frame t is centered at y[t * hop_length]. If False, then frame t begins at y[t * hop_length]
换句话说,默认情况下,librosa 会使信号更长(垫)以支持居中。
如果您想避免这种行为,您应该将 center=False
传递给您的 mfcc
调用。
总而言之,将 center
设置为 False
时,请记住 n_fft
长度为 2048,跃点长度为 400
,您不一定会得到 (time*sr/hop_length)=40
帧,因为您还必须考虑窗口而不是只是跳跃长度(除非你以某种方式填充)。跳跃长度仅指定您移动该窗口的样本数量。
举一个极端的例子,考虑一个非常大的窗口和非常短的跳变长度:假设 10 个样本(例如 time=1s
、sr=10Hz
),窗口长度为 n_fft=9
和 hop_length=1
且 center=False
。现在想象一下在 10 个样本上滑动窗口。
◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◻︎
◻︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎◼︎
t 0123456789
◻︎ sample not covered by window
◼︎ sample covered by window
首先,窗口从 t=0
开始,到 t=8
结束。我们可以将其移动 hop_length
多少次,并且仍然期望它不会用完样本?恰好一次,直到从 t=1
开始并于 t=9
结束。添加第一个未移动的帧,您将得到 2 帧。这与错误的 (time*sr/hop_length)=1*10/1=10
明显不同。
正确的是:(time*sr-n_fft)//hop_length+1=(1*10-9)//1+1=2
和 //
表示 Python 风格的整数除法。
使用默认值(即 center=True
)时,信号两端都会填充 n_fft//2
个样本,因此 n_fft
不属于这个等式。
关于python - 我的 librosa MFCC 输出正确吗?我认为使用 librosa MFCC 时得到的帧数错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68214065/