FFT Либроса и Scfty разные? - PullRequest
0 голосов
/ 24 мая 2019

У 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.

1 Ответ

1 голос
/ 24 мая 2019

Причиной этого является аргумент center для stft librosa. По умолчанию это True (вместе с pad_mode = 'reflect').

Из документов:

librosa.core.stft (y, n_fft = 2048, hop_length = None, win_length = None, window = 'hann', center = True, dtype =, pad_mode = 'отражения')

центр: булево

Если True, сигнал y дополняется так, что кадр D [:, t] центрируется по y [t * hop_length].

Если False, то D [:, t] начинается с y [t * hop_length]

pad_mode: строка

Если center = True, режим заполнения используется по краям сигнала. По умолчанию STFT использует отступ отражения.

Вызов STFT таким образом

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

ведет к прямой линии:

librosa.stft with center = False

Обратите внимание, что stft librosa также использует оконную функцию Hann по умолчанию. Если вы хотите избежать этого и сделать его более похожим на вашу реализацию Scipy stft, вызывайте 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

Вы заметите, что линия тоньше.

...