I have recorded some audio and would like to obtain a spectrum from it. As the audio is a real valued signal, I figure that I could perform a FFT with some window and obtain a spectrum for that period. There is the
scipy.signal.spectrogram function which can just do this in one go. This is the code that I have thrown together:
import numpy as np import matplotlib.pyplot as pl import scipy.io.wavfile import scipy.fftpack from scipy import signal rate, data = scipy.io.wavfile.read('audio.wav') N = rate // 10 f, t, Sxx = signal.spectrogram(data, rate, window=signal.blackman(N), nfft=N, mode='magnitude') pl.pcolormesh(t, f, 10 * np.log10(Sxx), shading='auto', cmap='jet')
The sampling rate is 44100 Hz. I thought that using a window of 100 ms should give me a lower frequency of 10 Hz, which is fine for my purpose.
Looking at the resulting spectrum plots I see that the upper half of the frequency seems to be different from the lower part.
From the documentation I would have expected that I just get the real amplitude as
return_onesided defaults to
True. In general I would expect to have amplitudes and phases, or real and imaginary part. But with the spectrum I just want the amplitudes. Are they just the lower part?
And if so, why is the maximum frequency just around 11 kHz whereas the sampling frequency is 44 kHz and from the Nyquist–Shannon sampling theorem I'd expect to be able to resolve like 22 kHz?
Update: Other recording
Using my laptop with Audacity instead of my phone with SmartRecorder to record some audio, I have no strange upper half in the spectrum.
Update: Jet colormap
I was asked why I have been using Jet instead of Viridis. When using the latter for the spectrum plot, one cannot see so much of the structure.
I know that Jet isn't so great, but I just want to have more contrast.