Skip to content

Hot Path Audio Attenuation Lookup

OpenAI Codex edited this page Nov 1, 2026 · 5 revisions

Audio Attenuation Lookup Table

Reviewed: November 1, 2026 · Source: b7140848
State: Performance - Researched: #193 measured and closed unmerged.
Release availability: Lookup candidate is absent from current main and v0.8.136-0-g458730bf5373 (September 30, 2026); current main retains powf().

The 4,096-entry attenuation-table experiment was built and measured. Its retained result did not justify landing it. This page records the mechanism, adverse evidence and reopening conditions so it is not mistaken for an untested opportunity or a delivered feature.

Current main

attenuate() masks a 12-bit volume and keeps the mute sentinel:

static float attenuate(uint16_t vol)
{
    vol &= 0xFFF;
    return (vol == 0xFFF) ? 0.0 :
           powf(10.0f, vol / (64.0 * -20.0f));
}

Voice mix-bin and monitor gains use this calculation. A small finite domain makes an exhaustive comparison possible, but does not establish that this math dominates a representative workload.

Retained #193 result

Reported metric Candidate change Interpretation
Guest cadence +0.70% Small observed increase; not a universal FPS gain
CPU usage −0.62% Small reported reduction
p99 interval +6.32% Worse tail latency

These are the reported changes in #193, not a new measurement of November main. They remain a mixed/negative result; the p99 loss must accompany the favorable rows. No fresh matched campaign was run for this documentation repair. The experiment is closed/unmerged and the current implementation still calls powf().

Experiment mechanism

Before (also current main):

flowchart LR
    A[Read attenuation] --> B[Mask to 12 bits]
    B --> C{0xFFF mute sentinel?}
    C -->|Yes| D[Zero gain]
    C -->|No| E[Evaluate reference powf expression]
    D --> F[Apply route / monitor gain]
    E --> F
Loading

Rejected candidate:

flowchart LR
    A[Initialize all 4096 reference values before workers] --> B[Immutable 16 KiB float table]
    C[Read attenuation and mask to 12 bits] --> D[Indexed gain load]
    B --> D
    D --> E[Existing route / monitor multiplication and mix]
Loading

The research sketch is not a current-main helper:

initialize table[value] from the unchanged reference expression
    for every value in 0..4095, including exactly-zero mute sentinel
publish the complete immutable table before starting voice workers
lookup table[volume & 0x0fff] during processing

Runtime generation can retain the active host expression/compiler/libm environment. Precomputed serialized constants or replacing division with a reciprocal introduces an additional numerical change and would require separate validation. The table changes xemu's computation of its current attenuation law; it is not a claim about the physical MCPX's internal implementation.

Correctness and ownership contract

All 4,096 values, masked high-bit inputs and the 0xFFF sentinel must match the maintained reference under the declared build/FPU policy. Keep gain application order and routing unchanged. The table must be fully initialized before workers read it, immutable afterward, and free of per-lookup locking. Filter/envelope progression, guest-control reads and mixing remain mandatory.

Risks include initialization races, different floating-point modes, libm/toolchain differences, cache locality, profiling overhead, and a locally cheaper operation with no useful game result. A temporary diagnostic toggle is not evidence that the final product needs another setting.

Reopening conditions

Reopen only with a concrete explanation for the prior tail cost or a new measured bottleneck where attenuation dominates. Count attenuation calls, routed bins and active voices; measure preparation cost, worker CPU, audio underruns and whole-game cadence/p95/p99. Compare matched Release builds at equal guest progress and disclose variation and losses alongside gains.

An exhaustive table test, output hashes across PCM/ADPCM, monitor/mute cases and many-voice workloads establish numerical coverage. They do not override a repeatable material game regression. Preserve the prior #193 record when evaluating a new candidate; do not benchmark repeatedly until a favorable run appears.

Source and related work

Clone this wiki locally