The audio format contract is verified on three boards across three ESP32 families. One property is not covered, and no board currently owned can cover it.
The gap
Every board whose audio has been heard declares native_channels=1:
| board |
transducer |
| ESP32-P4 |
ES8311 → one speaker |
| T-Embed |
MAX98357A → one speaker |
| QT Py + Audio BFF |
MAX98357A → one speaker (averages L+R in hardware) |
So every stereo test run so far would pass identically with the channels swapped. The BFF's power chord proved both channels arrive and stay distinct — which rules out a dropped channel — but an average cannot distinguish left from right.
Also uncovered: native_channels=2 has never run on hardware, and neither has adapt_channels in the 1→2 (expansion) direction.
Why it is still open
- A PCM5102A module was wired up for exactly this and never produced sound. Clocks proven on the same pins, jumpers confirmed correct (FLT/DEMP low, XSMT high, FMT low), powered, tried at 32fs and 64fs, all six pin permutations, and finally moved from 3V3 to 5V for the LDO dropout. Brad's call: the module is suspect, set aside. He prefers prewired boards so the human element is out of it.
- An Arduino GIGA R1 WiFi is available and would give true stereo — but its 3.5 mm jack is driven by the STM32H747's internal DACs (
DAC0=PA4, DAC1=PA5), not I2S, and machine.I2S is not compiled for ARDUINO_GIGA at all (only PYBV10/PYBV11/PYBD_SF2 define MICROPY_HW_I2S*).
What would close it
A pyb.DAC transport for audiodev — a PCMOutput over the STM32's analog DACs. It would close this gap and do something more valuable besides: prove the contract is not quietly shaped around I2S, since every MCU transport today is I2S. Fourth chip family, genuinely different peripheral.
Not free: it needs 16-bit-signed → 12-bit-unsigned conversion per sample, which is the same per-sample-cost problem measured for the channel remix (see audiodev/accel.py), and DMA playback via DAC.write_timed. Synchronising two DAC channels for interleaved stereo is the fiddly part.
Alternatively, any prewired board with a genuinely stereo output would close the narrow version of this in minutes.
Risk assessment: low. Channel order follows the standard interleave convention shared with CircuitPython. This is recorded so it is not mistaken for tested.
The audio format contract is verified on three boards across three ESP32 families. One property is not covered, and no board currently owned can cover it.
The gap
Every board whose audio has been heard declares
native_channels=1:So every stereo test run so far would pass identically with the channels swapped. The BFF's power chord proved both channels arrive and stay distinct — which rules out a dropped channel — but an average cannot distinguish left from right.
Also uncovered:
native_channels=2has never run on hardware, and neither hasadapt_channelsin the 1→2 (expansion) direction.Why it is still open
DAC0=PA4,DAC1=PA5), not I2S, andmachine.I2Sis not compiled forARDUINO_GIGAat all (only PYBV10/PYBV11/PYBD_SF2 defineMICROPY_HW_I2S*).What would close it
A
pyb.DACtransport for audiodev — aPCMOutputover the STM32's analog DACs. It would close this gap and do something more valuable besides: prove the contract is not quietly shaped around I2S, since every MCU transport today is I2S. Fourth chip family, genuinely different peripheral.Not free: it needs 16-bit-signed → 12-bit-unsigned conversion per sample, which is the same per-sample-cost problem measured for the channel remix (see
audiodev/accel.py), and DMA playback viaDAC.write_timed. Synchronising two DAC channels for interleaved stereo is the fiddly part.Alternatively, any prewired board with a genuinely stereo output would close the narrow version of this in minutes.
Risk assessment: low. Channel order follows the standard interleave convention shared with CircuitPython. This is recorded so it is not mistaken for tested.