Skip to content

fix: eliminate full-volume transient on keepalive oscillator start#231

Open
DasAmpharos wants to merge 1 commit into
mainfrom
fix/keepalive-gain-transient
Open

fix: eliminate full-volume transient on keepalive oscillator start#231
DasAmpharos wants to merge 1 commit into
mainfrom
fix/keepalive-gain-transient

Conversation

@DasAmpharos
Copy link
Copy Markdown
Owner

Problem

Fixes #229

When starting the timer, users occasionally heard a loud clipping sound. This happened ~50% of the time due to a race condition introduced in #227.

Root Cause

In startKeepAlive(), the keepalive GainNode is created with a default gain of 1.0. The line:

keepAliveGain.gain.value = 1e-5;

is equivalent to setValueAtTime(1e-5, audioCtx.currentTime). The Web Audio API processes audio in 128-sample rendering quanta (~2.9ms at 44.1kHz). If currentTime is at or near a quantum boundary when this runs, the gain change may not take effect until the next quantum.

Meanwhile, keepAliveOsc.start() starts the oscillator immediately (at time 0). For that one-quantum window, the oscillator outputs at the default gain of 1.0 (full volume, 440 Hz), producing an audible transient that clips audio systems near their limits.

The ~50% probability matches the chance that JS execution falls near a quantum boundary when currentTime is read.

Fix

Schedule the gain at t=0 instead:

keepAliveGain.gain.setValueAtTime(1e-5, 0);

t=0 is always in the past relative to any rendering quantum. The Web Audio API spec guarantees that a setValueAtTime event at t=0 is applied from the very first quantum the node renders, eliminating the race entirely.

The GainNode default gain is 1.0. Setting gain.value = 1e-5 is equivalent
to setValueAtTime(1e-5, currentTime), which may not take effect until the
next rendering quantum (~2.9ms). During that window the oscillator outputs
at gain=1.0, producing an intermittent loud clip that users hear when the
timer is started.

Fix by scheduling the gain at t=0 (setValueAtTime(1e-5, 0)), which is
always in the past. The Web Audio API spec guarantees this event is applied
from the very first quantum the node renders, eliminating the race entirely.

Fixes #229

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

🚀 Preview deployment

https://dasampharos.github.io/EonTimer-dev/pr-231/

Updated on every push to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Audio clipping when starting the timer

1 participant