From 00596f39cdb5dc4de4262ac58f5db7329c8642ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Saillant?= Date: Mon, 15 Jun 2026 10:02:12 +0200 Subject: [PATCH] fix(box): radio sound + add SuperLoustic station MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Webradio was silent: the streams are stereo 44.1 kHz MP3, and opening the ES8311 codec in stereo failed ("i2s_std_set_slot: dma descriptor") because the stereo I2S DMA no longer fits the tight internal RAM — the podcast path works only because its files are mono. Downmix the decoded stereo PCM to mono and open the codec at one channel. Also switch the stream URLs to plain HTTP: the HTTPS handshake intermittently failed to allocate AES memory, and these mounts serve identical audio over http with no redirect. Add SuperLoustic (3 stations). --- main/audio/radio_pipeline.c | 28 ++++++++++++++++++++-------- main/modes/radio.c | 9 +++++++-- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/main/audio/radio_pipeline.c b/main/audio/radio_pipeline.c index 8d2d43e..3ee0a32 100644 --- a/main/audio/radio_pipeline.c +++ b/main/audio/radio_pipeline.c @@ -178,6 +178,7 @@ static void decode_task(void *arg) uint32_t out_cap = DEC_OUT_CAP_INIT; uint8_t *out = malloc(out_cap); bool codec_open = false; + int dec_ch = 1; // channels reported by the stream (1 or 2) if (!inbuf || !out || !codec) { ESP_LOGE(TAG, "decode buffers/codec unavailable"); @@ -225,19 +226,21 @@ static void decode_task(void *arg) } if (frame.decoded_size > 0) { if (!codec_open) { - // Open the codec at the rate/channels reported by the stream - // on the first decoded PCM, exactly like aac_player.c. esp_audio_simple_dec_info_t info = {0}; esp_audio_simple_dec_get_info(dec, &info); - ESP_LOGI(TAG, "MP3 %" PRIu32 " Hz %u ch %u bit", + dec_ch = (info.channel >= 2) ? 2 : 1; + ESP_LOGI(TAG, "MP3 %" PRIu32 " Hz %u ch %u bit -> codec mono", info.sample_rate, info.channel, info.bits_per_sample); - lisael_udp_send("RADIO: decoded MP3 %" PRIu32 " Hz %u ch %u bit -> opening codec", - info.sample_rate, info.channel, info.bits_per_sample); + // Open the codec in MONO regardless of the stream: a stereo + // 44.1 kHz I2S slot needs more internal DMA RAM than is free + // (it fails "i2s_std_set_slot: dma descriptor"). The podcast + // path works precisely because its files are mono. We downmix + // stereo PCM below before writing. esp_codec_dev_close(codec); esp_codec_dev_sample_info_t fs = { .bits_per_sample = info.bits_per_sample, - .channel = info.channel, + .channel = 1, .sample_rate = info.sample_rate, }; esp_codec_dev_open(codec, &fs); @@ -245,8 +248,17 @@ static void decode_task(void *arg) (float)lisael_audio_get_volume()); codec_open = true; } - // Blocking write — this is what paces the whole pipeline. - esp_codec_dev_write(codec, frame.buffer, frame.decoded_size); + if (dec_ch == 2) { + // Downmix interleaved 16-bit stereo to mono, in place. + int16_t *pcm = (int16_t *)frame.buffer; + int frames = (int)(frame.decoded_size / 4); // 4 bytes/stereo frame + for (int i = 0; i < frames; i++) { + pcm[i] = (int16_t)(((int)pcm[2 * i] + (int)pcm[2 * i + 1]) / 2); + } + esp_codec_dev_write(codec, frame.buffer, frames * 2); + } else { + esp_codec_dev_write(codec, frame.buffer, frame.decoded_size); + } } if (raw.consumed == 0 && frame.decoded_size == 0) { break; // no progress on this chunk; fetch more from the network diff --git a/main/modes/radio.c b/main/modes/radio.c index f202ded..05a8dfd 100644 --- a/main/modes/radio.c +++ b/main/modes/radio.c @@ -38,9 +38,14 @@ typedef struct { // listen.radioking.com mounts. static const radio_station_t k_stations[] = { // Radio Doudou — comptines & berceuses pour les tout-petits. - { "Radio Doudou", "https://listen.radioking.com/radio/11565/stream/22961" }, + // Plain HTTP on purpose: the box's internal RAM is too tight to also run the + // mbedtls/AES handshake while streaming (TLS failed "esp-aes: alloc"). These + // RadioKing mounts serve identical audio over http:// (no 3xx to https). + { "Radio Doudou", "http://listen.radioking.com/radio/11565/stream/22961" }, // Radio Pomme d'Api (Bayard) — la radio des 3-7 ans. - { "Pomme d'Api", "https://listen.radioking.com/radio/361753/stream/411352" }, + { "Pomme d'Api", "http://listen.radioking.com/radio/361753/stream/411352" }, + // SuperLoustic — la radio des enfants (chansons, génériques, histoires). + { "SuperLoustic", "http://radio6.pro-fhi.net/radio/9004/stream" }, }; #define K_STATIONS_COUNT ((int)(sizeof(k_stations) / sizeof(k_stations[0])))