Librosa的fft和Scipy的fft有所不同吗?

7

Librosa和Scipy都有fft函数,然而,即使使用相同的信号输入,它们给出了不同的频谱图输出。

Scipy

我正在尝试使用以下代码获取频谱图:

import numpy as np                                       # fast vectors and matrices
import matplotlib.pyplot as plt                          # plotting
from scipy import fft      

X = np.sin(np.linspace(0,1e10,5*44100))

fs = 44100          # assumed sample frequency in Hz
window_size = 2048  # 2048-sample fourier windows
stride = 512        # 512 samples between windows
wps = fs/float(512) # ~86 windows/second
Xs = np.empty([int(2*wps),2048])

for i in range(Xs.shape[0]):
    Xs[i] = np.abs(fft(X[i*stride:i*stride+window_size]))

fig = plt.figure(figsize=(20,7))
plt.imshow(Xs.T[0:150],aspect='auto')
plt.gca().invert_yaxis()
fig.axes[0].set_xlabel('windows (~86Hz)')
fig.axes[0].set_ylabel('frequency')
plt.show()

然后我得到了以下的频谱图enter image description here

Librosa

现在我尝试使用Librosa获得相同的频谱图

from librosa import stft

X_libs = stft(X, n_fft=window_size, hop_length=stride)
X_libs = np.abs(X_libs)[:,:int(2*wps)]

fig = plt.figure(figsize=(20,7))
plt.imshow(X_libs[0:150],aspect='auto')
plt.gca().invert_yaxis()
fig.axes[0].set_xlabel('windows (~86Hz)')
fig.axes[0].set_ylabel('frequency')
plt.show()

enter image description here

问题

这两个频谱图明显不同,特别是Librosa版本在开头有一个攻击。是什么导致了这种差异?我在Scipy和Librosa的文档中没有看到我可以调整的参数。


3
你正在使用librosa中的STFT而不是FFT。它们有所区别,因为STFT通常包括窗口函数和填充。请参见我的下面的回答。 - Hendrik
1个回答

12
这是由于librosa的stft参数center的设置。默认情况下,它是True(与pad_mode = 'reflect'一起)。
从文档中可以看到:

librosa.core.stft(y, n_fft=2048, hop_length=None, win_length=None, window='hann', center=True, dtype=, pad_mode='reflect')

center:boolean

如果为True,则信号y将被填充,以便帧D [:,t]位于y [t * hop_length]的中心。

如果为False,则D [:,t]从y [t * hop_length]开始

pad_mode:string

如果center=True,则在信号边缘使用的填充模式。默认情况下,STFT使用反射填充。

像这样调用STFT:
X_libs = stft(X, n_fft=window_size, hop_length=stride,
              center=False)

确实会导致一条直线:

librosa.stft with center = False

请注意,librosa的stft默认也使用Hann窗函数。如果您想避免这种情况并使其更像Scipy的stft实现,请使用仅由ones组成的窗口调用stft:
X_libs = stft(X, n_fft=window_size, hop_length=stride,
              window=np.ones(window_size),
              center=False)

librosa.stft with center = False and no window function

你会注意到这条线更细了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接