Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jakelevi1996/604d9dc6dbbb82980caa77ea92254153 to your computer and use it in GitHub Desktop.
Save jakelevi1996/604d9dc6dbbb82980caa77ea92254153 to your computer and use it in GitHub Desktop.
Record audio and plot spectrogram in Python

Record audio and plot spectrogram in Python

Below is a Python script which demonstrates how to record audio in Python, calculate a spectrogram, and plot the spectrogram, followed by a few usage examples (me playing the opening bars of "Majorca" by Albeniz, and me whistling a major triad and then some random notes).

import sounddevice as sd
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
import os
def record_audio(duration=3, fs=44.1e3, playback=True):
print("Starting recording...")
x = sd.rec(int(duration * fs), fs, channels=1, blocking=True)
print("Finished recording")
if playback:
sd.play(x, fs, blocking=True)
return x.ravel()
def spectrogram(
x, fs=44.1e3, fs_spec=60, f_lo=20, f_hi=20e3, freqs_per_octave=60,
n_overlap=1
):
f_log2 = np.arange(np.log2(f_lo), np.log2(f_hi), 1/freqs_per_octave)
f = np.power(2, f_log2)
sample_interval = fs / fs_spec
n_per_sample = int(sample_interval * (1 + n_overlap))
n_samples = int(
(x.size - (n_per_sample - sample_interval)) // int(sample_interval)
)
t = np.arange(n_samples) / fs_spec
window = signal.windows.hamming(n_per_sample)
spectrogram_array = np.zeros([f.size, n_samples])
for i in range(n_samples):
start = int(i * sample_interval)
end = start + n_per_sample
x_chunk = x[start:end] * window
_, h = signal.freqz(x_chunk, worN=f, fs=fs)
spectrogram_array[:, i] = np.abs(h)
return t, f, spectrogram_array
def plot_spectrogram(
t, f, spectrogram_array, fs_spec=30, name="Spectrogram", dir_name="Images"
):
plt.figure(figsize=[8, 6])
plt.pcolormesh(t, np.log2(f), spectrogram_array)
plt.xlabel("Time (s)")
plt.ylabel("$\log_{2}$(frequency)")
plt.title(name)
if not os.path.isdir(dir_name): os.makedirs(dir_name)
plt.savefig("{}/{}.png".format(dir_name, name))
plt.close()
if __name__ == "__main__":
x = record_audio(5, playback=True)
t, f, sa = spectrogram(x, n_overlap=3)
plot_spectrogram(t, f, sa)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment