librosa y-axis spectrogram does not align properly

209 views Asked by At

How to align axis of spectrogram visualisations in Librosa or Matplotlib ?

Consider this example, from Librosa's documentation: enter image description here

as you can see, the rolloff are aligned with the spectrogram. I can't replicate the figure with my own audio.

The y-axis is never aligned.

Try:

sr = 250000
n_fft = 2048
hop_length=256
win_length = 1024
fmin = 220


S, phase = librosa.magphase(librosa.stft(filtered_audio))

sftf_spec = librosa.stft(filtered_audio, n_fft=n_fft, hop_length=hop_length)

S = np.abs(sftf_spec)

rolloff = librosa.feature.spectral_rolloff(S=S, 
                                           sr=sr, 
                                           n_fft=n_fft, 
                                           hop_length=hop_length, 
                                           win_length = win_length 
                                          )

amplitude_spec = librosa.amplitude_to_db(S, 
                                        
                                     
                                        ref=np.max)

rolloff_min = librosa.feature.spectral_rolloff(S=S, sr=sr, roll_percent=0.15)

fig, ax = plt.subplots()

librosa.display.specshow(amplitude_spec,

                         y_axis='log', x_axis='time', ax=ax)

ax.plot(librosa.times_like(rolloff), rolloff[0], label='Roll-off frequency (0.85)')

ax.plot(librosa.times_like(rolloff), rolloff_min[0], color='w',

        label='Roll-off frequency (0.15)')

ax.legend(loc='lower right')

ax.set(title='log Power spectrogram')

If you need to replicate, you can try download the audio wav :

https://drive.google.com/file/d/1UCUWAaczzejTN9m_y-usjPbG8__1mWI1/view?usp=sharing
filtered_audio  = np.array([[  #copy ]])

I got this:

enter image description here

and if I set the rate in specshow, I got this:

librosa.display.specshow(amplitude_spec,
                         sr=sr,

                         y_axis='log', x_axis='time', ax=ax)

enter image description here

I want to have the bandwidth following the same scale of the spectrogram they were build from...

1

There are 1 answers

2
Jon Nordby On BEST ANSWER

One has to be diligent in passing all the relevant parameters. In your code, both the call to specshow, times_like, and spectral_rolloff were missing key arguments like sr, hop_length et.c. Without these, both the X and Y axis will typically be off.

When ensuring this, the results look to be correct. See complete code below.

enter image description here

import librosa
import numpy as np
import pandas

from matplotlib import pyplot as plt
import librosa.display



def plot_spectral(audio, sr, hop_length=256, win_length=1024, n_fft=2048):

    # shared parameters
    spec_params = dict(n_fft=n_fft, hop_length=hop_length, win_length=win_length)

    # compute
    sftf_spec = librosa.stft(audio, **spec_params)
    S = np.abs(sftf_spec)
    amplitude_spec = librosa.amplitude_to_db(S, ref=np.max)

    up = librosa.feature.spectral_rolloff(S=S, sr=sr, **spec_params, roll_percent=0.85)
    
    rolloff = pandas.DataFrame({
        'upper': librosa.feature.spectral_rolloff(S=S, sr=sr, **spec_params, roll_percent=0.85)[0, :],
        'lower': librosa.feature.spectral_rolloff(S=S, sr=sr, **spec_params, roll_percent=0.15)[0, :],
    })
    rolloff['time'] = librosa.times_like(rolloff['lower'], sr=sr, hop_length=hop_length)

    fig, ax = plt.subplots()

    librosa.display.specshow(amplitude_spec, sr=sr, **spec_params,
                             y_axis='log', x_axis='time', ax=ax, )

    ax.plot(rolloff['time'], rolloff['upper'], color='blue', label='Roll-off frequency (0.85)')

    ax.plot(rolloff['time'], rolloff['lower'], color='white', label='Roll-off frequency (0.15)')

    ax.legend(loc='lower right')

    ax.set(title='log Power spectrogram')

    fig.savefig('spectral-rolloffs.png')


def load_data():
    p = 'test_wav_segment.wav'
    audio, sr = librosa.load(p, sr=None)
    return audio, sr

audio, sr = load_data()


plot_spectral(audio, sr=sr)

The use of Pandas is not critical. However it keeps the related data together, and ensures that the times array is equal length to the rolloffs which they are fo.