improve(c1): fade-out/hold/fade-in for FPS switch mute

Replace the hard-zero mute around the FPS on/off toggle with a linear fade-out, hold, fade-in (new C1_SWITCH_FADE_SAMPLES=512, ~10.7ms per edge, inside the 60ms window). Per-sample Q10 gain applied via 64-bit intermediate so there is no click at the mute boundaries; the hold still covers the FPS pipeline flush + refill.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Steven Dan
2026-06-22 20:53:25 +08:00
parent c61e5f4db5
commit c911160b0e
2 changed files with 23 additions and 6 deletions

View File

@@ -76,9 +76,9 @@ void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudi
}
#if C1_DFS_EN
/* Proactive output mute around FPS on/off: zeroes the playback path for
* ~C1_SWITCH_MUTE_SAMPLES after each toggle, masking the path-switch pop
* and the stale FPS data tail until the flushed pipeline refills. */
/* Smooth fade-out / hold / fade-in around the FPS on/off toggle: masks
* the path-switch pop and the stale FPS data tail without the click a
* hard zero would make at the mute edges. gain is 0..1024 (Q10), 1024 = unity. */
{
static unsigned sw_mute_samps = 0;
static unsigned prev_sw_mute = 0;
@@ -86,9 +86,20 @@ void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudi
GET_SHARED_GLOBAL(sw_mute, g_fps_switch_mute);
if (sw_mute)
{
if (!prev_sw_mute) sw_mute_samps = 0; /* re-armed: restart count */
sampsFromUsbToAudio[0] = 0;
sampsFromUsbToAudio[1] = 0;
unsigned n, gain;
int s0, s1;
if (!prev_sw_mute) sw_mute_samps = 0; /* re-armed: restart at fade-out */
n = sw_mute_samps;
if (n < C1_SWITCH_FADE_SAMPLES)
gain = 1024u - (n * 1024u / C1_SWITCH_FADE_SAMPLES); /* fade out: 1024 -> 0 */
else if (n >= C1_SWITCH_MUTE_SAMPLES - C1_SWITCH_FADE_SAMPLES)
gain = ((n - (C1_SWITCH_MUTE_SAMPLES - C1_SWITCH_FADE_SAMPLES)) * 1024u / C1_SWITCH_FADE_SAMPLES); /* fade in: 0 -> ~1024 */
else
gain = 0; /* hold */
s0 = (int)sampsFromUsbToAudio[0];
s1 = (int)sampsFromUsbToAudio[1];
sampsFromUsbToAudio[0] = (unsigned)(((long long)s0 * gain) >> 10);
sampsFromUsbToAudio[1] = (unsigned)(((long long)s1 * gain) >> 10);
if (++sw_mute_samps >= C1_SWITCH_MUTE_SAMPLES)
{
SET_SHARED_GLOBAL(g_fps_switch_mute, 0);

View File

@@ -62,6 +62,12 @@
* pipeline flush + 1-frame refill. 2880 ~= 60 ms. */
#define C1_SWITCH_MUTE_SAMPLES 2880
/* Per-edge fade length (fade-out and fade-in each) inside the mute window, in
* audio samples (@ 48 kHz). The window fades out over this many samples, holds
* near-zero, then fades in -- avoids the click a hard mute makes at its edges.
* Must be <= C1_SWITCH_MUTE_SAMPLES/2. 512 ~= 10.7 ms. */
#define C1_SWITCH_FADE_SAMPLES 512
/* One-time enable of the tile[1] core divider output path. MUST run on tile[1]. */
void c1_tile1_clk_enable(void);