为什么 `scipy.signal.stft()` 中的样本频率数与跳跃大小有关?

Why is the number of sample frequencies in `scipy.signal.stft()` tied to the hop size?

此问题涉及 SciPy's Short-time Fourier Transform 信号处理函数。

出于某种原因我不明白,输出的大小 'array of sample frequencies' 正好等于跃点大小。来自文档:

nperseg : int, optional

    Length of each segment. Defaults to 256.

noverlap : int, optional

    Number of points to overlap between segments. If None, noverlap = nperseg // 2. Defaults to None. When specified, the COLA constraint must be met (see Notes below).


f : ndarray

    Array of sample frequencies.

hop size H = nperseg - noverlap

我是信号处理和傅里叶变换的新手,但据我了解,STFT 只是将音频文件切成片段 ('time frames'),您可以在这些片段上执行傅里叶变换。因此,如果我想在 100 个时间范围内进行 STFT,我希望输出是一个大小为 100 x F 的矩阵,其中 F 是一组测量频率('measured' 可能不是正确的词在这里,但你知道我的意思)。

这有点像 SciPy 的实现,但是 f 的大小让我很困扰。它应该是一个描述不同频率的数组,如 [0Hz 500Hz 1000Hz],确实如此,但由于某些原因,它的大小与跳跃大小完全相同。如果跳数为700,则测量的频率数为700。

跳跃大小是每个时间帧之间的样本数(即时间),正确计算为H = nperseg - noverlap,但这与频率数组有什么关系?


编辑:与 this question

有关

FFT 是从一个正交基到另一个相同维数的方阵变换。这是因为 N 是适合长度为 N 的时域矢量的正交(例如,不相互干扰)复正弦波的确切数量。

更长的时间向量可以包含更多的频率信息(例如,仅使用 3 个样本点很难区分 2 个频率,但使用 3000 个样本就容易得多,等等)

您可以对长度为 N 的短时间向量进行零填充以使用更长的 FFT,但这等同于在 N 个频率点之间插入一条漂亮的曲线,这使得所有 FFT 结果相互依赖。

对于许多目的(可视化等),STFT 是重叠的,其中相邻的段共享一些重叠的数据,而不仅仅是端到端的。这提供了更好的时间局部性(例如,段可以间隔得更近但仍然足够长,以便每个段都可以提供所需的频率分辨率)。