From 4a64961244a0e95d7fa88ddf000f8f141e2ca9fb Mon Sep 17 00:00:00 2001 From: Brad Barnett <127794626+bdbarnett@users.noreply.github.com> Date: Wed, 21 Oct 2026 11:18:56 -0500 Subject: [PATCH] ESP32 and other CMake builds: take the MP3 decoder's buffers from the heap micropython.cmake set the allocator macros on buffers.c with set_source_files_properties(), which belongs to the directory that sets it. The ESP32 build compiles each module source a second time from the project's directory, and that is the copy that gets linked, so it had the static fallback: 23.8 kB of .bss, internal RAM on an S3. Define the macros in src/audiomp3/mp3_buffers.c and include buffers.c from there, so every compile of it gets them. On an ESP32-S3 audiodsp's .bss goes from 25,296 to 1,480 bytes, and each MP3Decoder has buffers of its own. --- micropython.cmake | 13 +++++++------ src/audiomp3/mp3_buffers.c | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/audiomp3/mp3_buffers.c diff --git a/micropython.cmake b/micropython.cmake index d75f2de8..65bf0f6c 100644 --- a/micropython.cmake +++ b/micropython.cmake @@ -204,7 +204,6 @@ if(EXISTS ${MPAUDIO_MP3_SRC_DIR}/mp3dec.c) target_include_directories(usermod_mpaudio INTERFACE ${MPAUDIO_MP3_SRC_DIR}) target_sources(usermod_mpaudio INTERFACE ${MPAUDIO_MP3_SRC_DIR}/bitstream.c - ${MPAUDIO_MP3_SRC_DIR}/buffers.c ${MPAUDIO_MP3_SRC_DIR}/dct32.c ${MPAUDIO_MP3_SRC_DIR}/dequant.c ${MPAUDIO_MP3_SRC_DIR}/dqchan.c @@ -219,16 +218,18 @@ if(EXISTS ${MPAUDIO_MP3_SRC_DIR}/mp3dec.c) ${MPAUDIO_MP3_SRC_DIR}/subband.c ${MPAUDIO_MP3_SRC_DIR}/trigtabs.c ${MPAUDIO_SRC_DIR}/audiomp3/mp3_alloc.c + ${MPAUDIO_SRC_DIR}/audiomp3/mp3_buffers.c ${MPAUDIO_SRC_DIR}/audiomp3/MP3Decoder.c ${MPAUDIO_SRC_DIR}/audiomp3/module.c ) # buffers.c's MPDEC_ALLOCATOR(x)/MPDEC_FREE(x) (used nowhere else in - # lib/mp3) route through this port's own mp3_alloc()/mp3_free() -- same - # -include + -fwrapv treatment as micropython.mk's buffers.o rule. - set_source_files_properties(${MPAUDIO_MP3_SRC_DIR}/buffers.c PROPERTIES - COMPILE_OPTIONS "-include;${MPAUDIO_SRC_DIR}/audiomp3/mp3_alloc.h;-DMPDEC_ALLOCATOR(x)=mp3_alloc(x);-DMPDEC_FREE(x)=mp3_free(x);-fwrapv" - ) + # lib/mp3) route through this port's own mp3_alloc()/mp3_free(): the + # compile is src/audiomp3/mp3_buffers.c, which defines them and includes + # buffers.c. Not a set_source_files_properties() on buffers.c: that is + # scoped to this directory, and the ESP32 build compiles the linked copy of + # every usermod source from the project's directory, where it was lost + # (the buffers stayed static .bss, 23.8 kB of internal RAM). endif() # --- audiovorbis (VorbisDecoder) --- diff --git a/src/audiomp3/mp3_buffers.c b/src/audiomp3/mp3_buffers.c new file mode 100644 index 00000000..0b7c937a --- /dev/null +++ b/src/audiomp3/mp3_buffers.c @@ -0,0 +1,26 @@ +// Helix's buffers.c, compiled with this port's allocator. +// +// buffers.c takes its eight decoder buffers from MPDEC_ALLOCATOR(x) when that +// is defined, and from static arrays when it is not. The static arrays are +// 23,816 bytes of .bss, which on an ESP32-S3 is internal RAM the Wi-Fi, BLE +// and display drivers want. Defined, they come from the GC heap the first time +// an MP3Decoder is made, as in CircuitPython's own port, and each decoder gets +// buffers of its own. +// +// The macros used to be set with set_source_files_properties() in +// micropython.cmake. That property belongs to the directory that sets it, and +// the ESP32 build compiles every module source twice, once in the main +// component's directory and once more in the project's: the linked copy was +// the one without the flags. Defining the macros in a file of our own works +// the same in every build, whichever directory compiles it. buffers.c itself +// is not changed. +// +// SPDX-FileCopyrightText: Copyright (c) 2026 PyDevices +// SPDX-License-Identifier: MIT + +#include "audiomp3/mp3_alloc.h" + +#define MPDEC_ALLOCATOR(x) mp3_alloc(x) +#define MPDEC_FREE(x) mp3_free(x) + +#include "buffers.c"