writeFrame() called i2s_channel_write() once per decoded PCM sample (up to
1152 separate driver calls per MP3 frame), each with its own locking/DMA
bookkeeping overhead. Now accumulates a whole frame into one buffer and
writes it in a single call.
The I2S TX channel also used the ESP-IDF default DMA config (6 descriptors
x 240 frames = ~30 ms of buffering at 48 kHz), leaving almost no headroom
against network jitter in this single-task fetch+decode+play pipeline.
Widened to 12 x 480 (~120 ms) so a brief HTTP stall doesn't immediately
starve the DMA and audibly crackle.
Both are static/architectural fixes verified by build only — not confirmed
live yet (board disconnected this session).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0178rASQ6ZETPMUamvpoR2KR