You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Oct 19, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Oct 19, 2026. It is now read-only.
I2SOut.starved() reads thousands of bytes on a clean P4 playback, and a gc.collect() makes it go down #26
On the ESP32-P4 panel (ESP32_GENERIC_P4 PRE_REV3_C6_WIFI, MicroPython 1.29), I2SOut.starved() doesn't work as an underrun count. Through audiodev's audio_out() I played a looping 1 kHz RawSample at 24 kHz, with no recorder open:
play alone 1 s: 9654
3 s: 9689
gc.collect() (4 ms): 510
after 3 more gc.collect(): 1536
stop, play again, 1 s later: 9658
Starved audio can't un-happen, so the count should never go down, and a clean playback should read 0. An acoustic recording of the same kind of playback (through the panel's microphones, with the change in #25) shows no dropout at all: no 2 ms window falls below half the median envelope in six seconds.
So the number moves, but it isn't measuring silence on the wire. My guess is the wall-clock witness (due = fed0 + elapsed × byte_rate) set against fed0, which is taken at the last armed write. I haven't confirmed that. Until it's fixed, the honest underrun witness on this board is the recording, or i2s_sink_bytes() − i2s_dma_bytes() sampled over time, which stays flat to within one descriptor when nothing starves.
Fixed by #27. starved() now counts two events in the DMA's interrupt: a descriptor started empty (on_send_q_ovf), and the DMA standing still for more than two descriptor periods. It no longer subtracts what the pump has fed from where the wire is, which also carried the ring's fill level. On the P4 panel it reads 0 through clean playback, gc.collect() and recording while playing, and a planted 200 ms audiopump.park() reads 15 360 bytes (160 ms) and stays there.
Activity
I2SOut.starved() counts silence as DMA events, so a clean playback re…
bdbarnett commentedon Oct 9, 2026
Fixed by #27.
starved()now counts two events in the DMA's interrupt: a descriptor started empty (on_send_q_ovf), and the DMA standing still for more than two descriptor periods. It no longer subtracts what the pump has fed from where the wire is, which also carried the ring's fill level. On the P4 panel it reads 0 through clean playback,gc.collect()and recording while playing, and a planted 200 msaudiopump.park()reads 15 360 bytes (160 ms) and stays there.