简体   繁体   中英

Librosa's fft and Scipy's fft are different?

Both Librosa and Scipy have the fft function, however, they give me a different spectrogram output even with the same signal input.

Scipy

I am trying to get the spectrogram with the following code

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()

Then I get the following spectrogram 在此处输入图片说明

Librosa

Now I try to get the same spectrogram with 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()

在此处输入图片说明

Question

The two spectrogram are obviously different, specifically, the Librosa version has an attack at the very beginning. What causes the difference? I don't see many parameters that I can tune in the documentation for Scipy and Librosa.

The reason for this is the argument center for librosa's stft . By default it's True (along with pad_mode = 'reflect' ).

From the docs:

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.

Calling the STFT like this

X_libs = stft(X, n_fft=window_size, hop_length=stride,
              center=False)

does lead to a straight line:

librosa.stft,中心= False

Note that librosa's stft also uses the Hann window function by default. If you want to avoid this and make it more like your Scipy stft implementation, call the stft with a window consisting only of ones:

X_libs = stft(X, n_fft=window_size, hop_length=stride,
              window=np.ones(window_size),
              center=False)

librosa.stft,center = False,没有窗口函数

You'll notice that the line is thinner.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM