Librosa 的 fft 和 Scipy 的 fft 不一样?
Librosa's fft and Scipy's fft are different?
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()
然后我得到下面的频谱图
图书馆
现在我尝试用 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()
问题
两者的频谱图明显不同,具体来说,Librosa版本在一开始就有攻击。
造成差异的原因是什么?我在 Scipy 和 Librosa.
的文档中看不到很多可以调整的参数
原因是 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
If True, the signal y is padded so that frame D[:, t] is centered at y[t * hop_length].
If False, then D[:, t] begins at y[t * hop_length]
pad_mode:string
If center=True, the padding mode to use at the edges of the signal. By default, STFT uses reflection padding.
像这样调用 STFT
X_libs = stft(X, n_fft=window_size, hop_length=stride,
center=False)
确实导致一条直线:
请注意,librosa 的 stft 默认也使用 Hann window function。如果您想避免这种情况并使其更像您的 Scipy stft 实现,请使用仅包含一个的 window 调用 stft:
X_libs = stft(X, n_fft=window_size, hop_length=stride,
window=np.ones(window_size),
center=False)
您会注意到线条变细了。
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()
然后我得到下面的频谱图
图书馆
现在我尝试用 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()
问题
两者的频谱图明显不同,具体来说,Librosa版本在一开始就有攻击。 造成差异的原因是什么?我在 Scipy 和 Librosa.
的文档中看不到很多可以调整的参数原因是 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
If True, the signal y is padded so that frame D[:, t] is centered at y[t * hop_length].
If False, then D[:, t] begins at y[t * hop_length]
pad_mode:string
If center=True, the padding mode to use at the edges of the signal. By default, STFT uses reflection padding.
像这样调用 STFT
X_libs = stft(X, n_fft=window_size, hop_length=stride,
center=False)
确实导致一条直线:
请注意,librosa 的 stft 默认也使用 Hann window function。如果您想避免这种情况并使其更像您的 Scipy stft 实现,请使用仅包含一个的 window 调用 stft:
X_libs = stft(X, n_fft=window_size, hop_length=stride,
window=np.ones(window_size),
center=False)
您会注意到线条变细了。