0
$\begingroup$

I have come across 2 different ways of generating log-mel spectrograms for audio files using librosa and I don't know why they differ in the final output, which one is "correct" or how different is one from the other.

#1

path = "path/to/my/file"
scale, sr = librosa.load(path)
mel_spectrogram = librosa.feature.melspectrogram(scale, sr, n_fft=2048, hop_length=512, n_mels=10, fmax=8000)
log_mel_spectrogram = librosa.power_to_db(mel_spectrogram)
librosa.display.specshow(log_mel_spectrogram, x_axis="time", y_axis="mel", sr=sr)

#2

path = "path/to/my/file"
scale, sr = librosa.load(path)
X = librosa.stft(scale)
Xdb = librosa.amplitude_to_db(abs(X))
librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='hz')

The respective images are:

#1#2

** EDIT ** Now that I specify the number of mel bins to be = 64, I obtain the spectrogram as below:

enter image description here

If I want to process many such spectrograms, should I trim off the bold blue portion above as it is common to all? What does the bold, dark region represent? Is it advisable to use fmax parameter to trim it?

$\endgroup$
0
$\begingroup$

The mel spectrogram additionally includes a step of projecting (power of) STFT bins onto Mel-frequency bins via a Mel filterbank; I don't have access to path so I made demo on exponential chirp:

enter image description here

You can visualize the kind of projection taking place by plotting the mel basis:

enter image description here

Note in general the two won't look alike unless filters.mel are carefully selected (nor do they have to).


Code

import numpy as np
import librosa
import librosa.display
import matplotlib.pyplot as plt

def echirp(N, fmin=.1, fmax=None, tmin=0, tmax=1):
    """https://overlordgolddragon.github.io/test-signals/ (bottom)"""
    fmax = fmax or N // 2
    t = np.linspace(tmin, tmax, N)

    a = (fmin**tmax / fmax**tmin) ** (1/(tmax - tmin))
    b = fmax**(1/tmax) * (1/a)**(1/tmax)

    phi = 2*np.pi * (a/np.log(b)) * (b**t - b**tmin)
    return np.cos(phi)

#%%
N = 2**16
n_fft, hop_length, n_mels, sr = 2048, 512, 128, 16384
x = echirp(N)

#%%
mel_spectrogram = librosa.feature.melspectrogram(
    x, sr, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels)
log_mel_spectrogram = librosa.power_to_db(mel_spectrogram)
librosa.display.specshow(log_mel_spectrogram, x_axis="time", y_axis="mel", sr=sr)
plt.show()

#%%
X = librosa.stft(x, hop_length=hop_length)
mel_basis = librosa.filters.mel(sr, n_fft, n_mels=n_mels)
Xmel = np.dot(mel_basis, abs(X)**2)
Xdb = librosa.power_to_db(Xmel)
librosa.display.specshow(Xdb, x_axis='time', y_axis='hz', sr=sr)
plt.show()

#%%
mel_basis = librosa.filters.mel(sr, n_fft, n_mels=10)
plt.plot(mel_basis.T, color='tab:blue')
kw = dict(weight='bold', fontsize=16, loc='left')
plt.title("n_mels=10", **kw)
plt.show()

mel_basis = librosa.filters.mel(sr, n_fft, n_mels=n_mels)
plt.plot(mel_basis.T, color='tab:blue')
kw = dict(weight='bold', fontsize=16, loc='left')
plt.title("n_mels=%s" % n_mels, **kw)
plt.show()
$\endgroup$
7
  • $\begingroup$ Thanks. Could you answer my edit to the question above? $\endgroup$ May 9 at 12:48
  • $\begingroup$ @VITTHALBHANDARI Yes, trim with fmax - also set it for specshow to adjust y-axis. $\endgroup$ May 9 at 12:55
  • $\begingroup$ Thank you so much $\endgroup$ May 9 at 14:23
  • $\begingroup$ If my original audio was sampled at 8k Hz, can I set fmax=4k Hz (using nyquist's theorem)? It does omit almost all of the bold blue space. $\endgroup$ May 9 at 14:27
  • $\begingroup$ Also, will upsampling the audio to 22050Hz (say), something which librosa does by default, change my audio in a way that will affect my machine learning algorithm's output? $\endgroup$ May 9 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.