diff --git a/fixed_point_dsp_for_data_scientists.ipynb b/fixed_point_dsp_for_data_scientists.ipynb index b13a42e..1dc6046 100644 --- a/fixed_point_dsp_for_data_scientists.ipynb +++ b/fixed_point_dsp_for_data_scientists.ipynb @@ -1099,7 +1099,7 @@ } ], "source": [ - "!pip install git+https://github.com/ARM-software/CMSIS_5.git@5.8.0#egg=CMSISDSP\\&subdirectory=CMSIS/DSP/PythonWrapper" + "!pip install cmsisdsp" ] }, { @@ -1163,7 +1163,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "You can see the signal has a similiar shape to the one created with NumPy, however the values on the Y-axis range from -32768 to 32767 rather than 0 to 1.\n" + "You can see the signal has a similiar shape to the one created with NumPy, however the values on the Y-axis range from -32768 to 32767 rather than -1 to 1.\n" ] }, { @@ -1172,9 +1172,8 @@ "source": [ "### Hanning Window in CMSIS-DSP\n", "\n", - "CMSIS-DSP does not have a built-in function for creating a Hanning Window for a specific window size. However, we can levergage the built-in [`arm_cos_f32(...)`](https://arm-software.github.io/CMSIS_5/DSP/html/group__cos.html#gace15287f9c64b9b4084d1c797d4c49d8) and `arm_float_to_q15(...)` API's to create a fixed-point Hanning Window. Let's do this using the formula for the [Hann Function](https://en.wikipedia.org/wiki/Hann_function):\n", - "\n", - "$$ f(x; window\\_size) = \\frac{1}{2} \\left[ 1 - cos \\left(\\frac{2\\pi x}{window\\_size}\\right) \\right]$$" + "CMSIS-DSP provide a built-in floating-point Hanning function `arm_hanning_f32(...)` for a specific window size and we can levergage the `arm_float_to_q15(...)` API to to convert to fixed-point format. ", + "\n" ] }, { @@ -1185,15 +1184,9 @@ "source": [ "# Generate the Hanning Window\n", "from numpy import pi as PI\n", - "from cmsisdsp import arm_cos_f32, arm_float_to_q15\n", - "\n", - "hanning_window_f32 = np.zeros(window_size)\n", + "from cmsisdsp import arm_float_to_q15, arm_hanning_f32\n", "\n", - "for i in range(window_size):\n", - " hanning_window_f32[i] = 0.5 * (1 - arm_cos_f32(2 * PI * i / window_size ))\n", - " \n", - "\n", - "hanning_window_q15 = arm_float_to_q15(hanning_window_f32)" + "hanning_window_q15 = arm_float_to_q15(arm_hanning_f32(window_size))" ] }, { @@ -1623,7 +1616,7 @@ "As we have seen, the CMSIS-DSP pipeline is similar to the NumPy pipeline. Let's recap the what we've done to create it:\n", "\n", "1. Converted the audio samples into Q15 format using the `arm_float_to_q15` function.\n", - "2. Calculated the Hanning Window using the Hann Function formula using the `arm_cos_f32` and `arm_float_to_q15` functions.\n", + "2. Generated the Q15 format Hanning Window using the `arm_hanning_f32` and `arm_float_to_q15` functions.\n", "3. Learned how to multiply to vectors of the same length using the `arm_mult_q15` function.\n", "4. Learned how to calculate a Q15 FFT in CMSIS-DSP using the `arm_rfft_instance_q15`, `arm_rfft_init_q15`, and `arm_rfft_q15` functions.\n", "5. Created a spectrogram representation of the audio signal by striding over the audio signal over time, applying a Hanning Window, and using the FFT function for each window period." @@ -1793,27 +1786,20 @@ "\n", "### Hanning Windows\n", "\n", - "For the Hanning Window function you must declare a global array variable to store the window function values:\n", + "For the Hanning Window function you must declare two global array variables to hold the floating-point intermediate values and store the final Q15 format window function values:\n", "\n", "\n", "```c\n", + "float_t hanning_window_f32[WINDOW_SIZE];\n", "q15_t hanning_window_q15[WINDOW_SIZE];\n", "\n", "```\n", "\n", - "Then we can create a C function that initializes the `hanning_window_q15` array at runtime:\n", + "Then we call cmsis functions to initializes the `hanning_window_q15` array at runtime:\n", "\n", "```c\n", - "void hanning_window_init_q15(q15_t* hanning_window_q15, size_t size) {\n", - " for (size_t i = 0; i < size; i++) {\n", - " // calculate the Hanning Window value for i as a float32_t\n", - " float32_t f = 0.5 * (1.0 - arm_cos_f32(2 * PI * i / size ));\n", - " \n", - " // convert value for index i from float32_t to q15_t and store\n", - " // in window at position i\n", - " arm_float_to_q15(&f, &hanning_window_q15[i], 1);\n", - " }\n", - "}\n", + "arm_hanning_f32(hanning_window_f32, WINDOW_SIZE);\n", + "arm_float_to_q15(hanning_window_f32, hanning_window_q15, WINDOW_SIZE);\n", "```\n", "\n", "We will need another variable to store the value of the applied Hanning Window on the Input Signal:\n", @@ -1932,18 +1918,6 @@ " // all done loop forever ...\n", " while (1);\n", "}\n", - "\n", - "\n", - "void hanning_window_init_q15(q15_t* hanning_window_q15, size_t size) {\n", - " for (size_t i = 0; i < size; i++) {\n", - " // calculate the Hanning Window value for i as a float32_t\n", - " float32_t f = 0.5 * (1.0 - arm_cos_f32(2 * PI * i / size ));\n", - "\n", - " // convert value for index i from float32_t to q15_t and store\n", - " // in window at position i\n", - " arm_float_to_q15(&f, &hanning_window_q15[i], 1);\n", - " }\n", - "}\n", "```" ] }, @@ -2039,7 +2013,7 @@ "| | **NumPy** Python | **CMSIS-DSP** Python | **CMSIS-DSP** C |\n", "| - | ---------------- | -------------------- | --------------- |\n", "| **Import / Include** | `import numpy as np`| `from cmsisdsp import arm_cos_f32, arm_rfft_instance_q15, arm_rfft_init_q15, arm_mult_q15, arm_rfft_q15, arm_cmplx_mag_q15` | `#include ` |\n", - "| **Hanning Window initialization** |`hanning_window = np.hanning(window_size)` | hanning_window_f32 = np.zeros(window_size)

for i in range(window_size):
  hanning_window_f32[i] = 0.5 * (1 - arm_cos_f32(2 * PI * i / window_size ))

hanning_window_q15 = arm_float_to_q15(hanning_window_f32)
| for (size_t i = 0; i < size; i++) {
  float32_t f = 0.5 * (1.0 - arm_cos_f32(2 * PI * i / size ));
  arm_float_to_q15(&f, &hanning_window_q15[i], 1);
}
|\n", + "| **Hanning Window initialization** |`hanning_window = np.hanning(window_size)` | hanning_window_q15 = arm_float_to_q15(arm_hanning_f32(window_size)) | arm_hanning_f32(hanning_window_f32, WINDOW_SIZE); arm_float_to_q15(hanning_window_f32, hanning_window_q15, WINDOW_SIZE); |\n", "| **FFT Initialization** | N/A | rfft_instance_q15 = arm_rfft_instance_q15()
arm_rfft_init_q15(rfft_instance_q15, window_size, 0, 1)
| `arm_rfft_init_q15(&S_q15, WINDOW_SIZE, 0, 1);` |\n", "| **Hanning Window applying** |`processed_window = hanning_window * window` | `processed_window_q15 = arm_mult_q15(window_q15, hanning_window_q15)` | `arm_mult_q15(input_q15, hanning_window_q15, processed_window_q15, WINDOW_SIZE);` |\n", "| **FFT** | `fft = np.fft.rfft(processed_window)` | `rfft_q15 = arm_rfft_q15(rfft_instance_q15, processed_audio)` | `arm_rfft_q15(&S_q15, processed_window_q15, fft_q15);` |\n",