TL;DR 答案
是的,没错。
长答案
您正在使用时间序列作为输入 (signal),这意味着 librosa 首先使用 melspectrogram 函数计算梅尔频谱图。它需要一堆参数,其中您已经指定了一个 (n_fft)。需要注意的是melspectrogram还提供了center和pad_mode这两个参数,默认值分别为True和"reflect"。
来自文档:
pad_mode:字符串:
如果 center=True,则在信号边缘使用的填充模式。
默认情况下,STFT 使用反射填充。
中心:布尔值:
如果为 True,则填充信号 y,使帧 t 以 y[t * hop_length] 为中心。
如果为 False,则帧 t 开始于 y[t * hop_length]
换句话说,默认情况下,librosa 使您的信号更长(焊盘)以支持居中。
如果您想避免这种行为,您应该将center=False 传递给您的mfcc 调用。
话虽如此,当将center 设置为False 时,请记住,n_fft 长度为 2048 且跃点长度为400,不一定会得到(time*sr/hop_length)=40 帧,因为您还必须考虑 window 而不仅仅是 hop 长度(除非您以某种方式填充)。跳跃长度仅指定您移动该窗口的样本数。
举一个极端的例子,考虑一个非常大的窗口和一个非常短的跳跃长度:假设有 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不在等式中。