3

I'm analysing a lot of short .wav files and for a part of the analysis I want to plot the fundamental frequency only of the file. My signal processing is a bit rusty, but I'm now getting plots that look like they should be correct. I'm just not getting why the y axis scale is off (the F0 is around 300Hz when it should be around 8000Hz). So I want to plot the F0 across the duration of the .wav file like a spectrogram without the intensity information. Can anybody help me out? happy to provide additional info!

from scipy import signal
import numpy as np
import soundfile as sf

y, samplerate = sf.read('audiofile.wav') 
chunks = np.array_split(y,int(samplerate/2000))
peaks = []

for chunk in chunks:
    # simulated pure signal
    t = np.linspace(0, 1, samplerate)
    wave = chunk
    # compute the magnitude of the Fourier Transform and its corresponding frequency values
    freq_magnitudes = np.abs(np.fft.fft(wave))
    freq_values = np.fft.fftfreq(samplerate, 1/samplerate)
    # find the max. magnitude
    max_positive_freq_idx = np.argmax(freq_magnitudes[:samplerate//2 + 1])
    peaks.append(freq_values[max_positive_freq_idx])
Deniz Dohmen
  • 31
  • 1
  • 2

3 Answers3

0

The numpy.fft.fftfreq documentation refers to the first argument as "window length", so I would recommend replacing

freq_values = np.fft.fftfreq(samplerate, 1/samplerate)

with

freq_values = np.fft.fftfreq(len(wave), 1/samplerate)

or

freq_values = np.fft.fftfreq(wave.shape[0], 1/samplerate)
Andris
  • 921
  • 7
  • 14
0

Hard to jugde since you have not provided your plot code but if your wav file is in stereo you will get y as a two dimensional array and that could be a potential problem. As @Andris suggests, the window length also needs to be corrected.

If you make your own spectrogram plot, please check your output from fft and fftfreq, the order is like [0 .. Fs/2 -Fs/2 ..]. You can reorder them using fftshift.

Otherwise there is also a spectrogram plot ready to use in signal package

f,t,Sxx = signal.spectrogram(y[:,0],samplerate)

plt.pcolormesh(t, f, np.log10(Sxx))
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()
Claes Rolen
  • 1,446
  • 1
  • 9
  • 21
0

spectrogram plot ready to use the below error thrown can u help in rectifying f, t, Sxx = signal.spectrogram(y[:, 0], samplerate) IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 14 '22 at 11:04