Pink noise as a source (mode "pink")
Core: aes67_tx_pink_noise(), a ready-made TX source: xorshift32 white noise through Paul Kellet's pink filter, -18 dBFS RMS (peaks about -6 dBFS), same on L and R. The player uses it like the tone (straight to TX, no volume or gain). Checked on the board: -18 dBFS RMS, octave bands 63 Hz-4 kHz flat within +-0.4 dB, L = R. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+17
-9
@@ -27,9 +27,9 @@
|
||||
|
||||
static const char *TAG = "player";
|
||||
|
||||
typedef enum { MODE_TONE, MODE_OFF, MODE_HLS, MODE_SPOTIFY, MODE_AUTO } mode_t_;
|
||||
static const char *const SRC_NAME[] = { "tone", "off", "hls", "spotify" };
|
||||
static const char *const MODE_NAME[] = { "tone", "off", "hls", "spotify", "auto" };
|
||||
typedef enum { MODE_TONE, MODE_OFF, MODE_HLS, MODE_SPOTIFY, MODE_AUTO, MODE_PINK } mode_t_;
|
||||
static const char *const SRC_NAME[] = { "tone", "off", "hls", "spotify", "pink" };
|
||||
static const char *const MODE_NAME[] = { "tone", "off", "hls", "spotify", "auto", "pink" };
|
||||
|
||||
static volatile mode_t_ s_mode = MODE_OFF;
|
||||
static volatile player_src_t s_src = PLAYER_SRC_OFF; // what is playing now
|
||||
@@ -110,7 +110,7 @@ static void apply_fade(int32_t *buf, size_t frames, int *left, bool in)
|
||||
static mode_t_ mode_of(const char *m)
|
||||
{
|
||||
return !strcmp(m, "tone") ? MODE_TONE : !strcmp(m, "hls") ? MODE_HLS : !strcmp(m, "spotify") ? MODE_SPOTIFY :
|
||||
!strcmp(m, "auto") ? MODE_AUTO : MODE_OFF;
|
||||
!strcmp(m, "auto") ? MODE_AUTO : !strcmp(m, "pink") ? MODE_PINK : MODE_OFF;
|
||||
}
|
||||
|
||||
/* ----- output (AES67 TX pull callback, TX task, must not block) ----- */
|
||||
@@ -168,8 +168,14 @@ static size_t player_read(int32_t *buf, size_t frames)
|
||||
return got;
|
||||
}
|
||||
|
||||
// Set the source to play. Tone comes from TX itself (phase-locked to PTP), so switches from/to it
|
||||
// are immediate; everything else fades through player_read.
|
||||
// Test signals: straight from the core to TX, not through the ring, volume or gain.
|
||||
static bool is_test_signal(player_src_t src)
|
||||
{
|
||||
return src == PLAYER_SRC_TONE || src == PLAYER_SRC_PINK;
|
||||
}
|
||||
|
||||
// Set the source to play. Test signals come from the core (the tone phase-locked to PTP), so
|
||||
// switches from/to them are immediate; everything else fades through player_read.
|
||||
static void select_source(player_src_t src)
|
||||
{
|
||||
if (src == s_target) {
|
||||
@@ -180,10 +186,11 @@ static void select_source(player_src_t src)
|
||||
s_hls_paused = false;
|
||||
hls_suspend(HLS_SUSPEND_USER, false);
|
||||
}
|
||||
if (src == PLAYER_SRC_TONE || s_src == PLAYER_SRC_TONE) {
|
||||
if (is_test_signal(src) || is_test_signal(s_src)) {
|
||||
s_target = s_src = src;
|
||||
s_flush = true;
|
||||
aes67_tx_set_source(src == PLAYER_SRC_TONE ? NULL : player_read);
|
||||
aes67_tx_set_source(src == PLAYER_SRC_TONE ? NULL : src == PLAYER_SRC_PINK ? aes67_tx_pink_noise :
|
||||
player_read);
|
||||
return;
|
||||
}
|
||||
s_target = src; // player_read fades out and switches
|
||||
@@ -213,6 +220,7 @@ static void apply_mode(void)
|
||||
hls_suspend(HLS_SUSPEND_FAILOVER, mode == MODE_AUTO);
|
||||
switch (mode) {
|
||||
case MODE_TONE: select_source(PLAYER_SRC_TONE); break;
|
||||
case MODE_PINK: select_source(PLAYER_SRC_PINK); break;
|
||||
case MODE_HLS: select_source(PLAYER_SRC_HLS); break;
|
||||
case MODE_SPOTIFY: select_source(PLAYER_SRC_SPOTIFY); break;
|
||||
case MODE_AUTO: select_source(PLAYER_SRC_SPOTIFY); break; // Spotify inactive: HLS after the delay
|
||||
@@ -369,7 +377,7 @@ static void on_ota(bool starting)
|
||||
|
||||
static const char *source_state(player_src_t src)
|
||||
{
|
||||
return src == PLAYER_SRC_TONE ? "playing" : src == PLAYER_SRC_OFF ? "idle" :
|
||||
return is_test_signal(src) ? "playing" : src == PLAYER_SRC_OFF ? "idle" :
|
||||
src == PLAYER_SRC_SPOTIFY && !spotify_session_active() ? "idle" :
|
||||
src == PLAYER_SRC_SPOTIFY && s_paused ? "paused" :
|
||||
src == PLAYER_SRC_HLS && s_hls_paused ? "paused" : s_playing ? "playing" : "buffering";
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// Project player: picks the audio source for AES67 TX (test tone, silence, HLS, Spotify).
|
||||
// Project player: picks the audio source for AES67 TX (test tone, pink noise, silence, HLS, Spotify).
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "cJSON.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef enum { PLAYER_SRC_TONE, PLAYER_SRC_OFF, PLAYER_SRC_HLS, PLAYER_SRC_SPOTIFY } player_src_t;
|
||||
typedef enum { PLAYER_SRC_TONE, PLAYER_SRC_OFF, PLAYER_SRC_HLS, PLAYER_SRC_SPOTIFY, PLAYER_SRC_PINK } player_src_t;
|
||||
|
||||
esp_err_t player_init(void);
|
||||
// Apply the "source" config group (mode etc.).
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ static const char SOURCE_DEFAULTS[] =
|
||||
|
||||
static bool source_validate(const cJSON *g, char *err, size_t n)
|
||||
{
|
||||
static const char *const modes[] = { "spotify", "hls", "auto", "tone", "off", NULL };
|
||||
static const char *const modes[] = { "spotify", "hls", "auto", "tone", "pink", "off", NULL };
|
||||
static const double bitrates[] = { 96, 160, 320 };
|
||||
return cfg_check_enum(g, "mode", modes, err, n) &&
|
||||
cfg_check_str(g, "spotify_name", 1, 63, err, n) &&
|
||||
|
||||
Reference in New Issue
Block a user