使用SciPy stft函数指定用于短时傅立叶变换的段中的样本数

时间:2017-07-14 10:03:33

标签: python numpy scipy fft data-processing

我想对我的数据执行短时傅立叶变换,每个段的特定样本长度。我想使用信号子模块中的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,)

将{SciPy stft函数应用于nperseg=1000,我没有按预期获得100个细分。相反,输出的形状是:

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

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

2 个答案:

答案 0 :(得分:2)

当我运行您的代码段时:

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的输出是201乘以501。

正如你所说,501是频率仓的数量(每段1000个时间仓,在实际FFT之后变成501个频率仓;如果你想要完全复杂的FFT,你可以传入return_onesided=False

201是因为npersegnoverlap的组合。 docs表示noverlap是“段之间重叠的点数。如果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 ...

答案 1 :(得分:0)

signal.stft的默认窗口重叠率为50%,大致是段数的两倍。 在谷歌搜索“stft overlap”将帮助您了解有关此重叠的更多信息。