Skip to content
RetrogamingDeep Dive Published Updated 3 min readViews unavailable

Audio Resampling in Emulators: Reconciling Console Clocks with Modern Sound Hardware

An engineering view of emulator audio clocks, sample generation, resampling, buffer control, drift, latency, time-stretching, and deterministic testing.

An emulated sound chip advances from the console’s master clock, while a host audio device consumes samples at a nominal rate such as 48 kHz according to a different physical clock. Video presentation adds a third schedule. Even if every nominal rate is configured correctly, small clock error and scheduling jitter will eventually underrun or overrun a fixed audio buffer unless the emulator reconciles them.

Generate from emulated time, not host callbacks

The audio-processing unit should be clocked by emulated CPU/APU cycles. Register writes take effect at precise emulated times, channels evolve, and the mixer produces samples or intermediate transitions. Tying chip advancement directly to unpredictable host callback intervals makes game speed and sound depend on operating-system scheduling.

A rational conversion tracks fractional phase between the emulated source rate and host output rate:

source_position += source_rate / output_rate
for each output sample:
    reconstruct source signal at source_position

Nearest-neighbor sampling is cheap and spectrally poor. Linear interpolation reduces steps but aliases high-frequency content. Band-limited converters use a low-pass reconstruction filter, often with polyphase tables, trading CPU time, latency, and stop-band quality. The selected converter should have measured frequency and impulse behavior rather than a name such as “high quality” with no test.

Buffer fill exposes clock disagreement

Place converted frames in a bounded ring buffer consumed by the audio device. Track its fill level and underrun/overrun counts. A static nominal ratio cannot absorb long-term drift between hardware clocks; the fill level will walk toward one edge.

A slow feedback controller can adjust the resampling ratio by a very small bounded amount to keep the buffer near a target. Smooth the measurement and correction so pitch does not flutter. Record the actual correction in parts per million and reset the controller after pause, device change, or discontinuity.

If video is the master clock, audio correction can preserve visual cadence. If audio is master, video frames may be duplicated/dropped or presentation timing adjusted. Synchronizing to an exact display refresh can speed or slow the entire emulation slightly. These policies are user-visible and should not be mixed unknowingly.

Time-stretching changes duration while trying to preserve pitch and can absorb larger dynamic mismatch, but it adds artifacts and latency. It is different from sample-rate conversion. Use it as an explicit synchronization mode, not as a hidden repair for an incorrect emulated clock.

Latency is a budget, not one number

Total latency includes emulated batching, resampler filter delay, ring-buffer target, host API buffering, device buffering, and wireless output. Shrinking only the ring buffer can increase crackles without materially changing end-to-end latency. Instrument each stage and measure on actual devices.

Pause and save-state transitions need discontinuity handling. Flush or crossfade stale buffered audio, restore emulated chip and resampler phase deterministically, and avoid playing pre-load samples after state load. Fast-forward and rewind need separate audio policy; feeding ordinary output faster is not synchronization.

Verify signal and system behavior

Use deterministic test tones, impulses, silence, and known register sequences. Compare sample hashes before host resampling, measure frequency response and DC offset, and run long-duration tests that expose drift. Then test real titles across 44.1/48/96 kHz devices, device switching, sleep/wake, CPU load, variable refresh, and capture.

Correct emulator audio preserves chip timing first, performs a documented conversion second, and uses bounded clock reconciliation last. Crackle is evidence to measure—never a reason to randomize latency and speed settings until it disappears.

Related:

Sources:

Comments