From eff587ed85669d17a17c4ad8cff9b0acea0d45fa Mon Sep 17 00:00:00 2001 From: Siddartha Pothapragada Date: Tue, 16 Jun 2026 23:28:48 -0700 Subject: [PATCH] Add ExecuTorch Arduino library with CMSIS-NN keyword spotting example Package ExecuTorch as an Arduino library installable via Library Manager. Includes build script that vendors runtime sources, DS-CNN keyword spotting example with CMSIS-NN acceleration, and pre-generated MFCC test inputs from Google Speech Commands. Tested on Arduino Uno Q (STM32U585, Cortex-M33). --- examples/arduino/.gitignore | 2 + examples/arduino/ExecuTorchArduino.h | 30 ++ examples/arduino/README.md | 314 ++++++++++++++++++ examples/arduino/build_arduino_library.sh | 258 ++++++++++++++ .../arduino/examples/AddModel/AddModel.ino | 158 +++++++++ .../HelloExecuTorch/HelloExecuTorch.ino | 50 +++ .../KeywordSpotting/KeywordSpotting.ino | 183 ++++++++++ .../examples/KeywordSpotting/mfcc_down.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_go.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_left.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_no.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_off.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_on.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_right.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_stop.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_up.h | 105 ++++++ .../examples/KeywordSpotting/mfcc_yes.h | 105 ++++++ examples/arduino/export_model.py | 233 +++++++++++++ examples/arduino/generate_test_input.py | 115 +++++++ examples/arduino/library.properties | 16 + examples/arduino/platform_stubs.c | 42 +++ .../boards/arduino_uno_q.conf | 20 ++ 22 files changed, 2471 insertions(+) create mode 100644 examples/arduino/.gitignore create mode 100644 examples/arduino/ExecuTorchArduino.h create mode 100644 examples/arduino/README.md create mode 100755 examples/arduino/build_arduino_library.sh create mode 100644 examples/arduino/examples/AddModel/AddModel.ino create mode 100644 examples/arduino/examples/HelloExecuTorch/HelloExecuTorch.ino create mode 100644 examples/arduino/examples/KeywordSpotting/KeywordSpotting.ino create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_down.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_go.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_left.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_no.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_off.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_on.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_right.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_stop.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_up.h create mode 100644 examples/arduino/examples/KeywordSpotting/mfcc_yes.h create mode 100644 examples/arduino/export_model.py create mode 100644 examples/arduino/generate_test_input.py create mode 100644 examples/arduino/library.properties create mode 100644 examples/arduino/platform_stubs.c create mode 100644 zephyr/samples/hello-executorch/boards/arduino_uno_q.conf diff --git a/examples/arduino/.gitignore b/examples/arduino/.gitignore new file mode 100644 index 00000000000..453c723c671 --- /dev/null +++ b/examples/arduino/.gitignore @@ -0,0 +1,2 @@ +# Generated by build_arduino_library.sh — do not check in +arduino_lib/ diff --git a/examples/arduino/ExecuTorchArduino.h b/examples/arduino/ExecuTorchArduino.h new file mode 100644 index 00000000000..dc5e97147d1 --- /dev/null +++ b/examples/arduino/ExecuTorchArduino.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +// Arduino's custom header omits , which breaks +// std::bad_variant_access in . Include it first. +#include + +#ifndef C10_USING_CUSTOM_GENERATED_MACROS +#define C10_USING_CUSTOM_GENERATED_MACROS +#endif +#ifndef ET_ENABLE_DEPRECATED_CONSTANT_BUFFER +#define ET_ENABLE_DEPRECATED_CONSTANT_BUFFER 0 +#endif +#ifndef FLATBUFFERS_MAX_ALIGNMENT +#define FLATBUFFERS_MAX_ALIGNMENT 1024 +#endif + +#include +#include +#include +#include +#include +#include diff --git a/examples/arduino/README.md b/examples/arduino/README.md new file mode 100644 index 00000000000..453b01a0708 --- /dev/null +++ b/examples/arduino/README.md @@ -0,0 +1,314 @@ + + +# ExecuTorch Arduino Library + +Run PyTorch models on Arduino microcontrollers using ExecuTorch. + +This directory contains everything needed to package ExecuTorch as an +Arduino library. A build script vendors the runtime sources from this +repository into a self-contained library that Arduino users install +through the Library Manager or by copying into their libraries folder. + +## How It Works + +``` +PyTorch Model ──► torch.export ──► .pte file ──► model.h (C array) + │ + Arduino Sketch (.ino) + #include + #include "model.h" + │ + arduino-cli compile ──► Upload ──► Runs on board +``` + +### The three pieces + +1. **The library** (`arduino_lib/ExecuTorchArduino/`) — the ExecuTorch + runtime, CMSIS-NN kernels, and portable ops packaged for the Arduino + build system. Generated by `build_arduino_library.sh`; not checked in. + +2. **The model** (`model.h`) — a `.pte` file converted to a C byte array. + Each user brings their own model, exported from PyTorch with the + Cortex-M backend. + +3. **The sketch** (`.ino`) — a standard Arduino program that loads the + model, feeds it input, and reads the output. Uses the native + ExecuTorch C++ API (`Program::load`, `Method::execute`, etc.). + +## Supported Boards + +| Board | MCU | Status | +|-------|-----|--------| +| Arduino Uno Q | STM32U585 (Cortex-M33) | Tested | +| Arduino Nano 33 BLE | nRF52840 (Cortex-M4F) | Planned (requires mbed PAL) | +| Arduino Giga R1 WiFi | STM32H747 (Cortex-M7) | Planned (requires mbed PAL) | +| Arduino Portenta H7 | STM32H747 (Cortex-M7) | Planned (requires mbed PAL) | + +The library currently requires the Zephyr board core. Non-Zephyr boards +(mbed) need a platform abstraction layer port before they can compile. +CMSIS-NN accelerated ops work on any ARM Cortex-M with DSP extensions. +Portable ops work on any architecture. + +## Quick Start + +### 1. Build the Arduino library + +```bash +cd examples/arduino +./build_arduino_library.sh +``` + +This copies the required ExecuTorch sources from the repository into +`arduino_lib/ExecuTorchArduino/`, ready for Arduino. + +### 2. Install the library + +Copy the generated library into your Arduino libraries folder: + +```bash +# macOS: +cp -r arduino_lib/ExecuTorchArduino ~/Documents/Arduino/libraries/ +# Linux: +cp -r arduino_lib/ExecuTorchArduino ~/Arduino/libraries/ +``` + +Or with `arduino-cli`: + +```bash +cd arduino_lib && zip -r ExecuTorchArduino.zip ExecuTorchArduino && cd .. +arduino-cli lib install --zip-path arduino_lib/ExecuTorchArduino.zip +``` + +### 3. Export a model + +The KeywordSpotting example requires a `model.h` file containing the +DS-CNN model as a C byte array. Generate it with `export_model.py`: + +```bash +# Download the dataset (one time, ~2.3 GB) — run from repo root: +python -c "import torchaudio; torchaudio.datasets.SPEECHCOMMANDS( + root='outputs/speech_commands', download=True)" + +# Train DS-CNN, quantize with CMSIS-NN, and export model.h: +python examples/arduino/export_model.py \ + --output examples/arduino/examples/KeywordSpotting/model.h +``` + +This trains DS-CNN on Google Speech Commands v2 (100 samples/class), +quantizes to int8 via `CortexMQuantizer`, calibrates with real MFCC +audio data, and exports a 54 KB `.pte` as a C header. + +To export with a pre-trained checkpoint instead of training: + +```bash +python examples/arduino/export_model.py --checkpoint my_weights.pth \ + --output examples/arduino/examples/KeywordSpotting/model.h +``` + +**Note:** `build_arduino_library.sh` requires schema headers from a prior +cmake build. If you haven't built ExecuTorch yet, run +`./install_executorch.sh` first. + +### 4. Write a sketch + +```cpp +#include +#include "model.h" + +using executorch::extension::BufferDataLoader; +using executorch::runtime::Error; +using executorch::runtime::HierarchicalAllocator; +using executorch::runtime::MemoryAllocator; +using executorch::runtime::MemoryManager; +using executorch::runtime::Method; +using executorch::runtime::MethodMeta; +using executorch::runtime::Program; +using executorch::runtime::Result; +using executorch::runtime::Span; + +alignas(16) uint8_t method_pool[28 * 1024]; +alignas(16) uint8_t temp_pool[8 * 1024]; + +void setup() { + Serial.begin(115200); + delay(2000); + + executorch::runtime::runtime_init(); + + auto loader = BufferDataLoader(model_pte, model_pte_size); + Result program = Program::load(&loader); + if (!program.ok()) { + Serial.println("Failed to load program"); + return; + } + + // ... load method, set inputs, execute, read outputs + // See examples/ for complete working sketches. +} + +void loop() { + // Run inference periodically + delay(2000); +} +``` + +The sketch uses the **native ExecuTorch C++ API** — the same API used on +Linux, Android, and bare-metal targets. No wrapper layer, no +Arduino-specific abstractions. + +### 5. Compile and upload + +```bash +arduino-cli compile --fqbn arduino:zephyr:unoq MySketch +arduino-cli upload --fqbn arduino:zephyr:unoq -p /dev/cu.usbmodem* MySketch +arduino-cli monitor -p /dev/cu.usbmodem* --config baudrate=115200 +``` + +## What is inside the library + +The `build_arduino_library.sh` script assembles these components from +the ExecuTorch repository: + +| Component | Source in repo | Purpose | +|-----------|---------------|---------| +| ET Runtime | `runtime/executor/`, `runtime/core/`, `runtime/kernel/`, `runtime/platform/` | Model loading, memory management, op dispatch | +| Portable Ops | `kernels/portable/` | Software op implementations (any CPU) | +| Cortex-M Ops | `backends/cortex_m/ops/` | CMSIS-NN accelerated int8 ops | +| CMSIS-NN | fetched by cmake / Zephyr module | ARM's optimized DSP kernels | +| flatcc | `third-party/flatcc/` | .pte file parsing | +| flatbuffers | `third-party/flatbuffers/` | Schema headers | +| c10 | `runtime/core/portable_type/c10/` | Core type definitions | + +The library uses no external dependencies beyond what the Arduino board +core provides. + +## Arduino-specific patches + +The build script applies these patches to make ExecuTorch compile under +Arduino's build system: + +1. **`#include ` before ``** — Arduino's custom + `` header omits ``, breaking `std::bad_variant_access`. + +2. **`cmake_macros.h` stub** — c10/torch headers expect a cmake-generated + file. The build script generates a stub; `C10_USING_CUSTOM_GENERATED_MACROS` + is defined in `ExecuTorchArduino.h` to skip the include. + +3. **`platform_stubs.c`** — provides weak stubs for `_Exit()`, `fprintf()`, + and `__aeabi_f2lz` for the LLEXT environment on boards that lack them. + +4. **Compile-time defines** — `ExecuTorchArduino.h` sets + `ET_ENABLE_DEPRECATED_CONSTANT_BUFFER=0` (requires models exported with + current ExecuTorch) and `FLATBUFFERS_MAX_ALIGNMENT=1024`. + +## Development + +### Updating the library + +After modifying ExecuTorch sources, regenerate the library: + +```bash +./build_arduino_library.sh # rebuild +./build_arduino_library.sh --clean # remove generated output +``` + +### Testing + +```bash +arduino-cli compile --fqbn arduino:zephyr:unoq examples/HelloExecuTorch +arduino-cli upload --fqbn arduino:zephyr:unoq -p /dev/cu.usbmodem* examples/HelloExecuTorch +arduino-cli monitor -p /dev/cu.usbmodem* --config baudrate=115200 +``` + +### Publishing to Arduino Library Manager + +The library is published by adding its repository URL to the +[Arduino Library Registry](https://github.com/arduino/library-registry). +After the initial registration, new git tags are picked up automatically. + +## Build Validation + +Tested on Arduino Uno Q (STM32U585, Cortex-M33 @ 160 MHz): + +- **Portable ops**: Add model (`x + 1.0`) produces correct output + `[1,2,3] + 1 = [2.0, 3.0, 4.0]` +- **CMSIS-NN linear**: Quantized linear model (int8, 2.2 KB) runs + `arm_fully_connected_s8` via `cortex_m::quantized_linear` +- **CMSIS-NN keyword spotting**: DS-CNN (MLPerf Tiny KWS benchmark, + 54 KB, int8) correctly classifies real audio from Google Speech + Commands dataset via 16 CMSIS-NN accelerated ops (conv2d, depthwise + conv2d, avgpool, linear, quantize, dequantize, pad) + +### Keyword Spotting Results + +Verified with real audio on hardware: + +``` +"yes" → [yes]=7.82 >>> Detected: yes CORRECT! +"no" → [no]=1.60 >>> Detected: no CORRECT! +``` + +To test different keywords, change one line in the sketch: + +```cpp +// In KeywordSpotting.ino, change this line: +#include "mfcc_yes.h" // → detects "yes" +// #include "mfcc_no.h" // → detects "no" +// #include "mfcc_stop.h" // → detects "stop" +// Available: mfcc_yes.h, mfcc_no.h, mfcc_up.h, mfcc_down.h, +// mfcc_left.h, mfcc_right.h, mfcc_on.h, mfcc_off.h, +// mfcc_stop.h, mfcc_go.h +``` + +To test with your own audio recording: + +```bash +python generate_test_input.py --input my_recording.wav --output mfcc_custom.h +# Then: #include "mfcc_custom.h" in the sketch +``` + +## End-to-End Flow + +``` +Google Speech Commands "yes" audio (.wav, 16kHz, 1 second) + → MFCC extraction (49 time frames × 10 coefficients) + → DS-CNN model (23K params, trained on MacBook CPU) + → CortexMQuantizer → int8 (calibrated with real MFCC data) + → CMSIS-NN ops (conv2d, depthwise_conv2d, avgpool, linear) + → Export to .pte (54 KB) + → Arduino library → arduino-cli compile → upload + → Cortex-M33 @ 160 MHz (Arduino Uno Q, STM32U585) + → Serial output: ">>> yes" ✅ +``` + +## Dataset + +Training and test audio from [Google Speech Commands v2](https://arxiv.org/abs/1804.03209) +— 65,000 one-second recordings of 35 words spoken by thousands of +people. Standard dataset used by the MLPerf Tiny benchmark. Download +via `torchaudio.datasets.SPEECHCOMMANDS` (2.3 GB). + +The DS-CNN KWS benchmark uses 12 output classes (silence, unknown, plus +10 keywords). The Arduino export script trains the 10 keyword classes: +yes, no, up, down, left, right, on, off, stop, go. + +## LLEXT Memory Budget + +The Arduino Uno Q loads sketches as LLEXT (Loadable Extensions) into +131 KB of dynamic memory. Both code and data share this budget: + +| Build | Code | Data | Total | Status | +|-------|------|------|-------|--------| +| Add model (portable ops) | 97 KB | 2 KB | 99 KB | ✅ | +| DS-CNN (selective CMSIS-NN) | 87 KB | 25 KB | 112 KB | ✅ | +| DS-CNN (all CMSIS-NN) | 230 KB | 39 KB | 269 KB | ❌ Too large | + +Selective CMSIS-NN inclusion (~30 compiled files vs 111 total) keeps the +build within budget. Arduino only compiles sources referenced by your +sketch; unused CMSIS-NN functions are excluded by the linker. diff --git a/examples/arduino/build_arduino_library.sh b/examples/arduino/build_arduino_library.sh new file mode 100755 index 00000000000..34eda865a07 --- /dev/null +++ b/examples/arduino/build_arduino_library.sh @@ -0,0 +1,258 @@ +#!/bin/bash +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +# build_arduino_library.sh — Assemble the ExecuTorch Arduino library +# from sources in this repository. +# +# Usage: +# ./build_arduino_library.sh # build the library +# ./build_arduino_library.sh --clean # remove generated output +# ./build_arduino_library.sh --bump patch # 0.1.0 → 0.1.1 +# ./build_arduino_library.sh --bump minor # 0.1.0 → 0.2.0 +# ./build_arduino_library.sh --bump major # 0.1.0 → 1.0.0 +# +# Output: arduino_lib/ExecuTorchArduino/ (self-contained, installable) + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +ET_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +OUT_DIR="$SCRIPT_DIR/arduino_lib/ExecuTorchArduino" +PROPS="$SCRIPT_DIR/library.properties" + +if [ "${1:-}" = "--clean" ]; then + echo "Cleaning generated library..." + rm -rf "$SCRIPT_DIR/arduino_lib" + echo "Done." + exit 0 +fi + +if [ "${1:-}" = "--bump" ]; then + PART="${2:-patch}" + CURRENT=$(grep "^version=" "$PROPS" | cut -d= -f2) + IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" + case "$PART" in + major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; + minor) MINOR=$((MINOR + 1)); PATCH=0 ;; + patch) PATCH=$((PATCH + 1)) ;; + *) echo "Usage: $0 --bump [major|minor|patch]"; exit 1 ;; + esac + NEW="$MAJOR.$MINOR.$PATCH" + sed -i '' "s/^version=.*/version=$NEW/" "$PROPS" 2>/dev/null || \ + sed -i "s/^version=.*/version=$NEW/" "$PROPS" + echo "Version: $CURRENT → $NEW" + exit 0 +fi + +echo "=== Building ExecuTorch Arduino Library ===" +echo " ET repo: $ET_ROOT" +echo " Output: $OUT_DIR" + +rm -rf "$OUT_DIR" +mkdir -p "$OUT_DIR/src" "$OUT_DIR/examples" + +# ───────────────────────────────────────────────────────── +# 1. Copy library metadata, wrapper header, and stubs +# ───────────────────────────────────────────────────────── +cp "$SCRIPT_DIR/library.properties" "$OUT_DIR/" +cp "$SCRIPT_DIR/ExecuTorchArduino.h" "$OUT_DIR/src/" +cp "$SCRIPT_DIR/platform_stubs.c" "$OUT_DIR/src/" +cp -r "$SCRIPT_DIR/examples/"* "$OUT_DIR/examples/" + +echo "[1/7] Metadata and examples copied" + +# ───────────────────────────────────────────────────────── +# 2. Vendor ET runtime sources +# ───────────────────────────────────────────────────────── +ET_SRC="$OUT_DIR/src/executorch" +mkdir -p "$ET_SRC" + +for dir in runtime/core runtime/executor runtime/kernel \ + runtime/platform runtime/backend; do + mkdir -p "$ET_SRC/$dir" + find "$ET_ROOT/$dir" -maxdepth 1 -name "*.h" -exec cp {} "$ET_SRC/$dir/" \; + find "$ET_ROOT/$dir" -maxdepth 1 -name "*.cpp" -exec cp {} "$ET_SRC/$dir/" \; +done + +# Subdirectories with headers +for dir in runtime/core/exec_aten runtime/core/exec_aten/util \ + runtime/core/portable_type runtime/platform/default; do + mkdir -p "$ET_SRC/$dir" + find "$ET_ROOT/$dir" -maxdepth 1 -name "*.h" -exec cp {} "$ET_SRC/$dir/" \; + find "$ET_ROOT/$dir" -maxdepth 1 -name "*.cpp" -exec cp {} "$ET_SRC/$dir/" \; +done + +# Extension data loader +mkdir -p "$ET_SRC/extension/data_loader" +cp "$ET_ROOT/extension/data_loader/"*.h "$ET_SRC/extension/data_loader/" +cp "$ET_ROOT/extension/data_loader/buffer_data_loader.cpp" \ + "$ET_SRC/extension/data_loader/" 2>/dev/null || true + +# Runner util headers +mkdir -p "$ET_SRC/extension/runner_util" +cp "$ET_ROOT/extension/runner_util/"*.h "$ET_SRC/extension/runner_util/" 2>/dev/null || true + +# Schema headers (generated — need a prior cmake build) +mkdir -p "$ET_SRC/schema" +cp "$ET_ROOT/schema/"*.h "$ET_SRC/schema/" 2>/dev/null || true +# Look for generated headers in common build dirs +for build_dir in "$ET_ROOT/cmake-out" "$ET_ROOT/cmake-out-mac" \ + "$ET_ROOT/outputs/build_uno_q"; do + if [ -d "$build_dir/schema/include/executorch/schema" ]; then + cp "$build_dir/schema/include/executorch/schema/"*.h "$ET_SRC/schema/" + break + fi +done + +# Verify schema headers were found +if [ ! -f "$ET_SRC/schema/program_generated.h" ]; then + echo "ERROR: Schema headers not found. Run a cmake build first (e.g. cmake -Bbuild -DCMAKE_INSTALL_PREFIX=cmake-out)." + exit 1 +fi + +echo "[2/7] ET runtime sources copied" + +# ───────────────────────────────────────────────────────── +# 3. Vendor portable kernels +# ───────────────────────────────────────────────────────── +mkdir -p "$ET_SRC/kernels/portable/cpu/util" \ + "$ET_SRC/kernels/portable/cpu/pattern" + +# Copy all portable op sources and headers +find "$ET_ROOT/kernels/portable/cpu" -maxdepth 1 \( -name "*.cpp" -o -name "*.h" \) \ + -exec cp {} "$ET_SRC/kernels/portable/cpu/" \; +cp "$ET_ROOT/kernels/portable/cpu/util/"*.h "$ET_SRC/kernels/portable/cpu/util/" +cp "$ET_ROOT/kernels/portable/cpu/util/"*.cpp "$ET_SRC/kernels/portable/cpu/util/" 2>/dev/null || true +cp "$ET_ROOT/kernels/portable/cpu/pattern/"*.h "$ET_SRC/kernels/portable/cpu/pattern/" +cp "$ET_ROOT/kernels/portable/cpu/pattern/"*.cpp "$ET_SRC/kernels/portable/cpu/pattern/" 2>/dev/null || true + +echo "[3/7] Portable kernels copied" + +# ───────────────────────────────────────────────────────── +# 4. Vendor Cortex-M backend ops +# ───────────────────────────────────────────────────────── +mkdir -p "$ET_SRC/backends/cortex_m/ops" +cp "$ET_ROOT/backends/cortex_m/ops/"*.cpp "$ET_SRC/backends/cortex_m/ops/" +cp "$ET_ROOT/backends/cortex_m/ops/"*.h "$ET_SRC/backends/cortex_m/ops/" + +echo "[4/7] Cortex-M ops copied" + +# ───────────────────────────────────────────────────────── +# 5. Vendor third-party dependencies +# ───────────────────────────────────────────────────────── + +# c10 / torch headers +cp -r "$ET_ROOT/runtime/core/portable_type/c10/c10" "$OUT_DIR/src/c10" +cp -r "$ET_ROOT/runtime/core/portable_type/c10/torch" "$OUT_DIR/src/torch" + +# cmake_macros.h stub +mkdir -p "$OUT_DIR/src/torch/headeronly/macros" +cat > "$OUT_DIR/src/torch/headeronly/macros/cmake_macros.h" << 'STUB' +#pragma once +#define C10_BUILD_SHARED_LIBS +#define C10_USE_GLOG 0 +#define C10_USE_MINIMAL_GLOG 0 +#define C10_USE_GFLAGS 0 +STUB + +# flatcc runtime and headers +mkdir -p "$OUT_DIR/src/flatcc/portable" +cp "$ET_ROOT/third-party/flatcc/include/flatcc/"*.h "$OUT_DIR/src/flatcc/" +cp -r "$ET_ROOT/third-party/flatcc/include/flatcc/portable" "$OUT_DIR/src/flatcc/" +mkdir -p "$OUT_DIR/src/flatcc/runtime" +cp "$ET_ROOT/third-party/flatcc/src/runtime/"*.c "$OUT_DIR/src/flatcc/runtime/" + +# flatbuffers headers +cp -r "$ET_ROOT/third-party/flatbuffers/include/flatbuffers" "$OUT_DIR/src/flatbuffers" + +# CMSIS-NN (from Zephyr workspace or cmake fetchcontent) +CMSIS_NN="" +for candidate in \ + "$ET_ROOT/outputs/zephyrproject/modules/lib/cmsis-nn" \ + "$ET_ROOT/third-party/cmsis-nn" \ + "$ET_ROOT/backends/arm/third-party/cmsis-nn/CMSIS-NN"; do + if [ -d "$candidate/Source" ]; then + CMSIS_NN="$candidate" + break + fi +done + +if [ -n "$CMSIS_NN" ]; then + mkdir -p "$OUT_DIR/src/cmsis-nn" + cp -r "$CMSIS_NN/Source" "$OUT_DIR/src/cmsis-nn/" + cp "$CMSIS_NN/Include/"*.h "$OUT_DIR/src/" 2>/dev/null || true + if [ -d "$CMSIS_NN/Include/Internal" ]; then + mkdir -p "$OUT_DIR/src/Internal" + cp "$CMSIS_NN/Include/Internal/"*.h "$OUT_DIR/src/Internal/" + fi + echo "[5/7] CMSIS-NN copied from $CMSIS_NN" +else + echo "[5/7] WARNING: CMSIS-NN not found. Cortex-M ops will not link." +fi + +# CMSIS Core headers (for arm_math_types.h) +for candidate in \ + "$ET_ROOT/outputs/zephyrproject/modules/hal/cmsis_6/CMSIS/Core/Include" \ + "$ET_ROOT/third-party/cmsis/CMSIS/Core/Include"; do + if [ -d "$candidate" ]; then + cp "$candidate/"*.h "$OUT_DIR/src/" 2>/dev/null || true + break + fi +done + +echo "[6/7] Third-party dependencies copied" + +# ───────────────────────────────────────────────────────── +# 6. Apply Arduino-specific patches +# ───────────────────────────────────────────────────────── + +# Fix: #include before in all ET headers +find "$OUT_DIR/src/executorch" -name "*.h" -print0 | \ + xargs -0 perl -pi -e 's/#include /#include \n#include /g' + +# Remove test files, ATen-specific files, non-Zephyr platform backends +find "$OUT_DIR" -path "*testing*" -delete 2>/dev/null || true +find "$OUT_DIR" -name "*_aten.cpp" -delete 2>/dev/null || true +find "$OUT_DIR" -path "*test*" -name "*.cpp" -delete 2>/dev/null || true +rm -f "$OUT_DIR/src/executorch/runtime/platform/default/android.cpp" +rm -f "$OUT_DIR/src/executorch/runtime/platform/default/posix.cpp" +rm -f "$OUT_DIR/src/executorch/runtime/platform/default/windows.cpp" + +# Regenerate schema headers if flatc is available +FLATC="" +for flatc_candidate in "$ET_ROOT/cmake-out-mac/third-party/flatc_ep/bin/flatc" \ + "$ET_ROOT/cmake-out/third-party/flatc_ep/bin/flatc" \ + "$ET_ROOT/build/third-party/flatc_ep/bin/flatc"; do + if [ -x "$flatc_candidate" ]; then FLATC="$flatc_candidate"; break; fi +done +if [ -n "$FLATC" ]; then + "$FLATC" --cpp --cpp-std c++11 --gen-mutable --scoped-enums \ + -o "$ET_SRC/schema/" \ + "$ET_ROOT/schema/program.fbs" \ + "$ET_ROOT/schema/scalar_type.fbs" 2>/dev/null + echo " Schema headers regenerated" +fi + +echo "[7/7] Arduino patches applied" + +# ───────────────────────────────────────────────────────── +# Summary +# ───────────────────────────────────────────────────────── +NSRC=$(find "$OUT_DIR/src" -name "*.cpp" -o -name "*.c" | wc -l | tr -d ' ') +NHDR=$(find "$OUT_DIR/src" -name "*.h" | wc -l | tr -d ' ') + +echo "" +echo "=== Library built ===" +echo " Location: $OUT_DIR" +echo " Sources: $NSRC" +echo " Headers: $NHDR" +echo "" +echo "Install:" +echo " cp -r $OUT_DIR ~/Arduino/libraries/" +echo "" +echo "Or clean up:" +echo " $0 --clean" diff --git a/examples/arduino/examples/AddModel/AddModel.ino b/examples/arduino/examples/AddModel/AddModel.ino new file mode 100644 index 00000000000..706c79e341d --- /dev/null +++ b/examples/arduino/examples/AddModel/AddModel.ino @@ -0,0 +1,158 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +// AddModel — Verified end-to-end ExecuTorch inference on Arduino +// +// Runs a simple add model (x + 1.0) using portable ops. +// Input: [1.0, 2.0, 3.0] → Output: [2.0, 3.0, 4.0] +// +// This example uses the native ExecuTorch C++ API with no backend-specific +// ops — it works on any Arduino board that supports the ExecuTorch library. +// +// To generate model.h from a PyTorch model: +// python -c " +// import torch +// from executorch.exir import to_edge +// from torch.export import export +// class AddModel(torch.nn.Module): +// def forward(self, x): return x + 1.0 +// et = to_edge(export(AddModel().eval(), (torch.tensor([1.,2.,3.]),))).to_executorch() +// open('model.h','w').write( +// '#pragma once\n#include \n#include \n' +// + 'alignas(16) static const uint8_t model_pte[] = {' +// + ','.join(f'0x{b:02x}' for b in et.buffer) + '};\n' +// + f'static const size_t model_pte_size = {len(et.buffer)};\n') +// " + +#include +#include "model.h" +#include + +using executorch::aten::ScalarType; +using executorch::extension::BufferDataLoader; +using executorch::runtime::Error; +using executorch::runtime::EValue; +using executorch::runtime::HierarchicalAllocator; +using executorch::runtime::MemoryAllocator; +using executorch::runtime::MemoryManager; +using executorch::runtime::Program; +using executorch::runtime::Result; +using executorch::runtime::Span; + +alignas(16) static uint8_t method_pool[8 * 1024]; +alignas(16) static uint8_t temp_pool[2 * 1024]; + +static BufferDataLoader* g_loader = nullptr; +static Program* g_prog = nullptr; + +void setup() { + Serial.begin(115200); + delay(2000); + Serial.println("=== ExecuTorch Add Model ==="); + + executorch::runtime::runtime_init(); + + static BufferDataLoader loader(model_pte, model_pte_size); + g_loader = &loader; + Result program = Program::load(g_loader); + if (!program.ok()) { + Serial.print("FAIL: load 0x"); + Serial.println((int)program.error(), HEX); + while (1) delay(1000); + } + Serial.print("Model: "); + Serial.print(model_pte_size); + Serial.println(" bytes"); + + static Program prog = std::move(program.get()); + g_prog = &prog; + Serial.println("Ready!"); +} + +void loop() { + auto name_result = g_prog->get_method_name(0); + if (!name_result.ok()) { + Serial.println("FAIL: no methods"); + delay(5000); + return; + } + const char* name = *name_result; + auto meta = g_prog->method_meta(name); + if (!meta.ok()) { + Serial.println("FAIL: method_meta"); + delay(5000); + return; + } + + MemoryAllocator ma(sizeof(method_pool), method_pool); + size_t np = meta->num_memory_planned_buffers(); + Span* sp = static_cast*>( + ma.allocate(np * sizeof(Span))); + if (!sp) { Serial.println("FAIL: OOM spans"); delay(5000); return; } + for (size_t i = 0; i < np; i++) { + auto sz_r = meta->memory_planned_buffer_size(i); + if (!sz_r.ok()) { Serial.println("FAIL: planned buf size"); delay(5000); return; } + size_t sz = static_cast(sz_r.get()); + uint8_t* buf = static_cast(ma.allocate(sz)); + if (!buf) { Serial.println("FAIL: OOM planned buf"); delay(5000); return; } + sp[i] = {buf, sz}; + } + HierarchicalAllocator pl({sp, np}); + MemoryAllocator ta(sizeof(temp_pool), temp_pool); + MemoryManager mm(&ma, &pl, &ta); + + auto method = g_prog->load_method(name, &mm); + if (!method.ok()) { + Serial.print("FAIL: load_method 0x"); + Serial.println((int)method.error(), HEX); + delay(5000); + return; + } + + float input_data[] = {1.0f, 2.0f, 3.0f}; + int32_t sizes[] = {3}; + uint8_t dim_order[] = {0}; + executorch::aten::TensorImpl impl( + ScalarType::Float, 1, sizes, input_data, dim_order); + executorch::aten::Tensor input(&impl); + Error err = method->set_input(EValue(input), 0); + if (err != Error::Ok) { + Serial.print("FAIL: set_input 0x"); + Serial.println((int)err, HEX); + delay(5000); + return; + } + + Error status = method->execute(); + if (status != Error::Ok) { + Serial.print("FAIL: execute 0x"); + Serial.println((int)status, HEX); + delay(5000); + return; + } + + EValue output; + err = method->get_outputs(&output, 1); + if (err != Error::Ok) { + Serial.print("FAIL: get_outputs 0x"); + Serial.println((int)err, HEX); + delay(5000); + return; + } + if (output.isTensor()) { + auto tensor = output.toTensor(); + Serial.print("[1,2,3] + 1 = ["); + for (int i = 0; i < tensor.numel(); i++) { + if (i > 0) Serial.print(", "); + Serial.print(tensor.const_data_ptr()[i]); + } + Serial.println("]"); + } + + delay(3000); +} diff --git a/examples/arduino/examples/HelloExecuTorch/HelloExecuTorch.ino b/examples/arduino/examples/HelloExecuTorch/HelloExecuTorch.ino new file mode 100644 index 00000000000..33867a1f507 --- /dev/null +++ b/examples/arduino/examples/HelloExecuTorch/HelloExecuTorch.ino @@ -0,0 +1,50 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +// HelloExecuTorch — Minimal ExecuTorch sketch +// +// Initializes the ExecuTorch runtime and loads a model using the core +// ET library (portable ops only, no hardware-specific backends). +// Use this to verify the library works on your board. + +#include +#include "model.h" + +using executorch::extension::BufferDataLoader; +using executorch::runtime::MemoryAllocator; +using executorch::runtime::Program; +using executorch::runtime::Result; + + +void setup() { + Serial.begin(115200); + delay(2000); + + Serial.println("=== HelloExecuTorch ==="); + + executorch::runtime::runtime_init(); + Serial.println("Runtime initialized."); + + auto loader = BufferDataLoader(model_pte, model_pte_size); + Result program = Program::load(&loader); + if (program.ok()) { + Serial.println("Model loaded OK!"); + Serial.print(" Size: "); + Serial.print(model_pte_size); + Serial.println(" bytes"); + Serial.print(" Methods: "); + Serial.println(program->num_methods()); + } else { + Serial.println("ERROR: Model load failed"); + } +} + +void loop() { + Serial.println("ExecuTorch ready"); + delay(5000); +} diff --git a/examples/arduino/examples/KeywordSpotting/KeywordSpotting.ino b/examples/arduino/examples/KeywordSpotting/KeywordSpotting.ino new file mode 100644 index 00000000000..9546755b8f6 --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/KeywordSpotting.ino @@ -0,0 +1,183 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +// KeywordSpotting — DS-CNN inference with ExecuTorch + CMSIS-NN +// +// Runs a quantized DS-CNN model (MLPerf Tiny KWS benchmark) on real +// MFCC audio features and prints the detected keyword. +// +// To test a different keyword, change the #include below: +// #include "mfcc_yes.h" → detects "yes" + +// #include "mfcc_no.h" → detects "no" +// #include "mfcc_stop.h" → detects "stop" +// etc. +// +// To test your own audio: +// python generate_test_input.py --input my_audio.wav --output mfcc_custom.h +// Then: #include "mfcc_custom.h" +// +// Pre-generated MFCC files from Google Speech Commands v2: +// mfcc_yes.h, mfcc_no.h, mfcc_up.h, mfcc_down.h, mfcc_left.h, +// mfcc_right.h, mfcc_on.h, mfcc_off.h, mfcc_stop.h, mfcc_go.h + +#include +#include +#include +#include "model.h" + +// *** Change this line to test different keywords *** +#include "mfcc_yes.h" + + +using executorch::aten::ScalarType; +using executorch::extension::BufferDataLoader; +using executorch::runtime::Error; +using executorch::runtime::EValue; +using executorch::runtime::HierarchicalAllocator; +using executorch::runtime::MemoryAllocator; +using executorch::runtime::MemoryManager; +using executorch::runtime::Program; +using executorch::runtime::Result; +using executorch::runtime::Span; + +static const char* kLabels[] = { + "silence", "unknown", "yes", "no", "up", "down", + "left", "right", "on", "off", "stop", "go"}; + +alignas(16) static uint8_t method_pool[28 * 1024]; +alignas(16) static uint8_t temp_pool[8 * 1024]; + +void setup() { + Serial.begin(115200); + delay(3000); + + Serial.println("=== ExecuTorch Keyword Spotting ==="); + Serial.print("Testing: "); + Serial.println(test_label); + + executorch::runtime::runtime_init(); + + static BufferDataLoader loader(model_pte, model_pte_size); + auto program = Program::load(&loader); + if (!program.ok()) { + Serial.print("FAIL: load 0x"); + Serial.println((int)program.error(), HEX); + while (1) delay(1000); + } + + static Program prog = std::move(program.get()); + auto name_r = prog.get_method_name(0); + if (!name_r.ok()) { Serial.println("FAIL: name"); while (1) delay(1000); } + auto meta = prog.method_meta(*name_r); + if (!meta.ok()) { Serial.println("FAIL: meta"); while (1) delay(1000); } + + MemoryAllocator ma(sizeof(method_pool), method_pool); + size_t np = meta->num_memory_planned_buffers(); + Span* sp = static_cast*>( + ma.allocate(np * sizeof(Span))); + if (!sp) { Serial.println("FAIL: OOM"); while (1) delay(1000); } + for (size_t i = 0; i < np; i++) { + auto sz_r = meta->memory_planned_buffer_size(i); + if (!sz_r.ok()) { Serial.println("FAIL: planned buf size"); while (1) delay(1000); } + size_t sz = static_cast(sz_r.get()); + uint8_t* buf = static_cast(ma.allocate(sz)); + if (!buf) { Serial.println("FAIL: OOM buf"); while (1) delay(1000); } + sp[i] = {buf, sz}; + } + + HierarchicalAllocator pl({sp, np}); + MemoryAllocator ta(sizeof(temp_pool), temp_pool); + MemoryManager mm(&ma, &pl, &ta); + + auto method = prog.load_method(*name_r, &mm); + if (!method.ok()) { + Serial.print("FAIL: method 0x"); + Serial.println((int)method.error(), HEX); + while (1) delay(1000); + } + + // Set input from MFCC data + auto imeta = meta->input_tensor_meta(0); + if (!imeta.ok()) { Serial.println("FAIL: imeta"); while (1) delay(1000); } + // Copy sizes/dim_order to local mutable arrays — TensorImpl stores pointers. + const size_t ndim = imeta->sizes().size(); + if (ndim != 4 || imeta->dim_order().size() != 4) { + Serial.println("FAIL: expected 4D input"); while (1) delay(1000); + } + if (imeta->scalar_type() != ScalarType::Float) { + Serial.println("FAIL: expected float input"); while (1) delay(1000); + } + int32_t input_sizes[4]; + for (size_t d = 0; d < imeta->sizes().size(); d++) input_sizes[d] = imeta->sizes()[d]; + uint8_t input_dim_order[4]; + for (size_t d = 0; d < imeta->dim_order().size(); d++) input_dim_order[d] = imeta->dim_order()[d]; + static float input_data[490]; + memcpy(input_data, test_input, sizeof(input_data)); + executorch::aten::TensorImpl iimpl( + ScalarType::Float, imeta->sizes().size(), + input_sizes, input_data, input_dim_order); + executorch::aten::Tensor it(&iimpl); + Error serr = method->set_input(EValue(it), 0); + if (serr != Error::Ok) { + Serial.print("FAIL: input 0x"); + Serial.println((int)serr, HEX); + while (1) delay(1000); + } + + // Run inference + Error status = method->execute(); + if (status != Error::Ok) { + Serial.print("FAIL: execute 0x"); + Serial.println((int)status, HEX); + while (1) delay(1000); + } + + // Read and display results + EValue output; + Error oerr = method->get_outputs(&output, 1); + if (oerr != Error::Ok) { + Serial.print("FAIL: output 0x"); + Serial.println((int)oerr, HEX); + while (1) delay(1000); + } + + if (output.isTensor()) { + auto tensor = output.toTensor(); + int best = 0; + float best_val = -1e9f; + for (int i = 0; i < 12 && i < tensor.numel(); i++) { + float val; + if (tensor.scalar_type() == ScalarType::Float) + val = tensor.const_data_ptr()[i]; + else + val = static_cast(tensor.const_data_ptr()[i]); + Serial.print(" ["); + Serial.print(kLabels[i]); + Serial.print("]="); + Serial.println(val); + if (val > best_val) { best_val = val; best = i; } + } + + Serial.print("\n>>> Detected: "); + Serial.println(kLabels[best]); + + if (strcmp(test_label, kLabels[best]) == 0) { + Serial.println(">>> CORRECT!"); + } else { + Serial.print(">>> Expected: "); + Serial.println(test_label); + } + } + + Serial.println("=== DONE ==="); +} + +void loop() { + delay(10000); +} diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_down.h b/examples/arduino/examples/KeywordSpotting/mfcc_down.h new file mode 100644 index 00000000000..e0d53958c39 --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_down.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "down" (0cb74144_nohash_4.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -507.322296f, 19.031570f, 11.984641f, 4.382929f, 2.187682f, + -2.236901f, -5.487720f, -4.277254f, -3.514820f, -2.503060f, + -506.204712f, 16.616709f, 9.791165f, 1.699199f, 0.929732f, + -2.286182f, -1.775557f, -3.822668f, -5.983240f, -4.030620f, + -505.818787f, 18.477285f, 12.980515f, 4.151159f, -2.317702f, + -6.760072f, -9.771207f, -7.646851f, -8.984913f, -8.239711f, + -505.996124f, 19.471718f, 11.576015f, 6.461376f, 1.549109f, + -5.414501f, -6.885021f, -5.290980f, -5.431142f, -5.739652f, + -506.938141f, 22.361822f, 15.468247f, 3.967310f, -1.717137f, + -4.964677f, -5.905561f, -5.998286f, -7.678048f, -7.802891f, + -506.387817f, 21.944481f, 13.497569f, 2.220078f, -2.636032f, + -8.040266f, -10.937485f, -11.317524f, -11.105369f, -8.468291f, + -500.701172f, 19.412809f, 9.432601f, 4.001873f, 0.222245f, + -4.719224f, -6.627161f, -11.446534f, -14.340959f, -11.206966f, + -506.475494f, 18.093817f, 11.830796f, 3.394541f, -4.562102f, + -7.641331f, -9.069060f, -8.102795f, -7.968098f, -6.782180f, + -508.402344f, 17.802567f, 11.093653f, 4.198254f, 0.158075f, + -2.341327f, -6.425941f, -8.639082f, -9.682294f, -8.308583f, + -511.346924f, 16.587252f, 13.014997f, 4.039328f, -0.194213f, + -4.509769f, -5.810899f, -6.675086f, -9.108331f, -8.172515f, + -509.027283f, 22.162457f, 16.678679f, 6.867827f, 1.536411f, + -4.212164f, -10.553008f, -11.947165f, -13.144227f, -12.000507f, + -509.567780f, 22.211918f, 15.144291f, 6.882088f, 1.521042f, + -1.588232f, -4.835599f, -7.431235f, -10.057443f, -8.429801f, + -509.334106f, 17.419577f, 12.041722f, 5.337184f, 1.816456f, + -5.854978f, -6.630109f, -5.379322f, -3.416212f, -3.990121f, + -505.931152f, 19.444708f, 14.868617f, 6.207478f, -0.725857f, + -5.438529f, -7.107523f, -6.254251f, -7.737273f, -6.257424f, + -233.417343f, -18.773762f, -33.208809f, -14.974154f, -42.168556f, + 4.453810f, -14.281873f, -0.944977f, 1.277727f, 4.912548f, + -51.916065f, 32.266281f, -1.444840f, 7.316195f, -24.188118f, + 8.379232f, -22.730383f, -4.223300f, -1.941792f, 6.928730f, + 0.524539f, 66.435463f, -3.533064f, -0.701846f, -17.307106f, + -6.932579f, -32.307350f, -5.578140f, -3.574250f, 6.760275f, + 61.356987f, 50.438007f, -11.829906f, -8.320004f, -19.319883f, + -6.834112f, -29.980610f, -6.082206f, -2.539225f, 9.499821f, + 69.046478f, 48.126640f, -16.597343f, -20.410593f, -19.310026f, + -2.789631f, -25.321642f, -4.993752f, -1.663412f, 0.005825f, + 52.769432f, 55.177128f, -23.456247f, -17.839691f, -21.768991f, + 2.860769f, -22.064938f, -2.694108f, -4.239452f, -0.276229f, + 51.789234f, 55.842739f, -22.901646f, -21.306458f, -25.636705f, + 6.972529f, -17.317434f, 2.140889f, -7.470555f, -1.707357f, + 52.760483f, 55.721001f, -22.876581f, -22.304995f, -25.359991f, + 10.320010f, -21.273653f, 5.542525f, -4.495225f, -0.818654f, + 38.854576f, 61.610809f, -24.478935f, -24.934580f, -23.740362f, + 13.263118f, -23.640944f, -0.954478f, -11.095513f, -0.557147f, + 17.594910f, 62.097698f, -25.234026f, -25.208311f, -23.462837f, + 13.048333f, -15.684798f, -2.577419f, -6.873055f, -0.160807f, + -2.131227f, 73.486931f, -19.371086f, -25.697151f, -12.281122f, + 17.127220f, -9.946334f, -3.486397f, -3.805796f, -1.350557f, + -24.142216f, 72.274178f, -18.884977f, -18.534166f, -15.370871f, + 10.304958f, -10.891193f, -1.587738f, -0.729112f, -5.124106f, + -34.094181f, 71.473351f, -12.348652f, -17.748163f, -9.484776f, + 6.049494f, -10.897481f, 4.274040f, -6.381884f, -10.536913f, + -42.133160f, 68.270500f, -7.885006f, -16.042437f, -7.629818f, + 4.078376f, -21.103462f, -1.746187f, -6.761323f, -13.378450f, + -57.396065f, 69.173752f, -9.265109f, -14.295838f, -9.473177f, + -0.001761f, -20.559929f, -4.527402f, -8.094525f, -16.715185f, + -66.970268f, 69.615097f, -9.278084f, -3.021064f, -12.089108f, + 7.720308f, -24.838995f, 9.071280f, -8.296083f, -13.953154f, + -87.619713f, 71.132607f, -17.220169f, -3.062248f, -18.675968f, + 7.467236f, -31.920027f, 8.799542f, -8.172060f, -16.163795f, + -102.435066f, 66.097969f, -12.565002f, -5.263019f, -5.481183f, + 1.185128f, -26.341061f, 8.528359f, -12.718545f, -18.022022f, + -125.793381f, 71.212776f, -9.139709f, -7.224747f, -2.445361f, + 11.398049f, -22.070894f, 9.940904f, -11.080328f, -20.856096f, + -149.292160f, 69.897682f, -20.164228f, -8.177670f, -11.236770f, + 16.335350f, -18.867929f, 6.474272f, 0.167069f, -14.358007f, + -170.785950f, 78.100182f, -25.013943f, 0.426577f, -0.126179f, + 22.432596f, -15.167599f, 0.381453f, -2.983838f, -17.116583f, + -210.749008f, 88.590286f, -20.295345f, -12.164929f, 5.577830f, + 17.578348f, -12.068939f, 9.743690f, 5.825704f, -13.488422f, + -248.466751f, 68.573311f, -34.753895f, -21.628881f, 7.435274f, + 13.963330f, -7.382347f, 9.528517f, 12.298244f, -4.573327f, + -257.232178f, 72.631157f, -31.575735f, -28.226479f, 5.488611f, + 11.304405f, -10.840772f, 3.116375f, -1.194503f, -6.782937f, + -275.919403f, 73.766258f, -26.776489f, -25.073481f, 2.009468f, + 2.415470f, -13.018000f, 0.019539f, -1.832458f, -7.613223f, + -290.051575f, 69.017395f, -24.283852f, -24.857849f, -3.692513f, + -3.765363f, -14.622233f, -2.500009f, 1.437706f, -6.448485f, + -304.143829f, 70.720428f, -20.235710f, -27.356569f, 1.353084f, + -1.782369f, -6.079440f, 1.300235f, -3.784695f, -4.102912f, + -322.640839f, 58.063107f, -21.912497f, -19.939934f, 0.910101f, + -3.736703f, -15.073252f, -5.256995f, -10.015132f, -8.713769f, + -344.188049f, 55.043549f, -11.508602f, -14.114518f, 3.332988f, + -4.554156f, -16.974634f, -8.131078f, -10.772052f, -12.197089f, + -369.054321f, 53.481846f, -8.396021f, -14.150714f, 1.562392f, + -0.888018f, -7.449115f, -3.163893f, -13.680581f, -10.426185f, + -366.412750f, 59.806522f, -6.645803f, -11.310626f, 7.245811f, + 0.900045f, -3.644734f, 0.617200f, -8.343790f, -11.822113f, + -374.937134f, 59.233135f, 2.138354f, -3.106777f, 5.815517f, + -4.063235f, -8.982433f, -5.773739f, -13.140655f, -6.683125f, + -376.088623f, 54.151615f, 0.996340f, -4.418665f, 4.527509f, + -6.044516f, -15.033484f, -6.865699f, -7.489244f, -10.945578f, + -383.581787f, 52.732090f, -3.948974f, -4.933663f, 6.657369f, + -1.411044f, -9.479708f, -9.636075f, -14.452873f, -12.297873f, + -395.112640f, 49.289108f, -7.477889f, -8.997663f, 4.438389f, + -1.353047f, -3.613108f, -4.462629f, -5.584886f, -7.019111f, +}; +static const char* test_label = "down"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_go.h b/examples/arduino/examples/KeywordSpotting/mfcc_go.h new file mode 100644 index 00000000000..4a45b375cfa --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_go.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "go" (0b7ee1a0_nohash_3.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -258.684387f, 58.165886f, 3.168766f, 7.946958f, 3.306427f, + 9.479866f, 5.606411f, 3.052066f, -7.099144f, -2.936588f, + -265.543152f, 59.884911f, 7.261999f, 10.668991f, 5.931267f, + 4.584619f, 6.415506f, 5.698777f, -4.840302f, -7.368863f, + -261.450989f, 67.328598f, 7.807492f, 10.740813f, 11.516668f, + 12.568173f, 6.090078f, 10.969121f, 2.093266f, 3.139061f, + -247.694214f, 72.167358f, 12.603948f, 13.085489f, 13.021913f, + 18.496819f, 14.583529f, 14.823390f, -0.313948f, -0.153162f, + -248.934967f, 71.984940f, 4.157509f, -3.291713f, 9.526205f, + 24.618210f, 19.448750f, 6.892644f, -7.624357f, -0.457214f, + -245.488800f, 77.017426f, -1.450082f, -3.263329f, 10.621976f, + 24.380650f, 10.302718f, -0.600537f, -7.051674f, 4.950284f, + -245.841476f, 75.056862f, 0.053982f, -8.607631f, 8.391766f, + 20.775085f, 12.774779f, 1.839712f, -5.829136f, 3.907905f, + -266.039001f, 57.804302f, -8.021625f, -9.907011f, 1.736082f, + 12.333413f, 0.618316f, -1.157191f, -8.927226f, 1.439108f, + -265.595612f, 56.980259f, -0.809913f, -3.165477f, 5.404812f, + 9.159380f, 6.833573f, 1.542262f, -5.905739f, -2.326056f, + -272.291321f, 48.318031f, -3.124114f, -4.932032f, -1.239811f, + 4.508043f, 0.768501f, 5.535897f, -8.593522f, -7.549623f, + -263.612122f, 46.459988f, -1.565371f, -4.495640f, -6.547681f, + 6.382434f, 7.057686f, 10.263206f, -8.496628f, -0.869186f, + -257.519470f, 56.208519f, 7.699003f, 1.832457f, 3.582071f, + 13.231422f, -0.690775f, 12.410045f, -10.512872f, 5.442217f, + -271.121704f, 55.439014f, 10.491429f, 8.730375f, 8.558974f, + 14.051036f, 0.979433f, 3.192002f, -6.179225f, 2.272071f, + -283.603912f, 60.296844f, 5.060544f, 3.411142f, 9.968216f, + 9.569582f, 7.232870f, 1.816353f, -6.039360f, 2.854254f, + -296.906250f, 58.471397f, 8.340752f, 1.925119f, 4.386575f, + 7.042078f, 9.626685f, 2.216291f, -1.309660f, 0.848360f, + -298.703217f, 59.024906f, 8.843916f, 9.410458f, 1.579674f, + -0.558678f, 3.686982f, 2.493636f, 4.773709f, 2.228428f, + -295.702423f, 62.052017f, 10.556588f, 5.243321f, -3.816046f, + -2.360946f, 1.858859f, -4.422950f, -1.698255f, 1.292449f, + -299.393616f, 62.980663f, 7.235863f, -1.169396f, -10.396679f, + -8.696449f, -3.311109f, 0.172374f, 1.471793f, 3.117180f, + -302.554077f, 55.524006f, 3.062272f, -1.437958f, -8.297327f, + -1.627803f, -3.334121f, -5.691231f, -3.677602f, 6.714097f, + -308.227722f, 55.342293f, 8.533342f, 0.088304f, -4.333204f, + -3.401862f, -5.304789f, -3.896513f, -1.608136f, 1.795526f, + -298.573730f, 50.544609f, 5.220587f, 4.240304f, -8.364341f, + -2.193643f, -2.206986f, -2.081728f, -5.536115f, 5.097906f, + -291.736023f, 41.657085f, 13.038486f, 12.287671f, -2.873858f, + -0.110142f, -2.001389f, 10.068936f, -5.099032f, 2.390112f, + -271.868805f, 31.013023f, 13.688851f, 22.379616f, 1.619889f, + 12.395024f, 3.311365f, 7.266938f, -1.445635f, -7.828583f, + -246.938263f, 37.114246f, 5.099811f, 14.530663f, 7.702501f, + 21.160440f, 14.007000f, -3.555299f, 9.571302f, -4.024559f, + -265.955902f, 47.718159f, 7.232500f, 12.193524f, 16.964987f, + 23.184057f, 8.458573f, -7.174916f, 5.558735f, -0.859142f, + -282.504700f, 51.953865f, 6.814737f, 11.476005f, 13.491703f, + 13.248959f, 7.393323f, -2.137792f, -2.719359f, -0.490541f, + -297.715698f, 56.549122f, 10.721964f, 13.943802f, 11.996499f, + 14.304326f, 8.544175f, -4.312725f, -3.517070f, 6.172511f, + -303.908661f, 60.084843f, 11.499557f, 10.148754f, 8.973708f, + 13.396643f, 4.520869f, -1.371719f, 5.289819f, 10.115798f, + -270.623871f, 79.504128f, 17.444323f, 10.620357f, 5.461596f, + -5.321368f, -13.765951f, -11.942596f, -10.015426f, 3.742810f, + -188.256409f, 104.825119f, 24.856968f, 10.471697f, -13.016205f, + -18.985203f, -19.921093f, -8.113038f, -17.250338f, -4.749073f, + -108.770164f, 82.032776f, 9.229815f, -11.152035f, -16.616148f, + 16.380005f, -5.940687f, -9.903221f, -23.280090f, -10.046761f, + -28.351120f, 83.628662f, -3.727554f, -23.957537f, -26.821072f, + 1.506450f, -20.112173f, -11.770592f, -11.269871f, -10.589793f, + 32.517754f, 74.625008f, -22.798254f, -24.452402f, -32.881859f, + -7.751269f, -12.750412f, -8.347761f, -2.547829f, -19.236145f, + 30.666733f, 74.137917f, -20.721458f, -16.046864f, -34.185307f, + -8.289972f, -4.829823f, -9.411785f, -2.890075f, -12.189639f, + 17.752249f, 77.268356f, -15.175599f, -13.829691f, -37.063419f, + -5.576386f, 2.921218f, -10.759706f, -5.343363f, -10.471645f, + -4.986353f, 83.916748f, -8.216382f, -14.409312f, -44.324764f, + -1.842638f, 2.717536f, -6.128869f, -12.985895f, -3.612979f, + -22.618717f, 93.324234f, -3.205875f, -14.630292f, -47.271755f, + -1.626729f, 10.260363f, -5.876639f, -11.048802f, -8.201968f, + -52.462551f, 97.390472f, 3.389474f, -11.157327f, -48.735828f, + 2.106047f, 12.649693f, -9.567084f, -8.275345f, -7.281185f, + -96.448700f, 110.701355f, 14.618032f, -7.431903f, -46.351025f, + -2.495469f, 7.835785f, -11.513941f, -14.634655f, -4.328918f, + -118.111572f, 108.380692f, 8.018286f, -15.006529f, -51.138168f, + -19.202633f, -0.032105f, -13.026246f, -21.705767f, -8.529022f, + -143.854691f, 111.655762f, 13.469487f, -12.000585f, -46.705036f, + -22.137926f, -0.995611f, -4.168562f, -15.025013f, -9.148951f, + -163.027542f, 115.135712f, 16.119896f, -16.237106f, -38.552612f, + -15.090075f, -2.453022f, -3.225814f, -12.471083f, -8.552173f, + -171.334045f, 116.834503f, 23.535027f, -8.514393f, -27.013376f, + -16.373064f, -0.826742f, -3.075041f, -13.580709f, -15.004889f, + -174.023453f, 98.243607f, 29.903000f, -4.235966f, -22.439539f, + -15.025865f, -4.172791f, 5.475010f, -11.485394f, -15.221976f, + -167.852402f, 86.210304f, 25.890661f, 1.593102f, -9.996384f, + -1.705152f, -6.307052f, 8.394310f, -20.579544f, -9.607389f, + -196.164886f, 85.712486f, 26.891079f, 9.202659f, 2.756447f, + 9.942529f, 6.633292f, 1.341381f, -15.376878f, -9.590471f, + -226.169098f, 81.653618f, 24.446896f, 10.448780f, 2.870896f, + 5.386434f, 7.075875f, 2.611335f, -2.091816f, -1.829653f, + -228.746979f, 82.571693f, 16.443325f, 5.360307f, 6.712085f, + 8.852267f, 14.646254f, 11.288535f, -1.627099f, 6.565755f, + -241.318054f, 75.191467f, 7.399539f, -1.192508f, 0.465279f, + 4.417620f, 12.240314f, 13.449103f, 5.996547f, 11.863089f, +}; +static const char* test_label = "go"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_left.h b/examples/arduino/examples/KeywordSpotting/mfcc_left.h new file mode 100644 index 00000000000..ae8e9af9a0c --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_left.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "left" (0cb74144_nohash_1.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -506.012085f, 19.527250f, 16.936848f, 10.008033f, 5.769112f, + 2.787449f, -1.006611f, -2.850882f, -6.202645f, -7.454649f, + -507.090790f, 17.847679f, 13.063059f, 4.104880f, 0.178153f, + -2.686456f, -9.882728f, -8.636114f, -9.374991f, -8.824610f, + -504.712189f, 19.014126f, 12.488060f, 5.407307f, 2.927734f, + -3.681661f, -8.774637f, -9.204267f, -9.223279f, -8.530737f, + -510.486572f, 14.815270f, 12.828111f, 6.269959f, 0.980239f, + -4.823809f, -9.079157f, -8.990329f, -8.767043f, -7.414506f, + -502.659149f, 20.050655f, 13.468282f, 4.174362f, -1.806779f, + -5.894049f, -7.084158f, -7.943963f, -9.147487f, -7.294190f, + -504.495972f, 17.926785f, 9.366157f, -1.458860f, -6.270693f, + -7.445010f, -9.074288f, -8.053514f, -8.303525f, -6.491162f, + -504.563110f, 22.905872f, 14.717093f, 4.638975f, -1.677507f, + -7.436291f, -8.545445f, -6.870066f, -8.726649f, -8.942259f, + -494.626678f, 33.314785f, 21.442652f, 8.805228f, 0.350599f, + -4.474137f, -8.273041f, -8.383290f, -11.102431f, -11.070917f, + -230.219543f, 101.816017f, 64.168335f, -20.846220f, -26.698648f, + -6.002532f, -16.262400f, 8.068827f, 1.072253f, -18.495407f, + -98.119705f, 86.019188f, 32.003223f, -28.518078f, -25.399303f, + 8.279219f, -18.645485f, -4.590584f, 7.160919f, -12.669938f, + -43.575119f, 91.908134f, 0.224955f, -28.786968f, -20.283918f, + -0.630669f, -16.925861f, -10.186966f, 4.014014f, -7.867799f, + 11.554101f, 76.225426f, -14.844007f, -16.850368f, -29.134029f, + 3.054079f, -15.024886f, -6.689816f, -4.428313f, 2.815104f, + 46.167061f, 55.646255f, -17.222391f, -13.838810f, -25.263887f, + 1.709689f, -20.273258f, 3.241217f, -7.417082f, 8.566366f, + 49.279930f, 50.432720f, -18.717331f, -16.811049f, -26.041351f, + -5.056023f, -21.115141f, -1.204810f, -4.136174f, 1.881091f, + 59.738697f, 46.328545f, -16.254808f, -15.289686f, -22.490953f, + 0.861660f, -28.054111f, 1.521902f, -1.857537f, -1.075949f, + 48.031723f, 53.868565f, -16.799932f, -19.255075f, -19.244896f, + -3.438048f, -24.502453f, -1.038976f, -0.370981f, 2.158753f, + 31.233316f, 62.780735f, -10.692986f, -23.630816f, -16.818989f, + 0.520281f, -26.507013f, 0.260356f, 1.242642f, 2.598099f, + -23.887215f, 63.181984f, -8.341108f, -14.057200f, -14.738199f, + -0.230197f, -33.055424f, -1.056288f, 2.667593f, -1.104876f, + -52.400421f, 38.322021f, -7.186706f, -12.584892f, -7.673135f, + -0.901490f, -17.274693f, -4.932013f, 2.401767f, 4.018554f, + -58.180225f, 19.744091f, -5.861428f, -19.809677f, -15.450445f, + -2.508889f, -14.857366f, -3.249192f, 4.985347f, 4.166790f, + -56.323235f, 6.452377f, -8.305979f, -11.372234f, -15.890434f, + -1.416915f, -10.662848f, 2.433321f, 3.277672f, 5.073952f, + -68.993439f, 4.341392f, -3.379050f, -18.345322f, -19.414036f, + 0.988408f, -17.252853f, 1.359294f, 5.392758f, -1.664796f, + -91.530914f, 10.733970f, -6.474942f, -13.942562f, -13.920525f, + -1.320707f, -27.044334f, -9.182508f, 3.276017f, -2.743755f, + -133.417999f, 49.461559f, -8.909091f, -12.338620f, 0.046590f, + -1.422341f, -25.272484f, -5.762285f, -0.461709f, -8.059032f, + -157.399200f, 40.428680f, -9.354987f, -14.983674f, -11.576035f, + 13.739234f, -28.479036f, 2.584141f, 0.361703f, -3.323383f, + -73.616333f, -10.187391f, -12.079355f, -16.999496f, -37.492691f, + 8.408251f, -12.159419f, 3.208642f, 1.422541f, -8.579693f, + -109.417252f, -17.481194f, -9.415914f, -14.741226f, -26.552820f, + 2.457851f, -19.498152f, -7.472057f, 3.084176f, -3.585266f, + -147.998703f, 6.307499f, -13.806252f, -10.341417f, -26.286766f, + 1.670421f, -14.618180f, -1.513089f, 1.124860f, -0.715613f, + -180.525742f, 18.399717f, -20.249126f, -4.367635f, -20.347712f, + 5.740208f, -19.272820f, -8.098443f, 2.915152f, 5.772588f, + -219.920883f, 31.006905f, -26.692169f, -2.232058f, -16.551916f, + 7.401434f, -18.561207f, -5.691230f, 9.471541f, 2.866665f, + -249.914047f, 26.701777f, -31.373001f, 0.531489f, -7.042736f, + 9.272597f, -24.326027f, -8.674443f, 14.924012f, -5.105545f, + -280.283020f, 29.976032f, -26.890930f, -6.913718f, -14.168249f, + 2.684060f, -17.900410f, -0.654678f, 18.905540f, -3.785923f, + -316.498260f, 31.604357f, -17.698591f, -8.332629f, -8.896801f, + 1.629671f, -19.165012f, -6.422843f, 6.421667f, -7.623162f, + -313.705322f, 42.273777f, -13.930285f, -11.368241f, -8.462008f, + -5.542631f, -20.000229f, -11.541041f, 0.905707f, -5.876251f, + -327.906006f, 51.381908f, 2.603258f, -2.990967f, 0.568319f, + 2.409693f, -12.666842f, -6.670992f, -0.569414f, -6.978323f, + -347.148254f, 48.317894f, -2.794570f, -6.355229f, 3.619469f, + 9.821987f, -18.487902f, -7.932727f, -1.668829f, -4.850416f, + -371.591400f, 34.411640f, -8.856921f, -1.089926f, 6.772787f, + 6.229154f, -13.804800f, -7.043574f, -2.075923f, -5.001316f, + -387.378235f, 32.900242f, -13.626599f, -10.191523f, -1.669689f, + -0.538277f, -7.059030f, 4.771879f, 4.250018f, -7.188478f, + -399.386536f, 33.647404f, -3.531438f, -6.956944f, -8.022587f, + -6.747808f, -18.559916f, -5.519172f, -1.974501f, -12.108636f, + -403.000519f, 38.808086f, -3.146765f, -7.194926f, -6.860067f, + -10.059160f, -15.716140f, -6.812335f, -5.273818f, -8.067824f, + -412.281067f, 39.410988f, 2.648008f, -4.921536f, -7.451239f, + -10.391664f, -19.733097f, -13.858146f, -5.947808f, -4.019344f, + -412.199097f, 45.600586f, 9.171257f, -4.714833f, -4.719308f, + -12.563010f, -15.239301f, -9.507317f, -5.620919f, -7.093112f, + -406.699188f, 52.819973f, 13.846893f, 2.547099f, 5.386619f, + -7.198190f, -6.747060f, -0.342218f, -10.475143f, -13.462276f, + -415.750793f, 45.428242f, 13.971397f, 7.646526f, 4.631693f, + -10.719019f, -12.436637f, -1.135199f, -7.367539f, -13.358871f, + -430.619232f, 40.165585f, 16.314878f, 5.687082f, 8.722616f, + -1.271505f, -8.283772f, -2.784053f, -7.204997f, -10.850478f, + -445.000183f, 39.140671f, 18.274670f, 0.573249f, -2.469311f, + -6.861283f, -10.157856f, -10.686414f, -16.982983f, -13.921798f, + -444.858673f, 39.347256f, 20.533155f, 5.817375f, 0.067364f, + -4.524391f, -9.671576f, -11.302940f, -19.441463f, -19.669163f, + -448.192047f, 41.531925f, 19.026546f, 10.027369f, 5.298583f, + -4.892449f, -13.632318f, -8.233046f, -13.403317f, -12.961916f, + -461.162598f, 33.923450f, 13.851480f, 5.059017f, 2.909534f, + -7.591222f, -14.902029f, -10.181064f, -9.388212f, -10.040904f, +}; +static const char* test_label = "left"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_no.h b/examples/arduino/examples/KeywordSpotting/mfcc_no.h new file mode 100644 index 00000000000..704a1ecc5b4 --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_no.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "no" (0cb74144_nohash_4.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -503.800079f, 18.831722f, 14.820873f, 5.787148f, 0.999313f, + 0.268913f, -0.730756f, -3.137853f, -7.256411f, -5.541068f, + -504.038208f, 16.911341f, 7.856658f, 4.925719f, 2.151710f, + -0.556691f, 0.079510f, -1.914600f, -8.044741f, -7.877474f, + -426.756836f, 60.071419f, 24.338228f, 18.390913f, 15.208146f, + -23.263933f, -34.016163f, 2.055451f, 0.811446f, -8.457688f, + -200.678177f, 88.895065f, 7.676383f, 24.439552f, 0.690405f, + -5.571877f, -50.326675f, -6.901711f, -1.486406f, -19.245256f, + -40.082523f, 65.078621f, -0.153385f, -8.944237f, -12.541508f, + 11.973069f, -38.677132f, -17.748127f, 4.094797f, -8.466416f, + 14.308125f, 62.390228f, -8.248801f, -16.585695f, -12.250292f, + -0.318896f, -30.233192f, -14.670798f, 0.612174f, -2.473883f, + 31.747751f, 65.969147f, -12.166895f, -22.060410f, -12.586976f, + -5.170432f, -19.685312f, -14.313992f, -2.177921f, -7.339259f, + 38.785019f, 64.541321f, -13.447023f, -26.396320f, -16.568228f, + -2.011296f, -18.565790f, -14.375247f, -8.609786f, -4.456972f, + 43.188728f, 59.609089f, -11.499858f, -26.551308f, -18.502220f, + 0.796937f, -13.297047f, -10.628222f, -2.920013f, -6.361561f, + 32.062572f, 63.511696f, -14.119819f, -20.244057f, -23.631765f, + 0.700744f, -10.321781f, -3.080753f, -8.691831f, -8.933956f, + 17.358210f, 66.898193f, -8.339510f, -16.795074f, -23.977848f, + -1.774536f, -8.739221f, -3.240367f, -7.910559f, -10.709051f, + -0.077384f, 71.129639f, -10.642125f, -18.832569f, -30.350468f, + -2.228574f, -9.303934f, -6.790329f, -8.559271f, -15.426883f, + -10.214184f, 70.680817f, -2.023574f, -18.159361f, -30.679451f, + -0.722029f, -9.335035f, -3.435390f, 1.427995f, -11.900517f, + -38.943550f, 66.085503f, 7.770816f, -18.174328f, -26.894491f, + 3.940692f, -21.714294f, -1.826449f, -3.455717f, -12.517036f, + -52.985130f, 67.325745f, 3.214951f, -10.489717f, -22.134567f, + 1.078026f, -17.454811f, 4.387514f, -5.269409f, -11.079865f, + -79.600662f, 71.214561f, 2.565531f, -10.876870f, -12.171929f, + 6.486385f, -15.744264f, -1.019413f, -7.342085f, -9.520034f, + -125.111298f, 68.695198f, -5.390625f, -15.590599f, -8.632075f, + 0.923541f, -10.417510f, 3.173978f, -4.070229f, -10.715789f, + -151.135513f, 74.287842f, -22.270117f, -12.386673f, -13.922252f, + 6.598403f, -4.012808f, 2.981860f, -1.808738f, -12.903899f, + -184.993332f, 62.959930f, -44.012192f, -16.493807f, -17.744265f, + 7.721551f, -6.149614f, 4.085435f, 6.886113f, -11.679289f, + -197.300095f, 72.085091f, -36.745747f, -15.468684f, -19.214775f, + 4.946892f, -1.323922f, -3.583887f, -1.829917f, -15.678226f, + -224.543030f, 81.067543f, -28.338276f, -13.989230f, -3.961564f, + 10.608101f, -0.606166f, -6.912090f, -5.965957f, -21.610344f, + -240.918106f, 79.416344f, -23.040396f, -19.848269f, -7.967560f, + 3.286935f, 4.836977f, 1.187573f, 5.970539f, -11.260608f, + -261.657135f, 71.312485f, -26.144693f, -21.696634f, -10.786104f, + 6.701050f, 1.653365f, -3.407401f, -5.539808f, -13.597770f, + -281.117157f, 65.627266f, -27.355608f, -25.816351f, -16.549248f, + 7.070354f, 6.181352f, -6.260331f, -8.896704f, -10.720094f, + -284.588257f, 61.887344f, -24.905436f, -21.359770f, -16.360046f, + -1.294411f, 1.747497f, -11.427790f, -9.124812f, -12.077961f, + -299.520844f, 45.535480f, -18.865978f, -20.115860f, -19.805588f, + 3.077741f, -6.543871f, -7.005965f, -5.165814f, -14.227622f, + -298.986176f, 39.726635f, -11.893592f, -18.573168f, -15.797060f, + 3.729555f, -14.759222f, -14.259581f, -14.732922f, -16.033813f, + -293.617310f, 27.129696f, -10.257781f, -20.213797f, -25.667267f, + 5.766401f, -20.258411f, -6.384029f, -7.925086f, -20.215115f, + -301.127319f, 14.306280f, -5.271445f, -11.017246f, -24.973337f, + 4.428306f, -23.287073f, -3.871495f, -4.311951f, -23.391457f, + -319.543518f, 18.751291f, -0.363005f, -1.992103f, -17.144321f, + 1.802311f, -25.983736f, -6.586136f, -6.192271f, -26.851280f, + -326.473694f, 22.960207f, 7.745535f, -4.774464f, -16.519775f, + 6.204826f, -24.007397f, -1.633327f, -5.330925f, -25.049822f, + -343.928986f, 28.911091f, 9.944736f, 1.076226f, -19.088730f, + -2.841424f, -18.586946f, -2.144077f, -4.786069f, -19.755640f, + -358.416443f, 32.285049f, 7.590352f, -0.715984f, -14.017404f, + -3.957863f, -13.103881f, -7.582900f, -12.126310f, -19.876053f, + -368.088928f, 44.734715f, 8.553982f, -3.326559f, -10.071790f, + -0.830044f, -5.798881f, -12.881082f, -17.169605f, -20.146826f, + -384.426239f, 38.126854f, 6.933444f, -0.325530f, -3.548989f, + 2.079419f, -12.224577f, -7.055751f, -10.479879f, -15.421949f, + -378.498810f, 47.260048f, 10.333267f, 5.721529f, 2.312911f, + 3.149262f, -13.208268f, -5.655255f, -7.166509f, -21.526379f, + -396.275787f, 36.962181f, 7.097786f, 0.945819f, -0.394759f, + 4.377489f, -12.228715f, -6.545863f, -10.518173f, -20.279459f, + -409.117676f, 29.374916f, 0.705670f, 0.799098f, -6.852448f, + 2.298820f, -10.471405f, -7.286994f, -9.036343f, -23.949583f, + -407.744629f, 30.590124f, 11.554751f, 9.048569f, -0.698870f, + -0.045266f, -11.977724f, -14.773769f, -10.515213f, -21.375404f, + -393.579224f, 45.807137f, 25.660696f, 13.450216f, 1.417644f, + 1.587788f, -16.800428f, -13.226058f, -10.701055f, -16.244797f, + -396.787201f, 50.530422f, 29.177990f, 13.977935f, -0.813237f, + -5.206570f, -14.174069f, -7.819930f, -3.887472f, -15.180594f, + -413.261414f, 41.089039f, 8.066552f, 1.697238f, -4.953945f, + -6.404896f, -15.741414f, -8.617703f, -9.708153f, -14.856959f, + -434.299377f, 31.255131f, 6.039766f, 5.619424f, 0.442211f, + -8.583801f, -11.456949f, -4.890213f, -6.896707f, -13.555737f, + -431.001556f, 35.800056f, 13.320564f, 5.525602f, -1.735401f, + -9.670103f, -16.101543f, -15.773440f, -9.826070f, -11.670356f, + -433.248718f, 38.091816f, 14.509241f, 4.614880f, -7.181812f, + -10.445882f, -17.405914f, -16.610868f, -11.524208f, -10.821240f, + -442.154144f, 30.831245f, 19.059862f, 6.624634f, -4.947022f, + -11.492108f, -17.787535f, -11.764639f, -9.899225f, -11.558023f, + -444.601288f, 23.735504f, 9.074905f, 3.116518f, -11.162773f, + -9.906630f, -15.880805f, -4.538301f, -7.963338f, -16.589918f, + -444.719391f, 23.589258f, 13.122929f, 8.898996f, -6.940963f, + -1.529727f, -11.323105f, -5.159711f, -9.097204f, -19.381771f, + -440.910950f, 26.628819f, 13.035597f, 9.584769f, 2.865429f, + -2.748848f, -18.949715f, -14.859841f, -13.333447f, -23.944433f, +}; +static const char* test_label = "no"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_off.h b/examples/arduino/examples/KeywordSpotting/mfcc_off.h new file mode 100644 index 00000000000..41bf16cbe33 --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_off.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "off" (0d53e045_nohash_0.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -175.550064f, 36.675400f, 1.704316f, 19.794855f, 6.347660f, + 5.608477f, -0.642213f, 12.882412f, 10.317157f, 1.862832f, + -170.788635f, 46.692368f, 3.367630f, 18.206554f, 4.198709f, + 8.750317f, 1.418444f, 7.905148f, -0.359086f, 6.306063f, + -134.891418f, 13.906617f, 7.684140f, 19.752119f, 3.589190f, + 6.307348f, 9.062503f, -0.402657f, 1.685427f, 3.037107f, + -153.497986f, 38.337196f, 3.760705f, 17.199451f, 2.555657f, + 6.194610f, 0.759410f, -1.560215f, 2.599649f, -2.534871f, + -173.119003f, 40.792915f, -0.282972f, 20.161650f, 2.989707f, + 10.613208f, 3.702376f, -1.546616f, -2.942449f, 0.859029f, + -176.505386f, 37.398602f, 0.710847f, 21.232258f, 6.096910f, + 5.258308f, 3.052750f, 10.834261f, 1.711467f, -2.411982f, + -167.707932f, 42.645905f, -2.247131f, 17.410042f, 6.411298f, + 2.941954f, -0.206528f, 9.283484f, -0.046865f, -2.308608f, + -171.754532f, 44.235153f, -2.092806f, 16.728231f, 4.358239f, + 3.145913f, -1.002280f, 6.719184f, -4.087154f, 2.993385f, + -169.380066f, 44.498905f, -5.499633f, 18.067724f, 7.260520f, + 10.198251f, -1.274899f, 8.246006f, -0.698363f, 1.318980f, + -172.975937f, 42.924343f, -2.596572f, 17.573786f, 5.914616f, + 11.423919f, 1.460478f, 6.915914f, 0.304758f, 3.216393f, + -166.895340f, 46.306602f, -4.099897f, 17.203352f, 3.201559f, + 8.696205f, 2.658857f, 7.401233f, 1.265657f, 1.118268f, + -177.089981f, 40.663113f, -3.496551f, 17.893576f, 6.055820f, + 7.445264f, 1.072951f, 4.422747f, 0.656861f, 1.367759f, + -176.338013f, 45.393768f, -0.396475f, 16.414612f, 3.318347f, + 11.227816f, -0.187583f, 3.915947f, 1.753402f, 2.821689f, + -172.075256f, 41.346752f, -6.156380f, 14.021360f, 0.506856f, + 7.052283f, 3.386266f, 7.788628f, -1.458220f, 1.101996f, + -167.418274f, 47.425823f, 4.247186f, 19.530020f, 12.811087f, + 10.835044f, -0.526893f, 5.883533f, -1.135479f, 0.785001f, + -176.128479f, 44.403603f, 0.695894f, 22.087790f, 10.377028f, + 9.905500f, 4.875934f, 6.831546f, -0.870059f, 2.366532f, + -181.348541f, 42.727612f, -1.884570f, 13.991997f, -0.122259f, + 5.009651f, -3.864775f, -0.068525f, -6.997971f, -0.475701f, + -177.845779f, 45.084724f, 1.287757f, 20.703459f, 3.784126f, + 5.275654f, -2.279424f, 5.661321f, 3.438914f, 6.958514f, + -178.064194f, 34.686131f, -8.303454f, 9.324844f, 4.470550f, + 6.648875f, -0.552480f, 2.630620f, 0.959897f, 3.652256f, + -168.350052f, 44.595745f, -5.015650f, 14.202213f, 0.909312f, + 9.848797f, 4.828877f, 12.712883f, 3.637007f, 1.838945f, + -176.831268f, 45.714699f, -1.868813f, 13.111609f, 2.539756f, + 7.896408f, 3.116760f, 8.653262f, -1.825197f, 7.365798f, + -167.709213f, 45.946751f, 1.470658f, 17.689850f, 0.804546f, + 6.486207f, 2.650599f, 1.569782f, 1.429494f, 1.578999f, + -177.731598f, 42.315784f, -2.814915f, 18.003950f, 5.596950f, + 9.428136f, -0.638582f, 3.952142f, 0.500698f, -0.183789f, + -175.702713f, 41.220310f, -1.927994f, 13.276777f, -1.551774f, + 1.656475f, -4.549188f, 7.229406f, 0.206164f, 5.304949f, + -173.951904f, 42.495438f, -1.831116f, 15.261646f, 5.588197f, + 12.981462f, -1.216111f, 5.589494f, -0.610365f, 1.925042f, + -176.843399f, 37.813869f, -4.443784f, 12.855937f, 2.219504f, + 6.717692f, -4.438768f, 3.141726f, -3.122634f, -5.807518f, + -168.164948f, 42.847595f, -6.193535f, 17.867182f, 3.537366f, + 6.923075f, 1.326558f, 7.147236f, -1.019616f, -0.197130f, + -170.022827f, 42.246155f, -3.075882f, 12.002017f, 1.501511f, + 6.337908f, -0.347840f, 5.970262f, 2.782215f, 3.635200f, + -95.842041f, 68.223648f, -21.159416f, -6.944205f, -18.251789f, + 7.715225f, 0.198520f, 8.187741f, -2.636201f, -2.259747f, + -12.115479f, 56.329506f, -51.412983f, -12.581666f, -35.582771f, + 12.901364f, -4.298117f, 5.038718f, -2.988178f, -12.671979f, + 4.615732f, 50.978500f, -54.407959f, -9.588323f, -31.505793f, + 16.560987f, 2.799593f, 7.933708f, 1.258814f, -8.470124f, + 6.439747f, 58.905411f, -54.889679f, -5.440887f, -24.988934f, + 20.297800f, 1.314596f, -0.831091f, -1.283858f, -0.766248f, + -3.107297f, 74.546951f, -50.509647f, -5.851325f, -28.978600f, + 19.279406f, 2.297874f, -1.539328f, -3.040057f, -3.698415f, + -11.070913f, 68.782616f, -46.119476f, -6.999808f, -30.787571f, + 15.848431f, 4.289850f, -1.296671f, -4.230511f, -11.287413f, + -11.844690f, 65.695312f, -47.711178f, -12.919445f, -31.315102f, + 18.079084f, 5.313334f, 5.143531f, -4.913166f, -6.904611f, + -30.398956f, 78.331009f, -38.966412f, -17.310205f, -27.917477f, + 16.846502f, 7.830893f, 8.272285f, -7.480401f, -2.270466f, + -57.746147f, 80.480545f, -30.556387f, -20.972200f, -22.258278f, + 14.941533f, 8.800563f, 7.381102f, -11.045966f, -5.748206f, + -102.849579f, 65.112396f, -23.836035f, -14.796358f, -13.102851f, + 23.871111f, 17.521648f, 4.739951f, -13.390308f, -8.877999f, + -107.498032f, 60.973110f, -18.422413f, -7.769625f, -8.134667f, + 13.860308f, 11.876146f, 9.212308f, -5.561235f, -3.472903f, + -102.086525f, 52.680496f, -12.973725f, 0.212965f, -0.476137f, + 16.839315f, 9.179756f, 10.039167f, -3.918544f, -5.428117f, + -105.106918f, 36.402607f, -13.343434f, 0.328838f, 1.738321f, + 9.904573f, 3.571863f, 7.389468f, 0.461458f, -6.373577f, + -111.966843f, 35.168262f, -8.294093f, 4.289005f, 3.270743f, + 13.259997f, 6.878382f, 10.845652f, 1.959150f, -8.501569f, + -126.342636f, 29.336378f, -6.362985f, 2.477507f, 9.671542f, + 16.222378f, 1.521655f, 6.798978f, 0.328260f, -2.095651f, + -127.427757f, 21.314144f, -2.405918f, 8.728305f, 5.397822f, + 9.789675f, -1.057462f, 9.546239f, -0.055960f, -0.456501f, + -124.765335f, 18.898502f, 1.112397f, 14.476859f, 11.779296f, + 14.112469f, 4.658665f, 9.843539f, 3.699153f, -3.687514f, + -119.040253f, 15.355839f, -4.655316f, 12.485530f, 9.000069f, + 13.089846f, 2.374743f, 10.744249f, 2.864407f, -6.463474f, + -114.321350f, 21.600311f, -3.673971f, 13.023613f, 13.122231f, + 15.510297f, -1.330246f, 7.939383f, 2.872687f, 1.466406f, + -128.396545f, 35.545113f, -5.706383f, 8.745801f, 8.584070f, + 14.386497f, -2.695918f, 7.286284f, 2.952384f, 1.804982f, + -155.033157f, 38.649521f, -8.757853f, 11.830804f, 5.040468f, + 15.141876f, 4.577050f, 8.357815f, 4.666540f, 2.037514f, +}; +static const char* test_label = "off"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_on.h b/examples/arduino/examples/KeywordSpotting/mfcc_on.h new file mode 100644 index 00000000000..bcf1df949c4 --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_on.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "on" (0d2bcf9d_nohash_1.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -169.743530f, 21.981453f, 11.185447f, 14.363379f, 7.026345f, + 8.041018f, 2.363853f, 10.931651f, 1.520875f, 0.555498f, + -170.588623f, 23.007666f, 8.181622f, 8.672327f, 4.949448f, + 7.235571f, 2.507399f, 4.126958f, -3.697513f, 5.757244f, + -170.711395f, 17.566763f, 10.234138f, 13.146772f, 5.826707f, + 10.245035f, 1.915118f, 7.540258f, -1.164257f, 5.276564f, + -180.981461f, 16.655621f, 8.290622f, 9.735038f, 6.464472f, + 11.566790f, 6.276535f, 9.714305f, 1.773990f, 5.129745f, + -166.394867f, 24.420076f, 13.014115f, 16.654652f, 5.230084f, + 11.390706f, 7.774345f, 12.023060f, 4.422025f, 5.448427f, + -168.596222f, 18.903772f, 6.420733f, 11.282873f, 5.725691f, + 9.089666f, 0.247090f, 7.497897f, 2.583506f, 6.990332f, + -169.919296f, 23.266535f, 16.225828f, 15.787846f, 3.479285f, + 6.942927f, -2.470106f, 7.251230f, 4.264881f, 5.873113f, + -59.526989f, 49.514786f, -10.525371f, -21.353935f, -14.240564f, + 29.313463f, 5.559427f, 0.110475f, -8.372005f, 1.075319f, + -91.706688f, 46.875298f, -0.885726f, -16.870920f, -14.887864f, + 17.245834f, -1.254840f, -7.884146f, -15.538888f, 3.447939f, + -43.700352f, 58.485489f, -7.565490f, -28.615202f, -20.569309f, + 21.697313f, -0.519015f, -15.488145f, -20.510048f, -3.909213f, + -1.371083f, 45.486702f, -11.997430f, -24.262083f, -30.013060f, + 34.950394f, -1.285944f, -9.292583f, -18.246870f, -3.628577f, + -5.254961f, 37.221462f, -19.493666f, -24.658485f, -30.096607f, + 34.509365f, -8.589672f, -14.065257f, -23.074596f, -2.004493f, + -9.254828f, 44.738026f, -13.000523f, -22.903524f, -24.241590f, + 37.021526f, -4.775533f, -10.203371f, -17.507044f, 3.327447f, + -20.945520f, 48.915031f, -12.026912f, -21.383680f, -23.453878f, + 35.905567f, -3.086184f, -7.545226f, -10.686644f, 4.195365f, + -14.469835f, 44.266693f, -19.103750f, -19.364552f, -25.831709f, + 32.958931f, -4.876031f, -8.051491f, -11.425132f, 4.780692f, + -1.150020f, 43.599133f, -20.703367f, -16.568960f, -16.845442f, + 32.614391f, -7.381915f, -4.579306f, -5.929265f, 6.902700f, + 2.021674f, 40.790390f, -23.469070f, -11.925346f, -13.479347f, + 31.321095f, -7.532947f, -1.125573f, -4.166052f, 11.450824f, + -9.153925f, 41.060688f, -33.131771f, -14.405152f, -5.419637f, + 12.243809f, -10.734316f, -5.069800f, -4.452832f, 12.894636f, + -19.467804f, 40.716278f, -28.165068f, -6.882953f, -4.593771f, + -0.480881f, -14.084489f, -1.418872f, -0.586967f, 4.594918f, + -50.356239f, 55.092602f, -7.442216f, 2.784323f, -6.387009f, + -7.914539f, -14.509838f, -5.918291f, -2.229359f, 2.152317f, + -73.454262f, 66.176544f, 12.257412f, -4.454286f, -6.637758f, + -5.325802f, -11.801738f, -6.333472f, -8.809584f, -5.416708f, + -84.497978f, 64.003914f, 11.791294f, -1.564394f, -5.200786f, + -4.394699f, -15.005710f, 0.812877f, -8.377439f, -2.945145f, + -94.685806f, 63.927361f, 12.903334f, -6.455096f, -11.324501f, + -5.807748f, -17.350176f, -1.064172f, -6.875169f, -3.966329f, + -108.389435f, 61.351059f, 19.531462f, 1.172545f, -11.485486f, + -3.555627f, -8.420695f, -3.181929f, -9.421062f, -3.806577f, + -117.995583f, 56.138969f, 20.236822f, 11.022847f, -2.477570f, + -3.208819f, -6.145271f, -3.272026f, -12.023836f, -6.483802f, + -135.271454f, 44.837585f, 13.114229f, 9.557211f, 0.022194f, + 4.714481f, -7.879201f, -2.293595f, -5.749257f, -0.700028f, + -151.454376f, 31.930546f, 12.368952f, 14.086825f, 2.614970f, + 5.231466f, 2.636117f, 11.855149f, 6.987696f, 8.031981f, + -135.942291f, 43.909466f, 19.641270f, 19.766502f, 17.758097f, + 18.158932f, 4.188447f, 7.521109f, 3.943696f, 5.285779f, + -142.997269f, 38.610958f, 13.543789f, 19.210596f, 14.088657f, + 18.607321f, 4.850644f, 7.176558f, 2.439148f, 7.057638f, + -148.441956f, 36.070511f, 20.805349f, 20.131180f, 7.015635f, + 14.541881f, 3.796073f, 7.728209f, 2.361016f, 6.103575f, + -149.154495f, 34.963608f, 19.329010f, 25.001152f, 11.208577f, + 12.146420f, 5.410884f, 5.797572f, 2.375488f, 6.188735f, + -156.463272f, 35.818295f, 13.720514f, 11.918379f, 8.919817f, + 13.682453f, 1.820469f, 3.840196f, -0.514587f, 10.692966f, + -158.119644f, 32.919273f, 18.099529f, 19.861654f, 14.555037f, + 17.862316f, 7.796447f, 12.859709f, 0.513363f, 5.111146f, + -163.532974f, 34.967239f, 19.956121f, 22.815363f, 11.589540f, + 16.557837f, 6.553095f, 12.424227f, 6.687156f, 7.835659f, + -162.314209f, 25.795826f, 9.441463f, 9.192601f, 5.950475f, + 13.348969f, 0.136483f, 9.245258f, 5.703249f, 9.765658f, + -157.213531f, 28.779974f, 12.720572f, 20.940645f, 13.181377f, + 13.970716f, 10.240959f, 17.580530f, 6.001926f, 13.803370f, + -156.248749f, 29.403109f, 11.627034f, 16.206987f, 7.298179f, + 17.293139f, 11.396393f, 17.114916f, 4.737962f, 6.359304f, + -162.540085f, 27.625244f, 16.007416f, 22.172903f, 12.253745f, + 13.992543f, 6.013775f, 8.144978f, 5.534141f, 9.548781f, + -166.678528f, 25.087717f, 15.777296f, 15.101035f, 8.084700f, + 16.612007f, 6.790802f, 12.970088f, 7.985202f, 9.283078f, + -165.832916f, 23.560301f, 13.088272f, 16.200762f, 11.467529f, + 15.901381f, 6.614357f, 14.261275f, 8.258833f, 6.507204f, + -163.782730f, 24.339428f, 13.501058f, 16.931410f, 9.441717f, + 13.128924f, 7.018571f, 13.241953f, 6.590178f, 10.073491f, + -160.540588f, 32.004322f, 15.358393f, 19.506981f, 8.654356f, + 13.059896f, 9.092509f, 7.993970f, 5.054218f, 8.566644f, + -164.397171f, 26.313154f, 13.960023f, 15.659625f, 9.719680f, + 15.797880f, 3.733044f, 11.666046f, 9.616336f, 10.490781f, + -164.184479f, 23.783636f, 10.929818f, 13.106108f, 8.679225f, + 14.426532f, 8.210668f, 14.855896f, 5.848501f, 11.433056f, + -164.994019f, 24.661367f, 14.713041f, 15.690244f, 7.705078f, + 10.086197f, 6.479597f, 10.457314f, 5.216175f, 6.012651f, + -174.166519f, 18.156610f, 9.821244f, 19.952486f, 7.846135f, + 14.647315f, 9.274931f, 9.824169f, 7.950802f, 5.951091f, + -159.893417f, 26.448166f, 14.211676f, 18.788132f, 7.703917f, + 10.101252f, 10.744093f, 16.404072f, 10.698339f, 7.263455f, + -170.891281f, 22.215553f, 8.206742f, 14.705871f, 10.904925f, + 12.416936f, 6.234036f, 8.041464f, -0.354699f, 6.599545f, + -171.227722f, 20.318668f, 12.818903f, 14.380090f, 8.180261f, + 10.215039f, 4.693879f, 10.555336f, -0.377321f, 4.075587f, +}; +static const char* test_label = "on"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_right.h b/examples/arduino/examples/KeywordSpotting/mfcc_right.h new file mode 100644 index 00000000000..7cf35341fe8 --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_right.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "right" (0cb74144_nohash_1.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -476.811279f, -5.110255f, 17.742918f, 12.991923f, -10.009543f, + 16.099197f, -8.517653f, -1.396785f, -3.775454f, -5.338952f, + -485.660583f, 5.495706f, 14.872177f, 5.643840f, -11.644445f, + 6.077923f, -11.585464f, -8.569006f, -8.339223f, -9.617785f, + -497.953644f, 12.002529f, 11.932704f, 6.512242f, -3.873271f, + 2.030073f, -5.141654f, -7.377081f, -5.686092f, -6.361062f, + -501.380707f, 14.826461f, 7.028099f, 1.530697f, -1.258568f, + 1.046963f, -1.635951f, -6.097977f, -6.073578f, -4.128834f, + -474.346924f, 30.661173f, 7.090061f, -12.183537f, -6.904297f, + 0.280143f, -5.705201f, -3.552727f, -5.252443f, 5.018535f, + -169.173645f, 131.342758f, -13.190001f, -37.530819f, 13.604557f, + -6.749993f, -32.990326f, 13.862399f, -26.793985f, 8.420262f, + -36.185143f, 85.643677f, -17.867056f, -26.878229f, -11.255525f, + -8.813963f, -25.454390f, -0.020468f, -15.623137f, -3.644925f, + 19.677189f, 78.472649f, -22.862652f, -20.852289f, -19.613468f, + -3.186718f, -19.644310f, -3.426139f, -8.021279f, 3.591484f, + 33.407616f, 75.475227f, -20.407362f, -19.909105f, -22.927589f, + 3.472613f, -27.290264f, -0.402704f, -6.050898f, 4.039707f, + 54.822010f, 62.881565f, -32.095490f, -19.181837f, -24.531898f, + -0.268707f, -27.678009f, -10.372414f, -0.597070f, 4.456160f, + 50.991184f, 55.835430f, -31.823879f, -18.816116f, -24.432001f, + -7.658944f, -33.822945f, -16.226845f, 2.480823f, 5.378402f, + 66.943787f, 42.522762f, -27.277149f, -9.428803f, -20.655081f, + -6.781660f, -38.461468f, -13.698420f, 7.922556f, 3.494053f, + 51.380718f, 45.470131f, -13.326624f, -1.332194f, -16.969543f, + -14.697284f, -40.252449f, -8.503066f, 9.763275f, -2.004855f, + 42.138863f, 46.470474f, -11.857041f, 8.098478f, -12.363612f, + -14.092970f, -36.902309f, -6.402689f, 3.027732f, -6.886939f, + 15.535865f, 49.414146f, -11.429092f, 15.783111f, -9.912390f, + -16.404793f, -28.247793f, -15.302882f, -1.122416f, -9.661588f, + -45.733772f, 59.268421f, -12.031635f, 9.807646f, -1.019204f, + -5.557240f, -24.080357f, -9.840779f, 1.327384f, -0.005686f, + -83.884575f, 56.282070f, -25.171387f, -3.152745f, -9.435108f, + -9.988351f, -36.182102f, -1.257526f, 0.260212f, -0.762198f, + -79.120872f, 41.814888f, -23.151958f, -7.455102f, -12.670218f, + -7.327922f, -40.660316f, 4.625578f, -5.857724f, 4.430045f, + -76.930252f, 33.369865f, -20.469511f, -11.796146f, -8.772202f, + -5.521982f, -30.419304f, -8.383953f, -1.671117f, -0.159568f, + -80.947678f, 26.682219f, -32.308346f, 4.400959f, -24.827780f, + -2.196539f, -29.129385f, -8.293195f, -1.111334f, -1.944397f, + -136.436508f, 57.409115f, -30.867964f, 3.164559f, -8.523247f, + 6.457678f, -23.268517f, -1.377302f, 2.100123f, 1.722579f, + -172.730698f, 60.957397f, -44.188976f, -5.468324f, -10.739993f, + 2.330824f, -28.215002f, 1.310405f, 19.418716f, 1.798007f, + -207.956482f, 60.662739f, -44.440434f, -2.368906f, 1.779775f, + 3.307293f, -23.377115f, -6.386176f, 10.379613f, -3.653887f, + -215.499374f, 62.601009f, -37.861393f, 3.254998f, 5.350939f, + -3.973682f, -26.782829f, -7.367877f, 13.566010f, -4.257746f, + -231.809494f, 62.215694f, -37.966755f, -0.910922f, 3.135464f, + 0.154742f, -30.190048f, -8.837763f, 15.278373f, -2.433867f, + -247.380524f, 57.647797f, -28.486225f, 2.884933f, 3.775208f, + 0.671707f, -43.875858f, -19.499035f, 14.215229f, 2.366831f, + -261.396942f, 50.132454f, -34.361523f, -0.635981f, 9.437448f, + -3.286609f, -41.857018f, -8.132699f, 15.838316f, -0.463945f, + -263.441101f, 65.429764f, -35.335857f, -11.163828f, 7.540871f, + -7.650087f, -37.171856f, -9.283327f, 12.732716f, -5.295934f, + -283.705261f, 62.864632f, -34.807117f, -5.963061f, 13.774532f, + -6.111038f, -31.219650f, -10.767553f, 5.818870f, -8.715145f, + -305.138397f, 60.560772f, -26.768276f, -5.294718f, 8.710928f, + -12.684956f, -34.196209f, -2.524669f, 11.934772f, -3.172359f, + -324.913971f, 49.079319f, -23.238638f, -4.327532f, 9.136567f, + -13.906662f, -36.895912f, -7.275558f, 8.791815f, -14.095496f, + -334.410980f, 47.234901f, -25.261692f, -1.930622f, 16.338446f, + -8.694038f, -30.383482f, -4.372900f, 6.151885f, -11.750580f, + -349.144348f, 45.145611f, -17.189713f, 0.264211f, 11.266344f, + -4.732132f, -27.641298f, -1.228229f, 8.080056f, -13.189114f, + -348.135162f, 48.582844f, 0.778133f, 10.627200f, 6.515348f, + -0.804691f, -27.399841f, -1.198007f, 6.661041f, -13.774557f, + -339.584381f, 44.035046f, -1.728068f, 10.613739f, 0.847929f, + -2.477574f, -20.594906f, 5.222211f, 7.303184f, -9.403607f, + -339.460663f, 39.367264f, 4.626776f, 7.110023f, -5.317962f, + 3.931841f, -25.527813f, -3.712787f, 5.828611f, -13.372594f, + -350.023895f, 35.217289f, 1.598920f, 7.182700f, -6.235275f, + -4.340419f, -27.327457f, -5.114068f, 3.291681f, -23.039335f, + -357.646210f, 37.478996f, 6.699231f, 6.572836f, -6.868581f, + 4.906129f, -29.913418f, -3.619405f, 2.140931f, -21.890520f, + -361.953583f, 30.373819f, 0.693688f, 9.250819f, -6.467010f, + 5.015504f, -30.699001f, -3.350270f, 4.257475f, -26.070589f, + -376.291901f, 37.312649f, 9.650178f, 7.872832f, 3.673865f, + 8.340858f, -24.015417f, -2.309363f, -3.852184f, -19.934437f, + -389.656006f, 29.151281f, 10.985962f, 9.630241f, -1.164809f, + -2.178107f, -28.393896f, -2.591658f, 2.138024f, -13.071285f, + -400.853210f, 39.653732f, 13.998889f, 9.694842f, 1.345620f, + -2.139286f, -14.273139f, -1.101587f, 8.142659f, -11.862904f, + -405.191589f, 37.407764f, 8.889712f, 5.024510f, -2.883222f, + -8.415211f, -20.612871f, -8.934474f, -1.852324f, -18.123917f, + -407.640350f, 38.908123f, 11.675131f, 3.541821f, -1.783426f, + 1.152004f, -13.759952f, -6.939627f, -7.164379f, -22.900309f, + -417.159332f, 35.289230f, 6.513436f, 5.442031f, 0.489946f, + 0.279710f, -11.478283f, -7.406686f, -7.237171f, -23.166121f, + -415.096741f, 36.941418f, 17.704369f, 9.756015f, -1.425931f, + 1.163394f, -16.945749f, -12.371449f, -8.276403f, -23.585104f, + -424.219971f, 37.167404f, 15.060420f, 1.820348f, -10.562889f, + -2.642692f, -14.413963f, -5.118250f, -6.926515f, -21.559444f, + -435.219879f, 36.009304f, 14.803327f, 1.991337f, -6.559261f, + -3.454398f, -16.554604f, -7.008936f, -8.164426f, -21.078379f, + -434.803131f, 36.312267f, 23.437431f, 13.790796f, -5.352476f, + 1.695035f, -9.157008f, -9.044562f, -6.049176f, -15.375594f, +}; +static const char* test_label = "right"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_stop.h b/examples/arduino/examples/KeywordSpotting/mfcc_stop.h new file mode 100644 index 00000000000..445119e6c1d --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_stop.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "stop" (0cd323ec_nohash_0.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -247.903046f, 55.235271f, 10.757340f, 6.266783f, 2.433547f, + 10.195817f, 7.269604f, 12.213093f, -0.981211f, 1.087342f, + -238.716736f, 62.930332f, 18.089561f, 13.942317f, 5.814198f, + 9.860006f, 5.142281f, 7.529990f, 1.967143f, 7.934083f, + -243.356216f, 58.282757f, 5.738654f, 5.628653f, 3.157279f, + 8.953043f, 1.980114f, 6.454770f, -1.295774f, 3.316453f, + -249.302933f, 52.551037f, 9.803054f, 11.430079f, 3.835268f, + 9.598733f, 6.440479f, 5.748522f, -3.578346f, 5.685051f, + -246.630814f, 58.993359f, 13.194911f, 13.831144f, 3.734620f, + 8.083550f, 1.631741f, 10.964947f, 0.858943f, 6.327641f, + -251.298630f, 58.721790f, 9.981870f, 10.728008f, 2.833369f, + 4.943981f, -0.621271f, 3.566943f, -3.520044f, 9.369270f, + -129.734772f, 36.571640f, -17.379675f, 28.675354f, 24.656612f, + 13.950118f, 0.300834f, -11.528755f, -6.441894f, 18.567085f, + -214.265060f, 61.232086f, 2.411011f, 13.492119f, 15.492842f, + 8.653697f, -0.355135f, 1.685035f, -1.390031f, 4.633168f, + -229.016068f, 65.085289f, 14.426193f, 15.578371f, 6.596465f, + 10.615154f, 0.787942f, 6.888181f, -1.835914f, -0.846374f, + -246.871658f, 54.959385f, 8.800753f, 9.578133f, 2.000040f, + 0.494963f, -8.218131f, 4.380305f, -2.893187f, 3.780052f, + -242.357620f, 59.219280f, 11.362532f, 10.135014f, 5.286281f, + 8.375216f, 3.596354f, 4.661822f, -4.538393f, 0.715693f, + -240.942825f, 61.048584f, 8.246812f, 6.826957f, 3.227907f, + 9.847815f, 2.672457f, 4.585345f, 1.179112f, 8.982553f, + -247.606384f, 61.041447f, 12.881911f, 8.409924f, -0.950739f, + 7.243961f, 3.688463f, 8.329419f, -0.994687f, 1.048729f, + -243.702667f, 64.761009f, 10.532848f, 11.966675f, -1.077527f, + 8.471701f, 0.538366f, 2.882601f, 0.653138f, 6.237946f, + -239.354767f, 65.325378f, 14.611927f, 9.657064f, 3.754848f, + 7.443675f, 3.569937f, 7.829645f, 1.163024f, 4.681349f, + -241.792038f, 63.843235f, 11.674726f, 12.994517f, 5.845258f, + 11.052966f, 1.356750f, 6.166146f, -3.005985f, 3.396178f, + -245.110535f, 57.541637f, 9.126384f, 12.832730f, 0.852562f, + 10.146805f, 3.303194f, 8.601923f, -4.523479f, 4.346843f, + -242.946274f, 60.558109f, 13.743235f, 4.064591f, -3.576256f, + 7.909890f, -0.158527f, 10.829655f, 6.127685f, 1.765645f, + -235.271881f, 53.528137f, 10.278755f, 1.865454f, -5.436500f, + 12.755242f, -2.354962f, 15.512096f, 6.412459f, 0.867410f, + -205.595734f, 41.738064f, 21.706938f, 1.590616f, -10.204861f, + 18.972551f, -1.749903f, 11.105855f, 1.035205f, -5.108109f, + -193.779495f, 21.675867f, 28.951424f, 2.220347f, -14.929116f, + 17.615967f, -12.875458f, 9.228103f, 1.657115f, -9.473878f, + -186.652649f, 14.388103f, 30.807110f, -0.761553f, -11.827315f, + 24.117407f, -10.992655f, 15.455255f, -1.621184f, -7.667939f, + -175.068039f, 14.022926f, 38.119385f, 3.879395f, -11.706611f, + 25.851219f, -7.900917f, 12.571947f, 0.199545f, -7.846080f, + -167.329666f, 11.705678f, 30.267258f, -3.473093f, -12.464375f, + 20.087843f, -4.976165f, 8.132445f, 1.075151f, -6.939085f, + -172.696548f, 8.494905f, 35.552834f, -0.398610f, -6.921345f, + 20.481655f, 3.179003f, 9.044418f, 1.658275f, -4.934620f, + -189.049301f, 16.204638f, 38.084846f, 5.291499f, -4.810946f, + 17.899082f, 0.907458f, 4.282096f, -2.900435f, -2.526069f, + -223.181320f, 41.927792f, 12.786986f, -1.574193f, -1.441847f, + 8.621080f, 6.125707f, 7.205752f, 2.343401f, 1.362414f, + -218.963470f, 60.637665f, 13.204506f, 1.637612f, 0.014135f, + 12.987506f, 9.601213f, 8.032558f, -0.028679f, 1.208940f, + -209.726044f, 65.230057f, 4.370491f, -2.124984f, -6.348258f, + 10.773990f, 6.291558f, 11.036055f, -5.091249f, -1.588681f, + -128.831833f, 57.356358f, 11.420697f, -1.997454f, -27.039125f, + 10.048029f, -6.250974f, 8.843756f, 0.067331f, -1.917581f, + -106.936806f, 97.736649f, 7.548665f, -15.266357f, -40.874207f, + -6.967868f, -10.904025f, -8.485807f, -13.959338f, -9.614430f, + -88.744080f, 114.065353f, -7.557261f, -18.694464f, -33.752338f, + -4.234693f, -5.028267f, -8.326457f, -14.400474f, -4.495411f, + -86.269379f, 123.949211f, -14.751705f, -25.380667f, -30.941059f, + -0.908934f, 3.021672f, -10.115823f, -16.196026f, -2.309418f, + -86.981895f, 123.710999f, -11.177822f, -29.612156f, -31.419455f, + 1.541667f, 13.608661f, -9.145361f, -16.582397f, 0.825692f, + -89.694733f, 123.477776f, -12.168178f, -30.585810f, -31.258774f, + 3.492178f, 11.085848f, -6.099338f, -17.350456f, -1.831996f, + -98.397995f, 123.288437f, -6.901544f, -32.448650f, -33.457333f, + 4.656273f, 6.918665f, -7.143093f, -16.519842f, -4.653820f, + -103.509842f, 123.287453f, -4.993807f, -31.429796f, -30.121714f, + 6.555971f, 6.330775f, -2.794863f, -14.848629f, -9.470103f, + -109.535797f, 126.807076f, -5.288414f, -35.479465f, -24.960909f, + 6.444807f, 6.456624f, -5.026789f, -13.533414f, -4.698610f, + -113.928818f, 127.342537f, -5.962997f, -34.382538f, -25.823156f, + 10.882989f, 6.180243f, -7.214186f, -14.145623f, -4.297201f, + -146.980194f, 117.379784f, 6.239149f, -28.148272f, -24.417919f, + 8.895160f, 9.768323f, -4.964267f, -18.436779f, -0.407022f, + -197.618347f, 79.664658f, 2.417989f, -3.316881f, -5.801378f, + 18.399048f, 4.498376f, 0.107022f, -14.473851f, -3.986700f, + -219.757858f, 63.383587f, 5.169377f, 1.387442f, -0.668010f, + 14.515150f, 4.637818f, 6.073237f, -7.032279f, 4.307002f, + -227.090424f, 59.851295f, 8.433007f, 4.101365f, -0.259381f, + 10.632672f, 0.735295f, 6.715592f, -8.938098f, 1.614223f, + -229.534393f, 63.917084f, 9.350581f, 4.659945f, -0.804398f, + 6.856936f, -1.529187f, 5.174334f, -1.984359f, 4.340262f, + -163.617004f, 75.352737f, 11.568272f, -11.139567f, -20.727209f, + 10.790704f, 5.027168f, 17.029463f, -0.020174f, 7.355111f, + -212.684616f, 72.892769f, 3.353456f, -2.865722f, -2.658869f, + 13.809787f, 7.073246f, 9.039082f, -3.240508f, 6.401322f, + -224.577728f, 66.825119f, 3.382325f, 6.732855f, -1.938397f, + 6.476405f, -1.684867f, 1.788171f, -4.454551f, 1.685288f, + -238.489990f, 63.068295f, 6.911209f, 3.836484f, -4.373940f, + 5.761092f, 0.003443f, 2.899395f, -3.152819f, 3.693636f, + -243.127258f, 62.009800f, 6.746598f, 4.871901f, 2.196154f, + 7.152668f, 3.654155f, 10.516904f, -3.004236f, 5.014597f, +}; +static const char* test_label = "stop"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_up.h b/examples/arduino/examples/KeywordSpotting/mfcc_up.h new file mode 100644 index 00000000000..dcf19235eb5 --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_up.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "up" (0d82fd99_nohash_0.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -485.746887f, -1.299434f, -3.842550f, -3.186123f, -0.103117f, + 2.111575f, -2.739380f, 2.771092f, -3.467221f, -0.501581f, + -476.447784f, 7.004504f, 1.368172f, 0.103827f, -1.262842f, + -1.680502f, -1.829651f, -3.587514f, -7.952619f, -1.492002f, + -483.192627f, -5.270230f, -5.502382f, 0.754594f, -3.398825f, + 0.758206f, -3.853338f, -2.108801f, -8.612317f, 0.693881f, + -479.231232f, 0.885384f, -3.340301f, -0.234139f, -3.496109f, + 2.671936f, -2.368057f, -2.839613f, -2.675169f, -2.075345f, + -483.717743f, 5.064721f, 0.782550f, -2.248441f, -5.045676f, + -1.561783f, -5.845972f, -1.859817f, -7.955959f, -4.880853f, + -489.763092f, 6.019841f, 5.874937f, 3.071285f, -5.339443f, + -5.221577f, -4.983146f, -4.025985f, -7.259840f, -2.243351f, + -484.714020f, 4.467926f, 2.999898f, 6.100367f, -1.493532f, + -4.524295f, -8.332382f, -7.775754f, -13.846100f, -5.734048f, + -484.398468f, 0.618714f, 1.175333f, 1.479579f, -3.188571f, + -1.620154f, -3.707342f, -4.773705f, -7.961167f, -0.688112f, + -488.405548f, 9.844829f, 0.712457f, 3.239386f, -1.704432f, + -1.453406f, -5.687759f, -6.640042f, -3.732365f, -0.213813f, + -493.425446f, 12.935517f, 4.238606f, 3.104447f, -2.219405f, + -5.290919f, -8.890505f, -5.408366f, -7.965898f, -6.225895f, + -486.178131f, 10.322077f, 0.463803f, 3.840244f, -1.203047f, + -3.370657f, -5.004294f, -5.851231f, -7.774158f, -6.461019f, + -483.994568f, 8.819135f, 2.372979f, 4.313247f, -4.961444f, + -3.282660f, -6.250150f, -3.413723f, -5.768752f, -3.008775f, + -488.407043f, 11.160426f, 6.229419f, 4.514224f, 0.632451f, + -4.042603f, -7.323616f, -5.919675f, -7.548122f, -6.444759f, + -492.906219f, 12.851225f, 5.856893f, 0.105406f, -3.895759f, + -4.511666f, -9.154658f, -4.256425f, -8.025245f, -6.462118f, + -488.247131f, 5.768585f, -0.409500f, 6.275218f, -0.558919f, + -2.998309f, -8.442787f, -4.274093f, -7.446038f, -9.814706f, + -481.866058f, 2.890296f, -4.872808f, 2.144219f, -1.045357f, + 1.432816f, -0.555548f, -2.710370f, -6.784501f, -3.458642f, + -484.207336f, 1.249280f, -5.244426f, 0.604447f, -3.716156f, + -2.304515f, -8.185934f, 0.427001f, -2.058667f, 1.064226f, + -484.849396f, -2.015248f, -6.308643f, -0.892735f, 0.486580f, + -2.940435f, -6.275057f, -0.256915f, -3.906849f, 0.002296f, + -481.108063f, -2.188304f, -0.081420f, -0.978224f, -2.728461f, + -1.564898f, -0.886847f, 1.558231f, -6.910547f, -1.157353f, + -483.748169f, -6.408059f, -1.296204f, -2.135336f, 2.838701f, + -1.584857f, 0.369886f, 0.671368f, -0.729082f, 1.949610f, + -483.296906f, -15.700537f, 6.450670f, -5.333608f, 5.587930f, + -2.554819f, -3.202023f, -1.749987f, 1.201093f, 0.655999f, + -484.187775f, -5.360173f, 0.823554f, -1.299104f, -0.731172f, + -1.191525f, 0.676595f, -2.136606f, -4.704145f, 0.154081f, + -480.791351f, -2.816906f, -6.912311f, -0.582588f, -2.722147f, + 2.693647f, -3.038830f, 3.841860f, -2.551561f, -0.823966f, + -484.343384f, -0.343333f, -5.563055f, -2.045864f, -0.728533f, + 3.426996f, -1.605272f, 0.291991f, -7.210569f, 0.811851f, + -482.896240f, 0.535408f, -4.083309f, -0.318921f, -1.455645f, + -0.040039f, -1.547849f, 3.098172f, -3.342702f, -1.893592f, + -480.718781f, 5.446145f, -2.476877f, 0.276039f, -3.706796f, + -2.368269f, -0.498752f, -1.256507f, 1.386366f, 1.211714f, + -478.115692f, 3.546202f, 1.492145f, 1.993473f, -2.300425f, + 1.263827f, -4.948519f, -1.817291f, 0.502560f, 1.469144f, + -480.229065f, -7.235173f, -0.803128f, -1.922536f, 1.886012f, + -2.096592f, -1.314541f, 0.484973f, -1.871390f, -3.320123f, + -492.649323f, -10.048859f, -0.692663f, -0.158323f, 0.969664f, + -5.422930f, -0.309246f, 0.862990f, -1.474001f, -2.783262f, + -480.834839f, -0.948111f, -1.829201f, 3.427356f, -3.828750f, + -3.777473f, -3.600707f, 1.981883f, -1.198404f, 1.398726f, + -480.594818f, -1.210936f, -1.678627f, 4.436676f, 1.268215f, + -0.866528f, -1.320945f, 1.066788f, -1.205763f, 2.917401f, + -479.122284f, -0.956503f, -4.218804f, 3.086526f, -2.364965f, + 0.590072f, -0.607048f, -2.523932f, -5.577894f, -3.130783f, + -480.037354f, 3.755734f, -4.374526f, -2.030389f, -1.166159f, + 0.357211f, -4.360946f, -0.922095f, -3.761424f, -4.149082f, + -483.667023f, -2.752057f, -3.750160f, 2.263306f, 3.125920f, + 2.929273f, -0.800978f, 1.405737f, -0.693497f, 0.506533f, + -484.198944f, -3.171960f, -6.380881f, -3.377930f, 2.638771f, + 7.261415f, 2.137481f, -1.011708f, -0.793121f, -0.263819f, + -456.367554f, -0.631995f, -32.990322f, -23.673361f, 7.202747f, + 20.680428f, 1.094623f, -3.236514f, -3.166705f, -0.082040f, + -466.855072f, 5.852163f, -26.135977f, -16.013083f, 9.563543f, + 13.960370f, -1.251658f, -2.317789f, -1.777759f, 0.515853f, + -484.492645f, 1.133410f, -12.363409f, -6.275114f, 5.629872f, + 9.834738f, -2.394207f, -3.050398f, -1.317569f, 2.607125f, + -479.277588f, 9.761244f, -4.098523f, -0.911023f, 0.183916f, + 3.221544f, -2.656950f, -6.196084f, -3.593109f, -0.762083f, + -129.090012f, 57.320824f, -35.463707f, -40.072147f, -7.947475f, + 11.250995f, -19.291363f, -17.636690f, -14.696002f, -9.212158f, + 16.581646f, 43.638283f, -42.030445f, -36.810055f, -9.569281f, + 9.336838f, -16.903320f, -11.238772f, -12.935355f, -5.916121f, + 21.646336f, 46.556084f, -55.361069f, -38.959396f, -13.771509f, + 1.345586f, -18.165867f, -18.599575f, -19.270346f, -4.683988f, + 26.812384f, 50.040421f, -57.211067f, -43.191811f, -14.844748f, + 1.879725f, -15.699242f, -21.068197f, -10.936151f, -3.433552f, + 29.023872f, 58.710991f, -56.896851f, -42.755772f, -14.165547f, + 1.577183f, -7.506759f, -20.421946f, -10.734262f, -10.593590f, + 42.858971f, 51.601936f, -49.230831f, -36.671780f, -10.549214f, + 1.687444f, -6.695996f, -12.835267f, -10.993724f, -7.717903f, + -10.858389f, 58.921505f, -34.518082f, -36.443707f, -16.660444f, + -7.539951f, -4.872108f, -9.454859f, -10.374325f, -7.921354f, + -116.413002f, 60.308636f, -42.380203f, -34.753235f, -8.089674f, + -2.601181f, -5.142118f, -3.186783f, -18.750700f, -6.305738f, + -146.189682f, 60.902672f, -43.753231f, -34.456020f, -13.023746f, + -0.671027f, -3.530688f, -5.984342f, -16.422308f, -4.526080f, + -183.317932f, 57.902649f, -35.059402f, -31.333654f, -3.357639f, + 4.766700f, -4.220462f, -5.265543f, -10.337341f, -5.337577f, +}; +static const char* test_label = "up"; diff --git a/examples/arduino/examples/KeywordSpotting/mfcc_yes.h b/examples/arduino/examples/KeywordSpotting/mfcc_yes.h new file mode 100644 index 00000000000..4d323f80803 --- /dev/null +++ b/examples/arduino/examples/KeywordSpotting/mfcc_yes.h @@ -0,0 +1,105 @@ +// MFCC from Google Speech Commands: "yes" (0b7ee1a0_nohash_2.wav) +// 49 time frames x 10 MFCC coefficients = 490 float values +#pragma once + +static const float test_input[490] = { + -234.681412f, 43.233639f, 5.400801f, 20.397280f, 2.792400f, + -1.854441f, 0.334868f, 19.084484f, 0.550039f, 8.545486f, + -228.795731f, 48.089474f, 16.147015f, 16.006577f, 4.168744f, + 7.709664f, 7.958074f, 16.550919f, -2.256079f, 2.175747f, + -241.192108f, 55.246910f, 18.408745f, 7.723566f, 2.441019f, + 10.972773f, 8.850321f, 10.102944f, 2.172477f, 0.227714f, + -251.832870f, 56.045090f, 12.272413f, 4.749208f, 4.248945f, + 6.421356f, 8.628399f, 3.529061f, -4.020200f, 0.405161f, + -257.266479f, 60.443138f, 17.557964f, 9.048207f, 5.462535f, + 6.328237f, 8.251295f, 7.812984f, -2.603148f, -0.834925f, + -259.889648f, 55.697521f, 13.212925f, 10.598886f, 8.840254f, + 9.866948f, 15.332352f, 10.658237f, 3.804531f, 3.397527f, + -266.476593f, 54.720219f, 12.629576f, 8.900606f, 3.008298f, + 10.898797f, 12.817170f, 10.181066f, 7.927325f, 0.854756f, + -257.437561f, 58.621464f, 18.241875f, 15.591273f, 9.036938f, + 10.959089f, 11.331177f, 8.392029f, 6.635571f, 4.014952f, + -268.118317f, 55.668289f, 12.081144f, 6.303514f, 8.508442f, + 14.618596f, 12.317489f, 7.507305f, -0.624102f, -1.160921f, + -263.935211f, 54.943790f, 13.036895f, 10.619770f, 13.622162f, + 11.523499f, 8.821464f, 8.997932f, -6.086756f, -3.404617f, + -264.006226f, 49.409897f, 12.999511f, 9.158457f, 14.594608f, + 13.427459f, 10.444116f, 9.490443f, -3.601915f, 1.855514f, + -259.858795f, 47.499798f, 10.758152f, 12.309957f, 3.362462f, + 15.104926f, 11.712075f, 9.220161f, 1.967170f, -0.683039f, + -252.779251f, 35.200573f, 9.168539f, 19.362122f, 11.304137f, + 13.709476f, 9.289248f, 13.619427f, 2.265857f, -7.207956f, + -233.856842f, 34.876930f, 7.593188f, 17.194534f, 8.984902f, + 14.420804f, 4.546815f, 21.219841f, -2.725543f, -1.221810f, + -239.650635f, 32.208843f, 12.607020f, 11.496256f, 7.936153f, + 6.783998f, -5.121169f, 16.602783f, -6.377575f, -3.745578f, + -259.776733f, 41.715401f, 8.152285f, 4.466871f, 3.015864f, + 4.434165f, -2.969853f, 0.590086f, -10.047478f, -1.725257f, + -248.613922f, 61.617828f, 19.168694f, 10.262343f, 6.371417f, + 5.440273f, -1.030592f, -2.554972f, -5.193404f, 2.727951f, + -241.758957f, 65.832069f, 22.905184f, 21.520571f, 14.528395f, + 13.792401f, 8.780795f, 4.172933f, 0.691113f, 8.904346f, + -222.467331f, 73.760109f, 26.771700f, 21.566545f, 11.335753f, + 16.471857f, 17.409412f, 7.046043f, 2.207555f, 8.806846f, + -231.766830f, 63.328838f, 24.024483f, 20.269243f, 12.423348f, + 12.440336f, 16.540758f, 12.800360f, 11.840703f, 11.091752f, + -237.301178f, 61.232521f, 23.229082f, 16.493349f, 9.809525f, + 3.532008f, 7.207474f, 4.894012f, 4.928386f, 7.013971f, + -236.078186f, 58.582184f, 14.988331f, 10.202160f, 6.668953f, + 0.222149f, 4.053197f, -0.523445f, -5.121991f, 6.264892f, + -228.809174f, 62.370396f, 13.996346f, 9.702862f, 3.569854f, + 8.373587f, 6.549867f, 6.018937f, -1.874455f, 3.215962f, + -230.689148f, 47.052952f, 12.928380f, 3.530421f, 5.808893f, + 11.541079f, 7.376608f, 2.261429f, -8.993920f, -2.746737f, + -224.829941f, 31.931934f, 12.172611f, 1.894642f, 3.829933f, + 6.311895f, -2.426771f, 4.537490f, -13.888083f, -9.635439f, + -248.401917f, 35.243050f, 18.340927f, 9.314278f, 3.538419f, + 4.398130f, -3.837168f, 1.325739f, -9.304583f, 2.187257f, + -240.059464f, 20.918175f, 29.886425f, -3.646750f, 1.282848f, + 2.748509f, -0.558900f, 7.788683f, -6.005089f, -0.312643f, + -178.279892f, 64.214172f, 32.522263f, -2.488780f, -29.869844f, + -26.071568f, -21.514923f, -20.730478f, 1.186075f, -9.757907f, + -84.594292f, 63.835575f, 24.210506f, -0.455038f, -50.154488f, + -27.054171f, -6.307866f, -26.940481f, 7.093529f, -21.011780f, + -22.897802f, 54.384663f, 4.777880f, 17.929218f, -46.112652f, + -26.420647f, -1.022891f, -16.579914f, 11.931128f, -20.049368f, + 13.893736f, 69.585533f, -5.071200f, 20.808155f, -34.377609f, + -15.193277f, 5.479661f, -3.318903f, 13.530760f, -13.381321f, + 25.274822f, 76.342606f, -15.561139f, 23.014704f, -29.757202f, + -9.832362f, 3.238856f, 0.469400f, 11.067559f, -8.361760f, + 13.523623f, 84.284889f, -27.883121f, 19.608646f, -32.976501f, + -4.383229f, 1.006596f, -0.405658f, 9.962194f, -4.305982f, + -6.534761f, 82.881775f, -31.736248f, 12.043342f, -30.610407f, + -5.890024f, -1.442861f, -5.070271f, 5.840377f, -8.023405f, + -30.032322f, 72.369179f, -23.519142f, 3.961691f, -32.652710f, + -7.517621f, -4.036874f, -9.828003f, -0.686249f, -0.312814f, + -43.583763f, 80.302826f, -7.666708f, 10.932734f, -22.398018f, + -4.306559f, -6.198639f, -5.754010f, -2.895976f, 7.471755f, + -61.656425f, 41.639256f, 23.855309f, 3.351054f, -8.767569f, + -9.828515f, -2.790671f, -4.351893f, -11.057714f, 12.771217f, + -57.615463f, 1.897838f, 60.971989f, -2.455822f, -2.762581f, + -5.280724f, -0.188711f, -3.701698f, -2.663750f, 9.764828f, + -79.225914f, -5.375535f, 66.151794f, -11.967419f, -0.912968f, + -4.887309f, 5.875928f, -1.175956f, 5.853874f, 3.784406f, + -109.894936f, -39.430321f, 74.366234f, -22.863932f, 10.889661f, + -10.250796f, -0.925500f, -10.094064f, 3.740627f, 0.504248f, + -139.163651f, -44.115498f, 70.133354f, -30.318369f, 4.532646f, + -7.051695f, 1.062630f, -6.600904f, 4.206400f, -5.365909f, + -140.581650f, -38.114674f, 74.763290f, -23.267584f, 12.520188f, + -4.227964f, -0.624220f, 1.698124f, 7.477959f, -1.734360f, + -141.295578f, -42.059216f, 71.655762f, -21.087015f, 12.109696f, + 1.568535f, -0.225925f, 3.690533f, 1.076325f, -0.461506f, + -145.858658f, -44.901878f, 74.216560f, -17.009403f, 9.481274f, + 1.113154f, -3.929156f, -0.927356f, 3.342796f, -0.156648f, + -152.423553f, -53.252007f, 61.927761f, -22.145149f, 1.980226f, + -5.430344f, -8.661196f, -2.774011f, -8.981577f, 1.263445f, + -142.863907f, -54.793297f, 58.578423f, -15.521387f, 0.510913f, + 5.331514f, -8.993284f, 1.920983f, -1.463054f, 11.654953f, + -133.149033f, -42.017963f, 50.291420f, -8.434530f, -1.776678f, + 6.166668f, -1.936369f, 4.736414f, -8.531858f, 10.913676f, + -122.880341f, -28.736307f, 42.497105f, -13.191531f, -1.193018f, + 13.115855f, 0.672347f, 13.701841f, -19.346626f, 8.721835f, + -104.030289f, -12.899759f, 32.535419f, -1.614725f, -10.212351f, + 9.864163f, -4.448048f, 2.769550f, -18.147173f, 1.671773f, +}; +static const char* test_label = "yes"; diff --git a/examples/arduino/export_model.py b/examples/arduino/export_model.py new file mode 100644 index 00000000000..e951f6b86ee --- /dev/null +++ b/examples/arduino/export_model.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python3 +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +"""Export DS-CNN keyword spotting model to model.h for Arduino. + +Usage: + # Train on Google Speech Commands and export: + python export_model.py --output examples/KeywordSpotting/model.h + + # Export with a pre-trained checkpoint: + python export_model.py --checkpoint my_weights.pth --output model.h + +Requirements: + pip install executorch soundfile numpy torch torchao +""" + +import argparse +import os + +import numpy as np +import soundfile as sf +import torch +from executorch.backends.cortex_m.passes.cortex_m_pass_manager import CortexMPassManager +from executorch.backends.cortex_m.quantizer.quantizer import CortexMQuantizer +from executorch.backends.cortex_m.target_config import CortexM, CortexMTargetConfig +from executorch.backends.transforms.duplicate_dynamic_quant_chain import ( + DuplicateDynamicQuantChainPass, +) +from executorch.examples.models.mlperf_tiny.ds_cnn import DSCNNKWS +from executorch.exir import EdgeCompileConfig, to_edge +from torch.export import export +from torchao.quantization.pt2e.quantize_pt2e import convert_pt2e, prepare_pt2e + + +def wav_to_mfcc(path: str) -> torch.Tensor: + """Extract 49x10 MFCC features from a 1-second 16kHz audio file.""" + data, sr = sf.read(path, dtype="float32") + + # Convert to mono if stereo + if data.ndim > 1: + data = data[:, 0] + wav = torch.from_numpy(data).unsqueeze(0) + if wav.shape[1] < 16000: + wav = torch.nn.functional.pad(wav, (0, 16000 - wav.shape[1])) + else: + wav = wav[:, :16000] + n_fft, hop = 640, 320 + window = torch.hann_window(n_fft) + spec = torch.stft(wav, n_fft, hop, window=window, return_complex=True) + power = spec.abs() ** 2 + n_mels = 40 + mel_pts = torch.linspace( + 2595 * np.log10(1 + 0 / 700), 2595 * np.log10(1 + 8000 / 700), n_mels + 2 + ) + hz_pts = 700 * (10 ** (mel_pts / 2595) - 1) + bins = (hz_pts * n_fft / sr).long() + fb = torch.zeros(n_mels, n_fft // 2 + 1) + for m in range(n_mels): + for k in range(bins[m], bins[m + 1]): + if bins[m + 1] > bins[m]: + fb[m, k] = (k - bins[m]) / (bins[m + 1] - bins[m]) + for k in range(bins[m + 1], bins[m + 2]): + if bins[m + 2] > bins[m + 1]: + fb[m, k] = (bins[m + 2] - k) / (bins[m + 2] - bins[m + 1]) + mel_spec = torch.matmul(fb, power.squeeze(0)) + log_mel = torch.log(mel_spec + 1e-6) + dct_mat = torch.zeros(10, n_mels) + for i in range(10): + for j in range(n_mels): + dct_mat[i, j] = np.cos(np.pi * i * (2 * j + 1) / (2 * n_mels)) + mfcc = torch.matmul(dct_mat, log_mel)[:, :49] + return ( + mfcc.unsqueeze(0) + .unsqueeze(0) + .permute(0, 1, 3, 2) + .to(memory_format=torch.channels_last) + ) + + +def train_model(data_dir: str, samples_per_class: int = 100) -> DSCNNKWS: + """Train DS-CNN on 10 keyword classes from Google Speech Commands. + + Indices 0 (silence) and 1 (unknown) are reserved to match the 12-class + MLPerf label mapping but are not trained here. + """ + labels = ["yes", "no", "up", "down", "left", "right", "on", "off", "stop", "go"] + train_x, train_y = [], [] + + print("Loading training data...") + for cls_idx, name in enumerate(labels, start=2): + wavs = sorted( + f for f in os.listdir(os.path.join(data_dir, name)) if f.endswith(".wav") + )[:samples_per_class] + for wav in wavs: + train_x.append(wav_to_mfcc(os.path.join(data_dir, name, wav))) + train_y.append(cls_idx) + print(f" {name}: {len(wavs)}") + + train_x = torch.cat(train_x) + train_y = torch.tensor(train_y) + print(f"Total: {len(train_y)} samples") + + model = DSCNNKWS().train() + opt = torch.optim.Adam(model.parameters(), lr=0.003) + crit = torch.nn.CrossEntropyLoss() + + for epoch in range(80): + idx = torch.randperm(len(train_y)) + correct = 0 + for i in range(0, len(idx), 32): + b = idx[i : i + 32] + opt.zero_grad() + out = model(train_x[b]) + loss = crit(out, train_y[b]) + loss.backward() + opt.step() + correct += (out.argmax(1) == train_y[b]).sum().item() + if (epoch + 1) % 20 == 0: + print(f" Epoch {epoch + 1}: acc={correct / len(train_y):.0%}") + + return model.eval() + + +def export_model( + model: DSCNNKWS, calibration_dir: str, target: str = "cortex-m33" +) -> bytes: + """Quantize and export model to .pte bytes.""" + example = (torch.rand(1, 1, 49, 10) * 2 - 1).to(memory_format=torch.channels_last) + + captured = export(model, (example,), strict=True).module() + for n in [n for n in captured.graph.nodes if "_guards" in str(n.target)]: + n.replace_all_uses_with(list(captured.graph.nodes)[0]) + captured.graph.erase_node(n) + if hasattr(captured, "_guards_fn"): + delattr(captured, "_guards_fn") + captured.graph.lint() + captured.recompile() + + # Calibrate with real audio + quantizer = CortexMQuantizer() + prepared = prepare_pt2e(captured, quantizer) + + print("Calibrating with real audio...") + labels = ["yes", "no", "up", "down", "left", "right", "on", "off", "stop", "go"] + for label in labels: + label_dir = os.path.join(calibration_dir, label) + wavs = sorted(f for f in os.listdir(label_dir) if f.endswith(".wav")) + for wav in wavs[50:55]: + prepared(wav_to_mfcc(os.path.join(label_dir, wav))) + + converted = convert_pt2e(prepared, fold_quantize=True) + DuplicateDynamicQuantChainPass()(converted) + + # Export with Cortex-M passes + cpu = CortexM.M33 if "m33" in target else CortexM.M55 + edge = to_edge( + export(converted, (example,)), + compile_config=EdgeCompileConfig( + preserve_ops=[torch.ops.aten.linear.default], + _check_ir_validity=False, + _core_aten_ops_exception_list=[torch.ops.aten.max_pool2d.default], + ), + ) + pm = CortexMPassManager( + edge.exported_program(), + CortexMPassManager.pass_list, + target_config=CortexMTargetConfig(cpu=cpu), + ) + edge._edge_programs["forward"] = pm.transform() + et = edge.to_executorch() + return et.buffer + + +def buffer_to_header(buffer: bytes) -> str: + """Convert .pte bytes to a C header string.""" + h = "#pragma once\n#include \n#include \n\n" + h += "alignas(16) static const uint8_t model_pte[] = {\n" + for i in range(0, len(buffer), 16): + h += " " + ",".join(f"0x{b:02x}" for b in buffer[i : i + 16]) + ",\n" + h += "};\n" + h += f"static const size_t model_pte_size = {len(buffer)};\n" + return h + + +def main(): + parser = argparse.ArgumentParser( + description="Export DS-CNN keyword spotting model for Arduino" + ) + parser.add_argument("--output", required=True, help="Output model.h path") + parser.add_argument("--checkpoint", help="Pre-trained .pth weights (skip training)") + parser.add_argument( + "--data-dir", + default="outputs/speech_commands/SpeechCommands/speech_commands_v0.02", + help="Google Speech Commands dataset directory", + ) + parser.add_argument( + "--target", default="cortex-m33", help="Target CPU (cortex-m33 or cortex-m55)" + ) + parser.add_argument( + "--samples", type=int, default=100, help="Training samples per class" + ) + args = parser.parse_args() + + if args.checkpoint: + print(f"Loading checkpoint: {args.checkpoint}") + model = DSCNNKWS().eval() + model.load_state_dict(torch.load(args.checkpoint, weights_only=True)) + else: + if not os.path.isdir(args.data_dir): + print(f"Dataset not found at {args.data_dir}") + print( + 'Download: python -c "import torchaudio; ' + "torchaudio.datasets.SPEECHCOMMANDS(root='outputs/speech_commands', " + 'download=True)"' + ) + return + model = train_model(args.data_dir, args.samples) + torch.save(model.state_dict(), args.output.replace(".h", ".pth")) + + buffer = export_model(model, args.data_dir, args.target) + header = buffer_to_header(buffer) + + with open(args.output, "w") as f: + f.write(header) + print(f"\n{args.output}: {len(buffer)} bytes ({len(buffer) / 1024:.1f} KB)") + + +if __name__ == "__main__": + main() diff --git a/examples/arduino/generate_test_input.py b/examples/arduino/generate_test_input.py new file mode 100644 index 00000000000..4c9509e65bd --- /dev/null +++ b/examples/arduino/generate_test_input.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +"""Generate MFCC test input header from a .wav audio file. + +Usage: + python generate_test_input.py --input recording.wav --output mfcc_custom.h + +The output .h file can be included in an Arduino sketch: + #include "mfcc_custom.h" + +Requirements: + pip install soundfile numpy torch torchaudio +""" + +import argparse + +import numpy as np +import soundfile as sf +import torch + + +def wav_to_mfcc(path: str) -> np.ndarray: + """Extract 49x10 MFCC features from a 1-second 16kHz audio file.""" + data, sr = sf.read(path, dtype="float32") + + # Convert to mono if stereo + if data.ndim > 1: + data = data[:, 0] + + # Resample to 16kHz if needed + if sr != 16000: + import torchaudio + + data = torch.from_numpy(data).unsqueeze(0) + data = torchaudio.functional.resample(data, sr, 16000).squeeze(0).numpy() + sr = 16000 + + wav = torch.from_numpy(data).unsqueeze(0) + + # Pad or trim to exactly 1 second (16000 samples) + if wav.shape[1] < 16000: + wav = torch.nn.functional.pad(wav, (0, 16000 - wav.shape[1])) + else: + wav = wav[:, :16000] + + # STFT + n_fft, hop = 640, 320 + window = torch.hann_window(n_fft) + spec = torch.stft(wav, n_fft, hop, window=window, return_complex=True) + power = spec.abs() ** 2 + + # Mel filterbank (40 bands, 0-8kHz) + n_mels = 40 + mel_pts = torch.linspace( + 2595 * np.log10(1 + 0 / 700), 2595 * np.log10(1 + 8000 / 700), n_mels + 2 + ) + hz_pts = 700 * (10 ** (mel_pts / 2595) - 1) + bins = (hz_pts * n_fft / sr).long() + fb = torch.zeros(n_mels, n_fft // 2 + 1) + for m in range(n_mels): + for k in range(bins[m], bins[m + 1]): + if bins[m + 1] > bins[m]: + fb[m, k] = (k - bins[m]) / (bins[m + 1] - bins[m]) + for k in range(bins[m + 1], bins[m + 2]): + if bins[m + 2] > bins[m + 1]: + fb[m, k] = (bins[m + 2] - k) / (bins[m + 2] - bins[m + 1]) + + mel_spec = torch.matmul(fb, power.squeeze(0)) + log_mel = torch.log(mel_spec + 1e-6) + + # DCT → 10 MFCCs + n_mfcc = 10 + dct_mat = torch.zeros(n_mfcc, n_mels) + for i in range(n_mfcc): + for j in range(n_mels): + dct_mat[i, j] = np.cos(np.pi * i * (2 * j + 1) / (2 * n_mels)) + + mfcc = torch.matmul(dct_mat, log_mel)[:, :49] # 49 time frames + + # Reshape to model input format: (1, 1, 49, 10), channels_last + mfcc = mfcc.unsqueeze(0).unsqueeze(0).permute(0, 1, 3, 2) + return mfcc.contiguous().view(-1).numpy() + + +def main(): + parser = argparse.ArgumentParser(description="Generate MFCC header from .wav file") + parser.add_argument("--input", required=True, help="Input .wav file (16kHz, 1 sec)") + parser.add_argument("--output", required=True, help="Output .h file") + parser.add_argument("--label", default="custom", help="Label for the audio") + args = parser.parse_args() + + mfcc = wav_to_mfcc(args.input) + + h = f"// MFCC from: {args.input}\n" + h += "// 49 time frames x 10 MFCC coefficients = 490 float values\n" + h += "#pragma once\n\n" + h += "static const float test_input[490] = {\n" + for i in range(0, len(mfcc), 8): + h += " " + ",".join(f"{v:.6f}f" for v in mfcc[i : i + 8]) + ",\n" + h += "};\n" + h += f'static const char* test_label = "{args.label}";\n' + + with open(args.output, "w") as f: + f.write(h) + + print(f"Generated {args.output} from {args.input} ({len(mfcc)} values)") + + +if __name__ == "__main__": + main() diff --git a/examples/arduino/library.properties b/examples/arduino/library.properties new file mode 100644 index 00000000000..7e500dd5ff7 --- /dev/null +++ b/examples/arduino/library.properties @@ -0,0 +1,16 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +name=ExecuTorchArduino +version=0.1.0 +author=Meta Platforms +maintainer=ExecuTorch Team +sentence=Run PyTorch models on Arduino microcontrollers with ExecuTorch. +paragraph=ExecuTorch is a PyTorch runtime optimized for on-device inference. This library packages the ExecuTorch runtime with CMSIS-NN acceleration for ARM Cortex-M boards, enabling quantized model inference directly from Arduino sketches. +category=Data Processing +url=https://github.com/pytorch/executorch +architectures=zephyr +includes=ExecuTorchArduino.h diff --git a/examples/arduino/platform_stubs.c b/examples/arduino/platform_stubs.c new file mode 100644 index 00000000000..4abc7bdf411 --- /dev/null +++ b/examples/arduino/platform_stubs.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +// Platform stubs for Arduino LLEXT environment. +// Weak symbols — only used when the platform doesn't provide them. + +#include +#include +#include + +__attribute__((weak)) void _Exit(int status) { + (void)status; + while (1) {} +} + +__attribute__((weak)) int fprintf(FILE* stream, const char* fmt, ...) { + (void)stream; + (void)fmt; + return 0; +} + +#if defined(__ARM_EABI__) +// Use double intermediate to avoid the compiler lowering (long long)f back +// into a call to __aeabi_f2lz, which would cause infinite recursion. +__attribute__((weak)) long long __aeabi_f2lz(float f) { + double d = (double)f; + if (d < 0) { + d = -d; + uint32_t hi = (uint32_t)(d / 4294967296.0); + uint32_t lo = (uint32_t)(d - (double)hi * 4294967296.0); + return -(long long)(((uint64_t)hi << 32) | (uint64_t)lo); + } + uint32_t hi = (uint32_t)(d / 4294967296.0); + uint32_t lo = (uint32_t)(d - (double)hi * 4294967296.0); + return (long long)(((uint64_t)hi << 32) | (uint64_t)lo); +} +#endif diff --git a/zephyr/samples/hello-executorch/boards/arduino_uno_q.conf b/zephyr/samples/hello-executorch/boards/arduino_uno_q.conf new file mode 100644 index 00000000000..d3bb1935979 --- /dev/null +++ b/zephyr/samples/hello-executorch/boards/arduino_uno_q.conf @@ -0,0 +1,20 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +# Arduino Uno Q — STM32U585 (Cortex-M33, DSP, no MVE, no Ethos-U) +# 2 MB flash, 786 KB SRAM — plenty of room for DS-CNN int8 (50 KB .pte). +# +# CMSIS-NN uses the DSP path for M33 (no MVE on U5 series). + +# Memory tuning for DS-CNN on STM32U585: +# - method allocator: 64 KB (DS-CNN metadata + planned buffers) +# - temp allocator: 8 KB (scratch for CMSIS-NN kernels) +# - main stack: 8 KB +# - heap: 16 KB +CONFIG_EXECUTORCH_METHOD_ALLOCATOR_POOL_SIZE=65536 +CONFIG_EXECUTORCH_TEMP_ALLOCATOR_POOL_SIZE=8192 +CONFIG_MAIN_STACK_SIZE=8192 +CONFIG_HEAP_MEM_POOL_SIZE=16384