The PlatformIO dep sh123/esp32_codec2_arduino@1.0.7 bundles codec2 v0.9.2. Mac-side pycodec2 v3.0.4 links libcodec2 v1.2.0. Years of codec2 development between those releases. Replace the upstream lib with a local vendor of drowe67/codec2 v1.2.0 under lib/codec2/. Trim the 191-file source tree down to the ~100 files actually needed for codec2 (drop FreeDV, OFDM, COHPSK, FSK, FM-FSK, LDPC, Horus, CLI tools — pyxis only uses codec2_create/destroy/encode/decode + samples_per_frame / bytes_per_frame). Carry over the v0.9 codebook .c files since the codebook contents matched (compared against v1.2's src/codebook/*.txt). Define __EMBEDDED__ so the codebooks land in flash (.const) rather than RAM. Without it the codebooks add ~127KB to BSS and the LVGL task fails to start (RAM was 65% full vs 27% with __EMBEDDED__). Provide trivial codec2_malloc/codec2_free wrappers in codec2_alloc_esp32.c (codec2 v1.2 expects them when __EMBEDDED__ is defined; ESP-IDF's malloc/free already pull from internal RAM). Also explicitly add SD/FS to lib_deps and #include <SD.h> in main.cpp — the previous esp32_codec2 dep transitively pulled SD which let SDArchiveFileSystem.h get away with depending on it implicitly. With chain+ ldf mode and no esp32_codec2 dep, we have to declare the framework lib explicitly. DOES NOT fix the ~30x speech-decode RMS asymmetry between pycodec2 self-tests (~5800) and pyxis decoding the same encoded bytes (~170). Sine waves and 3-formant synthesis pass clean both directions; only real TTS speech triggers it. Probably a separate codec-state divergence (the encoder/decoder are independent codec2 instances in pyxis, both fresh per call) or a wire-format quirk we still need to track down. v1.2 is the right baseline regardless — same bug class as several upstream fixes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vendored codec2 v1.2.0
This is a local vendor of drowe67/codec2 v1.2.0
source files, replacing the sh123/esp32_codec2_arduino@1.0.7 PlatformIO
dependency.
Why?
sh123/esp32_codec2_arduino@1.0.7 bundles codec2 v0.9.2. The Mac-side
pycodec2 Python wrapper (used by Sideband, Columba python clients,
and the LXST harness) links libcodec2 v1.2.0. The version gap
introduces a real audio quality regression on pyxis-decoded speech:
| Test signal | pycodec2 round-trip RMS | pyxis decode RMS |
|---|---|---|
| 1kHz pure sine (amp 0.5) | 1394 | 6357 |
| 3-formant voice approx (amp 0.5) | 5749 | 4378 |
Real TTS speech (say output) |
5796 | 170 |
The 30× drop on real speech doesn't reproduce on tones or simple formants — it's content-specific. Decoder behavior is consistent (decode_fail = 0 in every case) but the amplitude collapses. Local pycodec2 vs the v0.9 esp32_codec2 lib using the same encoded bytes diverges, so the bug is in the v0.9 decoder code path.
The c2dec/c2enc/cli tools are excluded via srcFilter in
library.json since pyxis only needs codec2 itself (no FreeDV / OFDM /
FSK / LDPC etc).
Codebooks
codebook*.c files are the LSP/energy/etc. quantization tables. v0.9
codebook content matched v1.2's canonical text-form input (verified
with diff against src/codebook/dlsp1.txt etc), so the existing
generated .c files were carried over from sh123/esp32_codec2_arduino's
src/. The version.h was hand-written from cmake/version.h.in since
codec2 v1.2's CMake-driven generation isn't running here.
Updating
To pull a newer codec2 release: download
https://api.github.com/repos/drowe67/codec2/tarball/refs/tags/<version>,
extract, and replace lib/codec2/src/*.c and *.h with the contents
of the upstream src/. Don't overwrite the codebook .c files
unless you regenerate them via the upstream CMake build (codebook
content rarely changes).