0
$\begingroup$

I want to make a log-frequency spectrogram out of this audio. Later, I need this spectrogram for pitch sequence analysis.

This is a sample sequence I want to achieve:

[ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0 18 18 19 19 19 19 19 19 19 19 18  0  0  0  0 19 18 18 18 19
 19 19 19 19 19 19 20 20  0  0  0 25 26 26 26 26 26 26 26 26 25  0  0  0
  0  0 26 25 25 25 25 25 25 25 25 25 25 26 26 27 27 27 27 28 28 28 28 28
 28 28 28 28 27 26 27  0 28 28 28 28 28 28 28 28 28 27 26  0  0 26 26 26
 26 26 26 26 26 26 26 26 26 26 26 26 25 25  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0 24 24 24 24 24 24 24 24 24 24 24 24 24 24  0  0  0 25 24
 24 23 23 23 23 24 24 24 24 23 23 23 23 23 22 22 22 23 23 23 23 23 23 23
 22 23 23  0  0  0 23 23 23 22 23 23 23 23 23 23 22 22 23 22 23 22 21 21
 21 21 21 21 21 21 21 21 22  0  0  0 21 21 21 21 21 21 21 21 21 21 21 20
  0  0  0  0 19 19 19 19 19 19]

From what I am able to do now, I can only plot the audio using a linear scale spectrogram, with this code:

def make_spectrogram_b(songname, titles, filename):
  x, sr = librosa.load(songname, sr=None) #sr=None, buat dapet aslinya
  duration = librosa.get_duration(filename=songname)

  print("Audio shape: ", x.shape)
  print("Sample rate: ", sr)
  print("Duration of audio: ", duration)

  # compute stft
  window = np.hanning(window_size) # window size = 1024; hop_length = 256
  stft= librosa.core.spectrum.stft(x, n_fft = window_size, hop_length = hop_length, window = window)
  out = 2 * np.abs(stft) / np.sum(window)

  # plot result
  plt.figure(figsize=(12, 4))
  ax = plt.axes()
  ax.set_axis_off()
  librosa.display.specshow(librosa.amplitude_to_db(out, ref=np.max), y_axis='log', x_axis='time',sr=sr)
  plt.savefig(f'spectrogram_data_B/{titles}/{filename[:-3].replace(".", "")}.png', bbox_inches='tight', transparent=True, pad_inches=0.0)
  plt.clf() 

This here is an output sample from code above. Output My testing result is not so satisfying, as it detects too many zero pitch values, and I think I want to change the spectrogram type.

I read from a book source (Muller, Fundamentals of Music Processing, 2015), that if we want to make a spectrogram for music analysis, we must make a log-frequency spectrogram, as quoted:

To emphasize musical or tonal relationships, the frequency axis is often plotted in a logarithmic fashion, which yields a log-frequency representation. A logarithmic frequency axis also accounts for the fact that human perception of pitch is logarithmic in nature. Finally, in the case of audio signals, the amplitude values are also often visualized using a logarithmic scale, for example, by using a decibel scale. In this way, small intensity values of perceptual relevance become visible in the image. In the following, if not specified otherwise, we use in our visualizations a linear frequency axis and a logarithmic scale to represent amplitudes. The specific scale is not of importance, but only serves the purpose of enhancing the qualitative properties of the visualization.

In Python, how can I plot this log-frequency spectrogram? Or, is there any better way to 'convert' audio given above to a visual representation for pitch analysis?

$\endgroup$
10
  • $\begingroup$ librosa.display.specshow(librosa.amplitude_to_db(out, ref=np.max), y_axis='log', x_axis='time',sr=sr) in this line you have converted the output to db or log. Your y-axis is logarithmic also. Then, how do you say that "I can only plot the audio using a linear scale spectrogram"? $\endgroup$ – Duck Dodgers Feb 24 at 10:12
  • 2
    $\begingroup$ @DionisiusPratama, the good Prof. Dr. Müller (who you refer to in your post as well) provides such an example on this (probably his) website :). From the 2nd heading onwards. I hope I understood correctly and this is what you were looking for. $\endgroup$ – Duck Dodgers Feb 24 at 11:07
  • 2
    $\begingroup$ Alternatively, there's this question here on the DSP exchange. $\endgroup$ – JRE Feb 24 at 11:10
  • 1
    $\begingroup$ It boggles my mind that people who are doing music stick to the FFT with its linear spacing. Why not simply calculate the Fourier transform for just the frequencies corresponding to the center frequencies of the notes? Instead, everyone does an FFT at an extremely high resolution then tries to map the bins to fit the notes. Just make the bins fit the notes to start with. That's 88 bins for the whole piano range. As efficient as the FFT is, at some point computing fewer bins wins out. $\endgroup$ – JRE Feb 24 at 11:16
  • 1
    $\begingroup$ As an additional win, computing each bin individually lets you tailor the width of bin and the time resolution to each tone individually. Wider bins with better time resolution for high frequencies, narrower bins with worse time resolution for the lower tones. $\endgroup$ – JRE Feb 24 at 11:18

Your Answer

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

Browse other questions tagged or ask your own question.