我想对我的数据执行短时傅立叶变换,并为每个片段指定特定的样本长度。我想使用信号子模块中的SciPy函数stft。但是,当我通过以下方式创建长度为10e5的音频数组时:

fs = 10e3 # Sampling frequency
N = 1e5 # Number of samples
time = np.arange(N) / fs
x = 500*np.cos(time) # Some random audio wave
# x.shape gives (100000,)


并与stft一起应用SciPy nperseg=1000函数,我没有得到预期的100个细分。相反,输出的形状为:

f, t, Zxx = signal.stft(x, fs, nperseg=1000)
print(Zxx.shape) # -> (501, 201)


如果我正确理解了文档,那么501是“频率篮子”的数量,而20001是不同时间段的数量,我本来打算将其设为N / nperseg或10e5 / 1000 =100。我确实看到该函数具有一些参数指定填充和重叠,但是如果Nnperseg整除,那么它究竟能做什么?

最佳答案

当我运行您的代码段时:

In [1]: import numpy as np

In [2]: import scipy.signal as signal

In [3]: fs = 10e3 # Sampling frequency
   ...: N = 1e5 # Number of samples
   ...: time = np.arange(N) / fs
   ...: x = 500*np.cos(time) # Some random audio wave
   ...:

In [4]: f, t, Zxx = signal.stft(x, fs, nperseg=1000)
   ...: print(Zxx.shape) # -> (501, 20001)
   ...:
(501, 201)


我看到Zxx的输出是501 x 201。

如您所说,501是频点的数量(在纯FFT之后,每段1000个时间频点变为501频点;如果需要完整的复数FFT,则可以传入return_onesided=False)。

201是由于npersegnoverlap的组合。 docsnoverlap是“段之间重叠的点数。如果是Nonenoverlap = nperseg // 2。”因此,STFT不会将1e5 / 1e3 = 1e2划分为“段”,而是将1e3长的段重叠500个样本(半个段),因此最终会有200个以上的重叠段。

要获得所需的内容,请说noverlap=0

In [7]: f, t, Zxx = signal.stft(x, fs, nperseg=1000, noverlap=0)

In [8]: Zxx.shape
Out[8]: (501, 101)


我不太确定为什么它返回101个细分而不是100个……

关于python - 使用SciPy stft函数指定片段中用于短时傅立叶变换的样本数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45100189/

10-09 03:04