sladekm
sladekm

Reputation: 47

Why does librosa STFT show wrong frequencies?

I generated a 200 Hz sine wave using numpy and then used librosas stft() and specshow() functions to show a spectrogram. However, the frequency it is showing is not 200 Hz. When I use matplotlibs magnitude_spectrum() function, it shows exactly 200 Hz. Does anyone know why that might be? Am I doing something wrong? Any help will be much appriciated.

The results from librosas spectrogram and matplotlibs frequency spectrum can be seen in the image below.

Minimal working example:

import matplotlib.pyplot as plt
from matplotlib import mlab
%matplotlib inline
import numpy as np
import librosa
import librosa.display

sr = 20000
freq1 = 200
n_fft=2000

x = np.linspace(0, 1, sr)
y = 0.5*np.sin(freq1 * 2 * np.pi * x)
no_window = np.linspace(1, 1, n_fft)
D = np.abs(librosa.stft(y, n_fft=n_fft, hop_length=int(n_fft/2), window=no_window, center=False,))

plt.figure(figsize=(9, 4))

librosa.display.specshow(D, y_axis='linear')

plt.xlabel('Time [s]')
plt.ylabel('Frequency [Hz]')
plt.ylim(0, 250)
plt.tight_layout()
plt.show()

plt.figure(figsize=(9, 4))

plt.magnitude_spectrum(y, Fs=sr, color='C1', window=mlab.window_none)
plt.xlim(0, 250)
plt.xlabel('Frequency [Hz]')
plt.ylabel('Amplitude [-]')
plt.tight_layout()
plt.show()

Librosas spectrogram vs Matplotlibs frequency spectrum

Upvotes: 1

Views: 1420

Answers (1)

Hendrik
Hendrik

Reputation: 5310

Just passing the results to specshow is not enough. You also need to tell it what scale these results are on. You do this be passing the sample rate parameter sr like this:

librosa.display.specshow(D, y_axis='linear', sr=sr)

If you don't, it defaults to sr=22050, hop_length=512, which is certainly not correct in your case.

This is similar to the answer given here.

Upvotes: 4

Related Questions