Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

native: bigger SOF buffer (20ms/80ms) + louder keepalive dither (±32)

Log analysis from obsidian-nebula-moss showed two remaining issues:
- XRUN + short write 96/480 frames — 10ms buffer too tight
- sdmode still cycling — ±1 dither @ S32_LE <<8 = -108 dBFS,
below the SOF silence detector threshold

Fixes:
- SOF period/buffer bumped from 10ms/40ms to 20ms/80ms. Reduces
XRUNs at high gain where short writes create audible glitches.
- Keepalive dither bumped from ±1 to ±32 int16 (~-72 dBFS at
S32_LE). Still inaudible but enough RMS to hold the DSP
pipeline active so the amp doesn't cycle on/off mid-playback.

Should fix the "fuzzy" sound quality user reported.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+20 -11
+20 -11
fedac/native/src/audio.c
··· 1505 1505 buffer[i * 2] = (int16_t)(mix_l * 32000); 1506 1506 buffer[i * 2 + 1] = (int16_t)(mix_r * 32000); 1507 1507 1508 - /* DAPM keepalive: inject ±1 LSB when the buffer would 1509 - * otherwise be all zeros. At S32_LE (after <<16) this 1510 - * becomes ±65536 ≈ -90 dBFS — utterly inaudible. 1511 - * Previous ±160 was audible as 24kHz fizz through the 1512 - * amp. ±1 is enough to prevent the SOF DSP silence 1513 - * detector from powering down the SSP1 BE DAI. */ 1508 + /* DAPM keepalive: inject dither when buffer would otherwise 1509 + * be all zeros. At S32_LE with <<8 shift, int16 dither X 1510 + * becomes X<<8 int32 = roughly X/128 % of full scale. The 1511 + * SOF DSP silence detector cuts around -80 dBFS, so we 1512 + * need the dither amplitude in int32 to land around 1513 + * -70 dBFS to reliably hold the amp alive. ±32 int16 1514 + * → ±8192 int32 ≈ -72 dBFS — still inaudible but enough 1515 + * RMS to keep the pipeline active. (±1 was -108 dBFS, 1516 + * below the silence threshold, which is why the amp 1517 + * kept cycling on/off producing "fuzzy" audio.) */ 1514 1518 if (buffer[i * 2] == 0 && buffer[i * 2 + 1] == 0) { 1515 - buffer[i * 2] = (i & 1) ? 1 : -1; 1516 - buffer[i * 2 + 1] = (i & 1) ? -1 : 1; 1519 + int16_t d = (i & 1) ? 32 : -32; 1520 + buffer[i * 2] = d; 1521 + buffer[i * 2 + 1] = -d; 1517 1522 } 1518 1523 1519 1524 // HDMI audio: 1-pole low-pass filter + downsample ··· 2059 2064 snd_pcm_uframes_t period; 2060 2065 snd_pcm_uframes_t buffer_size; 2061 2066 if (sof_active) { 2062 - period = rate / 100; // 10ms (480 frames at 48kHz) 2063 - buffer_size = period * 4; // 40ms total — SOF DAPM-friendly 2064 - fprintf(stderr, "[audio] SOF platform detected — period=%lu buffer=%lu (10ms/40ms)\n", 2067 + period = rate / 50; // 20ms (960 frames at 48kHz) 2068 + buffer_size = period * 4; // 80ms total — larger buffer 2069 + // reduces XRUN-induced "fuzzy" 2070 + // audio at high software gain. 2071 + // Previous 10ms/40ms produced 2072 + // 96/480-frame short writes. 2073 + fprintf(stderr, "[audio] SOF platform detected — period=%lu buffer=%lu (20ms/80ms)\n", 2065 2074 (unsigned long)period, (unsigned long)buffer_size); 2066 2075 } else { 2067 2076 period = rate / 1000; // 1ms on HDA-direct paths