Step 7.4: HLS audio on AES67 (44.1 -> 48 kHz into the ring)
- decoder: s16 PCM -> stereo int32 -> esp_ae_rate_cvt 44.1 -> 48 kHz (32-bit, complexity 3; bypassed at 48 kHz; mono duplicated) -> ring. esp_audio_effects pinned to ~1.3.0 (1.4+ needs P4 rev >= 3). - hls: each segment is downloaded completely into PSRAM (max 4 MB), then decoded; the connection is not held open while the decoder waits for ring space at playback speed. - player: player_write() blocks while the ring is full and gives up when the source changes; the temporary 440 Hz producer is removed. - Verified with Triple J Hottest: 441344 -> 480375 frames (10.008 s) and 440320 -> 479260 (9.985 s) per segment; RTP 15000 packets, 0 gaps, peak -10 dBFS / RMS -22 dBFS; ring ~4.0 s, 0 underruns over ~50 s; heap 422 KB, PSRAM 27.5 MB free. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+13
-17
@@ -1,6 +1,5 @@
|
||||
#include "player.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aes67_cfg.h"
|
||||
@@ -72,24 +71,22 @@ void player_apply(const cJSON *source)
|
||||
ESP_LOGI(TAG, "source: %s", SRC_NAME[src]);
|
||||
}
|
||||
|
||||
/* ----- Step 7.1: temporary test producer (440 Hz into the ring), replaced by the HLS player ----- */
|
||||
|
||||
static void test_producer(void *arg)
|
||||
// Source side (HLS task): write converted 48 kHz frames, waiting for space at playback speed.
|
||||
// Gives up when the source is no longer HLS.
|
||||
size_t player_write(const int32_t *frames, size_t n)
|
||||
{
|
||||
static int32_t chunk[480 * CHANNELS];
|
||||
uint32_t phase = 0;
|
||||
const double amp = pow(10.0, -18.0 / 20.0) * 2147483647.0;
|
||||
while (1) {
|
||||
if (s_src != SRC_HLS || audio_ring_space() < 480) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
continue;
|
||||
size_t done = 0;
|
||||
while (done < n) {
|
||||
if (s_src != SRC_HLS) {
|
||||
return done;
|
||||
}
|
||||
for (int i = 0; i < 480; i++, phase++) {
|
||||
int32_t v = (int32_t)(amp * sin(2.0 * M_PI * 440.0 * (phase % RATE) / RATE));
|
||||
chunk[i * 2] = chunk[i * 2 + 1] = v;
|
||||
size_t w = audio_ring_write(frames + done * CHANNELS, n - done);
|
||||
if (!w) {
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
}
|
||||
audio_ring_write(chunk, 480);
|
||||
done += w;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
static void player_status(cJSON *st)
|
||||
@@ -113,12 +110,11 @@ esp_err_t player_init(void)
|
||||
s_src = (src_t)-1;
|
||||
player_apply(src);
|
||||
cJSON_Delete(src);
|
||||
xTaskCreate(test_producer, "test_prod", 3072, NULL, 5, NULL);
|
||||
err = decoder_init();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
err = hls_start(decoder_feed); // 7.3: decode and log; resampling + ring in 7.4
|
||||
err = hls_start(decoder_feed);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user