Repository navigation
Performance
The speed of the modulators and demodulators, as multiples of real time: everything above 1 is fast enough, the rest is CPU time which is left for your application. The memory is documented in Memory usage.
Measured with the benchmark example at 8000 Hz: the values are multiples of real time, so everything above 1 is fast enough. All modes decoded all characters on all boards and the PC, except one additional (wrong) character of qpsk125 on the RP2350.
| Mode | ESP32-S3 | ESP32-P4 | RP2040 | RP2350 | PC |
|---|---|---|---|---|---|
FSK 1200
|
40 | 120 | 9.1 | 20 | 4700 |
mfsk16 |
27 | 70 | 3.6 | 16 | 1600 |
mfsk64 |
10 | 27 | 1.2 | 6.2 | 490 |
psk125 |
58 | 127 | 7.6 | 62 | 6900 |
qpsk125 |
52 | 114 | 7.3 | 53 | 5100 |
8psk250 |
40 | 85 | 6.2 | 44 | 5000 |
ofdm32 |
10 | 27 | 2.0 | 7.0 | 1800 |
aprs |
24 | 57 | 4.8 | 23 | 1600 |
fx25 |
28 | 98 | 6.3 | 41 | 2900 |
il2p |
21 | 56 | 4.8 | 22 | 1600 |
olivia-8-250 |
4.0 | 8.2 | 0.7 | 3.2 | 390 |
olivia-32-1000 |
2.6 | 5.1 | 0.5 | 2.0 | 230 |
contestia-8-250 |
5.8 | 12 | 0.9 | 4.5 | 610 |
css7 |
5.5 | 7.2 | 1.0 | 5.2 | 900 |
css10 |
5.4 | 7.4 | 1.0 | 5.1 | 880 |
morse |
131 | 317 | 14 | 95 | 11000 |
morse-american |
127 | 304 | 14 | 93 | 10000 |
dtmf |
42 | 87 | 2.6 | 27 | 7500 |
| Mode | ESP32-S3 | ESP32-P4 | RP2040 | RP2350 | PC |
|---|---|---|---|---|---|
FSK 1200
|
72 | 142 | 20 | 75 | 4000 |
mfsk16 |
82 | 174 | 20 | 74 | 5700 |
mfsk64 |
84 | 183 | 21 | 87 | 6100 |
psk125 |
74 | 190 | 9.4 | 69 | 4600 |
qpsk125 |
73 | 190 | 9.4 | 69 | 3900 |
8psk250 |
70 | 176 | 9.1 | 63 | 3900 |
ofdm32 |
6.6 | 14 | 3.3 | 1.5 | 390 |
aprs |
63 | 115 | 17 | 62 | 3900 |
fx25 |
33 | 110 | 16 | 57 | 3600 |
il2p |
48 | 114 | 17 | 60 | 4500 |
olivia-8-250 |
5.6 | 10 | 5.4 | 23 | 2400 |
olivia-32-1000 |
5.8 | 11 | 5.8 | 24 | 2400 |
contestia-8-250 |
6.0 | 11 | 6.0 | 26 | 2800 |
css7 |
5.5 | 8.6 | 4.3 | 17 | 2300 |
css10 |
5.5 | 8.6 | 4.1 | 17 | 2300 |
morse |
200 | 456 | 33 | 104 | 16000 |
morse-american |
199 | 442 | 36 | 99 | 16000 |
dtmf |
17 | 34 | 18 | 83 | 7200 |
- ESP32-S3 at 240 MHz with 8 MB octal PSRAM (FQBN
esp32:esp32:esp32s3:PSRAM=opi), arduino-esp32 3.3.12. - ESP32-P4 (Waveshare ESP32-P4-WIFI6, FQBN
esp32:esp32:esp32p4:ChipVariant=postv3), arduino-esp32 3.3.12. - RP2040 (Raspberry Pi Pico, 133 MHz, no floating point unit, FQBN
rp2040:rp2040:rpipico), Arduino-Pico 6.3.0. - RP2350 (Raspberry Pi Pico 2 W with PSRAM, 150 MHz, single precision floating point unit, FQBN
rp2040:rp2040:rpipico2w), Arduino-Pico 6.3.0. The benchmark doesn't use the PSRAM. - PC: Intel Core i7-4650U (1.7 GHz, 2013), Linux, GCC 13 with
-O3, the benchmark sketch compiled for the desktop. The median of three runs, rounded to two digits: a run only takes a few milliseconds, so the values vary by about ±20%. -
The RP2040 is too slow for the Olivia and Contestia decoders (values below 1, in bold): they can only decode recorded audio, not in real time. CSS (1.0) has no headroom left: use the ESP32 for CSS.
mfsk64(1.2) andofdm32(2.0) leave little time for the application. All other modes run fine. The RP2350 is fast enough for all modes: thanks to its floating point unit it decodes 2 to 6 times faster than the RP2040. Only the OFDM encoder is slow on it (1.5). - Olivia needs the most CPU:
olivia-32-1000has the least headroom. CSS needs about the same for all spreading factors, because the FFT size grows with the symbol length. The CSS encoder calculates the chirp phase with double precision, which is slow on these chips (no double precision FPU). At higher sample rates the decoder also converts the input to 8000 Hz, which costs additional time. - The benchmark passes the generated audio directly to the decoder, so it doesn't need memory for the audio and also runs on boards without PSRAM. On an ESP32-S3 with octal PSRAM, select
PSRAM=opi: with quad PSRAM the PSRAM isn't found.
Use a recent version of the arduino-audio-tools: older versions compute double precision sin()/cos() in the Goertzel filter for each block, which is slow on MCUs without a double precision FPU (FSK, MFSK), and their Vector::push_back() grows the buffer by one element at a time (the modulation in the benchmark was then slower than real time).
To measure your board, run the benchmark example: it needs no audio hardware and prints the real time factor of each mode. The decoding speed depends mostly on the sample rate, so use the lowest sample rate your hardware supports (see the comment on Olivia and CSS above).
The PC values are in the tables above. ggwave isn't part of the benchmark: it is much slower, ggwave-fast decodes 79 times faster than real time at 24000 Hz on the PC.
The tinymodem --benchmarks option measures the FSK and MFSK modems on the desktop.