{ "cells": [ { "cell_type": "markdown", "id": "348dd2c6", "metadata": {}, "source": [ "# Noise suppression" ] }, { "cell_type": "markdown", "id": "5b114e7b", "metadata": {}, "source": [ "Very simplified noise suppression algorithm to show how to use the CMSIS-DSP Python wrapper and how it can help translating a float algorithm to a fixed point one ready to be implemented on a Cortex-M or Cortex-A processor." ] }, { "cell_type": "markdown", "id": "ba37a7e0", "metadata": {}, "source": [ "The CMSIS-DSP package must first be installed. This command will take some time to execute since the CMSIS-DSP will be built." ] }, { "cell_type": "code", "execution_count": null, "id": "19680a19", "metadata": {}, "outputs": [], "source": [ "!pip install cmsisdsp" ] }, { "cell_type": "markdown", "id": "934cf8b0", "metadata": {}, "source": [ "The packages required for this example must be loaded:" ] }, { "cell_type": "code", "execution_count": 1, "id": "bfb671b0", "metadata": {}, "outputs": [], "source": [ "# Numerical packages\n", "import cmsisdsp as dsp \n", "import cmsisdsp.fixedpoint as fix\n", "import numpy as np\n", "from numpy.lib.stride_tricks import sliding_window_view\n", "from scipy.signal.windows import hann\n", "\n", "# Package for plotting\n", "import matplotlib.pyplot as plt\n", "\n", "# Package to display Audio widget in the notebook and to upload sound files\n", "import ipywidgets\n", "from ipywidgets import FileUpload\n", "from IPython.display import display,Audio\n", "\n", "# To convert sound file to NumPy array\n", "import io\n", "import soundfile as sf\n", "\n", "# To load test pattern from Arm VHT Echo Canceller demo\n", "from urllib.request import urlopen\n" ] }, { "cell_type": "markdown", "id": "ae39ac8d", "metadata": {}, "source": [ "## Loading the audio file" ] }, { "cell_type": "markdown", "id": "153b71bb", "metadata": {}, "source": [ "You can either upload a .wav file or download the test pattern used in our echo canceller demo running on Arm Virtual Hardware." ] }, { "cell_type": "markdown", "id": "8130c184", "metadata": {}, "source": [ "### Test pattern from Arm Virtual Hardware demo" ] }, { "cell_type": "markdown", "id": "70e33e66", "metadata": {}, "source": [ "This is based on the Yes/No pattern from the TensorFlow Lite Microspeech demo but with added noise and a sequence of Yes/No which is different. It is working with the Q15 implementation (which is not the case of all speech pattern you may test)." ] }, { "cell_type": "code", "execution_count": 2, "id": "3c298f96", "metadata": {}, "outputs": [], "source": [ "test_pattern_url=\"https://github.com/ARM-software/VHT-SystemModeling/blob/main/EchoCanceller/sounds/yesno.wav?raw=true\"\n", "f = urlopen(test_pattern_url)\n", "filedata = f.read()" ] }, { "cell_type": "markdown", "id": "3fa31b19", "metadata": {}, "source": [ "### Wav file" ] }, { "cell_type": "markdown", "id": "918a12b0", "metadata": {}, "source": [ "Select a .wav file to upload" ] }, { "cell_type": "code", "execution_count": 451, "id": "0f4d0cff", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d582a97e382f4858a5e07321af8b1243", "version_major": 2, "version_minor": 0 }, "text/plain": [ "FileUpload(value={}, accept='wav', description='Upload')" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "uploader=FileUpload(accept='wav',multiple=False)\n", "display(uploader)" ] }, { "cell_type": "markdown", "id": "0853e7a9", "metadata": {}, "source": [ "The two next cell is loading the audio data from the uploaded file" ] }, { "cell_type": "code", "execution_count": 436, "id": "ad14cf43", "metadata": {}, "outputs": [], "source": [ "filename=list(uploader.value.keys())[0]\n", "filedata=uploader.value[filename][\"content\"]" ] }, { "cell_type": "markdown", "id": "95948301", "metadata": {}, "source": [ "### Audio player" ] }, { "cell_type": "markdown", "id": "66ab2923", "metadata": {}, "source": [ "You can now listen to the sound to check it is available in this notebook." ] }, { "cell_type": "code", "execution_count": 3, "id": "46f7169b", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "audio=Audio(data=filedata,autoplay=False)\n", "audio" ] }, { "cell_type": "markdown", "id": "f2eaeae6", "metadata": {}, "source": [ "A NumPy array is created from the audio and a Q15 and Q31 versions are created." ] }, { "cell_type": "code", "execution_count": 4, "id": "9b7c4b14", "metadata": {}, "outputs": [], "source": [ "data, samplerate = sf.read(io.BytesIO(filedata))\n", "if len(data.shape)>1:\n", " data=data[:,0]\n", "data = data + np.random.randn(len(data))*0.00\n", "data=data/np.max(np.abs(data))\n", "dataQ15 = fix.toQ15(data)\n", "dataQ31 = fix.toQ31(data)" ] }, { "cell_type": "markdown", "id": "e6dfbffa", "metadata": {}, "source": [ "The audio waveform is plotted" ] }, { "cell_type": "code", "execution_count": 5, "id": "1f446dfc", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(data)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "677cbf18", "metadata": {}, "source": [ "The audio is split into overlapping windows. Those windows will be used in the notebook to implement the processing.\n", "The signal will be rebuilt at the end with an overlap and add.\n", "\n", "If the window durations are changed, the thresholds for the VAD will also have to be changed." ] }, { "cell_type": "code", "execution_count": 6, "id": "4427ae73", "metadata": {}, "outputs": [], "source": [ "winDuration=30e-3\n", "winOverlap=15e-3\n", "\n", "# Decrease the duration so that Q15 is more likely to work with sampling freq of 48 kHz\n", "# (to avoid too long FFT length which may saturate in Q15)\n", "winDuration = winDuration/6 \n", "winOverlap = winOverlap/6\n", "\n", "winLength=int(np.floor(samplerate*winDuration))\n", "winOverlap=int(np.floor(samplerate*winOverlap))\n", "slices=sliding_window_view(data,winLength)[::winOverlap,:]\n", "slices_q15=sliding_window_view(dataQ15,winLength)[::winOverlap,:]\n", "slices_q31=sliding_window_view(dataQ31,winLength)[::winOverlap,:]" ] }, { "cell_type": "markdown", "id": "9f49559a", "metadata": {}, "source": [ "## Energy VAD" ] }, { "cell_type": "markdown", "id": "0ffe045f", "metadata": {}, "source": [ "This is a very simplified VAD algorithm based on energy threshold. " ] }, { "cell_type": "markdown", "id": "3159c218", "metadata": {}, "source": [ "### Double implementation" ] }, { "cell_type": "code", "execution_count": 7, "id": "cfa5a997", "metadata": {}, "outputs": [], "source": [ "def clean_vad(v):\n", " v = np.hstack([[0],v,[0]])\n", " # Remove isolated peak\n", " vmin=[np.min(l) for l in sliding_window_view(v,3)]\n", " vmin = np.hstack([[0,0],vmin,[0]])\n", " # Remove isolated hole\n", " vmax=[np.max(l) for l in sliding_window_view(vmin,4)]\n", " return(vmax)\n", " " ] }, { "cell_type": "code", "execution_count": 8, "id": "23a57a6b", "metadata": {}, "outputs": [], "source": [ "# Energy of the window\n", "def signal_energy(window):\n", " w = window - np.mean(window)\n", " return(10*np.log10(np.sum(window * window)))\n", " \n", "# Comparison with a threshold\n", "def signal_vad(window):\n", " if signal_energy(window)>-11:\n", " return(1)\n", " else:\n", " return(0)" ] }, { "cell_type": "markdown", "id": "83c9e318", "metadata": {}, "source": [ "Plotting of the signal and the VAD detection. It can be used to tune the threshold for the audio signal used in the notebook. It is unlikely that only one threshold will work with any audio signal. It is a very simplified VAD." ] }, { "cell_type": "code", "execution_count": 9, "id": "d8cf68d2", "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "_,ax=plt.subplots(1,1)\n", "cleaned=clean_vad([signal_vad(w) for w in slices])\n", "vad = np.array([[w]*winOverlap for w in cleaned]).flatten()\n", "#signal_energy = np.array([[signal_energy(w)]*winOverlap for w in slices]).flatten()\n", "ax.plot(data)\n", "ax.plot(vad)\n", "#ax.plot(signal_energy)" ] }, { "cell_type": "markdown", "id": "b3e2e0d4", "metadata": {}, "source": [ "### CMSIS-DSP Q15 implementation" ] }, { "cell_type": "markdown", "id": "0885101f", "metadata": {}, "source": [ "The same functions but in q15 and using CMSIS-DSP API." ] }, { "cell_type": "code", "execution_count": 10, "id": "37e41c05", "metadata": {}, "outputs": [], "source": [ "def signal_energy_q15(window):\n", " mean=dsp.arm_mean_q15(window)\n", " window=dsp.arm_offset_q15(window,-mean)\n", " energy=dsp.arm_power_q15(window)\n", " # Energy is not in q15 (refer to CMSIS-DSP documentation)\n", " energy=dsp.ssat(energy>>20,16)\n", " # The shift is by more than 15, so the result is not in q15\n", " # (With a shift smaller there is a saturation)\n", " dB=dsp.arm_vlog_q15([energy])\n", " # The output of the vlog is not in q15\n", " # The multiplication by 10 is missing.\n", " # The result of this function is not \"equal\" to the float implementation due to the different\n", " # formats used in the intermediate computations.\n", " return(dB[0])\n", " \n", "def signal_vad_q15(window):\n", " # The threshold is not easily related to the float implementation because\n", " # of the different intermediate formats used in the fixed poitn implementation\n", " if signal_energy_q15(window)>fix.toQ15(-0.38):\n", " return(1)\n", " else:\n", " return(0)" ] }, { "cell_type": "markdown", "id": "89b856d2", "metadata": {}, "source": [ "Plot of the signal and VAD which can be used to tune the threshdold. The threshold is different because we do not apply the multiplication by 10 and because the output format of the vlog is not Q15. And the output format of the power function is also not q15 (the formats are described in CMSIS-DSP documentation)" ] }, { "cell_type": "code", "execution_count": 11, "id": "276749ae", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAD4CAYAAADhNOGaAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAwTUlEQVR4nO2deZgdVZXAfyedDUjIDoTshLAEkBDasAkiBAiMEkTQgEpUNKOCM8ooBnCAQRmjjuI4shgBjRuLoBIFjBA2ERJoIGQF0iQgCQkJIRtk7e4zf7zq7urXVW+r9b06v+9736u6t6rOqe2ee889da+oKoZhGEZ26ZK0AoZhGEaymCEwDMPIOGYIDMMwMo4ZAsMwjIxjhsAwDCPjdE1agUoYOHCgjhw5Mmk1DMMwqornnnvubVUdlJ9elYZg5MiRNDQ0JK2GYRhGVSEir3ulm2vIMAwj45ghMAzDyDhmCAzDMDKOGQLDMIyMY4bAMAwj44RiCETkdhFZJyKLffJFRH4iIo0islBExrvyporIcuc3NQx9DMMwjNIJq0XwS2BSgfwzgTHObxpwM4CI9AeuAY4BJgDXiEi/kHQyDMMwSiCU7whU9QkRGVlgk8nArzQ35vU8EekrIoOBk4GHVPUdABF5iJxBuSMMvaqOXe/BMzNh1zbv/ANOhpEnxKpSB5beB2s9G33Qc2845ktQF/CRWnAHvLOic/roD8GI44MduxivPw2vPuKd120PmDANevSKVtY+h8Lh54YjoxL5EP65trJmISz7c+f0vsNg/EXhyvJi61p4bha0NHVM79bTOd/e4cp7uxEW3Q1eQ/3XdYOjPwu9On3blQhxfVA2BHjDtb7KSfNL74SITCPXmmD48OHRaJk0rz8FD1/rrEhepsLKx+Hiv8WslIs//zts34inbgAjT4T9x1V+/KZd8KcvOituGQqvPQmfe7DyY5fC3Ovgn0/he377jIWDCzV8y+CR78DrT9LpPLv3iscQeMp3dICcQTr4zHBl/uPHsPheOp0zwGEfDb8gzmfR7+Gx/3ZWWnVw5A8YA2PPDlfeMzPhmZ/he4336AcTvhCuzAqpmi+LVXUmMBOgvr6+NmfTaWnO/X/hURgyvmPer8+FHZvj18lNS0uu1n/mjI7pr8yB330ctDmgAOe2nno1nPgf7cm/mgy7twc8dinim3Otrovu65i+5kX42UkhnF+erFEfhKmz29MeuhrmzwxPRrnyIVdr/9mJ7c9imLQ0w6BD4JL57WlP3wRzrgBtCV+el3yAq9bmWj0A65bBTceGe29b0WbYcwBcntfC3fYOfH9UNNe4QuKKGloNDHOtD3XS/NINwzCMmIjLEMwGLnKih44FNqvqGmAOcLqI9HM6iU930jJKsYZO0g2hIvKDqldo2tQ4plQtJiNMHXyPFdM9LnouUeiR8P2NW34i17gyQnENicgd5Dp+B4rIKnKRQN0AVPUW4AHgLKAR2AZ81sl7R0S+DTzrHOq61o5jwzAMIx7Cihq6oEi+Apf45N0O3B6GHjWD5Hcu+aQlgaceYeuWf7w4zz2O82s9bJLn6SXfJy1coTHLK6ZDzOcL6XmXXdiXxYZhGBnHDEGaiNNHXQmR+zwL7Z+wDzl0HXyOFds9TuBZK3jMpPuAYu4TgeTfZxdmCFJJjO6JsomhqZt/vDib0rG6S5J2kyTwnCXtDsvXIeprHosrNThmCAzDMDKOGYJUkfZws4ibuhY+ioWPRomFj/phhsAwDCPjmCFIIxY+GvHxy5Edofyk/eUWPkr01zzF77ILMwSGkQgpjxqKRGTao96yixmCNGHhoxEeO6j8uHRICUk/azVByt9nF2YIDMNwkT63hRE9ZghSSXXEHrcReheBfUcQDwnH8KdBB/uOADBDkDLS7pqw8NHoZdVy+GghcRY+miRmCIzySGHEgxEidn8ziRmCNJLm8FFPLHy0MlEpDB+NXmjKdLDwUTBDYBgJYeGjeZkxyI9eRLVihiBNWPhohMcOKj8uHVJC0s9a7Njoo4ERkUki8rKINIrIdI/8G0RkgfN7RUQ2ufKaXXmz8/c10kb6mrVGmNj9zSKBZygTkTrgRuA0YBXwrIjMVtWlrduo6tdc238FOMp1iO2qOi6oHrVFdYSctWHDUJePKt7+8jijhuJ+ptRfZJxRQxY+2okwWgQTgEZVXaGqu4A7gckFtr8AuCMEuTVI2l0TFj6aHbJ0rlj4aAjHGAK84Vpf5aR1QkRGAKOAR1zJPUWkQUTmicg5fkJEZJqzXcP69etDUNuoiBRGPBghYvc3k8TdWTwFuEdVm11pI1S1HrgQ+LGIjPbaUVVnqmq9qtYPGjQoDl2Tw8JHIz5+ObIjlG/ho+nQIW5ZKXyXwzAEq4FhrvWhTpoXU8hzC6nqaud/BfAYHfsPDKNGsfDRvMyE5WebMAzBs8AYERklIt3JFfadon9E5BCgH/C0K62fiPRwlgcCJwBL8/fNDEV91PGo4S/fwkczQ+YKTQsfDYSqNgGXAnOAZcDdqrpERK4TkbNdm04B7lTtcPaHAg0i8iLwKDDDHW2UVTa8u5PnXt+YtBo+pK9Za4SJ3d8wUeCvi9eiKSr0vQilj0BVH1DVg1R1tKpe76RdraqzXdtcq6rT8/Z7SlWPUNUjnf/bwtCn2rng1mf42M1P5aWm4wVdt3UnI6ffz/P/dBmqGgofXbd1JyfMeISm5pZo5acgfHR3i3Lcd+ey4I1N8chE/ftFajR89N2dTXzxN88x9RfPulLT8S67sS+LU0XaXRPKvc+vAuDRl9Z5ZFd/+OjC1ZtZvWk7333wpWR0iJGnGjewZvMOvnbXgqRVSZ5IwkehuSV33CdeWe/RKkjP82SGIMWsWP9u0ip0QlNYm4mC255cybZdTUmrESlNTiG18u33WLt5Ry4xhREt1cy23e0BkrOeei05RYpghiCFtBa2p/zw8fbElL2g//dII7vb3Ce1Ez7qNnT3Pt8a/Fab4aPu+ugTy+P6NicF4aMdZEYr3/08PbxsnYf8dGCGwKiYHbubi29k+JC0W8DCR412zBCkibQPcaBa5HWt9fDRLBBn522asPBRwzCyTnrKJCMBzBCkkKp7J2sofLSDz1g9wg3Dwjd8lNgipOLv+E9J+GgH8fH1EbS3p62PwChI+sNHC2dHGT4a7NClyS+Wn/T1j5MsnSs2+mjSChjVRVbCRzNLCiNajOgxQ5BCPAvbVL+gtRQ+6kUU8tPgJon5mSrkDostaijhEV8hle+yGQLDMCgWD2YEJ82eRTMEaaIqwkcL1Wai1C/+ToLOElP8JodN0s9a7Fj4qGEYhpFhzBBUDenzK7ZRQ+GjsfXPKCTrL0+ifZOCfpGYny3V7Exeb8RG0k3JIp7kGhh9NFB+FdN2anEaozRh4aOGURmSwuiHMKnhct9IgDQ/T6EYAhGZJCIvi0ijiEz3yP+MiKwXkQXO7/OuvKkistz5TQ1Dn2rHwkeTO9f4vpNI3k0S+zchGQwf9TyrFL7LgQ2BiNQBNwJnAmOBC0RkrMemd6nqOOd3q7Nvf+Aa4BhgAnCNiPQLqpMRDfkP9cNL30pEj7jYsn130irExi73jGxGJDy9YkPSKvgSRotgAtCoqitUdRdwJzC5xH3PAB5S1XdUdSPwEDApBJ2qk7T7qPPCRxvX5U+cU1ujj/7woVcS0CEZrp29xFmy0UdjO2aKLnEYhmAI8IZrfZWTls/HRGShiNwjIsPK3BcRmSYiDSLSsH59XJNoGEZEpGxs/pZYCqWEgwHSVPKmjLg6i/8MjFTV95Gr9c8q9wCqOlNV61W1ftCgQaErmCa8fbfp8yu2UVPhox7EJT9ul30qhleIWYe4w0er5F0OwxCsBoa51oc6aW2o6gZV3ems3gocXeq+2SLd4WZSbHwaCx+tfix8NMZjpucah2EIngXGiMgoEekOTAFmuzcQkcGu1bOBZc7yHOB0EenndBKf7qQZhmEYMdE16AFUtUlELiVXgNcBt6vqEhG5DmhQ1dnAv4nI2UAT8A7wGWffd0Tk2+SMCcB1qvpOUJ2qnWoJOWsnat0S/rK4Rkcfjb0+msnw0eoIBQ9sCABU9QHggby0q13LVwBX+Ox7O3B7GHoYhmEY5WNfFqeJKvBRuzXoXLGprfDRZHRIGgsfje2YKbrGZgiMiklfA7eKSFn4aDxY+GhaMUOQQqol5GzeCqc7x8JHKyS58wQLH/VcD5n4ZrwLhhmCVJFi14RTY3MPq/v6O+95bhNURtl5YVEFrrnIsfDRGI+ZnmtshsComCyUi7VKi908w4UZghRSLSFn7dTG5PVNLX4jctZe+OiupmYLH80pEK3IKnmXzRAYZeF+sGutTtlstWTS6L82oscMQZpIs4/aQ3bnpOoOH5Uq8ulGTuaMooWPGoZBzMV80uGjiRg1Cx9NK2YIUki1hJy1UUPho57X2cJHwyNz4aPWR2CUTZpdE1pcg8CeoZTXGFPUlI8MCx+N8ZjpucZmCIyKefvdncU3MnxI1uglUidN2h2WBUNeIWYIUoi7ObllhzNvbgqbk+3URvgoxOyWS9pNkog5SNYdFuezVU3fapghSDlrNu1IWoUOJOJXjol3dzQlrUJsbNvld661e3/j5u13dyWtQsmYIUgTVRY+6rFRUCERHrs4O3YXMwTVU8MrxtZiRq+KarPhYOGjgRGRSSLysog0ish0j/zLRGSpM3n9XBEZ4cprFpEFzm92/r5ZJ9UeIaNy8gqBzdt389aW1j6XGu0jyOOpV9/mkZfeyq2kIRggwwQ2BCJSB9wInAmMBS4QkbF5m70A1DuT198DfN+Vt11Vxzm/s4PqUxtIwaXUEVH4qKoy4fqHeemtd8M9fgHiDfdrP+4nb53Hbf9YGZEcbxIpFl3X8sKfz2f2i2sTk7/0zS3UXz83UnH+rtR0vc9htAgmAI2qukJVdwF3ApPdG6jqo6q6zVmdR26SeqMTnV/NjmVQGsJH45u8/vZ/vMa6rTt55a2t6agxRqSDqrJ49ZZIjl02GQofPesnf29fsfDRwAwB3nCtr3LS/LgYeNC13lNEGkRknoic47eTiExztmtYv359IIWri3TVHOLizU3b+fZflsYrNN5PiwHYtG0Xo654IC8rDtdQAoWQc17bdjXxtbsWJCYfYOT0++OXn2Ji7SwWkU8B9cAPXMkjVLUeuBD4sYiM9tpXVWeqar2q1g8aNCgGbZPDXQ68tNapKaa6syD88NHjZzzSthZnpFKskwKJMPFHTxSRHR3JRIAJMx58iT++sNrRIX75bqKW73uNU/Y+h2EIVgPDXOtDnbQOiMhE4CrgbFVt+xJJVVc7/yuAx4CjQtCpZvjOX5YlrUIH8l+clpb0NG+jIOrzS+qjvJ1NLT450RdQG96rnrDKIFTTmxGGIXgWGCMio0SkOzAF6BD9IyJHAT8jZwTWudL7iUgPZ3kgcAIQsz8gRXi4BNZu2cHCVZt882PDR/b357zs3iiokArzwsHrA6DbO3TgVtOrXT7X3Le4fSXCZ23ZmynpD4mYpubmTmk/e/zV9pVaCh9V1SbgUmAOsAy4W1WXiMh1ItIaBfQDoBfw+7ww0UOBBhF5EXgUmKGq2TUEPmzf1fmBSgt/eH5VLHLimCugqblzLfk790fUIkt4uAWvPoJZT78esdSczBVvv+eRFV+huGjV5ljkLF7dWc53H3wpFtnl0jWMg6jqA8ADeWlXu5Yn+uz3FHBEGDrUAi2qdCFmP3XZdNRj++7m0FVbn/dFpgI7d7ewZ7hiPPEsjmIafTQVfQRR+64l2XNGhO/9tb0wjlJ+U4uivodPy/ucw74sThGa6nAzH9nu5JDCR3/wt5c7ZcUR5VL01Qy51vruzjQPaRHN9U76nBV4svFtj4zwz7d4UV9DriEjPPwei10eLou0sDWmFzvJV2b77ihcc8rcl9b5ZNVu+Ki/Wyae0UebW5J/lx71u+8JYoYgRbS+JPnN1U/f9kzqws06Eq5u+eefdPjom5ujGfgvv+iLu2j2krduS7RRTB6fTEYqL5/tuztqkET46CMvrUvd+2yGIEVsqILx/Wt59FE/snTGO3zDSo2wWOnVWZ4wZghSRNFKQqJdBMmOPqoxfK/g5y5pvy/h6VDYRZFcf0hbP1UE7qkWLXDOiQ8hEkUfgfcx2+YYqaXwUcOIgw3vpb+1VA47dqez5h1l0ZTWcwZ4z3d+hvBZGFP4ajmYIUgRbZUxr7xYNfHHS4/l66Nt6ioSW+XJy/V15R+WhC5n+65mD1nJh4/OW/FOZPLWbt7u0f8TL537ZXL67IwkICBbo48aoeH/Wtz7/Go2vJvkbGX+urUNIBby6KNu4gkf9ZbRuN4ZBjtEa5R0GKUf//O3V4BoplncnnCLoNBHicVDt8unUFGvEcmsFDMEKeKtLYUL+u0p78jT1LRb0k9Bw5aC8NGlEQwDsW3X7gK50Z/zy2vS45LZ3dzCkhQNtWGGIEW0ziPr1ZxsLRv+svDNOFXqrIeXbk7axm2FXvTKZcRpXny6iwFCf3GTDJP1k9d6/vcvepNdEVQ8/FwzzTEEA+xsUvy+5o7KJeZ3Vorw7GvRueHKxQxBiiilInjp716IXhEPShmF8/J7FrI5JGOQRn73zD8LTPpeW2zd0cRv50c99lA722IYT6uQK2bVxm2+eVGxfXdzap4nMwQJ8JeFbzJvxYZO6SvfLjwlYxx+8o3v7fKsqTz2cvGvIQXlL4sqb7HsbPIvDMKqK6/dvIOv3vkCOzw6B4vJEJSTvv9YKHoUvpfJu4YAVm3cHrJMf7RQaGlItI3i661BRcdct3UHB175AAve6HzsYtdYUC6/Z2FFcsPGDEECXPq7F5gyc17F+zeui24O3w//35Ocf8vTndL9x6/vyFV/XFx8Ix+KhdXN9zCe5fLt+5fypwVv8tDStyraP475A973X3+LxC3TSqmdlLc9ubL4RiGxZUf0NeNC571+607PykExnlz+Nk0tyqynXqtIp78sXOM56m3cmCGImVJcLIX88AC/mRddk331plwt0K/JWsiHHpQm5yMr7TRkY279EwGMZyv3L1wD+J+f17lE5bsvNMTE1h3RudgKhylH20/h1y/ymV88E8uX9X7XvLlFuezuBWUf77K7XwTan6vOFA8f9R1zKkbMEMTMAVe2j9Z9yg8f69BJVoprAuCXFdY+ijH93vZm6tir5/CeK8SxFFdCUNfVrgI1MpHg7pKnXm0fdfKb9y7i7mff6JBfqowwOjYL3WsBuoQwFs2O3c2MnH4/I6ff36nyUOqzFmYnbqHnQ4CX124NTVa5CPDAorUV77+ruYXnXu/oUi3uGsrx0prkzrsVMwQJsmL9e4y+8oHiG3rw3OsbQ9YG7swrGA+7Zk7b8j/L6EybMrOza6kUvnVfcbfSewHi7y/8+fwO65ffu5Alb+bcUeUUeJXes1ZKqfmGEVFywc/bW1Df+tPiNhdEOUV70HMth8deWR+brCj42M1P888NufeknG8Ebnj4lYrcUmESiiEQkUki8rKINIrIdI/8HiJyl5M/X0RGuvKucNJfFpEzwtAnDWzb1cTvG97oUMC84zNX62t5g1CV0mT/2M1PBdaxFFpr0Tc89IqnHrm0jgQNxfMLMYSccVq3NbwP61o768o5PwhmkLa2+cP9w0en/fo57s57fspl/daOBufAqx4E4Im2Are0c90dog+7UGjwzCdW8KcXOk13HirFvuY++6dPBjr+ST94FIB/v3OBj7xWPTqydE2y3xQEnqFMROqAG4HTgFXAsyIyO2/KyYuBjap6oIhMAb4HfEJExpKb4/gwYH/gYRE5SFXTOzdjiYy9Oleb/kYJUQEn/89jAFxYV56MkdPvL1etsmmtRe9R5n6V6DasRG/IhOvnln1sP5a8uaVN1yk9St/P3VqqhL93L77N5fcsDD2qpPVcS5HfyhjHgATl3hJkfvWuBXy19Uv1kLmmhNJu4arNgd+r1v0/3K30fc69qfSK3crvnoWEPIx1GFNVTgAaVXUFgIjcCUym4yT0k4FrneV7gJ9K7kwmA3eq6k5gpYg0OserzLdQhFnf+wqD3s1NU7ff3j1L3q+SL2Zv6lZ+x9dwKdxp1J+t3NTtx2UfNwy6Utw2f7HrnzlH/1GxjL3wr+kPYEvk5z6AwrWyC+oe4fgu4Yw7NFA2+/poftjtZnZRRikSsnyAC+oe5bgu4U4ffoCsYZGO8sy7uuuv2BrxZKRjxT/I4vy6x6nv0nlmvCAc2eVVNmgf3/zTuzzL8G7lR6/NeeFgJo0/MIhqnQjDEAwB3M7lVcAxftuoapOIbAYGOOnz8vYd4iVERKYB0wCGDx9ekaJdtr7J6C65OPfu27tEGh/RSyprTj/RfAQb6d0p/R8th3Nkl1cZLcl9Wby0ZQTPt4zplP6G7sMzLQfTh/cC67eoZSSL8wqLvzcfzhGyIvJz/6fuw5PNh3dK30QvHm9+H/vJO6Hp4CXrhZYDWdIygmESva/c71y3sBePNR/JYNkQ+vVep315vOXIDmnLdAQvthzAPrKJfdgUqrx8dtKNvza/v0Pau+zB3OajGCrrQz/fTdqLh1uO8sy7v+UYDpfXKpL5h9c3hG4IJOjARyJyHjBJVT/vrH8aOEZVL3Vts9jZZpWz/io5Y3EtME9Vf+Ok3wY8qKr3FJJZX1+vDQ0NgfSOmjjcNoZhZI/n//M0+u9Vhm/PhYg8p6r1+elhtAhWA8Nc60OdNK9tVolIV6APsKHEfauSx75+Mpfe8Tw3XXg0w/rvgYjw5qbtHD/jkU7bPnvVRAb17lG28XjlO2fSvWt4gV9e8q/5yFg+deyIsv3Ez31rIgN6leF095HvxQ/Oex/nHT20bD+p1/F79+jKgmtOLzs65rGvn8zIgXuVtU8rs556jWtmF3cxfeOMg/niB0dT16Wytuv8FRs6fXux8rtnMeqK8s71xWtOp88ewVxVC97YxDk3Fncb/vdHj+DCYypr8Rej1OfrtRn/EuiYL317Erc9uZIfzCnd1fSnS05g3LC+JW8fNmGUIs8CY0RklIh0J9f5Oztvm9nAVGf5POARzTVFZgNTnKiiUcAY4JkQdEqckQP34i9fOZHhA/ZsK7D27+vd5Tqod3kFJsAzV50aqhHw47MnjKJbXReOHz2grP3KNQKlctMnx3N+/bCKOstOH7tvp7RF/3UGdV2EWz51dFnHqtQIAHz62BFFtzl3/BAu+dCBFRsBgPyAo9dm/Asiwh+/fHzJx9ize11gIwBwyH6d3Z1eRGUESqUcI+DFM1eeSs9udfzrSQeUtV+p1ycqApckqtoEXArMAZYBd6vqEhG5TkTOdja7DRjgdAZfBkx39l0C3E2uY/mvwCW1EDFUKuOG9eXFa06vaN99epfe2V0qd3zh2A7rT00/pW3ZqxD14zcX53cRlcafL/1A0W3OOmJwRccGuPGT4zusv/TtSW3Lhw/Zu+TjPPr1kyvWAaBLCYX75WccEkgGdAxyWHD1aW3Lw/qX3im75L/Cieju2a14SNzMT5dnjNPGH758PPs4QShd60ovWhu+NbGk6xMloVQpVfUBVT1IVUer6vVO2tWqOttZ3qGq56vqgao6oTXCyMm73tnvYFUNJ04txbx4dXvB/6dLTqiotjW8jBe5HI5z1fr/d8q4Di2YcmrgHxgzsCL5BwyqvJZdCt3quvD9j70PgPHD+3Z4+Xr3KP0+jArQGiiV/foEN/St0yIfP3oAffds9ynXlXEvww5TLMTph+0Xmywvfn3xhLL3ufWidnf7+OH9KpI7MKLWczmE0UdglEGfPbvR8K2JbPT5uKwUPl4/NESNOrL8+jO5b8GbnH3k/h3SP/y+wSX5tSeM7B+VaowdXHqt3Y9TD90HgAuP6eie6dm9tDrRqYfsE1iHuDhkcM7d8JnjR3ZI71diR2PPbtkaeODgCtwzE8fuy5T3D+PscfsX3zjFmCFIgIG9elRcC/i3U8dwyYfCDR1z062uC+cd3dnQlOrzv/uLx4WtUhtXnBXcXTKgVw9PP3CPrqU1zWde1CngInTqR1RWs8xnoM+5lsqCqytzW1YrlbpbZzitzEoI2icRFtky+TXAl08eHWtzvRyCdl53K+JXrR8RXWujVIJ03pbKTZ8aX3yjGIjTb/34N06OXMYxo/yfn2pq6UWBGYIqYtJh+yXeqVSIL31wdKD9ixmSPbone+4/vdD746CwiSIQoBz279OTX3z2/cU3DJERA6Lvd5lWIJKnPkKXph+lBEfEhbmGqoQ9u9dxS4qjKpZedwZ7pNhIBWXZdZMSN0Rxcde/HldWZFG1UChMO+7JYZ74xocYPiA919haBFXCgfv0SlqFguzZvWtqXVZhELYR+MCBlUVWxUFURuDKEPp4gvC+oX19804+OF7XUI+UdcSnSxvDl5aAQ4EY6cKrQ77WOf/oYcU3SogjhvoPDhcFaXudzRBUCX33qGxskWrj5IMHeaaX80FbNXBcmV9q1wKlhq1mgRhiDsrCDEGKOL9ALfF/p4yLT5EyufdL4YWMftGnwzntrrFy2beMYdCN2uKYUf3bvkBOC2YIUkQhP2VUY/eEwdEhhnUe6ePH/WQJ4/NExZmHJ/vFa5zc/2/piWSJgn0qGNcrbKbmfeCXBswQpIgTD/LuQKzk0/dqxa9TNsmW9I0XxhfXf2TMvup8Dts/Wvl994x2wp1izLvi1ETlA0w8NH1uTjMEKUJ9ItjSMBZJnFQ61npURBUM9aOPH9kpLcAUxVXB3y//UKLySxnwL2riGDW4XNKnUYbxmxIzyATmUXNABAOwpaHW5iaqsNhzx3fuE0rzvQ6D3j2TbREY3pghSBF+ZUDaQs3cfOTI8AfbSmONKS6SDBPOH5yuVnEPyW3kyO4bl0L8pg0d3DddEQZuvjqx8xzGUdC1Lpkm/T0RDqIHcNFxHTvBh/hMXhQH1559WCxybvhER5dY7x7xDnDgHpLbyGGGIEV4tQi+fPLoVPcRxPU1cVLj70Q9Bs1eeYXg1047KFJ5aWDP7h3P+bpz4jFAaeDWGEavrYRAhkBE+ovIQyKy3PnvNH6uiIwTkadFZImILBSRT7jyfikiK0VkgfMbF0Sfasevj8CoXfIniSk2Amst0CPP9de1S+2fcysTU/phZNA7MB2Yq6pjgLnOej7bgItU9TBgEvBjEenryv+Gqo5zfgsC6lPVeHmGsmoajjsgG1/efirB7yOS4qQxHb8eT+IZf/KbyUYvpY2ghmAyMMtZngWck7+Bqr6iqsud5TeBdYD3OAIZx8YTaudXF0/o5EuuRfbr05OV3z2rbX1ov+T6COKiSxfpMATzyARG4Rzab8+2zvGszcTmRdArsK+qrnGW1wIF2z0iMgHoDrzqSr7ecRndICK+znARmSYiDSLSsH79+oBqpxPPFkFGbUO3ui589KhsDMwmIkx5/zAOH7J3pz6DWuWIoX04x5nesdCooFHylVMO5LSx+zL/yomRHP+QCqa+TIqiT52IPAx4fWN/lXtFVVVEfIstERkM/BqYqtr26dQV5AxId2Am8E3gOq/9VXWmsw319fU1WTzW8CjOFTP3Pz6Y6s7ysAgy3WG18uMpR/HjKfFM9uPFgF49+HmEnbdxzGYXFkVbBKo6UVUP9/jdB7zlFPCtBf06r2OIyN7A/cBVqjrPdew1mmMn8AsgO2MpeDC4T2e3QJo6kA/eN/4azuhBveizRzwfIf3uC8fEIicNJBmmmhXOGTckaRVKJqhraDYw1VmeCtyXv4GIdAf+CPxKVe/Jy2s1IkKuf2FxQH1qjrhjrLPMgL1qv+XRyoyPHZG0CjXP508clbQKJRPUEMwAThOR5cBEZx0RqReRW51tPg6cBHzGI0z0tyKyCFgEDAS+E1CfmuOwIckOQuam1l1XaWp9GdVPNc3YF6i6qaobgE4Dw6hqA/B5Z/k3wG989j8liPws8KGYp9Arh7hcNnGR1Y55w7C4KaNi/IbEqFZq7HQMo2TMEBgVU01N31Iw15CRVcwQGCWTX/DXmB0wjMxihsAomVov9801ZGQVMwRGxVx8QvWExxmG4Y8ZAqNk8l1BfRKef9aoHGv9GG7MEBgVU2uuIiscjaxihsAomVrvHLaoISOrmCEwSkZqrg3QEWsRGFnFDIFhGEbGMUNglEztu4YMI5uYITBKpsbtQM0NmWEYpWKGwKicWm8iGEZGMENglE6NF/xZag9k6VyN4pghMEqmts2AYWSXQIZARPqLyEMistz57+ezXbNrUprZrvRRIjJfRBpF5C5nNjOjSqg1w2BdBEZWCdoimA7MVdUxwFxn3YvtqjrO+Z3tSv8ecIOqHghsBC4OqI8RI7VWblpnsZFVghqCycAsZ3kWuXmHS8KZp/gUoHUe47L2N+KnxrsIDCOzBDUE+6rqGmd5LbCvz3Y9RaRBROaJyDlO2gBgk6o2OeurgCF+gkRkmnOMhvXr1wdU26iEWrcD1h4wskrROYtF5GFgP4+sq9wrqqoi4vcujVDV1SJyAPCIM2H95nIUVdWZwEyA+vp6e2dTQK0bBsPICkUNgapO9MsTkbdEZLCqrhGRwcA6n2Osdv5XiMhjwFHAvUBfEenqtAqGAqsrOAcjJmptasp8rIvAyCpBXUOzganO8lTgvvwNRKSfiPRwlgcCJwBLNdcz9yhwXqH9jfRQ22bAOouN7BLUEMwAThOR5cBEZx0RqReRW51tDgUaRORFcgX/DFVd6uR9E7hMRBrJ9RncFlAfwzBK4LD9905aBSNFFHUNFUJVNwCneqQ3AJ93lp8CjvDZfwUwIYgORnxMGNWfhtc3Jq1GZPTbKzufsQzs1SNpFYwUYV8WGyUzeZxvUFdNcNC+vZNWwTASwQyBYRhGxjFDYBiGkXHMEBglU+PRo4aRWcwQGBVjhsEwagMzBEbFWNi9YdQGZghSxqiBeyWtgi/7990jaRUMw4gAMwQpY0CKY9l79Qj02YlhGCnFDEHKOOuIwUmrUDLWR2AYtYEZgpTRpYoKV+sjMIzawAyBUTFdrElgGDWBGYKUUU1DPVdT68UwDH/MEBiGD9Y5bmQFMwRGxQzqXdsjWF79kbFJq2DUEIP79ExaBV/MEKSMKvIMceqhflNU1wY9umbn9ThmVP+kVah5xg/vl7QKvmTnSTcMw5fPnjAqaRWMBAlkCESkv4g8JCLLnf9OJk9EPiQiC1y/HSJyjpP3SxFZ6cobF0QfwzAqo5paokb4BG0RTAfmquoYYK6z3gFVfVRVx6nqOOAUYBvwN9cm32jNV9UFAfWpeux9NAwjboIagsnALGd5FnBOke3PAx5U1W0B5RqGYRghEdQQ7Kuqa5zltUCx3sMpwB15adeLyEIRuUFEfMNQRGSaiDSISMP69esDqGwYhmG4KWoIRORhEVns8Zvs3k5VFfAddEBEBpObxH6OK/kK4BDg/UB/4Jt++6vqTFWtV9X6QYMGFVO7ejFnrWEYMVP0ixlVneiXJyJvichgVV3jFPTrChzq48AfVXW369itrYmdIvIL4Osl6m0YkTPp8P2SVsEwYiGoa2g2MNVZngrcV2DbC8hzCznGA8mNq3AOsDigPoYRGj261iWtQmwMsbkmImf4gD2TVsGXoIZgBnCaiCwHJjrriEi9iNzaupGIjASGAY/n7f9bEVkELAIGAt8JqE/V43YM/emSExLTw8gWhw/pk7QKNc9lpx2UtAq+BBpMRVU3AKd6pDcAn3etvwYM8djulCDya52uNqqbYdQM3erS+/1uejXLKKeNre1hGwzDSB9mCFLGvnund2AqwzDKo2e36ihiq0NLwzAMIzLMEBiGYUREtUznaobAMAwj45ghMAzDyDhmCAzDMCKiWkaMMUNgGIaRccwQpJhq6WgyDMObanmHzRAYhmFkHDMEhmEYGccMgWEYRsYxQ2AYhhERFjVkBGZov/SOEV9nI6MaRlGss9gITL+9uietgi/zr+w0+nhN8dkTRiatQmx87oRRSatgJIwZAqMienar7dm7Dtq3d9IqxMbhQ/ZOWgUjYQIZAhE5X0SWiEiLiNQX2G6SiLwsIo0iMt2VPkpE5jvpd4lIeqvAhlGjHDCoV9Iq1Cx7dq/r8J9WgrYIFgPnAk/4bSAidcCNwJnAWOACERnrZH8PuEFVDwQ2AhcH1MeIiVqfPe2jR3WaUK/mmHhobhKkccP6JqtIDfP+kf0BuG7y4QlrUpigU1UuA5DCXeMTgEZVXeFseycwWUSWAacAFzrbzQKuBW4OolMt8KOPH8mB+6S7llarrqH/Of9IfjJ3ec2en5sbP3kUW7Y3Ja1GTdPf6ecb2Cvdzo5AhqBEhgBvuNZXAccAA4BNqtrkSvethonINGAawPDhw6PRNCWcO35o0ir48puLj2HDezuTViMyzjt6KOcdnd7rHyY9utYxqHftG7wk+c8Pj2Xs/nvzwYMGJa1KQYoaAhF5GNjPI+sqVb0vfJW8UdWZwEyA+vr6KgnKqj0+MGZg0ioYRtWwV4+uXHTcyKTVKEpRQ6CqEwPKWA0Mc60PddI2AH1FpKvTKmhNNwzDMGIkjvDRZ4ExToRQd2AKMFtVFXgUOM/ZbioQWwvDMAzDyBE0fPSjIrIKOA64X0TmOOn7i8gDAE5t/1JgDrAMuFtVlziH+CZwmYg0kuszuC2IPoZhGEb5iFbLN9Au6uvrtaGhIWk1DMMwqgoReU5VO33zZV8WG4ZhZBwzBIZhGBnHDIFhGEbGMUNgGIaRcaqys1hE1gOvV7j7QODtENWJCtMzfKpFV9MzXEzPdkaoaqfPnKvSEARBRBq8es3ThukZPtWiq+kZLqZnccw1ZBiGkXHMEBiGYWScLBqCmUkrUCKmZ/hUi66mZ7iYnkXIXB+BYRiG0ZEstggMwzAMF2YIDMMwMk6mDIGITBKRl0WkUUSmxyBvmIg8KiJLRWSJiPy7k36tiKwWkQXO7yzXPlc4+r0sImcU090Z3nu+k36XM9R3pfq+JiKLHJ0anLT+IvKQiCx3/vs56SIiP3HkLhSR8a7jTHW2Xy4iU13pRzvHb3T2LXviYxE52HXdFojIFhH5ahquqYjcLiLrRGSxKy3y6+cno0w9fyAiLzm6/FFE+jrpI0Vku+u63lKpPoXOuQw9I7/PItLDWW908kcW0rOArne59HxNRBYkfU19UdVM/IA64FXgAKA78CIwNmKZg4HxznJv4BVgLLm5mb/usf1YR68ewChH37pCugN3A1Oc5VuALwXQ9zVgYF7a94HpzvJ04HvO8lnAg4AAxwLznfT+wArnv5+z3M/Je8bZVpx9zwzhnq4FRqThmgInAeOBxXFePz8ZZep5OtDVWf6eS8+R7u3yjlOWPn7nXKaekd9n4MvALc7yFOCuSu59Xv4PgauTvqZ+vyy1CCYAjaq6QlV3AXcCk6MUqKprVPV5Z3krufkYfOdldvS5U1V3qupKoNHR21N3p7ZwCnCPs/8s4JyQT2Oyc9z8408GfqU55pGbbW4wcAbwkKq+o6obgYeASU7e3qo6T3NP8K9C0PVU4FVVLfSVeWzXVFWfAN7xkB/19fOTUbKeqvo3bZ8/fB65GQN9qVAfv3MuWc8ChHmf3frfA5zaWjOvRFdn348DdxQ6RhzX1I8sGYIhwBuu9VUULpRDxWleHgXMd5IudZpyt7ua8n46+qUPADa5XuCg56TA30TkORGZ5qTtq6prnOW1wL4V6jrEWc5PD8IUOr5cabymcVw/PxmV8jlytcxWRonICyLyuIic6NK/XH3Cegejvs9t+zj5m53tK+VE4C1VXe5KS9U1zZIhSAwR6QXcC3xVVbcANwOjgXHAGnLNxjTwAVUdD5wJXCIiJ7kznVpKKuKNHX/u2cDvnaS0XtM24rh+QWWIyFVAE/BbJ2kNMFxVjwIuA34nInvHpY8Hqb/PHlxAxwpL2q5ppgzBamCYa32okxYpItKNnBH4rar+AUBV31LVZlVtAX5OrvlaSEe/9A3kmoJd89IrQlVXO//rgD86er3V2tR0/tdVqOtqOrobgl7/M4HnVfUtR+dUXlPiuX5+MspCRD4DfBj4pFPY4LhaNjjLz5Hztx9UoT6B38GY7nPbPk5+H2f7snH2Pxe4y3UOqbqmkC1D8CwwxokU6E7OrTA7SoGOb/A2YJmq/siV7vbhfRRojTSYDUxxohZGAWPIdR556u68rI8C5zn7TwXuq1DXvUSkd+syuc7DxY5OrZEr7uPPBi5yohaOBTY7Tdc5wOki0s9ptp8OzHHytojIsc51uahSXR061LLSeE1d8qO+fn4ySkZEJgGXA2er6jZX+iARqXOWDyB3/VZUqI/fOZejZxz32a3/ecAjrYaxAiYCL6lqm8snbdcUyE7UkLb3sL9CzgJfFYO8D5Brwi0EFji/s4BfA4uc9NnAYNc+Vzn6vYwrqsZPd3LREM+Q6xz7PdCjQl0PIBdR8SKwpFUGOd/oXGA58DDQ30kX4EZHn0VAvetYn3P0aQQ+60qvJ/fivgr8FOfL9gp03YtcDa2PKy3xa0rOMK0BdpPz1V4cx/Xzk1Gmno3kfM2tz2lr1MzHnOdhAfA88JFK9Sl0zmXoGfl9Bno6641O/gGV3Hsn/ZfAF/O2Teya+v1siAnDMIyMkyXXkGEYhuGBGQLDMIyMY4bAMAwj45ghMAzDyDhmCAzDMDKOGQLDMIyMY4bAMAwj4/w/ufPS426B7TUAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "_,ax=plt.subplots(1,1)\n", "cleaned=clean_vad([signal_vad_q15(w) for w in slices_q15])\n", "vad_q15 = np.array([[w]*winOverlap for w in cleaned]).flatten()\n", "#vad = np.array([[signal_vad(w)]*winOverlap for w in slices]).flatten()\n", "ax.plot(data)\n", "#ax.plot(vad)\n", "ax.plot(vad_q15)" ] }, { "cell_type": "markdown", "id": "1576979d", "metadata": {}, "source": [ "### CMSIS-DSP Q31 Implementation" ] }, { "cell_type": "code", "execution_count": 12, "id": "51e5db4f", "metadata": {}, "outputs": [], "source": [ "def signal_energy_q31(window):\n", " mean=dsp.arm_mean_q31(window)\n", " window=dsp.arm_offset_q31(window,-mean)\n", " energy=dsp.arm_power_q31(window)\n", " # Energy is not in q31 (refer to CMSIS-DSP documentation)\n", " # If the scaling is not enough the int conversion will fail.\n", " scaled=energy>>25 \n", " if scaled > 0x7FFFFFFF:\n", " energy=0x7FFFFFFF\n", " elif scaled < -0x80000000:\n", " energy=-0x80000000\n", " else:\n", " energy=int(energy>>25)\n", " # The shift is by more than 17, so the result is not in q31\n", " # (With a shift smaller there is a saturation and int conversion is failing)\n", " dB=dsp.arm_vlog_q31([energy])\n", " # The output of the vlog is not in q15\n", " # The multiplication by 10 is missing.\n", " # The result of this function is not \"equal\" to the float implementation due to the different\n", " # formats used in the intermediate computations.\n", " return(dB[0])\n", " \n", "def signal_vad_q31(window):\n", " # The threshold is not easily related to the float implementation because\n", " # of the different intermediate formats used in the fixed poitn implementation\n", " if signal_energy_q31(window)>fix.toQ31(-0.255):\n", " return(1)\n", " else:\n", " return(0)" ] }, { "cell_type": "code", "execution_count": 13, "id": "3e9e5692", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "_,ax=plt.subplots(1,1)\n", "cleaned=clean_vad([signal_vad_q31(w) for w in slices_q31])\n", "vad_q31 = np.array([[w]*winOverlap for w in cleaned]).flatten()\n", "ax.plot(data)\n", "#ax.plot(vad)\n", "ax.plot(vad_q31)" ] }, { "cell_type": "markdown", "id": "7e278fc7", "metadata": {}, "source": [ "## Noise suppression" ] }, { "cell_type": "markdown", "id": "964c42e4", "metadata": {}, "source": [ "Each window of samples extracted from the signal is multiplied by a Hann window in below algorithms." ] }, { "cell_type": "code", "execution_count": 14, "id": "d780cca7", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "window=hann(winLength,sym=False)\n", "plt.plot(window)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "35aa4c9c", "metadata": {}, "source": [ "### Double reference implementation" ] }, { "cell_type": "markdown", "id": "f82508ce", "metadata": {}, "source": [ "Test of the overlap and add:" ] }, { "cell_type": "code", "execution_count": 15, "id": "4ae681e4", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Overlap and add\n", "offsets = range(0, len(data),winOverlap)\n", "offsets=offsets[0:len(slices)]\n", "res=np.zeros(len(data))\n", "i=0\n", "for n in offsets:\n", " res[n:n+winLength] += slices[i]*window\n", " i=i+1\n", "plt.plot(res)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 16, "id": "e8c4ce02", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "audio2=Audio(data=res,rate=samplerate,autoplay=False)\n", "audio2" ] }, { "cell_type": "markdown", "id": "6f5beccc", "metadata": {}, "source": [ "#### Reference noise suppression algorithm " ] }, { "cell_type": "code", "execution_count": 17, "id": "cca944e1", "metadata": {}, "outputs": [], "source": [ "def fft_length(length):\n", " result=2\n", " fft_shift=1\n", " while result < length:\n", " result = 2*result\n", " fft_shift = fft_shift + 1\n", " return(result,fft_shift)" ] }, { "cell_type": "code", "execution_count": 18, "id": "5706f45c", "metadata": {}, "outputs": [], "source": [ "class NoiseSuppression():\n", " def __init__(self,slices):\n", " self._windowLength=len(slices[0])\n", " self._fftLen,self._fftShift=fft_length(self._windowLength)\n", " \n", " self._padding_left=(self._fftLen - self._windowLength)//2 \n", " self._padding_right=self._fftLen- self._windowLength-self._padding_left\n", " \n", " self._signal=[]\n", " self._slices=slices\n", " self._window=None\n", " \n", " def window_and_pad(self,w):\n", " if w.dtype==np.int32:\n", " w=dsp.arm_mult_q31(w,self._window)\n", " elif w.dtype==np.int16:\n", " w=dsp.arm_mult_q15(w,self._window)\n", " else:\n", " w = w*self._window\n", " sig=np.hstack([np.zeros(self._padding_left,dtype=w.dtype),w,np.zeros(self._padding_right,dtype=w.dtype)])\n", " return(sig)\n", " \n", " def remove_padding(self,w):\n", " return(w[self._padding_left:self._padding_left+self._windowLength])\n", " " ] }, { "cell_type": "code", "execution_count": 19, "id": "69d451f5", "metadata": {}, "outputs": [], "source": [ "class NoiseSuppressionReference(NoiseSuppression):\n", " def __init__(self,slices):\n", " # In a better version this could be computed from the signal length by taking the\n", " # smaller power of two greater than the signal length.\n", " NoiseSuppression.__init__(self,slices)\n", " \n", " # Compute the vad signal\n", " self._vad=clean_vad([signal_vad(w) for w in slices])\n", " self._noise=np.zeros(self._fftLen)\n", " # The Hann window\n", " self._window=hann(self._windowLength,sym=False)\n", " \n", " # Subtract the noise\n", " def subnoise(self,v):\n", " # This is a Wiener estimate\n", " energy = v * np.conj(v) + 1e-6\n", " \n", " scaling = (energy - self._noise)/energy\n", " scaling[scaling<0] = 0\n", " \n", " return(v * scaling)\n", " \n", " def remove_noise(self,w):\n", " # We pad the signal with zero. It assumes that the padding can be divided by 2.\n", " # In a better implementation we would manage also the odd case.\n", " # The padding is required because the FFT has a length which is greater than the length of\n", " # the window\n", " sig=self.window_and_pad(w)\n", " \n", " # FFT\n", " fft=np.fft.fft(sig)\n", " # Noise suppression\n", " fft = self.subnoise(fft)\n", " # IFFT\n", " res=np.fft.ifft(fft)\n", " # We assume the result should be real so we just ignore the imaginary part\n", " res=np.real(res)\n", " # We remove the padding\n", " res=self.remove_padding(res)\n", " return(res)\n", " \n", " \n", " \n", " def estimate_noise(self,w):\n", " # Compute the padded signal\n", " sig=self.window_and_pad(w)\n", " fft=np.fft.fft(sig)\n", " \n", " # Estimate the noise energy\n", " self._noise = np.abs(fft)*np.abs(fft)\n", " \n", " # Remove the noise\n", " fft = self.subnoise(fft)\n", " \n", " # IFFT and we assume the result is real so we ignore imaginary part\n", " res=np.fft.ifft(fft)\n", " res=np.real(res)\n", " res=self.remove_padding(res)\n", " return(res)\n", " \n", " # Process all the windows using the VAD detection\n", " def nr(self):\n", " for (w,v) in zip(self._slices,self._vad):\n", " result=None\n", " if v==1:\n", " # If voice detected, we only remove the noise\n", " result=self.remove_noise(w)\n", " else:\n", " # If no voice detected, we update the noise estimate\n", " result=self.estimate_noise(w)\n", " self._signal.append(result)\n", " \n", " # Overlap and add to rebuild the signal\n", " def overlap_and_add(self):\n", " offsets = range(0, len(self._signal)*winOverlap,winOverlap)\n", " offsets=offsets[0:len(self._signal)]\n", " res=np.zeros(len(data))\n", " i=0\n", " for n in offsets:\n", " res[n:n+winLength]+=self._signal[i]\n", " i=i+1\n", " return(res)\n", " " ] }, { "cell_type": "code", "execution_count": 20, "id": "3915dc37", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "n=NoiseSuppressionReference(slices)\n", "n.nr()\n", "cleaned=n.overlap_and_add()\n", "plt.plot(cleaned)\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "f12a6f54", "metadata": {}, "source": [ "The audio to check the result:" ] }, { "cell_type": "code", "execution_count": 21, "id": "3091d6f5", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "audioRef=Audio(data=cleaned,rate=samplerate,autoplay=False)\n", "audioRef" ] }, { "cell_type": "markdown", "id": "8ee5a76d", "metadata": {}, "source": [ "### CMSIS-DSP Implementations" ] }, { "cell_type": "markdown", "id": "73276ee1", "metadata": {}, "source": [ "Test of the overlap and add. The Hann window is converted to Q15. The CMSIS-DSP functions are not used for this conversions because it is assumed that this conversion is done outside of CMSIS-DSP and the final code (Python or C) is using an array of Q15 values." ] }, { "cell_type": "code", "execution_count": 22, "id": "d0313891", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "offsets = range(0, len(data),winOverlap)\n", "offsets=offsets[0:len(slices_q15)]\n", "res=np.zeros(len(data))\n", "window_q15=fix.toQ15(window)\n", "i=0\n", "for n in offsets:\n", " w = dsp.arm_mult_q15(slices_q15[i],window_q15)\n", " res[n:n+winLength] = dsp.arm_add_q15(res[n:n+winLength],w)\n", " i=i+1\n", "res_q15=fix.Q15toF32(res)\n", "plt.plot(res_q15)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 23, "id": "b7518435", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "audio4=Audio(data=res_q15,rate=samplerate,autoplay=False)\n", "audio4" ] }, { "cell_type": "markdown", "id": "dafab1bf", "metadata": {}, "source": [ "Utilities functions since there is no specific datatype for complex in CMSIS-DSP. An array of complex is thus represented as an array of reals (of twice the number of samples)." ] }, { "cell_type": "code", "execution_count": 24, "id": "3a1be0da", "metadata": {}, "outputs": [], "source": [ "def imToReal1D(a):\n", " ar=np.zeros(np.array(a.shape) * 2)\n", " ar[0::2]=a.real\n", " ar[1::2]=a.imag\n", " return(ar)\n", "\n", "def realToIm1D(ar):\n", " return(ar[0::2] + 1j * ar[1::2])" ] }, { "cell_type": "markdown", "id": "cc594498", "metadata": {}, "source": [ "#### CMSIS-DSP F32 noise suppression algorithm" ] }, { "cell_type": "code", "execution_count": 25, "id": "328c0eee", "metadata": {}, "outputs": [], "source": [ "class NoiseSuppressionF32(NoiseSuppression):\n", " def __init__(self,slices):\n", " NoiseSuppression.__init__(self,slices)\n", "\n", " # VAD signal\n", " self._vad= clean_vad(np.array([signal_vad(w) for w in slices]))\n", " self._noise=np.zeros(self._fftLen,dtype=np.float32)\n", " # The Hann window\n", " self._window=hann(self._windowLength,sym=False)\n", " # CFTT F32 instance\n", " self._cfftF32=dsp.arm_cfft_instance_f32()\n", " status=dsp.arm_cfft_init_f32(self._cfftF32,self._fftLen)\n", " \n", " \n", " # Subtract the noise\n", " def subnoise(self,v):\n", " energy = dsp.arm_cmplx_mag_squared_f32(v)\n", " # To avoid division by zeros\n", " energy = dsp.arm_offset_f32(energy,1e-6)\n", " \n", " temp = dsp.arm_sub_f32(energy , self._noise)\n", " # C implementation will have to loop on the array and replace negative vaues\n", " temp[temp<0]=0\n", " \n", " scaling = np.zeros(len(temp),dtype=np.float32)\n", " # C implementation will have to loop on the arrays here\n", " scaling = temp / energy\n", " \n", " res=dsp.arm_cmplx_mult_real_f32(v,scaling) \n", " \n", " return(res)\n", " \n", " def remove_noise(self,w):\n", " sig=self.window_and_pad(w)\n", " \n", " # Convert real signal to complex \n", " signalR=np.zeros(len(sig) * 2)\n", " signalR[0::2]=sig\n", " \n", " resultR = dsp.arm_cfft_f32(self._cfftF32,signalR,0,1)\n", " \n", " # Remove the noise\n", " resultR = self.subnoise(resultR)\n", "\n", " # Inverse FFT and we keep only the real part\n", " res = dsp.arm_cfft_f32(self._cfftF32,resultR,1,1)*self._fftLen\n", " res=res[0::2]\n", " # Remove the padding\n", " res=self.remove_padding(res)\n", " return(res)\n", " \n", " def estimate_noise(self,w):\n", " sig=self.window_and_pad(w)\n", " \n", " signalR=np.zeros(len(sig) * 2)\n", " signalR[0::2]=sig\n", " \n", " resultR = dsp.arm_cfft_f32(self._cfftF32,signalR,0,1)\n", "\n", " self._noise = dsp.arm_cmplx_mag_squared_f32(resultR)\n", " \n", " # Set noise to zero. In reference code we substract the noise.\n", " # It is giving the same result with the noise estimation used.\n", " resultR = np.zeros(len(resultR),dtype=np.float32)\n", " \n", " # Not really needed since we set the values to zero. We could\n", " # just set the output to zero.\n", " # But in a more compelx algorithm we may still need to do the IFFT\n", " # so the line is kept.\n", " res = dsp.arm_cfft_f32(self._cfftF32,resultR,1,1)*self._fftLen\n", " \n", " res=res[0::2]\n", " res=self.remove_padding(res)\n", " return(res)\n", " \n", " def nr(self):\n", " for (w,v) in zip(self._slices,self._vad):\n", " result=None\n", " if v==1:\n", " result=self.remove_noise(w)\n", " else:\n", " result=self.estimate_noise(w)\n", " self._signal.append(result)\n", " \n", " def overlap_and_add(self):\n", " nbSamples = len(self._signal)*winOverlap\n", " offsets = range(0, nbSamples,winOverlap)\n", " offsets=offsets[0:len(self._signal)]\n", " res=np.zeros(nbSamples)\n", " i=0\n", " for n in offsets:\n", " res[n:n+winLength] = dsp.arm_add_f32(res[n:n+winLength],self._signal[i])\n", " i=i+1\n", " return(res)\n", " " ] }, { "cell_type": "code", "execution_count": 26, "id": "cca48f75", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX8AAAD4CAYAAAAEhuazAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAd/klEQVR4nO3deZQU1b0H8O+P2VhkmWETh8EBxQU30BE17sqTJRqM28OXF43mPcyL5mQ5xoMxL88TNYsxyzEaffjE5b0koEYCURMVAyoGhUFRQB0YxkEcEYYdWQYG7vuja4aanq7q6e6qurfqfj/nzJnuqu6qX1dX/frWrVv3ilIKRERkl266AyAiougx+RMRWYjJn4jIQkz+REQWYvInIrJQse4AumLAgAGqurpadxhERLGydOnSTUqpgZnmxSL5V1dXo7a2VncYRESxIiJrveax2oeIyEJM/kREFmLyJyKyEJM/EZGFmPyJiCzE5E9EZCEmfyIiCzH5ExEFqHHTLixcvUl3GFkx+Rvg7Y+3onra8/jxX97XHUpGC+o24lcvr9IdRmhWNG3H8k+26w4jEk8uakT1tOexq6VVdyiJdcF9C/Cvj76FvfsP6A7FF5O/Ae57sQ4AMOONjzRHktnXHluC+19ZrTuM0Fz624W47IGF2Lhzr+5QQvejOSsBAA3NuzRHkny/NrzAxORvgH+s2aw7BE/rt+/RHUKo3CPZbdjeojESSppHXm/QHYIvJn/y9fcPN7Y//u9X12iMJBz7DxxK/pc9sFBjJOHbsXd/++Okf1YTHFTAx5t36w7DE5O/YZau3aI7BE8//euHukOgAqiDuiOwz/6D5m50Jn/DPLTA7FNFIkoGJn8iW4juAMgkTP7kS5gxiBKJyZ+IKCSuxmTGYfInsoTwJI5cmPyNY3BRgYgSg8mffLG0SJRMTP5kNWXRmRZ/x8mNyZ+IyEJM/kREoTH3zJLJ3zAmNw2jeBNewCEXJn8iIgsx+RMRWYjJn8gSrPQhNyZ/IqKQmHwNj8nfMAbvKxRz67aaO7AIRY/Jn3zVfbZTdwih+mB9sj+f2+urNukOwToHDS7NMfkbZs++A7pD6ODxfzTqDiFUb6/d2uH5xh3JH8SdovOwwUOfMvkbZlGDuYO526Cl1dxh9wqV3sx/3RZWAwVNpVXyz36nSVMk2TH5E1lq34Hk/tBRdkz+REQWYvInq7HHAwqSyU070zH5ExFZiMmfyFJxKqVS8Jj8iYgsxORPVmOVPwUpTidTTP5ERBZi8ierpZfU9uw36w7rILGOP3zpN3mZrDjsFYhII4CdAA4AaFVK1YhIBYBZAKoBNAK4Rim11WsZRGFJP1Zb9if3xqfOg9XHJ1HFRZy2aFQl/wuVUqOVUjXO82kAXlFKjQTwivOcSLvOCZIomXRV+0wG8ITz+AkAl2uKg6iDGJ21ExUkiuSvALwkIktFZKozbbBSar3z+DMAg9PfJCJTRaRWRGqbm5sjCJNs9LFFnZu9/P4G3SEk3oqm7bpD6LLQ6/wBnKOUahKRQQBeFpEP3TOVUkpEOpW3lFLTAUwHgJqaGpbHKBTpXVYneUdb0tjxshrPcoK3dG18Ll2GXvJXSjU5/zcCmA1gLIANIjIEAJz/G8OOg4iIDgk1+YtILxHp3fYYwCUAVgCYC+B652XXA5gTZhxE1Bk7tQtenM6mwq72GQxgtqT2smIAf1BK/U1ElgB4SkS+DmAtgGtCjoOoS+LUTpvME6fWYqEmf6VUA4BTMkzfDODiMNdNRETeeIcvkaV4kmM3Jn8iF+ZDKkScflCZ/Cknn27bozuEUCW5e4d0Se7HSJeDTP6UVDHat/Py6MIG3SFE5tGFH+kOIXGWN23THUKXMflrdjBORQUA23fv1x1CqFpa7Sn572phyT9oLyz/THcIXcbkr9mrq+PVdcXmXS26QwhVnOpsCzXvA3b3YDMmf832W1TSjIM4tdMmKgSTP5GLTSV/shuTP5EmF/xiPr43a5nuMCL1q5dX4Zmln+gOg8Dkr53ErIOVsEvG8+s2onra8/jzO03hrshDea/SSNbT0noAjZt341lNn1OHBXUbcf8rq3Hr0+9qi+GR1xpQPe157N7Xqi0GUzD5a8a+ZDq64bElAIA5y/QkxR4lRZGs574X6yJZj0lWb/hcdwi454UPAADNO5PdcKErmPwNtOlzc3fMME9UnlzU2P74k616biaLokrirJ++gkdet6uN/XufbGtPvLosXbtF6/pNw+SvWaZqn5q752mIRL8fzVnZ/nhjgktm67fv1R1C5L70wBta19+4aReufGiR1hhMw+RPOVm3JdndO1Ay3feSvmq2vYZ2o8Hkr1m8LvcCP5i9HBt2hF9y1XkdfNm6bfpWHrHn3vtUdwiR0Hll7bpHF2tcuzcmf/LkdTHa5GsSQXj2bXuaItY2xmfM2UI8/976Ds8lwmLX4kYzrzUw+Wtmcluf5giT/Gdp9eDbEtqHUKYf1O17kvlZ/azbslvr+j/dzupLJn/NZi1ZpzsEbxH+Ms1c8nF0K9NoxhuNnabpToRhW7q289nF3z/cqCGSQ6ZMf1Pr+k3A5K9ZHDvXCuOU+TfzVge+TBPd9dz7ukOI3OP/aNS6fhvPrLqCyd9QRrQQ8MjxBwO+MW3Vhp2BLq9QTy5aG8pyvb5Tnff5RXFfw1/e1XtR+ZUYFrCiwORvqP97M5wElIs9+zInq0t/uzDQ9TRu2hXo8ky1w6MEqrMn0c9b9HRzEOWd7f/lun+EDmHyN9S+A/q7en741WhGtfqxpqqQqBOfzu905149VR8rmrZnnB7lz91OTT9wpmPyN5QJ/aDsjyhZ6erKYXPETVZnLGzMOD2KQvCWXfvCX0kGa5oz78fs0ko/Jn9DmVDyp2A1bPJIhBHHEaU752aucknyZ44LJn/Ki66SZJwtqMs8ZOfjbyS3k7etHvdrLFqzOZL1m9Jr7szF5jVlZvI3lAldzvodN/Ub9VdLhelvK6IbiHvBKr3jOL/ZEE0idouqifPazWbcQzHt2eW6Q+iEyd9Qiz/aghseW4ytGkvYTdu8D5ygSlQHD3ov54DPvCD43a/gVV0RV36fNckja7UeZPWpFyZ/g82va8YfNJ4urvx0h+e8Z98OZrCVva3e9zNE0YGcl8927MWSiPpk0V0zkeTk/59/NudH/Lx756PVoGt5TP7kzScpzapdh9oAkmPIhfuCXP1wNP2/B33THB2ySEOVlpePt+w2aiwHJn/Dmdz9w1UBJMe3fA5OW1KiCd16321htxOmXAzWhcnfcO98vE3buqM4NPy6u91jySDbO/aG/zmzjY/wPwuT2+LIS1J7ju0qJn/S6sAB75+Y/T7ziOLIpJMNJn/yFMVp8S6f0v0b9ZtCXXeUo4X5tWpKqm27eS+IyZj8yVMU6eqPi73HM1j8kZkjIOVjfp3e/ut12O3RMaDNTLq4z+RPnnTvpyXF+nfPoErsOyOo1zeNSYnOFCZtE/1HF5GH9HFXdTgQ0MHa4nM/Q1IZlOcy0jHIyzaDBpbRlvxFZIKI1IlIvYhM0xUHedPZz7wpgrrLOA6jSQXdi6vpyd+ro70wzdc8fKWbluQvIkUAHgQwEcAoANeKyCgdsZA30w/eKAR1mv766nAvXgch6O40gjprCkvLfnPuttWhWNN6xwKoV0o1AICIzAQwGUCgd5rs2XcAM9J6TExvwZJp/0yflPk1uS8n32z64Pz6vN5XqJbW7AdH2LE9OL8eIqm+aVL/0f4cONRiR0Ta5wFtrzv0nrYZ7ve/9H72ztsefrUBZcXdOuw37q9RZZzW+bXZkn/Y2/GdjzsPop7uoQVrUJrhOotfqy+/XXpzln6pdO3XbZ5Y1IiGiEeR+92CNeheUpTTewb36Y6rThsaeCyi4y43EbkKwASl1L85z78K4Ayl1C2u10wFMBUAhg0bdtratbkPa7j58xacdve8YIIOkLuJoeGFIyLSbHRVP/z55rPzeq+ILFVK1WSap6vkn5VSajqA6QBQU1OTV4qs6FWKVXdP7DQ9U/vu9EmS4UWdX5NhOTk2Hq+e9nzW19TdPSGnZQbl2B/+LetrCo0t2zo+vCu1fKVSJerUfzjTUmVspQC45iP1tMN8hUNvbJv22upm3PbMe77rd+8/7q9W2qdJp2mdXiuCdVt249x753uuJ+zveM47n+K2P/l/1tofjkOf7iWdpnfleDn02kNzlFI4+o6/eq4viv3ab/966qazcEpV38jWBwBXjKnET688Kadl+vXIWghdyb8JQJXr+VBnWqBEBKXFJvScUpiy4txOE6MUdmy5niLnYkMXOtnKVA0ShrC3Y1c6FCvvWYqibkEeL/7L0r1fF3WLPoaLjh+k/XO30dXaZwmAkSIyXERKAUwBMFdTLGSpIwf00h1CZCp6dS7Rpws28Ztv1JBgS/1dcWSFOfuclpK/UqpVRG4B8CKAIgAzlFLmdLxNRjiyf89Qlz+4d1moy3fTfW3n2MP76A3AQD1Koy+BR9mlSDba6vyVUi8AeEHX+omixHsmCDAr+fMOX9LqiycN8Zx3RN8eoa4714vzhbCwXzfKoJtB2Z/Jn/L25u0XF7yMyaOP8Jx36SnePwxxY/vAIZTC5E9ddsbwCt0heDq8b/eCl+FXIk5SN8iD+xS+rSj++h9WqjuEdkz+hvvOuGN0hxAy7wTfmqDk36vM2FtqAACP3XC67hCsMOCw6BoZZMPkb7gxw/ppW3dZBG3c/Q6GoPuaSceqmEMuPHaQ7hBC8YNJx+kOod29V52sO4QOmPwNtuDWC0K9ySmbfj2ztw0vVE21d7VW2CX/bO3af/PPo0Ndf5QMqmqOVI9Sc864rqmpyv6iCDH5G6xvj/CTrx+/kvcpVf1CX/9pR5aHuvxuWZL/5WMqQ11/lEy60EhmYPInT0f0825q2ad7+CWq033OCoJgU62Prbn/klGDdYdgLCZ/g/Us09sHiF+Vk02JM2xXnBr+GYau7+vWSzI3WKiqCPcejjZsZeWNyd9QM75Wo70DqIqe3s3STBqLNC66l2Q+3Cp9zrDi7opTM/dDf9DucVSMwORPnm656GjPeaZdvMpH7wiqrtwW3zEu4/Trv1AdaRzpBoXYx9HhHiVv2woPr33/Qt0hdMLkb6gxVeFe7OwKv+6Mg7wY+v3xxwa2rFwcM7i357x53zs/8PVl6isfiP5HKN0L3z43tGV7XVQPuxmvaYaF3ElhPpj8DVXeS/+dgFEVzm6+0PsMQ5ejBx0W2brCGqzDbbRP6ywdNx5995+iu3nxpvNGRLauOGHyp5w9en3GUeHIYKb11X/c4d5nXUG7fdLxka0rTpj8KWdh9LMfxd3EJrjv6lN0h9DB1AhKxY9c17mwYFOlT0mRWT+8bew44mLmgX8ZozsEX15114WYOfXMwJeZrzAT4vgTOrc719kGP4pmphcd17nriKi71viWT+OFsJUUmZlmzYzKcpee7N3NsW7njhyAQSG0nR4zTP8F7jZhtmTqHcIPZyGOi2CEr0xVTlEnxJOH9ot0fW5mlvuZ/ClHYXe5YIIoL/YCQJGFt9+eVBn9+Lm6nH30AN0hZMTkT54yDT3IPmKCl62PoSSKchS1TH5+5UmRrev+a82sxmXyp5xYmKcoAYakDTwUZW+5Onvm9cPkTznRXWJLgl8Y1q97FKacrveO8BMr++KuySdojcE0TP6UkzBz//nHDGx/3Nvwka8KcXVNFRp+Mkl3GJG6RnPyB4CvnlXd/vi8kQO9X2gJJn/Nehh6SuglzLtRn7hxLJ771jkAwu1ywAS21fOfOqwcq++ZqDsMlDsDFJlwB71uyS1excSQft3R0LxLdxgZVZV3vpkr7FqfEyv7ovFnXwx3JYa46fwRGH/C4brDiIwJ7d1f/O55+HTbXt1hGIHJX7NvXnA0bn36Xd1hZJRp0HG7yqvhun2ifd0OvH7bhVo7shvUuzsG9WYf/wCrfbS76rTM/Z2bik09qRBVFT3Rz2ecCIoOkz/lhLmfyJvuVk25YPKnnJw5or/uEEL1jfOP0h1CZC49eYjuEBInToUjJn/KyYkJvy3/wmPtaQJ46yV6BtEhMzD5E1mqZ2m8mhlTsJj8iVxsuoPZtAFekiBOQxMz+RMRBSROZQcmfyKiwMQn+zP5ExFZiMmfiMhCTP5ELgMO492nlL++PToO09nWkZyJmPyJXMIYn5jskd58dsrYYZoiyS605C8id4pIk4gsc/4muebdLiL1IlInIuPDioGIKEpxauoZdvd6v1ZK3eeeICKjAEwBcAKAIwDME5FjlFIHQo6FiChUmca9NpWOap/JAGYqpVqUUh8BqAcwVkMcREShMvlMIOzkf4uIvCciM0Sk3JlWCWCd6zWfONM6EJGpIlIrIrXNzc0hh0lEVDiTk326gpK/iMwTkRUZ/iYDeAjAUQBGA1gP4Je5LFspNV0pVaOUqhk40J7OtkgvFaejl4wTp72noDp/pdS4rrxORB4B8JzztAmAu9Proc40IqJ4Sys8mHwNIMzWPu7Owr8MYIXzeC6AKSJSJiLDAYwEsDisOIgoM3PTEkUhzNY+94rIaKT2sUYANwGAUmqliDwF4H0ArQBuZksfIkqCTj+oBv/Chpb8lVJf9Zl3D4B7wlo3EWUXny7IKAy8w5fIxeCCGsVAensBk/cnJn8iooCYfIE3HZM/EVFA0kv+JletMfkTEQUkvdxv8nkAkz+RC+/xokLEaf9h8iciCgjr/ImIbBSf3M/kT0QUlIPp3TsYXA/E5E9EFBCDc30nTP5EbjE6eMk8nVr7GLw/MfkTWaKyXw/dISSeye360zH5E1liwomH6w4h8b5+7nDdIXQZkz9Z7bJTjtAdAiVIz9KOfWUaXOvD5E/kFqd22rmKU6djsRWjjcrkT0QUEl7wJSLjxOniZFzE6cyRyZ/IEnFKTHHVuWrN3G3O5E9WKyli+ZfsxORPVrvx7I5N80yuoyXzxWn3YfInq5UV23MITDl9mO4QrGNyYcKePZ/yMmJgL90hUEAG9i7THULilfcs0R1ClzH5k68rxlTqDoEoNkTicw2JyZ98mXzaGoSSoo6HQMI/LlE7Jn+yWveSIt0hEGnB5E9EZCEmfyIiCzH5ExGFhMM4UmyZu+sGI71xRvcSHhJkB+7pRC7p/bETFaKmukJ3CJ6Y/A1zUmVf3SGQJYq78fAP21lH9dcdgid++4YZOfgw3SFYJT635ASvb4zuRqXgMfkTEVmIyZ+IyEJM/uTL4JZqRFQAJn+ym82V/mQ1Jn8iIgsVlPxF5GoRWSkiB0WkJm3e7SJSLyJ1IjLeNX2CM61eRKYVsn4iIspPoSX/FQCuAPCae6KIjAIwBcAJACYA+J2IFIlIEYAHAUwEMArAtc5riYgoQgXdzqiU+gDIOIDBZAAzlVItAD4SkXoAY5159UqpBud9M53Xvl9IHBSN3mXJu/tVWOlPlgqrzr8SwDrX80+caV7TOxGRqSJSKyK1zc3NIYVpnuvOqtYdQgfK1bvPnFvO1hgJUfwcZnCBKWtkIjIPwOEZZt2hlJoTfEgpSqnpAKYDQE1NjTUNDkdX9dMdQgfupp5F3ZJdSjb5QA1aZb8eukOwgsmDBWXd25VS4/JYbhOAKtfzoc40+Ewnipy7xnLc8YP0BRKx06vLdYdAmoVV7TMXwBQRKROR4QBGAlgMYAmAkSIyXERKkbooPDekGIhyYs3pJREKvOArIl8G8FsAAwE8LyLLlFLjlVIrReQppC7ktgK4WSl1wHnPLQBeBFAEYIZSamVBn4CIuqRXmblVEBS9Qlv7zAYw22PePQDuyTD9BQAvFLJeis7Rg5Ldy2jv7ocOgaR3ZVFWfCj5J/yjUhfwDl/yNe74wbpDCJU7IRLZhMmfuizpJWOb8LskJn8iIgsx+RMRWYjJn8jBmhCyCZM/EZGFmPzJl7KoPKwsugpqzyclL0z+1GVMGMlh0w8dZcbkT0RkISZ/IiILMfkTEVmIyZ+IyEJM/kSOC461pz//848ZqDuExKvu31N3CL6Y/MmXu1FIccJH8jpjeIXuECJz5oj+ukNIvOOH9NEdgi8mf+qyqgqzSzKFGlpuz9CGNn1WXUwbkjUdk79Bupfw69BJJNlnNm42fVZdJpyYaehzczDbEBFZiMnfILzpkig5+vYo0R2CLyZ/A/zx388EANx1+YmaI7GXLbUgp1eX4ytnDNMdhhX69SzVHYKvgsbwpWCcdVR/1N09wcghBUuLU+WDm84boTmS8Kz5ySRYkvvx9De+oDsEMgSTvyFMTPwAUFLUDfX3TERRgpt5JvmzUfSeuuksrN28S3cYWTH5U1bFRawdJOqqscMrMDYG94zwqCYishCTPxGRhZj8iYgsxORPRGQhJn8iIgsx+RMRWYjJn4jIQkz+REQWEhWD3sREpBnA2gIWMQDApoDCCRPjDBbjDF5cYmWcKUcqpTIO2xaL5F8oEalVStXojiMbxhksxhm8uMTKOLNjtQ8RkYWY/ImILGRL8p+uO4AuYpzBYpzBi0usjDMLK+r8iYioI1tK/kRE5MLkT0RkoUQnfxGZICJ1IlIvItMiWmeViMwXkfdFZKWIfNuZfqeINInIMudvkus9tzsx1onI+Gzxi8hwEXnLmT5LRPIaLFREGkVkuRNPrTOtQkReFpHVzv9yZ7qIyP3OOt8TkVNdy7neef1qEbneNf00Z/n1zntzHjJLRI51bbNlIrJDRL5jyvYUkRkislFEVrimhb4NvdaRY5y/EJEPnVhmi0g/Z3q1iOxxbduH843H7zPnEGfo37WIlDnP65351XnEOcsVY6OILNO9PX0ppRL5B6AIwBoAIwCUAngXwKgI1jsEwKnO494AVgEYBeBOALdmeP0oJ7YyAMOdmIv84gfwFIApzuOHAfxHnrE2AhiQNu1eANOcx9MA/Nx5PAnAXwEIgDMBvOVMrwDQ4Pwvdx6XO/MWO68V570TA/hOPwNwpCnbE8B5AE4FsCLKbei1jhzjvARAsfP45644q92vS1tOTvF4feYc4wz9uwbwTQAPO4+nAJiVa5xp838J4Ee6t6ffX5JL/mMB1CulGpRS+wDMBDA57JUqpdYrpd52Hu8E8AGASp+3TAYwUynVopT6CEA9UrFnjN8pGVwE4Bnn/U8AuDzAjzDZWWb6sicDeFKlvAmgn4gMATAewMtKqS1Kqa0AXgYwwZnXRyn1pkrttU8GEOfFANYopfzu9o50eyqlXgOwJUMMYW9Dr3V0OU6l1EtKqVbn6ZsAhvotI894vD5zl+P0EeR37Y7/GQAXt5XCc43Ted81AP7oF3wU29NPkpN/JYB1ruefwD8JB845dRwD4C1n0i3OqdoM12m6V5xe0/sD2OY6aAv5XArASyKyVESmOtMGK6XWO48/AzA4zzgrncfp0wsxBR0PKNO2Z5sotqHXOvJ1I1IlyjbDReQdEXlVRM51xZ9rPEEdh2F/1+3vceZvd16fj3MBbFBKrXZNM217Jjr5ayUihwH4E4DvKKV2AHgIwFEARgNYj9RpoW7nKKVOBTARwM0icp57plMaMaItsFM3+yUATzuTTNyenUSxDQtdh4jcAaAVwO+dSesBDFNKjQHwPQB/EJE+UcWTQSy+a5dr0bGQYtr2BJDs5N8EoMr1fKgzLXQiUoJU4v+9UupZAFBKbVBKHVBKHQTwCFKnpn5xek3fjNSpXnHa9JwppZqc/xsBzHZi2tB2Gun835hnnE3oWI1Q6PafCOBtpdQGJ2bjtqdLFNvQax05EZGvAbgUwFecJAOnGmWz83gpUvXnx+QZT8HHYUTfdft7nPl9ndfnxHnvFQBmueI3anu2SXLyXwJgpHN1vxSpKoO5Ya/Uqe97FMAHSqlfuaa76+W+DKCtlcBcAFOc1gbDAYxE6iJQxvidA3Q+gKuc918PYE4ecfYSkd5tj5G6+LfCiaettYl72XMBXOe0NjgTwHbntPRFAJeISLlzOn4JgBedeTtE5Exnm1yXT5wuHUpTpm3PNFFsQ691dJmITABwG4AvKaV2u6YPFJEi5/EIpLZhQ57xeH3mXOKM4rt2x38VgL+3/RjmaByAD5VS7dU5pm3PdulXgJP0h9SV8VVI/dLeEdE6z0HqFO09AMucv0kA/hfAcmf6XABDXO+5w4mxDq4WMV7xI9WKYTFSF7ieBlCWR5wjkGoF8S6AlW3LR6qe8xUAqwHMA1DhTBcADzqxLAdQ41rWjU4s9QBucE2vQepAXQPgATh3lOcRay+kSmF9XdOM2J5I/SCtB7AfqfrXr0exDb3WkWOc9UjVH7ftp22tXa509ollAN4GcFm+8fh95hziDP27BtDdeV7vzB+Ra5zO9McBfCPttdq2p98fu3cgIrJQkqt9iIjIA5M/EZGFmPyJiCzE5E9EZCEmfyIiCzH5ExFZiMmfiMhC/w+cVNX6Ccb2SgAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "n=NoiseSuppressionF32(slices)\n", "n.nr()\n", "cleaned_f32=n.overlap_and_add()\n", "plt.plot(cleaned_f32)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 27, "id": "fcfd59e8", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "audioF32=Audio(data=cleaned_f32,rate=samplerate,autoplay=False)\n", "audioF32" ] }, { "cell_type": "markdown", "id": "283082da", "metadata": {}, "source": [ "#### CMSIS-DSP Q31 noise suppression algorithm" ] }, { "cell_type": "code", "execution_count": 28, "id": "8ccaeae1", "metadata": {}, "outputs": [], "source": [ "class NoiseSuppressionQ31(NoiseSuppression):\n", " def __init__(self,slices):\n", " NoiseSuppression.__init__(self,slices)\n", " \n", " # VAD signal\n", " self._vad= clean_vad(np.array([signal_vad_q31(w) for w in slices]))\n", " self._noise=np.zeros(self._fftLen,dtype=np.int32)\n", " # Q31 version of the Hann window\n", " self._window=fix.toQ31(hann(self._windowLength,sym=False))\n", " # CFTT Q31 instance\n", " self._cfftQ31=dsp.arm_cfft_instance_q31()\n", " status=dsp.arm_cfft_init_q31(self._cfftQ31,self._fftLen)\n", " \n", " \n", " # Subtract the noise\n", " def subnoise(self,v):\n", " \n", " energy = dsp.arm_cmplx_mag_squared_q31(v)\n", " \n", " temp = dsp.arm_sub_q31(energy , self._noise)\n", " temp[temp<0]=0\n", " \n", " # Used for computing the division (energy - noise) / energy\n", " scalingQ31 = np.zeros(len(temp),dtype=np.int32)\n", " shift = np.zeros(len(temp),dtype=np.int32)\n", " \n", " # The scaling factor (energy - noise) / energy is computed\n", " k=0\n", " # We assume that |energy-noise|<=energy\n", " # otherwise we set scaling to 1\n", " # If energy is 0 we also set scaling to 1\n", " # When a == b shiftVal is equal to 1 because 1 is represented \n", " # as 0x40000000 and shift of 1 instead of 0x7FFF for output of division\n", " # We manage this case separately\n", " for a,b in zip(temp,energy):\n", " quotient=0x7FFFFFFF\n", " shiftVal=0\n", " if b!=0 and a!=b:\n", " # We compute the quotient\n", " status,quotient,shiftVal = dsp.arm_divide_q31(a,b)\n", " if shiftVal > 0:\n", " quotient=0x7FFFFFFF\n", " shiftVal = 0\n", " \n", " scalingQ31[k] = quotient\n", " shift[k] = shiftVal\n", " \n", " k = k + 1\n", " \n", " \n", " # We scale the values\n", " res=dsp.arm_cmplx_mult_real_q31(v,scalingQ31) \n", " \n", " return(res)\n", " \n", " def remove_noise(self,w):\n", " sig=self.window_and_pad(w)\n", " \n", " # Convert to complex \n", " signalR=np.zeros(len(sig) * 2,dtype=np.int32)\n", " signalR[0::2]=sig\n", " \n", "\n", " resultR = dsp.arm_cfft_q31(self._cfftQ31,signalR,0,1)\n", " \n", " resultR = self.subnoise(resultR)\n", "\n", " res = dsp.arm_cfft_q31(self._cfftQ31,resultR,1,1)\n", " res = dsp.arm_shift_q31(res,self._fftShift)\n", " \n", " res=res[0::2]\n", " res=self.remove_padding(res)\n", " return(res)\n", " \n", " def estimate_noise(self,w):\n", " sig=self.window_and_pad(w)\n", " \n", " signalR=np.zeros(len(sig) * 2,dtype=np.int32)\n", " signalR[0::2]=sig\n", " \n", " resultR = dsp.arm_cfft_q31(self._cfftQ31,signalR,0,1)\n", "\n", " self._noise = dsp.arm_cmplx_mag_squared_q31(resultR)\n", " \n", " resultR = np.zeros(len(resultR),dtype=np.int32)\n", " \n", " res = dsp.arm_cfft_q31(self._cfftQ31,resultR,1,1)\n", " res = dsp.arm_shift_q31(res,self._fftShift)\n", " \n", " res=res[0::2]\n", " res=self.remove_padding(res)\n", " return(res)\n", " \n", " def nr(self):\n", " for (w,v) in zip(self._slices,self._vad):\n", " result=None\n", " if v==1:\n", " result=self.remove_noise(w)\n", " else:\n", " result=self.estimate_noise(w)\n", " self._signal.append(result)\n", " \n", " def overlap_and_add(self):\n", " nbSamples = len(self._signal)*winOverlap\n", " offsets = range(0, nbSamples,winOverlap)\n", " offsets=offsets[0:len(self._signal)]\n", " res=np.zeros(nbSamples)\n", " i=0\n", " for n in offsets:\n", " res[n:n+winLength] = dsp.arm_add_q31(res[n:n+winLength],self._signal[i])\n", " i=i+1\n", " return(res)" ] }, { "cell_type": "code", "execution_count": 29, "id": "0ccb9512", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "n=NoiseSuppressionQ31(slices_q31)\n", "n.nr()\n", "cleaned_q31=n.overlap_and_add()\n", "plt.plot(fix.Q31toF32(cleaned_q31))\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 30, "id": "452cbc86", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "audioQ31=Audio(data=fix.Q31toF32(cleaned_q31),rate=samplerate,autoplay=False)\n", "audioQ31" ] }, { "cell_type": "markdown", "id": "510a343c", "metadata": {}, "source": [ "#### CMSIS-DSP Q15 noise suppression algorithm" ] }, { "cell_type": "markdown", "id": "7ad0778f", "metadata": {}, "source": [ "When the sampling rate is higher, the FFT length is bigger and on some signals it gives some internal saturations in the FFT Q15.\n", "\n", "In those cases, the algorithm will not work.\n", "\n", "You can decrease the sampling rate or the window duration. \n", "\n", "Scaling the signal to remove the saturations will not work if the background noise is too small because there won't be enough bits left to estimate the noise." ] }, { "cell_type": "code", "execution_count": 31, "id": "a23ff9eb", "metadata": {}, "outputs": [], "source": [ "class NoiseSuppressionQ15(NoiseSuppression):\n", " def __init__(self,slices):\n", " NoiseSuppression.__init__(self,slices)\n", " \n", " # VAD signal\n", " self._vad= clean_vad(np.array([signal_vad_q15(w) for w in slices]))\n", " self._noise=np.zeros(self._fftLen,dtype=np.int32)\n", " # Q15 version of the Hann window\n", " self._window=fix.toQ15(hann(self._windowLength,sym=False))\n", " # CFTT Q15 instance\n", " self._cfftQ15=dsp.arm_cfft_instance_q15()\n", " status=dsp.arm_cfft_init_q15(self._cfftQ15,self._fftLen)\n", " \n", " self._noise_status = -1 \n", " self._noise_max = 0x7FFF\n", " \n", " \n", " # Subtract the noise\n", " def subnoise(self,v,status,the_max):\n", " \n", " # We cannot compute the energy in Q15 because otherwise lots of values are 0.\n", " # The noise signal is too small for its energy to be representable in Q15.\n", " # So, we convert into Q31 and do noise subtraction in Q31\n", " vq31 = dsp.arm_q15_to_q31(v)\n", " energy = dsp.arm_cmplx_mag_squared_q31(vq31)\n", " \n", " # The energy for the signal and noise have been computed on rescaled signal.\n", " # So we remove the scaling from the values before computing the ratio (energy-noise)/energy\n", " if status==0:\n", " the_max_q31=dsp.arm_q15_to_q31([the_max])[0]\n", " energy=dsp.arm_scale_q31(energy,the_max_q31,0)\n", " energy=dsp.arm_scale_q31(energy,the_max_q31,0)\n", " \n", " noise = self._noise \n", " if self._noise_status==0:\n", " the_max_q31=dsp.arm_q15_to_q31([self._noise_max])[0]\n", " noise=dsp.arm_scale_q31(noise,the_max_q31,0)\n", " noise=dsp.arm_scale_q31(noise,the_max_q31,0)\n", " \n", " \n", " temp = dsp.arm_sub_q31(energy , noise)\n", " temp[temp<0]=0\n", " \n", " scalingQ31 = np.zeros(len(temp),dtype=np.int32)\n", " shift = np.zeros(len(temp),dtype=np.int32)\n", " \n", " # The scaling factor (energy - noise) / energy is computed\n", " k=0\n", " # We assume that |energy-noise|<=energy\n", " # otherwise we set scaling to 1\n", " # If energy is 0 we also set scaling to 1\n", " # When a == b shiftVal is equal to 1 because 1 is represented \n", " # as 0x40000000 and shift of 1 instead of 0x7FFF for output of division\n", " # We manage this case separately\n", " for a,b in zip(temp,energy):\n", " quotient=0x7FFFFFFF\n", " shiftVal=0\n", " if b!=0 and a!=b:\n", " # We compute the quotient\n", " status,quotient,shiftVal = dsp.arm_divide_q31(a,b)\n", " if shiftVal > 0:\n", " quotient=0x7FFFFFFF\n", " shiftVal = 0\n", " \n", " scalingQ31[k] = quotient\n", " shift[k] = shiftVal\n", " \n", " k = k + 1\n", " \n", " \n", " res=dsp.arm_cmplx_mult_real_q31(vq31,scalingQ31) \n", " resQ15 = dsp.arm_q31_to_q15(res)\n", " \n", " return(resQ15)\n", " \n", " # To have maximum accuracy with the FFT Q15, the signal is rescaled before computing the FFT\n", " def rescale(self,w):\n", " the_max,index=dsp.arm_absmax_q15(w)\n", " \n", " quotient=0x7FFF \n", " the_shift=0\n", " status = -1\n", " if the_max != 0:\n", " status,quotient,the_shift = dsp.arm_divide_q15(0x7FFF,the_max)\n", " if status == 0:\n", " w=dsp.arm_scale_q15(w,quotient,the_shift)\n", " return(w,status,the_max)\n", " \n", " # The scaling is removed after computing the IFFT\n", " def undo_scale(self,w,the_max):\n", " w=dsp.arm_scale_q15(w,the_max,0)\n", " return(w)\n", " \n", " \n", " def remove_noise(self,w):\n", " w,status,the_max = self.rescale(w)\n", " sig=self.window_and_pad(w)\n", " \n", " # Convert to complex \n", " signalR=np.zeros(len(sig) * 2,dtype=np.int16)\n", " signalR[0::2]=sig\n", " \n", "\n", " resultR = dsp.arm_cfft_q15(self._cfftQ15,signalR,0,1)\n", " \n", " resultR = self.subnoise(resultR,status,the_max)\n", "\n", " res = dsp.arm_cfft_q15(self._cfftQ15,resultR,1,1)\n", " res = dsp.arm_shift_q15(res,self._fftShift)\n", " \n", " res=res[0::2]\n", " res=self.remove_padding(res)\n", " \n", " if status == 0:\n", " res=self.undo_scale(res,the_max)\n", " return(res)\n", " \n", " def estimate_noise(self,w):\n", " w,status,the_max = self.rescale(w)\n", " self._noise_status = status \n", " self._noise_max = the_max\n", " \n", " sig=self.window_and_pad(w)\n", " \n", " signalR=np.zeros(len(sig) * 2)\n", " signalR[0::2]=sig\n", " \n", " resultR = dsp.arm_cfft_q15(self._cfftQ15,signalR,0,1)\n", "\n", " resultRQ31 = dsp.arm_q15_to_q31(resultR)\n", " \n", " \n", " self._noise = dsp.arm_cmplx_mag_squared_q31(resultRQ31)\n", " \n", " \n", " resultR = np.zeros(len(resultR),dtype=np.int16)\n", " \n", " res = dsp.arm_cfft_q15(self._cfftQ15,resultR,1,1)\n", " res = dsp.arm_shift_q15(res,self._fftShift)\n", " \n", " res=res[0::2]\n", " res=self.remove_padding(res)\n", " \n", " if status == 0:\n", " res=self.undo_scale(res,the_max)\n", " \n", " return(res)\n", " \n", " def do_nothing(self,w):\n", " w,status,the_max = self.rescale(w)\n", " sig=self.window_and_pad(w)\n", " \n", " \n", " # Convert to complex \n", " signalR=np.zeros(len(sig) * 2,dtype=np.int16)\n", " signalR[0::2]=sig\n", " \n", "\n", " resultR = dsp.arm_cfft_q15(self._cfftQ15,signalR,0,1)\n", " res = dsp.arm_cfft_q15(self._cfftQ15,resultR,1,1)\n", " res = dsp.arm_shift_q15(res,self._fftShift)\n", " \n", " res=res[0::2]\n", " \n", " res=self.remove_padding(res)\n", " \n", " if status == 0:\n", " res=self.undo_scale(res,the_max)\n", " \n", " return(res)\n", " \n", " \n", " def nr(self,nonr=False):\n", " for (w,v) in zip(self._slices,self._vad):\n", " result=None\n", " if nonr:\n", " result = self.do_nothing(w)\n", " else:\n", " if v==1:\n", " result=self.remove_noise(w)\n", " else:\n", " result=self.estimate_noise(w)\n", " self._signal.append(result)\n", " \n", " def overlap_and_add(self):\n", " nbSamples = len(self._signal)*winOverlap\n", " offsets = range(0, nbSamples,winOverlap)\n", " offsets=offsets[0:len(self._signal)]\n", " res=np.zeros(nbSamples,dtype=np.int16)\n", " i=0\n", " for n in offsets:\n", " res[n:n+winLength] = dsp.arm_add_q15(res[n:n+winLength],self._signal[i])\n", " i=i+1\n", " return(res)\n", " " ] }, { "cell_type": "markdown", "id": "0cf1b685", "metadata": {}, "source": [ "Processing with no noise suppression and only a FFT/IFFT. It is useful to check if the Q15 FFT/IFFT is working without any saturation. If the reconstructed signal is bad, then you probably need to decrease the FFT length by decreasing the window duration or the sampling frequency" ] }, { "cell_type": "code", "execution_count": 32, "id": "48a8041b", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "n=NoiseSuppressionQ15(slices_q15)\n", "n.nr(nonr=True)\n", "cleaned_q15=n.overlap_and_add()\n", "plt.plot(fix.Q15toF32(cleaned_q15))\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 33, "id": "a8cac01a", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "audioQ15_nonr=Audio(data=fix.Q15toF32(cleaned_q15),rate=samplerate,autoplay=False)\n", "audioQ15_nonr" ] }, { "cell_type": "markdown", "id": "9543f723", "metadata": {}, "source": [ "Same but with noise suppression:" ] }, { "cell_type": "code", "execution_count": 34, "id": "f99e212c", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAD5CAYAAAAqaDI/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAj4klEQVR4nO3deZxcdZnv8c+TzgZkXwnZOpGwhAECtAFEUSBAcJSgIgZRI4q5OjI6F7cwjIwvlHtBvaLj4BIBAUUCRBl6JkAMuwuEdCAkJBoSwpaQjUDCkj089486HaorVdXdVWerOt/369WvPvU721Onqs5zlt/5/czdERGR7OqSdAAiIpIsJQIRkYxTIhARyTglAhGRjFMiEBHJOCUCEZGM6xrGQsxsMvAToAG4zt2vKhh/DXBK8HJ/YIi79wvG7QGWBONedPez21vfoEGDvLGxMYzQRUQyY+HCha+4++DC8qoTgZk1ANcCpwOrgQVm1uzuy1qncff/nTf9PwPH5C1im7tP6Mw6GxsbaWlpqSpuEZGsMbMXipWHcWloIrDS3Ve5+05gFjClzPTnA7eGsF4REQlBGIlgOPBS3uvVQdk+zGw0MAZ4IK+4p5m1mNljZnZOCPGIiEgnhHKPoBOmArPdfU9e2Wh3X2NmY4EHzGyJuz9bOKOZTQemA4waNSqeaEVEMiCMM4I1wMi81yOCsmKmUnBZyN3XBP9XAQ/R9v5B/nQz3b3J3ZsGD97nXoeIiFQojESwABhnZmPMrDu5nX1z4URmdhjQH3g0r6y/mfUIhgcBJwHLCucVEZHoVH1pyN13m9nFwFxy1UdvcPelZnYF0OLurUlhKjDL2zZ3ejjwSzN7m1xSuiq/tpGIiETParEZ6qamJlf1URGRzjGzhe7eVFiuJ4tTaPm6N7hv2fqkwxCRjFAiSKEzf/wIF92sM54kPPzMRk754UPs2L2n/Ylr3PZde/jJfSvY+MaOpEOpW4tXb6Zxxhz+svKVpEMpS4lAOuVPKzZy+Lfv5Y3tu5IOJRL/+oclPPfKW1xy21NJhxK5r93+FNfc9wyTf/xI0qHUrcdWbQLgguvmJxxJeUoEKbNtZ7qPRD99/eNs27WHH9+3IulQIrFm8zYA5ixZm3Ak0Zv/XG4ntemtnQlHUr92v10b92CVCFLm4Wc2Jh1Ch+ypkS94NRav3px0CJF65U0lgKh9/97le4eff+WtBCMpT4kgxebphnGiHvx7bSTlMOg+QfQ+dX16Lw8pEaTYF1J8w/jGvz7Pzt1vJx2GhOSW+UUbpZQQ7Ujx70WJQCr2yps6ihSpB0oEIiIZp0QgUoJZ0hGIxEOJIGW08xGpT2luzUeJQERSvZOS6CkRSMXqfd+hkzPJCiUCEZGMUyIQEck4JQKREnTjXsKV3oupSgQpo32PJCG9u6j6keYb8koEUrFa7N1OJClpbuVViUBEJOOUCERKMN0kkIwIJRGY2WQzW25mK81sRpHxnzWzjWa2KPi7KG/cNDNbEfxNCyMeERHpuK7VLsDMGoBrgdOB1cACM2t292UFk97m7hcXzDsA+Hegidz9qoXBvK9VG1etykB/LyKSMmGcEUwEVrr7KnffCcwCpnRw3jOBee7+arDznwdMDiGmmvXTB2qnC0jdK64j+jAzLYxEMBx4Ke/16qCs0MfMbLGZzTazkZ2cNzOWvvx60iGUVNg95dKXtyQUSTxeDvovzoI1m7cnHYIkKK6bxf8NNLr7UeSO+m/q7ALMbLqZtZhZy8aN2elCME127Wnbw9LcpfXdleYt819MOoTY/P6J1UmHIAkKIxGsAUbmvR4RlO3l7pvcvbU7q+uA4zo6b94yZrp7k7s3DR48OISwRUQEwkkEC4BxZjbGzLoDU4Hm/AnMbFjey7OBvwXDc4EzzKy/mfUHzgjKpAaocqVIfai61pC77zazi8ntwBuAG9x9qZldAbS4ezPwFTM7G9gNvAp8Npj3VTP7LrlkAnCFu79abUwiItJxVScCAHe/G7i7oOzyvOFLgUtLzHsDcEMYcUi8VM9EpD7oyWKpmNoaEqkPSgQiIhmnRCAiknFKBCIiGadEIBXTHQKR+qBEIBXTvWKR+qBEICKScUoEIiIZp0QgHfZ2wbUgXRmqXYUtyUq2KRFIh92+4KU2r+vtgbLNW9PbuXjYtmzblXQIkiJKBNJhr2/fnXQIkdJBsmSVEoGISMYpEYhkUL1d1pPqKBFIh6n/AZH6pEQgHWZ1ngl0lCxZpUQgFSusTiq1Q5+c5FMikIrdvWRd0iGISAiUCFJu9Wtbkw5hL6v3a0MiGaVEkHLrX9+RdAh71fs19D11/v7yZeitJmbL1tp5aE+JIPXS84t98sXNSYcQqd8+9mLSIcRmzuKXkw6h7m3fvSfpEDoslERgZpPNbLmZrTSzGUXGX2Jmy8xssZndb2aj88btMbNFwV9zGPFINO7/+4akQ4jUxje2Jx1CbJavfzPpEOpeLV1I7VrtAsysAbgWOB1YDSwws2Z3X5Y32ZNAk7tvNbMvAd8HPhGM2+buE6qNo16p2QOJhr5YUaule2phnBFMBFa6+yp33wnMAqbkT+DuD7p7613Px4ARIaw3E95WJhCpSTWUB0JJBMOB/GYpVwdlpXweuCfvdU8zazGzx8zsnBDiEalQDf1yq5al91rc9l17aJwxh9sWRHNvqJa2cKw3i83sU0AT8IO84tHu3gR8Evixmb2rxLzTg4TRsnHjxhiilTRYuUHXsiUajz67CYCr710eyfK71NApQRiJYA0wMu/1iKCsDTObBFwGnO3ue+tEuvua4P8q4CHgmGIrcfeZ7t7k7k2DBw8OIezasOGN9FQfjducxWuZ9KOHmbu0/h9c27n7bdZu2RbjGrN9yXHTmzu48MYFALz6VjT9UGQtESwAxpnZGDPrDkwF2tT+MbNjgF+SSwIb8sr7m1mPYHgQcBKQf5M58/751idZtTGbR8XL1m4BoHlRXFUdk9s5HvJv93Di/32AHQlWOYy717LVr23lzidXx7rOVsd9777oV1I7eaD6WkPuvtvMLgbmAg3ADe6+1MyuAFrcvZncpaBewB3BnfQX3f1s4HDgl2b2NrmkdFVBbSMBXnptG2MH90o6jNhd++CzAMxZspZrE4ph4xs7GNy7R2TLf3rNFj700z/vfb1rj9Oj6l9lZWYteJELjh/d/oRV2vTmjjY74rGDenH0yH6RrzduXYokgrd27OaApD7gMkK5R+Dud7v7Ie7+Lne/Mii7PEgCuPskdx/q7hOCv7OD8r+6+5HufnTw//ow4pH4LHzh1UiWO2fx2kiWW87zr+zbnMdXbn0y0nX+/OFnI11+KcWeLL7szqdjWfecJW0/29e3184TuJ1RrProEf8+N4FI2qcni6Uqn7ru8UiW++XfPRHJcst5dNWmDpWF6dmEboa/uaO+ux0tZ+vOeN77GzWU4JQIpCrbdtXOY/RplFRT3v+TwBlXWixf90Ys6/nu/9TOVW4lApEEPVPQ1MNbGT5Sj0tcqfeN7bXzWSoRiKTI8f/n/qRDiNyS1VvavH4z5h3mR3/211jWU+ps77lX3opl/Z2hRFADnnppc9IhxKpYc9dPvPhaApFkTxxNjd+xsG2V0S/dEv/9oDi8/Xbx8i/+ZmG8gXSAEkGKlPoR/mjeMzFHkqxZC17ap2z1a3E+bNVWVNeUN72ZvocFn6zzg47tMd7TWr6++PemVHmSlAhSZMfuEocQGfOrR1YlHUIbUT15GstDTZ20Y1e038F5y9ZHuvz2zF4Y3wNsUX1voqBEkCK3Pp6djlHKWVXkGmqSvaMVezBIKvOFm1sSXf+//Vc8z0rUGiWCFNEZQTrVUrvy1crQW5U8SgQpklSd8mrd/Ojzka8jyU2jnaPUOyWCFKnVTmi+07w06RAi9fFfPJp0CLG58S/PJx1CInbvyfbZuBJBipTLA9+c/RR/XvFKfMF0Qpjpq1QbQ57xZpPjcu/SdXzjjqfYmbHLlI+syHYfJ0oEKVLu0tDtLav51PXzY4ym49xhfkht8iTRxlBHPPD3cGu73Pt0evtYuGPhav7ybPgHHWlu36hUnf+oNM6Yw7KXX493pWUoEaRIrV4aAvjEzMcirdmT9O2Tz93YwpMhPtQ24w+LQ1tWrYjjXlI5f1ubnh0vwAf/409Jh7CXEkGKLCp49L7WbKqhetOVWLE+vJZCN2+tnZYpw5L0gU65hxLXvb49xkjSR4kgRXYm2DtVGKLsmi/pMwKADW+Et7PomsGHE5I+4S13xpr15wuUCFIk6R9KtR5/LppOagC2pyBJ/uGJfbrirtieNGS2Mla/um8nPdWq1erRWaBEkCJJPj0bhuanwttRFoqr96xyij3xXKm0f9Tf+e/w29JP+kAn5Zs8UUoEKZL0D6VaazZn+zprPYmiI/uk6+qnPfkmSYkgRWr91Dl7V72lM372UDL9M7e67k/paswwTZQIUqTWzwjUFINU6sVN4d+TKNTygvq0KCWURGBmk81suZmtNLMZRcb3MLPbgvHzzawxb9ylQflyMzszjHhqVa3fI4iy1pDUt2Upq+OfNVUnAjNrAK4FzgLGA+eb2fiCyT4PvObuBwPXAFcH844HpgJHAJOBnwXLy6Tde2o7EVSbBuLsNCTNav2AoBI7UlArLMu6hrCMicBKd18FYGazgClAfrWDKcB3guHZwH9arm3fKcAsd98BPGdmK4PlRdLK1x+Xrku0p6v2dOSo6IY/PxdDJJVpeeG1quJ7pZ0eu9Lw3uOI4Ya/PJ+K+y1xbu/ZC1ez6c1kH0hM4vtVyTo/euxw+u3fPdQ4rNqjDzM7F5js7hcFrz8NHO/uF+dN83Qwzerg9bPA8eSSw2Pu/tug/HrgHnefXWQ904HpAKNGjTruhRde6HSsF/76cR5cnu3GpUSktt13yfs5eEiviuY1s4Xu3lRYHsYZQSzcfSYwE6Cpqami7PXTTx7LnhRffjn6ij+2O81Tl58RQyT72uPOsd+dV3aa3j278udvnlrxOjZv28n7f/BQyfFRv/c4t3+5dT3wtfcz8IAeoaynkvW3Cnt7l1vn7y46niMO6hvq+jqzfoj3/Vazzl49w99th7HENcDIvNcjgrJi06w2s65AX2BTB+cNTa8e6c57g3r1aPfySN/9u8UUTVsdOXMc2X//quLr3c4XPKn3HncMA3v1oO9+2Xivrfrs1y3y9U0+4kDuXVq61dckvl9p+E5DOLWGFgDjzGyMmXUnd/O3uWCaZmBaMHwu8IDn9izNwNSgVtEYYBzweAgx1aQ03yTsSHeNDVW2n9Mlg+3vFNOja/ZqdcdxkKZKbaVVvfXdfbeZXQzMBRqAG9x9qZldAbS4ezNwPfCb4Gbwq+SSBcF0t5O7sbwb+LK7Z7b6QK0/UKYdeTiymAgO7Nsz8nXsrvUHdSIUShp297uBuwvKLs8b3g58vMS8VwJXhhFHrav172k3JYJQdOTsSzqvXLMZx47qF18gKZS9Q48UG95vv6RDqMoPP3500iGIlFTujGDs4Mpq4dQLJYIUqfUDwcZBByQdgkhJI/qXPtBqqPUfX5WUCFKk1i8N1btyO5J6M+Osw0Jf5k+mTig5Lo7bYxe+p7HkuF1xd1qcMkoEKZLmWkPtOXHswKRDiNw9X31faMv6y4zKn7eIw6TDh4a+zCkThpcc1yWGPVHPbqVbr9mVwPNFQ3pH+6xIZygRpEh7eeCn5x8TTyAVuHX6CaEsZ1aJ5Rx2YO9Qll+N3j3Dq/M9uFd6dgKFmi8+qeInVyvVo2v0TYyNHLB/yXFJ9JXw4Nc/EPs6S1EiSJH2qo9++OiDYookOX1K7Gyj6CilM8I+40lzBatDU5B043bc6P6xru/nFxzLASl6wFWJIEXKJYJDhmajVkOpe3ZJ9/Eb1hlPqzRXEe0Wx3WalJk6cVSs60vbMzfZ+8Ql1Urt7//pAwfHG0jEUrYfaCNtO6k4xH1/Lm19dygRpMjJhwwuOe6cY0rfaKsn+3cvfq14wsh+8QYSsTSfEWRR3Fce05ZrlQhSpNxRwpfe/64YI0lOqWcRarlGVSlpaFgubpecfkjSIRRV6gAkKsP6pqsqshJBiowqU6shS0eQY4skg3p8xqJYcqv3j/mkg5OtZvz9jx1VtLxbQ3y7wg8ffRDjD+oT2/o6QokgRc5rGlm0PO3NZz/x7dMjX0f/A5I7ep5+8thIlltsZ5D0ic/PLjg20uUfN3rAPmVxtvPTJwVnYYfEXDW3I5QIUsQpvhf45PHx1mjorAEHhNtt3rc/XNjlNQzpHX3rlKVc9N4xkSz3+DH7Hh1X25R3tSaO2XdHHbUzjzgwtnUdkYIj8f1ivgzVEUoEKVLqaLAer4+Xc8qhQ5IOoY0oeoQC+Mpp4/Yp+9F5yTbc1z/kvnA7Is5vd7mHyuIyrUxTF0lRIkiRUj+I08fHd8TUWYN6xb/jiNv+3aNJBA1djIEFZ1NJnvlAPGckPzi37XX6ej3OaSrxkFqc9yM6Kn0RZVipI/93N8b71GNnNA5Ui6PV+MaZh7Z5XeryYBz6x9Rt4tEFVYHjfs9/jamdp1rKb0oEKVLsi3PB8aNSXWPoV59pSjqESH38uBGRLn+fjzbBvcfD3zwllvUU1o6L+4zgoJj6/ailS7pKBClSQ9+bvfqHfKO41amHpeM+wQ9i7mwnya9AqXaewlauFdB6UktVnpUIUqSWjiCidsjQbDR8dvCQtu8zi1+Bev3eF3tXj//rabHH0RFKBClS7PdQnz+R9qX4aliojhvdny+8L5rqqbWiTvNA0QQ3pE+ylQFKqSoRmNkAM5tnZiuC//vc1TSzCWb2qJktNbPFZvaJvHE3mtlzZrYo+JtQTTy1rk5/DxU56x9yNaUG9erOHV88MeFoonXZP77z3MRRI/smGEl8Hr/snSPjJJ6yfeBr7498HbWU4KqtFzcDuN/drzKzGcHrbxVMsxX4jLuvMLODgIVmNtfdNwfjv+Hus6uMoy4Ua4a6lr5MYTpqRD+ev+ofkw4jNg9/4wOs27I9tuv0SRvSuyd3fPFEXty0ldMi6A2tPWMH9+Kqjx7JjD8s4QOHlm7ssRrt9S+SJtUmginAB4Lhm4CHKEgE7v5M3vDLZrYBGAxsrnLddaeGvjcSstEDD2B0xqrivrtxAO9ujP9J5lattYei6ma1ln7P1d4jGOrua4PhdUDZ1G5mE4HuwLN5xVcGl4yuMbOS/feZ2XQzazGzlo0bN1YZdjoVr09dQ98mkRpy8iGDuf1/ncgX3hdNW1KDUtQncXvaTQRmdp+ZPV3kb0r+dJ67M1Jyr2Vmw4DfABe6e2sHoZcChwHvBgaw72Wl/OXPdPcmd28aPDiaU7mkdS/6xGFG7pqKJGDimAGRdcQzKKKq1VFoNxG4+yR3/4cif3cB64MdfOuOfkOxZZhZH2AOcJm7P5a37LWeswP4NTAxjDdVq/ol0M6LvOOHMT8zkKRi7RxJuL511mFJh9Bh1V4aagamBcPTgLsKJzCz7sCdwM2FN4XzkogB5wBPVxlP3SnWNn9Szhgf/029OB2WoU7bP33C6KRDqHtDU1pVtJhqE8FVwOlmtgKYFLzGzJrM7LpgmvOAk4HPFqkmeouZLQGWAIOA71UZT925KEV1zOPuxSluQ/rUzjXdaiXZppGkT1W1htx9E7DPo3Lu3gJcFAz/Fvhtifnjaf2phqWpnaHCXcdRI+qsznuW9o1Zeq/SLj1ZLBXb9ObOpEMIVZb2jVl6r9I+JQLpsMJ60U0pbh5bRDpOiUAqVm99EdTSA0DVytJ7lfYpEYiIZJwSgUgGqdaQ5FMiEAlo5yhZpUQgkkG6RyD5lAhEAlnaOWborUoHKBGIZFC9dg8plVEikA6r911Hvb8/kVKUCEQCWTpKztBblQ5QIpCKpagZpFBo5yhZpUQgIpJxSgTSYVm6dCKSJUoEUjHlhdqlz07yKRGIiGScEoFIIEtHyWpOQ/IpEYhkUJaSnrRPiUAkkKWj5Oy8U+kIJQLpsMKdh54jEKkPVSUCMxtgZvPMbEXwv2jfhWa2x8wWBX/NeeVjzGy+ma00s9vMrHs18YhUI0t5QFWBJV+1ZwQzgPvdfRxwf/C6mG3uPiH4Ozuv/GrgGnc/GHgN+HyV8YiISCdVmwimADcFwzcB53R0RjMz4FRgdiXzi4QtS0fJ2Xmn0hHVJoKh7r42GF4HDC0xXU8zazGzx8zsnKBsILDZ3XcHr1cDw6uMR0REOqlrexOY2X3AgUVGXZb/wt3dzEodaIx29zVmNhZ4wMyWAFs6E6iZTQemA4waNaozs4p0SJaOkjN08iMd0G4icPdJpcaZ2XozG+bua81sGLChxDLWBP9XmdlDwDHA74F+ZtY1OCsYAawpE8dMYCZAU1OTvsZJ0FYXqUvVXhpqBqYFw9OAuwonMLP+ZtYjGB4EnAQs89wF2QeBc8vNLxIXHSVLVlWbCK4CTjezFcCk4DVm1mRm1wXTHA60mNlT5Hb8V7n7smDct4BLzGwluXsG11cZj4h0QOPA/ZMOQVKk3UtD5bj7JuC0IuUtwEXB8F+BI0vMvwqYWE0MItJ5XRv0LKm8Q98G6bBjRvVr89qor0eLR/TfL+kQRBKhRCAddtaRw9q8rre2eXp2a0g6BJFEKBGIiGScEoGISMYpEYiIZJwSgYhIxikRiIhknBJBykw6fEjSIYhIxigRpMwZRxRr3y8devVo+/xhvT1HIJJVSgTSYX3365Z0CCISASUCEZGMUyIQEck4JQIRkYxTIhARyTglAhGRjFMiEBHJOCUCqdjoOu/l6iPHDE86BJFYKBFIxc44YmjSIUTqyOF9kw5B6sigXt2TDqEkJQIR4V8/eFjSIUiClAhEhK5dtCvIsqo+fTMbYGbzzGxF8L9/kWlOMbNFeX/bzeycYNyNZvZc3rgJ1cQjEiZTU0qSEdUeBswA7nf3ccD9wes23P1Bd5/g7hOAU4GtwB/zJvlG63h3X1RlPCIi0knVJoIpwE3B8E3AOe1Mfy5wj7tvrXK9IiISkmoTwVB3XxsMrwPaq0YyFbi1oOxKM1tsZteYWY8q4xERkU7q2t4EZnYfUKyR/MvyX7i7m5mXWc4w4Ehgbl7xpeQSSHdgJvAt4IoS808HpgOMGjWqvbBFRKSD2k0E7j6p1DgzW29mw9x9bbCj31BmUecBd7r7rrxlt55N7DCzXwNfLxPHTHLJgqamppIJR+LTpc7vpnbvqpo0kg3VftObgWnB8DTgrjLTnk/BZaEgeWBmRu7+wtNVxiMx6tmtIekQInVe08ikQ5A60qNren8v1SaCq4DTzWwFMCl4jZk1mdl1rROZWSMwEni4YP5bzGwJsAQYBHyvynjqyuUfGp90CJnWrSE7ZwQDU/zUa70Y0ie9t0DbvTRUjrtvAk4rUt4CXJT3+nlgn4Zb3P3UatZf744Z1S/pECQjzj76oKRDqHu/+NRxSYdQUnYOeUSkJKvz+z1pMLRPz6RDKEmJIGV69ajqJE1EpNOUCFJm8hHFauqKiERHiSBlunR55xRddWRFatvp42ujqXYlAhGRiPTbr1vSIXSIEoGISERq5axeiUBEJOOUCEREMk6JQEQk45QIUsxr5QKjiBRVK4/pKRGIiGScEoGISERq5aReiUBEJOOUCEREMk6JQEQk45QIREQyTokgxYb1TW/75SLSPlUflaod1G+/pEMQkSqo1pDUtW/XeX/KwzOUhD/7nsakQ5CEKRFIRT581LCkQ4hUrbQjLxKGqhKBmX3czJaa2dtm1lRmuslmttzMVprZjLzyMWY2Pyi/zcy6VxOPiIh0XrVnBE8DHwUeKTWBmTUA1wJnAeOB882s9brC1cA17n4w8Brw+SrjEZFO6qKO6yPTp2cGOqZx97+5+/J2JpsIrHT3Ve6+E5gFTDEzA04FZgfT3QScU008Ep9ePbsmHUKkDj2wd9IhRK5H19zP/8KTGpMNpI716tEAwFdPG5dwJOXFcY9gOPBS3uvVQdlAYLO77y4oF2BI7x5Jh1DW/t3rMxH815dP4qgRfflE08ikQ4ncoF6579j+3RsSjqR+9Qm6quy3f7rPDNr9NZvZfcCBRUZd5u53hR9SyTimA9MBRo0aFddqE7HiyrNSW//41i+cwNot25IOIzITRvaj+eL3Jh1GLG656HjmLFnLwF7pPuioZdPe00j3rl345MR077PaTQTuPqnKdawB8g+vRgRlm4B+ZtY1OCtoLS8Vx0xgJkBTU1OtVM+tSLeG9FbmOvFdA5MOQULSOOgAvnzKwUmHUde6NXThMyc2Jh1Gu+LY4ywAxgU1hLoDU4Fmd3fgQeDcYLppQGxnGCIiklNt9dGPmNlq4ERgjpnNDcoPMrO7AYKj/YuBucDfgNvdfWmwiG8Bl5jZSnL3DK6vJh4REek88xrsD7GpqclbWlqSDkNEpKaY2UJ33+eZr/RejBYRkVgoEYiIZJwSgYhIxikRiIhknBKBiEjG1WStITPbCLxQ4eyDgFdCDCcqijN8tRKr4gyX4nzHaHcfXFhYk4mgGmbWUqz6VNoozvDVSqyKM1yKs326NCQiknFKBCIiGZfFRDAz6QA6SHGGr1ZiVZzhUpztyNw9AhERaSuLZwQiIpInU4nAzCab2XIzW2lmM2JY30gze9DMlpnZUjP7alD+HTNbY2aLgr8P5s1zaRDfcjM7s73Yg+a95wfltwVNfVca7/NmtiSIqSUoG2Bm88xsRfC/f1BuZvYfwXoXm9mxecuZFky/wsym5ZUfFyx/ZTBvp/vfMbND87bbIjN73cz+JQ3b1MxuMLMNZvZ0Xlnk26/UOjoZ5w/M7O9BLHeaWb+gvNHMtuVt119UGk+599zJWCP/rM2sR/B6ZTC+sYI4b8uL8XkzW5SGbVqUu2fiD2gAngXGAt2Bp4DxEa9zGHBsMNwbeAYYD3wH+HqR6ccHcfUAxgTxNpSLHbgdmBoM/wL4UhXxPg8MKij7PjAjGJ4BXB0MfxC4BzDgBGB+UD4AWBX87x8M9w/GPR5Ma8G8Z4Xwma4DRqdhmwInA8cCT8e5/Uqto5NxngF0DYavzouzMX+6guV0Kp5S77mCWCP/rIF/An4RDE8FbutsnAXj/x9weRq2abG/LJ0RTARWuvsqd98JzAKmRLlCd1/r7k8Ew2+Q64+hXL/MU4BZ7r7D3Z8DVgZxF409OFo4FZgdzH8TcE7Ib2NKsNzC5U8Bbvacx8j1NjcMOBOY5+6vuvtrwDxgcjCuj7s/5rlv8M0hxHoa8Ky7l3u4MLZt6u6PAK8WWX/U26/UOjocp7v/0d/pP/wxcj0GllRhPKXec6diLSPMzzr/PcwGTms9Ou9snMF85wG3lgs+rm1aTJYSwXDgpbzXqym/Uw5VcGp5DDA/KLo4OJW7Ie9UvlSMpcoHApvzfsDVvicH/mhmCy3XRzTAUHdfGwyvA4ZWGOvwYLiwvBpTafvjSuM2jWP7lVpHpT5H7iiz1Rgze9LMHjaz9+XF39l4wvwNRv1Z750nGL8lmL4S7wPWu/uKvLJUbdMsJYLEmFkv4PfAv7j768DPgXcBE4C15E4b0+C97n4scBbwZTM7OX9kcJSSimpmwbXcs4E7gqK0btO94th+1a7DzC4DdgO3BEVrgVHufgxwCfA7M+sTVzwlpP6zLnA+bQ9YUrdNs5QI1gAj816PCMoiZWbdyCWBW9z9DwDuvt7d97j728CvyJ26louxVPkmcqeCXQvKK+Lua4L/G4A7g7jWt55qBv83VBjrGtpebqh2+58FPOHu64OYU7lNiWf7lVpHp5jZZ4EPARcEOxuCyyybguGF5K61H1JhPKH8BmP6rPfOE4zvG0zfKcG8HwVuy4s/dds0S4lgATAuqCXQndxlheYoVxhcG7we+Ju7/yivPP8a3keA1poGzcDUoMbCGGAcuZtHRWMPfqwPAucG808D7qow1gPMrHfrMLmbh08HMbXWXMlffjPwmaDWwgnAluDUdS5whpn1D07ZzwDmBuNeN7MTgu3ymUpjDbQ5ykrjNs1bf9Tbr9Q6OszMJgPfBM5296155YPNrCEYHktu+62qMJ5S77mzscbxWee/h3OBB1qTYydNAv7u7nsv+aRxm1ZcY6MW/8jdYX+GXAa+LIb1vZfcKdxiYFHw90HgN8CSoLwZGJY3z2VBfMvJq1VTKnZyNSEeJ3dj7A6gR4WxjiVXm+IpYGnrOshdF70fWAHcBwwIyg24NohnCdCUt6zPBfGsBC7MK28i96N9FvhPggcaK4j1AHJHZ33zyhLfpuQS01pgF7lrtZ+PY/uVWkcn41xJ7lpz6/e0tcbMx4LvwyLgCeDDlcZT7j13MtbIP2ugZ/B6ZTB+bGfjDMpvBL5YMG2i27TYn54sFhHJuCxdGhIRkSKUCEREMk6JQEQk45QIREQyTolARCTjlAhERDJOiUBEJOOUCEREMu7/A473fi8r8b78AAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "n=NoiseSuppressionQ15(slices_q15)\n", "n.nr()\n", "cleaned_q15=n.overlap_and_add()\n", "plt.plot(fix.Q15toF32(cleaned_q15))\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "abd36813", "metadata": {}, "source": [ "The audio to check the result:" ] }, { "cell_type": "code", "execution_count": 35, "id": "b31616ab", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "audioQ15=Audio(data=fix.Q15toF32(cleaned_q15),rate=samplerate,autoplay=False)\n", "audioQ15" ] }, { "cell_type": "markdown", "id": "7204cf08", "metadata": {}, "source": [ "## C Code" ] }, { "cell_type": "markdown", "id": "d83edfd5", "metadata": {}, "source": [ "Once the Python code is working, the C code should be easy to write since the API of the CMSIS-DSP Python wrapper is as close as possible to the C one.\n", "\n", "For instance, let's look at the F32 noise suppression:" ] }, { "cell_type": "markdown", "id": "e99015e9", "metadata": {}, "source": [ "```python\n", "energy = dsp.arm_cmplx_mag_squared_f32(v)\n", "# To avoid division by zeros\n", "energy = dsp.arm_offset_f32(energy,1e-6)\n", " \n", "temp = dsp.arm_sub_f32(energy , self._noise)\n", "# C implementation will have to loop on the array and replace negative vaues\n", "temp[temp<0]=0\n", " \n", "scaling = np.zeros(len(temp),dtype=np.float32)\n", "# C implementation will have to loop on the arrays here\n", "scaling = temp / energy\n", " \n", "res=dsp.arm_cmplx_mult_real_f32(v,scaling) \n", "```" ] }, { "cell_type": "markdown", "id": "bd93e60a", "metadata": {}, "source": [ "The C code could be:" ] }, { "cell_type": "markdown", "id": "540d8fb5", "metadata": {}, "source": [ "```C\n", "float32_t *v,*energy,*noise,*temp,*scaling,*res;\n", "\n", "arm_cmplx_mag_squared_f32(v,energy,windowLength);\n", "// To avoid division by zeros\n", "arm_offset_f32(energy,1e-6,energy,windowLength);\n", " \n", "arm_sub_f32(energy , noise,temp,windowLength);\n", "\n", "for(int i=0;i < windowLength; i++)\n", "{\n", " if (temp[i]<0)\n", " {\n", " temp[i]=0;\n", " }\n", "}\n", " \n", "for(int i=0;i < windowLength; i++)\n", "{\n", " scaling[i] = temp[i] / energy[i];\n", "}\n", " \n", "arm_cmplx_mult_real_f32(v,scaling,res,windowLength) ;\n", "```" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "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.10.0" } }, "nbformat": 4, "nbformat_minor": 5 }