File size: 7,160 Bytes
c3edab4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
---
license: apache-2.0
library_name: esp-idf
tags:
  - voice-activity-detection
  - vad
  - esp32-p4
  - embedded
  - audio
  - risc-v
  - dfsmn
  - quantization
---

# FireRedVAD Models for ESP32-P4

Converted [FireRedVAD](https://github.com/FireRedTeam/FireRedVAD) models optimized for ESP32-P4 microcontrollers.
All models use the custom `.frvd` binary format with native RISC-V PIE (Position Independent Execution) acceleration.

**Source Code:** https://github.com/Strg-Alt-Entf-0x00/firered-vad-esp32-p4

## Quick Start

```bash
cd examples/console_vad
pip install huggingface-hub
python download_models.py
```

```bash
idf.py build flash monitor
```

```
firevad> vad_model_list
firevad> vad_model_load stream-vad/int8-ch/firered-stream-vad-int8-ch.frvd
firevad> vad_infer_mic
```

## Available Models

### stream-vad/ β€” Real-time streaming (causal, 10ms latency)

Best for real-time voice activity detection. Model is fully **causal** β€” no future context.
Runs in ~4.5ms per 10ms frame on ESP32-P4 @ 400MHz.

| Quantization | File | Size | Notes |
|---|---|---|---|
| **INT8-CH** | `stream-vad/int8-ch/firered-stream-vad-int8-ch.frvd` | 576 KB | **Recommended.** Per-channel scale factors, near-FP32 accuracy |
| INT8 | `stream-vad/int8/firered-stream-vad-int8.frvd` | 556 KB | Global scale factor per layer, slightly lower accuracy |
| INT16 | `stream-vad/int16/firered-stream-vad-int16.frvd` | 1.1 MB | Higher precision, ~2x memory use |
| FP32 | `stream-vad/fp32/firered-stream-vad-fp32.frvd` | 2.2 MB | Development only. Too slow for real-time on P4 (~35ms/frame) |

### vad/ β€” Offline batch VAD (non-causal, 1-second chunks)

Uses bidirectional context. Higher accuracy than stream-vad, but adds latency.
Not suitable for real-time streaming.

| Quantization | File | Size | Notes |
|---|---|---|---|
| **INT8-CH** | `vad/int8-ch/firered-vad-int8-ch.frvd` | 597 KB | Recommended for batch processing |
| INT8 | `vad/int8/firered-vad-int8.frvd` | 576 KB | |
| INT16 | `vad/int16/firered-vad-int16.frvd` | 1.1 MB | |
| FP32 | `vad/fp32/firered-vad-fp32.frvd` | 2.3 MB | |

### aed/ β€” Audio Event Detection (Speech / Music / Singing)

Multi-class audio classifier. Identifies speech, music, and singing simultaneously.

| Quantization | File | Size | Notes |
|---|---|---|---|
| **INT8-CH** | `aed/int8-ch/firered-aed-int8-ch.frvd` | 598 KB | Recommended |
| INT8 | `aed/int8/firered-aed-int8.frvd` | 576 KB | |
| INT16 | `aed/int16/firered-aed-int16.frvd` | 1.1 MB | |
| FP32 | `aed/fp32/firered-aed-fp32.frvd` | 2.3 MB | |

## Quantization Explained

### Why INT8-CH (Per-Channel) is Recommended

Standard per-tensor INT8 quantization assigns **one** global scale factor per weight matrix.
DFSMN architectures have wide variance in weight distribution across output channels β€” a single
scale factor cannot capture this range accurately, causing silent accuracy loss.

**Per-Channel INT8 (`int8-ch`, Version 4 in the `.frvd` format)** assigns **one scale factor
per output channel**. This preserves near-FP32 accuracy at INT8 speed and memory cost.

| | int8 | int8-ch | int16 | fp32 |
|---|---|---|---|---|
| Format version | 2 | 4 | 3 | 1 |
| Inference time (P4) | ~4.47ms | ~4.54ms | ~6ms | ~35ms |
| Memory bandwidth | 4x less than FP32 | 4x less than FP32 | 2x less than FP32 | baseline |
| Accuracy vs FP32 | Lower | Near-identical | High | Reference |

## Benchmark Results (ESP32-P4, 400MHz, 10ms audio frame)

| Model | Avg Latency | Real-Time Load | Usable? |
|---|---|---|---|
| stream-fp32 | 35.2 ms | 352% | No β€” audio drops |
| stream-int8 | 4.47 ms | 44.7% | Yes |
| **stream-int8-ch** | **4.54 ms** | **45.4%** | **Yes β€” Recommended** |

Real-time budget for 10ms frames: 10ms. Anything above 10ms (>100% load) causes audio drops.

## Hardware Requirements

- MCU: ESP32-P4 (RISC-V dual-core, 400MHz)
- PSRAM: 32 MB
- Flash: 16–32 MB
- RAM at runtime: ~150 KB
- Microphone: INMP441 or equivalent I2S digital microphone @ 16kHz

**Note:** INT8 and INT8-CH models use ESP32-P4 PIE vector instructions
(`esp.vmulas.s8.xacc` etc.) with mandatory 16-byte memory alignment, handled automatically
by the runtime. FP32/INT16 models work on other ESP32 variants (S2, S3) but without
PIE acceleration.

## Known Limitations (Honest Assessment)

1. **Noise sensitivity:** Performance degrades in low-SNR environments (loud machinery, strong wind).
   False positive rate increases at SNR < 5dB.
2. **Microphone dependency:** Model was trained on clean 16kHz PCM. A high-quality I2S
   microphone with hardware PGA gain control is required for reliable results.
3. **No built-in noise suppression:** The ESP-IDF runtime does not include NS/AEC.
   Echo cancellation is available via the shared APLL (I2S0 + I2S1 synchronized clocking).
4. **APLL sharing warning:** When both TX and RX I2S ports are active, the ESP32-P4 APLL
   runs at 8,191,999 Hz instead of 8,192,000 Hz (1 Hz deviation). This is hardware-expected
   behavior, not a bug. Both ports share the same clock, which is ideal for AEC.

## .frvd File Format

Custom binary format, version-tagged in header byte [4..7]:

```
Header (32 bytes):
  [0..3]   Magic: "FRVD"
  [4..7]   Version: 1=fp32, 2=int8, 3=int16, 4=int8-per-channel
  [8..11]  Model type: 0=VAD, 1=Stream-VAD, 2=AED
  [12..15] Total parameter count
  [16..23] DFSMN block count + DNN layer count
  [24..31] Reserved

Architecture Metadata (32 bytes):
  Input dim, hidden size, projection size, output dim,
  lookback order/stride, lookahead order/stride

CMVN block:
  dim (uint32) + means[dim] (float32) + istd[dim] (float32)

Layer data (sequential):
  Per tensor: CRC32 name hash + element count + [scale per channel for int8-ch] + data
```

## Conversion Pipeline

Original FireRedVAD PyTorch checkpoints -> `.frvd`:

```bash
# Requirements
pip install torch kaldiio numpy

# Stream-VAD INT8-CH (recommended)
python tools/converter/export_weights.py \
    --model-dir tools/original_models/Stream-VAD \
    --output-dir examples/console_vad/converted_models/stream-vad/int8-ch \
    --model-type stream-vad \
    --quantize-int8-per-ch

# Stream-VAD INT8
python tools/converter/export_weights.py \
    --model-dir tools/original_models/Stream-VAD \
    --output-dir examples/console_vad/converted_models/stream-vad/int8 \
    --model-type stream-vad \
    --quantize-int8

# Verify conversion
python tools/converter/verify_conversion.py \
    --frvd examples/console_vad/converted_models/stream-vad/int8-ch/firered-stream-vad-int8-ch.frvd
```

## License & Attribution

### Original Models
- **FireRedVAD** by Xiaohongshu (FireRedTeam) β€” Apache 2.0
- Source: https://github.com/FireRedTeam/FireRedVAD
- HuggingFace: https://huggingface.co/FireRedTeam/FireRedVAD

### ESP32-P4 Port
- **FireRedVAD-ESP32-P4** by Strg-Alt-Entf-0x00 β€” Apache 2.0
- Repository: https://github.com/Strg-Alt-Entf-0x00/firered-vad-esp32-p4

## Citation

```bibtex
@misc{fireredvad-esp32p4,
  title={FireRedVAD for ESP32-P4: Optimized Voice Activity Detection for Embedded Systems},
  author={Strg-Alt-Entf-0x00},
  year={2026},
  howpublished={\url{https://github.com/Strg-Alt-Entf-0x00/firered-vad-esp32-p4}},
}
```