Skip to content

Instantly share code, notes, and snippets.

@mixuala
Created October 14, 2021 08:37
Show Gist options
  • Select an option

  • Save mixuala/9a4536e1fc284a74c906953a7135e04d to your computer and use it in GitHub Desktop.

Select an option

Save mixuala/9a4536e1fc284a74c906953a7135e04d to your computer and use it in GitHub Desktop.
FFT of an audio clip from .wav file
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# FFT of an audio clip from .wav file\n",
"The clip was exported as .wav file from `pianoteq7` from a known MIDI file\n",
"\n",
"> MIDI note: {'MIDI': 21, 'Note': 'A0', 'Frequency': 27.5, 'Volume': 115}"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from scipy.fft import rfft, rfftfreq\n",
"from scipy import signal\n",
"from scipy.io import wavfile # get the api\n",
"\n",
"def ms2samples(ms:int, samplerate=48000)->int:\n",
" return int(ms/1000*samplerate)\n",
"def samples2ms(samples:np.array, samplerate=48000)->int:\n",
" count = max(samples.shape)\n",
" return int(count/samplerate*1000) \n",
"def get_spectra(clip, samplerate=48000, durationMS=600):\n",
" \"\"\" \n",
" get spectra from a sound clip in the form of a numpy array using `scipy.fft.rfft()`\n",
" \n",
" args:\n",
" clip:np.array with shape=(channels, samples)\n",
"\n",
" returns: \n",
" [ (xf,yf), ...], list of tuples, one for each channel\n",
" \"\"\"\n",
" channels, samples = clip.shape\n",
" assert channels<6, f'ERROR: expecting data.shape=(channels, samples), got shape={clip.shape}'\n",
"\n",
" result = []\n",
" for ch in range(clip.shape[0]):\n",
" # see https://realpython.com/python-scipy-fft/\n",
" # Number of samples in normalized_tone\n",
" samples = ms2samples(durationMS, samplerate=samplerate) # 600ms sample\n",
" # samples = len(clip[ch]) # use ENTIRE clip\n",
" yf = rfft(clip[ch][0:samples])\n",
" xf = rfftfreq(samples, d=1./samplerate)\n",
" result.append( (xf,yf) )\n",
" return result "
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"channels=2, samples=32767, samplerate=48000, duration=0.6826458333333333s, bitdepth=16.0\n",
"fft freq[0:4]= [ 55. 81.66666667 110. 136.66666667]\n",
"fft freq[0:4]= [ 55. 81.66666667 110. 136.66666667]\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"expecting MIDI note: {'MIDI': 21, 'Note': 'A0', 'Frequency': 27.5, 'Volume': 115}\n"
]
}
],
"source": [
"# load clip\n",
"path = \"./clip-A0.wav\"\n",
"samplerate, data = wavfile.read(path) # load the data\n",
"clip = data.T # audio.shape = (channels, data)\n",
"channels, samples = audio.shape\n",
"duration = samples/samplerate\n",
"bitdepth_lu = {'int8':8., 'int16':16., 'int32':24., 'int64':64.}\n",
"bitdepth = bitdepth_lu[ type(data[0,0]).__name__ ]\n",
"print(f'channels={channels}, samples={samples}, samplerate={samplerate}, duration={duration}s, bitdepth={bitdepth}')\n",
"\n",
"# get scipy.fft.rfft() spectra\n",
"clip_spectra_by_channel = get_spectra(clip, samplerate=samplerate, durationMS=600)\n",
"for ch, (xf,yf) in enumerate(clip_spectra_by_channel):\n",
" yf_real = np.abs(yf)\n",
" plt.plot(xf, yf_real)\n",
"\n",
" # find the frequencies in xf for peaks in yf, using height=1/7 of max( yf_real)\n",
" min_peak_ratio = 1./7\n",
" peaks, _ = signal.find_peaks(yf_real, height=(min_peak_ratio * max(yf_real)) )\n",
" x_freq = np.asarray([ xf[i] for i in peaks])\n",
" print(\"fft freq[0:4]= \", x_freq[0:4])\n",
" \n",
"\n",
"plt.xlim([ max(20, x_freq[0]/2), min((2**3*x_freq[0]),20000) ])\n",
"plt.title(f'fundamental={fundamentals}, duration={samples2ms(clip)}ms')\n",
"plt.show()\n",
"print (\"expecting MIDI note: \", {'MIDI': 21, 'Note': 'A0', 'Frequency': 27.5, 'Volume': 115})"
]
}
],
"metadata": {
"interpreter": {
"hash": "a52e194d266978d7a7fe240b7965270feff9caba8a8e7547458d9d80ffdace14"
},
"kernelspec": {
"display_name": "Python 3.9.1 64-bit ('base': conda)",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment