CMSIS-DSP: Moved example application to a new repository.

Kernel examples are still in CMSIs-DSP.
pull/19/head
Christophe Favergeon 5 years ago
parent 7accd563b9
commit 22a3e4a048

@ -1,8 +0,0 @@
Applications
============
This folder is containing more complex examples of the use of the CMSIS-DSP.
Those examples are not available as part of the MDK.
Some examples may rely on external technologies (Arduino ...)

@ -1,73 +0,0 @@
/*
* Copyright (c) 2020 Arm Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* This example reads audio data from the on-board PDM microphones
* and try to detect a 1kHz sine signal using a SVM predictor.
*
* Circuit:
* - Arduino Nano 33 BLE board
*/
import processing.serial.*;
Serial myPort;
// Color opacity for the test display
int n = 0;
// Decay of color opacity
int decay = 5;
void setup()
{
size(380, 150);
myPort = new Serial(this, "COM6", 115200);
textSize(72); // set text size
myPort.clear();
}
void draw() {
// If some data is available on the serial port then some signal was detected.
if (myPort.available() > 0)
{
// Opacity is set to maximum.
n=255;
myPort.clear();
}
background(255);
textAlign(CENTER);
// Define a green color with some oapcity
fill(0, 255, 0, n);
// Decrease the opacity until it is 0.
if (n >= decay)
{
n = n - decay;
}
else
{
n = 0;
}
// Display the word "Detected"
text("DETECTED", 190, 95);
}

@ -1,48 +0,0 @@
# Sine Detection
This example is showing how to detect a sine of 1 kHz with Support Vector Machine.
It is not the simplest nor best way to detect a sine. It is just an example of the use of a SVM classifier which may be extended to signal a bit more complex than a sine by using the same method.
The performance of the app is highly dependent on the training data which was used.
On my tests, it is working well. But if your environment is quite different from mine (more noisy ...), then the training data I have used may not give good results.
The difficulty with machine learning is to find the right training set which will give a good generalization and a good behavior of unseen data.
For detection of more complex signals, smart features may be required. In this example, we work on the raw data. There is a bit of pre-processing:
1 - The data is rescale because SVM are not scale indepdendent ;
2 - Energy is used to rescale. We don't use the amplitude to avoid being impacted too much by sample outliers ;
3 - An Hanning window is applied. This step may not be needed but we have not experimented without it.
The training is done with this pre-processing applied to the signals.
If you want to know how to use a SVM with CMSIS-DSP, you can refer to this tutorial:
https://developer.arm.com/solutions/machine-learning-on-arm/developer-material/how-to-guides/implement-classical-ml-with-arm-cmsis-dsp-libraries
and the DSP/Examples/ARM/arm_svm_example folder.
## Sine Detection App
It is an Arduino app. It was tested on an Arduino Nano 33 BLE Sense.
It is using the PDM driver coming with this board.
If you want to use BLE, you'll need to install the ArduinoBLE and define BLEOUTPUT in the codee.
Then you'll need to install a BLE scanner on your phone.
If you don't enable BLE, you can see the detection status in the serial console.
You can also use the DetectionDisplay app.
## DetectionDisplay
This app is using https://processing.org/
You will have to change the serial port name in the app before building it.
This app is connecting to the serial port and listening to message from the Arduino.
When a sine is detected, it is displaying a green word with some fading.

@ -1,339 +0,0 @@
/*
* Copyright (c) 2020 Arm Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* This example reads audio data from the on-board PDM microphones
* and try to detect a 1kHz sine signal using a SVM predictor.
*
* Circuit:
* - Arduino Nano 33 BLE board
*/
#include <PDM.h>
/*
The CMSIS-DSP coming with the Arduino Nano 33 BLE board is not yet the
latest release and thus is not yet including the SVM predictor.
So, it is duplicated in this app (svmDef.cpp and svmDef.h)
*/
#include "arm_math.h"
#include "svmDef.hpp"
/*
Undefine this line if you want to use BLE rather than the serial console
for the detection information.
*/
//#define BLEOUTPUT
#if defined(BLEOUTPUT)
#include <ArduinoBLE.h>
// The UUID are coming from Arduino examples.
BLEService svmDetectionService("19B10010-E8F2-537E-4F6C-D104768A1214");
BLEBoolCharacteristic svmDetectionStatus("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
#endif
/*
Use to enable / disable the interrupts
*/
#include <hal/nrf_pdm.h>
/* Header generated by a training script (not included in this app) */
#include "svm.hpp"
//#define DUMP
/*
Dimension of the vector.
The training data has used segment of 256 samples.
*/
#define BUFSIZE vectorDimensions
/*
Hanning window.
*/
const float32_t hanning[BUFSIZE]={0.0f, 0.000151774f, 0.000607004f, 0.00136541f, 0.00242654f, 0.00378975f,
0.0054542f, 0.00741888f, 0.00968261f, 0.012244f, 0.0151015f, 0.0182534f,
0.0216978f, 0.0254325f, 0.0294554f, 0.0337639f, 0.0383554f, 0.0432273f,
0.0483764f, 0.0537997f, 0.0594939f, 0.0654555f, 0.071681f, 0.0781664f,
0.084908f, 0.0919015f, 0.0991429f, 0.106628f, 0.114351f, 0.122309f,
0.130496f, 0.138907f, 0.147537f, 0.156382f, 0.165435f, 0.174691f, 0.184144f,
0.19379f, 0.203621f, 0.213632f, 0.223818f, 0.23417f, 0.244684f, 0.255354f,
0.266171f, 0.277131f, 0.288226f, 0.299449f, 0.310794f, 0.322255f, 0.333823f,
0.345492f, 0.357254f, 0.369104f, 0.381032f, 0.393033f, 0.405099f, 0.417223f,
0.429397f, 0.441614f, 0.453866f, 0.466146f, 0.478447f, 0.490761f, 0.50308f,
0.515398f, 0.527706f, 0.539997f, 0.552264f, 0.5645f, 0.576696f, 0.588845f,
0.600941f, 0.612976f, 0.624941f, 0.636831f, 0.648638f, 0.660355f, 0.671974f,
0.683489f, 0.694893f, 0.706178f, 0.717338f, 0.728366f, 0.739256f, 0.75f,
0.760592f, 0.771027f, 0.781296f, 0.791395f, 0.801317f, 0.811056f, 0.820607f,
0.829962f, 0.839118f, 0.848067f, 0.856805f, 0.865327f, 0.873626f, 0.881699f,
0.88954f, 0.897145f, 0.904508f, 0.911626f, 0.918495f, 0.925109f, 0.931464f,
0.937558f, 0.943387f, 0.948946f, 0.954233f, 0.959243f, 0.963976f, 0.968426f,
0.972592f, 0.976471f, 0.980061f, 0.983359f, 0.986364f, 0.989074f, 0.991487f,
0.993601f, 0.995416f, 0.99693f, 0.998142f, 0.999052f, 0.999659f, 0.999962f,
0.999962f, 0.999659f, 0.999052f, 0.998142f, 0.99693f, 0.995416f, 0.993601f,
0.991487f, 0.989074f, 0.986364f, 0.983359f, 0.980061f, 0.976471f, 0.972592f,
0.968426f, 0.963976f, 0.959243f, 0.954233f, 0.948946f, 0.943387f, 0.937558f,
0.931464f, 0.925109f, 0.918495f, 0.911626f, 0.904508f, 0.897145f, 0.88954f,
0.881699f, 0.873626f, 0.865327f, 0.856805f, 0.848067f, 0.839118f, 0.829962f,
0.820607f, 0.811056f, 0.801317f, 0.791395f, 0.781296f, 0.771027f, 0.760592f,
0.75f, 0.739256f, 0.728366f, 0.717338f, 0.706178f, 0.694893f, 0.683489f,
0.671974f, 0.660355f, 0.648638f, 0.636831f, 0.624941f, 0.612976f, 0.600941f,
0.588845f, 0.576696f, 0.5645f, 0.552264f, 0.539997f, 0.527706f, 0.515398f,
0.50308f, 0.490761f, 0.478447f, 0.466146f, 0.453866f, 0.441614f, 0.429397f,
0.417223f, 0.405099f, 0.393033f, 0.381032f, 0.369104f, 0.357254f, 0.345492f,
0.333823f, 0.322255f, 0.310794f, 0.299449f, 0.288226f, 0.277131f, 0.266171f,
0.255354f, 0.244684f, 0.23417f, 0.223818f, 0.213632f, 0.203621f, 0.19379f,
0.184144f, 0.174691f, 0.165435f, 0.156382f, 0.147537f, 0.138907f, 0.130496f,
0.122309f, 0.114351f, 0.106628f, 0.0991429f, 0.0919015f, 0.084908f,
0.0781664f, 0.071681f, 0.0654555f, 0.0594939f, 0.0537997f, 0.0483764f,
0.0432273f, 0.0383554f, 0.0337639f, 0.0294554f, 0.0254325f, 0.0216978f,
0.0182534f, 0.0151015f, 0.012244f, 0.00968261f, 0.00741888f, 0.0054542f,
0.00378975f, 0.00242654f, 0.00136541f, 0.000607004f, 0.000151774f, 0.0f};
/*
Sample buffer for samples coming from PDM
*/
short sampleBuffer[512];
/*
svm buffer : The PDM samples converted to float,
rescaled and multiplied by the Hanning window.
*/
float svmBuffer[BUFSIZE];
/*
Number of PDM samples copied to SVM buffer.
*/
int svmSamplesConverted=0;
/*
Number of samples read from PDM
*/
volatile int samplesRead=0;
/*
PDM buffer ID.
It is used for debugging. Each time a new buffer of smples is
received, this number is incremented.
*/
volatile int bufferNb=0;
/*
Detection ID : Each time a new sine is detected, this number is incremented.
It is to display in the console and help deugging.
*/
int nbDetect=0;
// Class 0 is signal present
// Class 1 is signal missing
int32_t classes[2]={0,1};
/*
Configuration of the SVM data structure with parameters generated
from the training script.
*/
arm_svm_polynomial_instance_f32 svm = {
nbSupportVectors,
vectorDimensions,
intercept,
dualCoefs,
supportVectors,
classes,
degree,
coef0,
gamma
};
void setup() {
Serial.begin(115200);
while (!Serial);
PDM.setBufferSize(1024);
// configure the data receive callback
PDM.onReceive(onPDMdata);
// optionally set the gain, defaults to 20
// PDM.setGain(30);
// initialize PDM with:
// - one channel (mono mode)
// - a 16 kHz sample rate
if (!PDM.begin(1, 16000)) {
Serial.println("Failed to start PDM!");
while (1);
}
#if defined(BLEOUTPUT)
if (!BLE.begin())
{
Serial.println("starting BLE failed!");
while (1);
}
BLE.setLocalName("Sound Detection");
BLE.setAdvertisedService(svmDetectionService);
svmDetectionService.addCharacteristic(svmDetectionStatus);
BLE.addService(svmDetectionService);
svmDetectionStatus.writeValue(false);
BLE.advertise();
#endif
}
void loop() {
#if defined(BLEOUTPUT)
BLE.poll();
#endif
// If there are enough samples to apply the SVM prediction
if (samplesRead >0)
{
int i=0;
// We copy the received PDM samples to the SVM buffer.
// We don't want the sampleBuffer buffer to be modified
// while this copy is taking place.
// So PDM interrupts are disablsd.
NVIC_DisableIRQ(PDM_IRQn);
while((svmSamplesConverted < BUFSIZE) && (samplesRead > 0))
{
svmBuffer[svmSamplesConverted] = (float)sampleBuffer[i];
svmSamplesConverted++;
i++;
samplesRead--;
}
samplesRead = 0;
NVIC_EnableIRQ(PDM_IRQn);
}
// If the SVM buffer is full, we preprocess the sample
// and apply the SVM classifier.
if (svmSamplesConverted == BUFSIZE)
{
float32_t avgEnergy;
svmSamplesConverted = 0;
float32_t result=0;
// Convert samples to float and normalize them
// since SVM algorithm is not scale invariant.
// Clip to avoid outlier sample which would be too big.
// Apply the Hanning window.
arm_rms_f32(svmBuffer,BUFSIZE,&avgEnergy);
for (int i = 0; i < BUFSIZE; i++) {
svmBuffer[i] = svmBuffer[i] / avgEnergy;
// Analysis of the scaled tests patterns have shown
// that most values are between -2 and 2.
// So to avoid outliers, we clip between [-2,2].
// We have not checked if it is making a difference
// to the final quality of the prediction so this
// clipping is perhaps not needed.
if (svmBuffer[i] < -2)
{
svmBuffer[i] = -2;
}
if (svmBuffer[i] > 2)
{
svmBuffer[i] = 2;
}
}
// We multiply with the Hanning window.
arm_mult_f32(svmBuffer,(float32_t*)hanning,svmBuffer,BUFSIZE);
// We try to classify the result.
arm_svm_polynomial_predict_f32(&svm, svmBuffer,&result);
// If negative then a signal was detected.
if (result < 0)
{
nbDetect = nbDetect + 1;
#if defined(BLEOUTPUT)
if (!svmDetectionStatus.value())
{
svmDetectionStatus.writeValue(true);
}
#else
Serial.print(" d:");
Serial.print(nbDetect);
Serial.print(" b:");
Serial.print(bufferNb);
Serial.print(" ");
Serial.println("DETECTED");
#endif
}
else
{
#if defined(BLEOUTPUT)
if (svmDetectionStatus.value())
{
svmDetectionStatus.writeValue(false);
}
#endif
}
}
}
/*
Interrupt handler.
Received PDM data is copied into the buffer sampleBuffer.
*/
void onPDMdata() {
int bytesAvailable = PDM.available();
PDM.read(sampleBuffer , bytesAvailable);
samplesRead = bytesAvailable / 2;
bufferNb = bufferNb + 1;
}

@ -1,28 +0,0 @@
#include "svm.hpp"
const float dualCoefs[155]={
-1.000000,-1.000000,-1.000000,-0.718688,-0.678784,-1.000000
,-1.000000,-1.000000,-0.005257,-0.972356,-1.000000,-1.000000
,-1.000000,-1.000000,-0.657661,-0.144265,-0.228971,-1.000000
,-1.000000,-1.000000,-1.000000,-1.000000,-1.000000,-0.101008
,-1.000000,-1.000000,-1.000000,-1.000000,-1.000000,-0.225662
,-1.000000,-1.000000,-1.000000,-1.000000,-1.000000,-1.000000
,-0.371067,-1.000000,-1.000000,-1.000000,-1.000000,-1.000000
,-0.750365,-1.000000,-1.000000,-1.000000,-1.000000,-1.000000
,-1.000000,-1.000000,-1.000000,-1.000000,-0.200459,-0.736618
,-1.000000,-1.000000,-0.013296,-1.000000,-1.000000,-1.000000
,0.543122,1.000000,0.294495,0.146869,0.411956,0.169854
,1.000000,0.246227,0.463989,0.137775,0.347754,0.171902
,0.047820,1.000000,0.058865,1.000000,1.000000,1.000000
,1.000000,0.723999,1.000000,0.622752,0.702207,0.682727
,0.483939,0.316732,1.000000,0.328298,0.166691,0.484577
,0.801786,0.057679,0.843401,0.836016,0.303296,0.296567
,0.083458,0.380835,0.487379,1.000000,0.280286,0.866654
,0.029825,0.423952,0.652876,1.000000,0.601692,0.464190
,1.000000,0.074890,0.008204,1.000000,1.000000,1.000000
,0.630193,1.000000,1.000000,1.000000,0.702675,0.577836
,0.153860,0.539869,0.052447,1.000000,1.000000,0.996619
,1.000000,0.636447,0.985060,1.000000,1.000000,0.113309
,0.141574,0.186510,0.045323,0.091481,0.291608,0.146172
,0.121734,0.096191,0.124460,0.211330,0.095382,0.746746
,0.198886,0.937543,0.274358,1.000000,1.000000,0.001097
,0.120421,0.575083,0.875442,0.507657,0.581607};

@ -1,15 +0,0 @@
#ifndef _SVM_H_
#define _SVM_H_
#define nbSupportVectors 155
#define vectorDimensions 256
#define degree 3
#define coef0 1.000000
#define gamma 0.003906
#define intercept 0.849596
extern const float dualCoefs[nbSupportVectors];
extern const float supportVectors[nbSupportVectors*vectorDimensions];
#endif

@ -1,69 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_svm_polynomial_predict_f32.c
* Description: SVM Polynomial Classifier
*
*
* Target Processor: Cortex-M and Cortex-A cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2019 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "svmDef.hpp"
#define STEP(x) (x) <= 0 ? 0 : 1
static float32_t arm_exponent_f32(float32_t x, int32_t nb)
{
float32_t r = x;
nb --;
while(nb > 0)
{
r = r * x;
nb--;
}
return(r);
}
void arm_svm_polynomial_predict_f32(
const arm_svm_polynomial_instance_f32 *S,
const float32_t * in,
float32_t *pResult)
{
float32_t sum=S->intercept;
float32_t dot=0;
uint32_t i,j;
const float32_t *pSupport = S->supportVectors;
for(i=0; i < S->nbOfSupportVectors; i++)
{
dot=0;
for(j=0; j < S->vectorDimension; j++)
{
dot = dot + in[j]* *pSupport++;
}
sum += S->dualCoefficients[i] * arm_exponent_f32(S->gamma * dot + S->coef0, S->degree);
}
/*
Original CMSIS-DSP is returning the class.
Here we are returning the value and the class is computed by the client.
*/
*pResult=sum;
}

@ -1,49 +0,0 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_svm_polynomial_predict_f32.c
* Description: SVM Polynomial Classifier
*
*
* Target Processor: Cortex-M and Cortex-A cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2019 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _SVMDEFH_
#define _SVMDEFH_
#include "arm_math.h"
typedef struct
{
uint32_t nbOfSupportVectors; /**< Number of support vectors */
uint32_t vectorDimension; /**< Dimension of vector space */
float32_t intercept; /**< Intercept */
const float32_t *dualCoefficients; /**< Dual coefficients */
const float32_t *supportVectors; /**< Support vectors */
const int32_t *classes; /**< The two SVM classes */
int32_t degree; /**< Polynomial degree */
float32_t coef0; /**< Polynomial constant */
float32_t gamma; /**< Gamma factor */
} arm_svm_polynomial_instance_f32;
void arm_svm_polynomial_predict_f32(const arm_svm_polynomial_instance_f32 *S,
const float32_t * in,
float32_t * pResult);
#endif
Loading…
Cancel
Save