librosa.f0_harmonics(x, *, f0, freqs, harmonics, kind='linear', fill_value=0, axis=-2)[source]

Compute the energy at selected harmonics of a time-varying fundamental frequency.

This function can be used to reduce a frequency * time representation to a harmonic * time representation, effectively normalizing out for the fundamental frequency. The result can be used as a representation of timbre when f0 corresponds to pitch, or as a representation of rhythm when f0 corresponds to tempo.

This function differs from interp_harmonics, which computes the harmonics of all frequencies.

xnp.ndarray [shape=(…, frequencies, n)]

The input array (e.g., STFT magnitudes)

f0np.ndarray [shape=(…, n)]

The fundamental frequency (f0) of each frame in the input Shape should match x.shape[-1]

freqsnp.ndarray, shape=(x.shape[axis]) or shape=x.shape

The frequency values corresponding to X’s elements along the chosen axis. Frequencies can also be time-varying, e.g. as computed by reassigned_spectrogram, in which case the shape should match x.

harmonicslist-like, non-negative

Harmonics to compute as harmonics[i] * f0 Values less than one (e.g., 1/2) correspond to sub-harmonics.


Interpolation type. See scipy.interpolate.interp1d.


The value to fill when extrapolating beyond the observed frequency range.


The axis corresponding to frequency in x

f0_harmnp.ndarray [shape=(…, len(harmonics), n)]

Interpolated energy at each specified harmonic of the fundamental frequency for each time step.


This example estimates the fundamental (f0), and then extracts the first 12 harmonics

>>> y, sr = librosa.load(librosa.ex('trumpet'))
>>> f0, voicing, voicing_p = librosa.pyin(y=y, sr=sr, fmin=200, fmax=700)
>>> S = np.abs(librosa.stft(y))
>>> freqs = librosa.fft_frequencies(sr=sr)
>>> harmonics = np.arange(1, 13)
>>> f0_harm = librosa.f0_harmonics(S, freqs=freqs, f0=f0, harmonics=harmonics)
>>> import matplotlib.pyplot as plt
>>> fig, ax =plt.subplots(nrows=2, sharex=True)
>>> librosa.display.specshow(librosa.amplitude_to_db(S, ref=np.max),
...                          x_axis='time', y_axis='log', ax=ax[0])
>>> times = librosa.times_like(f0)
>>> for h in harmonics:
...     ax[0].plot(times, h * f0, label=f"{h}*f0")
>>> ax[0].legend(ncols=4, loc='lower right')
>>> ax[0].label_outer()
>>> librosa.display.specshow(librosa.amplitude_to_db(f0_harm, ref=np.max),
...                          x_axis='time', ax=ax[1])
>>> ax[1].set_yticks(harmonics-1)
>>> ax[1].set_yticklabels(harmonics)
>>> ax[1].set(ylabel='Harmonics')