Skip to main content

Technical — Decode and buffers

Prefetch

After open or seek, the decoder primes PrefetchMs of PCM (mode-dependent: 400 / 800 / 1400 ms). This reduces the chance that the first GO or a scrub finds an empty ring.

Ring sizing formula

RecommendedRingMs = clamp(
max(400, PrefetchMs * 2, TargetBufferMs * 3),
400,
10_000
)
ModePrefetchTargetRecommended ring
Prefer low latency40050max(400, 800, 150) → 800 ms
Balanced800100max(400, 1600, 300) → 1600 ms
Prefer stability1400220max(400, 2800, 660) → 2800 ms

Fill loop mental model

loop:
if sdl_queued_ms < LowWaterMs:
mix frames from ring into sdl until ~TargetBufferMs queued
sleep / wait for callback cadence

If the ring cannot supply samples (decode too slow, disk stall, CPU spike), the SDL queue drains → underrun.

De-click ramp

On start/seek, a raised-cosine ramp of DeclickRampMs (0 disables) suppresses clicks from discontinuous PCM. This is orthogonal to fade-in duration on the component.

Waveform generation

Waveform peaks are generated asynchronously (MediaEngine single-flight jobs, limited concurrency) for UI only. They are stripped from undo snapshots and regenerated on demand after restore.

Failure modes

SymptomLikely stage
Silence, no errorNo device/patch; muted master; volume 0
Startup media failureFFmpeg natives missing
Crackles under loadTarget buffer too small; raise stability
Delay after GOLarge prefetch + large device buffer; or pre-wait
Seek clickDe-click 0 with discontinuous content