Skip to content

Commit 89c52e8

Browse files
Merge pull request #1944 from madeline-underwood/cmsis
Cmsis_JA to review
2 parents aea6241 + 289f158 commit 89c52e8

File tree

9 files changed

+155
-133
lines changed

9 files changed

+155
-133
lines changed

content/learning-paths/embedded-and-microcontrollers/cmsisdsp-dev-with-python/_index.md

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
---
2-
title: Getting Started with CMSIS-DSP Using Python
2+
title: Getting started with CMSIS-DSP using Python
33

4-
minutes_to_complete: 30
4+
minutes_to_complete: 45
55

6-
draft: true
7-
cascade:
8-
draft: true
6+
who_is_this_for: This is an advanced topic for developers looking to integrate the CMSIS-DSP library into their applications using Python.
97

10-
who_is_this_for: Developers who want to learn how the CMSIS-DSP package can be integrated into their applications
118

129
learning_objectives:
13-
- Understand how to use the CMSIS-DSP Python package
14-
- Understand how the Python implementation maps to the C implementation
15-
- Develop a complex application using CMSIS-DSP
10+
- Use the CMSIS-DSP Python package to prototype DSP algorithms.
11+
- Understand how the Python API maps to the C implementation.
12+
- Build and port a complex DSP application using CMSIS-DSP.
1613

1714
prerequisites:
18-
- Some familiarity with Python and DSP programming
19-
- Knowledge of C
20-
- Some familiarity with CMSIS-DSP
21-
- Python installed on your system
15+
- Familiarity with Python and digital signal processing concepts.
16+
- Working knowledge of C.
17+
- Prior exposure to CMSIS-DSP.
18+
- Python installed on your machine.
2219

2320
author: Christophe Favergeon
2421

@@ -33,27 +30,27 @@ tools_software_languages:
3330
- Python
3431
- C
3532
- Jupyter Notebook
36-
- numpy
33+
- NumPy
3734
operatingsystems:
3835
- Linux
3936
- Windows
4037
- macOS
4138

4239
further_reading:
4340
- resource:
44-
title: Biquad filters with CMSIS-DSP Python package
41+
title: Biquad Filters with CMSIS-DSP Python Package
4542
link: https://developer.arm.com/documentation/102463/latest/
4643
type: documentation
4744
- resource:
48-
title: CMSIS-DSP library
45+
title: CMSIS-DSP Library (GitHub)
4946
link: https://github.com/ARM-software/CMSIS-DSP
5047
type: Open-source project
5148
- resource:
52-
title: CMSIS-DSP python package
49+
title: CMSIS-DSP Python Package (PyPi)
5350
link: https://pypi.org/project/cmsisdsp/
5451
type: Open-source project
5552
- resource:
56-
title: CMSIS-DSP Python package examples and tests
53+
title: CMSIS-DSP Python Package Examples and Tests
5754
link: https://github.com/ARM-software/CMSIS-DSP/tree/main/PythonWrapper/examples
5855
type: Open-source project
5956
- resource:

content/learning-paths/embedded-and-microcontrollers/cmsisdsp-dev-with-python/how-to-1.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,23 @@ layout: learningpathall
88

99
## What is CMSIS-DSP?
1010

11-
CMSIS-DSP is a general-purpose compute library with a focus on DSP. It was initially developed for Cortex-M processors and has recently been upgraded to also support Cortex-A.
11+
CMSIS-DSP is a general-purpose computation library focused on digital signal processing (DSP).
1212

13-
On each processor, CMSIS-DSP is optimized for the architecture: DSP extensions on M4 and M7; Helium on M55 and M85; Neon on A55, etc.
13+
Originally developed for Cortex-M processors, it now also supports Cortex-A.
1414

15-
## What is the CMSIS-DSP Python package?
15+
The library is optimized for each architecture:
16+
17+
- DSP extensions on Cortex-M4 and M7.
18+
- Helium on M55 and M85.
19+
- Neon on Cortex-A55 and other Cortex-A cores.
1620

17-
The CMSIS-DSP Python package is a Python API for CMSIS-DSP. Its goal is to make it easier to develop a C solution using CMSIS-DSP by decreasing the gap between a design environment like Python and the final C implementation.
21+
## What is the CMSIS-DSP Python package?
22+
23+
The CMSIS-DSP Python package provides a Python API for CMSIS-DSP. Its goal is to make it easier to develop a C solution using CMSIS-DSP by bridging the gap between a Python-based design environment and a final C implementation.
1824

19-
For this reason, the Python API is as close as possible to the C one.
25+
The API is designed to closely mirror the C version in both function and structure.
2026

21-
Fixed-point arithmetic is rarely provided by Python packages, which generally focus on floating-point operations. The CMSIS-DSP Python package provides the same fixed-point arithmetic functions as the C version: Q31, Q15 and Q7. The package also provides floating-point functions and will also support half-precision floats in the future, like the C API.
27+
Fixed-point arithmetic is rarely supported by Python libraries, which generally focus on floating-point operations. The CMSIS-DSP Python package includes the same fixed-point arithmetic functions as the C version: Q31, Q15 and Q7. Support for half-precision floats will be added in a future release, matching the C API.
2228

23-
Finally, the CMSIS-DSP Python package is compatible with NumPy and can be used with all other scientific and AI Python packages such as SciPy and PyTorch.
29+
The package is compatible with NumPy and integrates well with scientific and AI libraries such as SciPy and PyTorch.
2430

content/learning-paths/embedded-and-microcontrollers/cmsisdsp-dev-with-python/how-to-2.md

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,64 @@
11
---
2-
title: Install the Python packages
2+
title: Set up environment
33
weight: 3
44

55
### FIXED, DO NOT MODIFY
66
layout: learningpathall
77
---
88

9-
The application you will develop requires a few additional Python packages besides CMSIS-DSP. These need to be installed before you start writing code.
9+
## Create a Python virtual environment
1010

11-
You should install the packages in a Python virtual environment. For example, you can use:
11+
To follow this Learning Path, you'll need to install a few additional Python packages alongside CMSIS-DSP.
1212

13-
```
13+
Start by installing the packages in a Python virtual environment. For example, you can use:
14+
15+
```bash
1416
python -m venv cmsis-dsp-venv
1517
```
18+
If required, activate the environment.
19+
20+
## Install CMSIS-DSP
1621

17-
The first package to install is CMSIS-DSP:
22+
Now install the required packages, starting with CMSIS-DSP:
1823

1924
```bash
2025
pip install cmsisdsp
2126
```
22-
It will also install `NumPy`, which is a dependency of the CMSIS-DSP Python package.
27+
This will also install `NumPy`, which is a dependency of the CMSIS-DSP Python package.
2328

24-
You'll be working with a Jupyter notebook, so the `jupyter` package must also be installed:
29+
## Install Jupyter
30+
31+
You'll be working with a Jupyter notebook, so install the `jupyter` package:
2532

2633
```bash
2734
pip install jupyter
2835
```
36+
## Install additional tools
2937

30-
Finally, you'll need packages to read sound files, play sound using widgets, and display plots:
38+
Finally, you'll also need packages for reading sound files, playing sound using widgets, and displaying plots:
3139

3240
```bash
3341
pip install soundfile ipywidgets matplotlib
3442
```
3543

44+
## Launch Jupyter and set up your notebook
45+
3646
You can now launch the Jupyter notebook with the following command:
3747

3848
```bash
3949
jupyter notebook
4050
```
41-
A browser window should open showing the source tree your terminal launched from. Create a new Jupyter notebook by clicking the `New` dropdown and selecting `Python 3 (ipykernel)`. The new notebook will be named `Untitled`. Rename it to something more descriptive, for example `cmsis-dsp`.
51+
A browser window should open, displaying the source tree.
52+
53+
Create a new Jupyter notebook by clicking **New** and selecting **Python 3 (ipykernel)**. The new notebook is called `Untitled`. Rename it to something descriptive, for example `cmsis-dsp`.
54+
55+
Now import all the required packages by copying and running the following Python code into your notebook and run the cell (Shift+Enter).
56+
57+
{{% notice Note%}}
58+
All the Python code blocks in this Learning Path are intended to be executed in the same Jupyter notebook.
59+
{{% /notice %}}
60+
4261

43-
You can now import all the required packages. Copy the following Python code into your notebook and run the cell (Shift+Enter).
44-
All the Python code blocks in this learning path are intended to be executed in the same Jupyter notebook.
4562

4663
```python
4764
import cmsisdsp as dsp
@@ -65,4 +82,4 @@ import soundfile as sf
6582
from urllib.request import urlopen
6683
```
6784

68-
You're now ready to move on to the next steps, where you will set up some audio files for processing.
85+
You're now ready to move on and set up the audio files you'll use for processing.

content/learning-paths/embedded-and-microcontrollers/cmsisdsp-dev-with-python/how-to-3.md

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,49 @@ weight: 4
66
layout: learningpathall
77
---
88

9-
## Load an audio file
9+
## Load and screen audio file
1010

11-
You will use an audio file from one of the Arm demo repositories on GitHub.
11+
You'll use a sample audio file from an Arm demo repository on GitHub:
1212

1313
```python
14-
test_pattern_url="https://github.com/ARM-software/VHT-SystemModeling/blob/main/EchoCanceller/sounds/yesno.wav?raw=true"
14+
test_pattern_url = "https://github.com/ARM-software/VHT-SystemModeling/blob/main/EchoCanceller/sounds/yesno.wav?raw=true"
1515
f = urlopen(test_pattern_url)
1616
filedata = f.read()
1717
```
1818

19-
You can now play and listen to the audio:
19+
Play the audio in your Jupyter notebook:
2020

2121
```python
22-
audio=Audio(data=filedata,autoplay=False)
22+
audio = Audio(data=filedata,autoplay=False)
2323
audio
2424
```
2525

26-
An audio widget will appear in your Jupyter notebook:
26+
An audio widget will appear:
2727

28-
![audio widget alt-text#center](audiowidget.png "Figure 1. Audio widget")
28+
![audio widget alt-text#center](audiowidget.png "Audio widget")
2929

30-
You can use it to listen to the audio. You'll hear a sequence of the words "yes" and "no", with some noise between them. The goal of this learning path is to design an algorithm to remove the noise.
30+
You'll hear a sequence of the words "yes" and "no" with background noise. The goal of this Learning Path is to design an algorithm that removes that noise.
3131

32-
Next, convert the audio into a NumPy array so that it can be processed using CMSIS-DSP:
32+
### Convert the Audio to a NumPy array
33+
34+
Convert the audio into a NumPy array so it can be processed with CMSIS-DSP:
3335

3436
```python
3537
data, samplerate = sf.read(io.BytesIO(filedata))
36-
if len(data.shape)>1:
37-
data=data[:,0]
38+
if len(data.shape) > 1:
39+
data = data[:, 0]
3840
data = data.astype(np.float32)
39-
data=data/np.max(np.abs(data))
41+
data = data / np.max(np.abs(data))
4042
dataQ15 = fix.toQ15(data)
4143
```
4244

4345
The code above does the following:
44-
- Converts the audio into a NumPy array
45-
- If the audio is stereo, only one channel is kept
46-
- Normalizes the audio to ensure no value exceeds 1
47-
- Converts the audio to Q15 fixed-point representation to enable the use of CMSIS-DSP fixed-point functions
46+
- Converts the audio to a NumPy array.
47+
- Keeps only one channel if the audio is stereo.
48+
- Normalizes the audio to ensure no value exceeds 1.
49+
- Converts the audio to Q15 fixed-point representation to enable the use of CMSIS-DSP fixed-point functions.
50+
51+
### Plot the audio signal
4852

4953
Now, plot the audio waveform:
5054

@@ -53,27 +57,30 @@ plt.plot(data)
5357
plt.show()
5458
```
5559

56-
You'll get the following output:
60+
You'll see:
61+
62+
![audio signal alt-text#center](signal.png "Audio signal")
5763

58-
![audio signal alt-text#center](signal.png "Figure 2. Audio signal")
64+
The waveform shows a sequence of words. Between the words, the signal is not zero; there is some noise.
5965

60-
In the picture, you can see a sequence of words. Between the words, the signal is not zero: there is some noise.
66+
### Prepare for block-based processing
6167

62-
In a real application, you don't wait for the entire signal to be received. The signal is continuous. The samples are processed as they are received. Processing can either be sample-based or block-based. For this learning path, the processing will be block-based.
68+
In real applications, audio streams are processed in real time. Processing can either be sample-based or block-based. For this Learning Path, the processing is block-based.
6369

64-
Before you can move to the next step, this signal must be split into blocks. The processing will occur on small blocks of samples of a given duration, known as windows.
70+
Before you can move to the next step, this signal must be split into overlapping blocks. The processing will occur on small blocks of samples of a given duration, known as windows.
6571

6672
```python
67-
winDuration=30e-3/6
68-
winOverlap=15e-3/6
73+
winDuration = 30e-3 / 6
74+
winOverlap = 15e-3 / 6
6975

70-
winLength=int(np.floor(samplerate*winDuration))
71-
winOverlap=int(np.floor(samplerate*winOverlap))
72-
slices=sliding_window_view(data,winLength)[::winOverlap,:]
73-
slices_q15=sliding_window_view(dataQ15,winLength)[::winOverlap,:]
76+
winLength = int(np.floor(samplerate*winDuration))
77+
winOverlap = int(np.floor(samplerate*winOverlap))
78+
slices = sliding_window_view(data,winLength)[::winOverlap,:]
79+
slices_q15 = sliding_window_view(dataQ15,winLength)[::winOverlap,:]
7480
```
7581

7682
Refer to the [NumPy documentation](https://numpy.org/doc/stable/reference/generated/numpy.lib.stride_tricks.sliding_window_view.html) for details about `sliding_window_view`. It's not the most efficient function, but it is sufficient for this tutorial. The signal is split into overlapping blocks: each block reuses half of the samples from the previous block as defined by the `winOverlap` variable.
7783

78-
By running that last block, you have an audio signal that has been split into overlapping blocks. The next step is to do some processing on those blocks.
84+
By running that last block, you have an audio signal that has been split into overlapping blocks.
7985

86+
The next step is to do some processing on those blocks.

content/learning-paths/embedded-and-microcontrollers/cmsisdsp-dev-with-python/how-to-4.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ layout: learningpathall
88

99
## Write a simple voice activity detection
1010

11-
To remove the noise between speech segments, you need to detect when voice is present. Voice activity detection (VAD) can be complex, but for this learning path, you'll implement a very simple and naive approach based on _energy_. The idea is that if the environment isn't too noisy, speech should have more energy than the noise.
11+
To remove the noise between speech segments, you need to detect when voice is present. Voice activity detection (VAD) can be complex, but for this Learning Path, you'll implement a simple energy-based approach. The idea is that if the environment isn't too noisy, speech should have more energy than noise.
1212

13-
The detection will rely on a comparison with a threshold that must be manually tuned. That threshold will be hard-coded, which might not work in a real-life use-case, but is a sufficient solution for this learning path. You'll first implement a version of the VAD with NumPy, which will serve as a reference. Then you'll implement the same version using CMSIS-DSP with the Q15 fixed-point format.
13+
The detection relies on a comparison with a threshold that must be manually tuned. That threshold is hard-coded, which might not work in a real-life use case, but is a sufficient solution for this Learning Path.
1414

15-
Throughout this section, you should copy the code-blocks and run them in your Jupyter notebook.
15+
You'll first implement a version of the VAD with NumPy, which serves as a reference. Then you'll implement the same version using CMSIS-DSP with the Q15 fixed-point format.
16+
17+
Throughout this section, you should copy the code blocks and run them in your Jupyter notebook.
1618

1719
### NumPy VAD
1820

@@ -56,7 +58,7 @@ vad = np.array([[w]*(winLength-winOverlap) for w in cleaned]).flatten()
5658
ax.plot(data)
5759
ax.plot(vad)
5860
```
59-
![vad alt-text#center](vad.png "Figure 3. VAD reference implementation")
61+
![vad alt-text#center](vad.png "VAD reference implementation")
6062

6163
This plot shows you that the reference implementation works. The next step is to implement a similar graph using CMSIS-DSP.
6264

@@ -65,13 +67,15 @@ This plot shows you that the reference implementation works. The next step is to
6567
#### Energy
6668
First, you need to compute the signal energy from audio in Q15 format using CMSIS-DSP.
6769

68-
If you look at the CMSIS-DSP documentation, you'll see that the `power` and `vlog` functions don't produce results in Q15 format. Tracking the fixed-point format throughout all lines of an algorithm can be challenging. In this example, this means that:
70+
If you look at the CMSIS-DSP documentation, you'll see that the `power` and `vlog` functions don't produce results in Q15 format. Tracking the fixed-point format throughout all lines of an algorithm can be challenging.
71+
72+
In this example, this means that:
6973

7074
* Subtracting the mean to center the signal - as you did in the reference implementation - is handled in CMSIS-DSP by negating the mean and applying it as an offset to the window. Using CMSIS-DSP, `arm_negate_q15` is needed to avoid saturation issues that could prevent the value sign from changing (`0x8000` remaining unchanged as `0x8000`). In practice, the mean should be small, and there should be no difference between `-` and `dsp.arm_negate_q15`. However, it is good practice to avoid using `-` or `+` in a fixed-point algorithm when translating it to CMSIS-DSP function calls.
71-
* The resulting `energy` and `dB` values are not in Q15 format because the `power` and `vlog` functions are used
72-
* The multiplication by 10 from the reference implementation is missing
75+
* The resulting `energy` and `dB` values are not in Q15 format because the `power` and `vlog` functions are used.
76+
* The multiplication by 10 from the reference implementation is missing.
7377

74-
This means that the `signal_energy_q15` will have a different output than the above implementation. Instead of trying to determine the exact fixed-point format of the output and applying the necessary shift to adjust the output's fixed-point format, you will address it in the next step by tuning the threshold of the detection function.
78+
This means that the `signal_energy_q15` will have a different output than the above implementation. Instead of trying to determine the exact fixed-point format of the output and applying the necessary shift to adjust the output's fixed-point format, you will address it in the next step by tuning the threshold of the detection function:
7579

7680

7781
```python
@@ -91,7 +95,7 @@ def signal_energy_q15(window):
9195

9296
#### VAD
9397

94-
The comparison function is very similar to the NumPy reference, but the threshold is different:
98+
The comparison function is similar to the NumPy reference, but the threshold is different:
9599

96100
```python
97101
def signal_vad_q15(window):
@@ -102,12 +106,12 @@ def signal_vad_q15(window):
102106
```
103107

104108
{{% notice Note %}}
105-
In C code, you would hard-code the output of `fix.toQ15(-0.38)`. `fix.toQ15` is a utility of the Python package to convert float to fixed-point, but it is not available in the CMSIS-DSP C implementation. CMSIS-DSP C has functions like `arm_float_to_q15` which work on arrays and are meant to be used at runtime. If you need a pre-computed constant, you can use a utility function like `fix.toQ15` during development and use the resulting value in the C code.
109+
In C code, you can hard-code the output of `fix.toQ15(-0.38)`. `fix.toQ15` is a utility of the Python package to convert float to fixed-point, but it is not available in the CMSIS-DSP C implementation. CMSIS-DSP C provides functions like `arm_float_to_q15` which operate on arrays and are intended for use at runtime. To define a precomputed constant, use a utility function like `fix.toQ15` during development and copy the resulting value into your C code.
106110
{{% /notice %}}
107111

108112
#### Plot the Q15 implementation
109113

110-
The clean VAD function is now the same for both the NumPy and Q15 versions. You can check whether the Q15 version is working by plotting the signal and the output of the Q15 VAD algorithm.
114+
The clean VAD function is now the same for both the NumPy and Q15 versions. You can check whether the Q15 version is working by plotting the signal and the output of the Q15 VAD algorithm:
111115

112116
```python
113117
_,ax=plt.subplots(1,1)

0 commit comments

Comments
 (0)