Dry/wet floor sums an undelayed dry copy with the delayed denoised path (comb filtering) #25

Closed
opened 2026-09-12 02:13:10 -04:00 by jared · 0 comments
Owner

Severity: low · Type: bug · Confidence: medium

Location: src/lotus/lotusDenoiseProcessor.ts:285-314

Problem

The floor mix routes source → dryGain → dest in parallel with source → worklet → … → wetGain → dest. The comment justifies this for "low-latency" models, but RNNoise is a framed algorithm (480-sample / 10 ms frames at 48 kHz) and the sapphi worklet adds its own ring-buffer delay, so the two paths are offset by at least one frame. Summing them produces comb filtering with notches spaced by the inverse of that delay — a hollow/phasey colouration on voice, which is the same family of artefact ("robotic/underwater") the floor was added to fix. At floor = 0.15 the notches are shallow (~-1.4 dB), so it is a quality regression rather than a breakage, but it partially cancels the intended benefit.

How to trigger

A/B lotusDenoiseFloor=0 vs the default 0.15 on RNNoise with a steady tone; the floored version shows periodic nulls in the spectrum.

Suggested fix

Insert a DelayNode on the dry path matched to the model's algorithmic latency (measurable once, per model), or replace the parallel dry mix with a post-worklet noise-floor generator.


Filed from the September 2026 audit (branch lotus).

**Severity:** low · **Type:** bug · **Confidence:** medium **Location:** `src/lotus/lotusDenoiseProcessor.ts:285-314` ### Problem The floor mix routes `source → dryGain → dest` in parallel with `source → worklet → … → wetGain → dest`. The comment justifies this for "low-latency" models, but RNNoise is a framed algorithm (480-sample / 10 ms frames at 48 kHz) and the sapphi worklet adds its own ring-buffer delay, so the two paths are offset by at least one frame. Summing them produces comb filtering with notches spaced by the inverse of that delay — a hollow/phasey colouration on voice, which is the same family of artefact ("robotic/underwater") the floor was added to fix. At `floor = 0.15` the notches are shallow (~-1.4 dB), so it is a quality regression rather than a breakage, but it partially cancels the intended benefit. ### How to trigger A/B `lotusDenoiseFloor=0` vs the default `0.15` on RNNoise with a steady tone; the floored version shows periodic nulls in the spectrum. ### Suggested fix Insert a `DelayNode` on the dry path matched to the model's algorithmic latency (measurable once, per model), or replace the parallel dry mix with a post-worklet noise-floor generator. --- _Filed from the September 2026 audit (branch `lotus`)._
jared added this to the EC fork audit 2026-09 · Medium & Low milestone 2026-09-12 02:13:10 -04:00
jared added the bugpriority: lowarea: denoise labels 2026-09-12 02:13:10 -04:00
jared self-assigned this 2026-09-12 02:13:10 -04:00
jared closed this issue 2026-09-13 01:22:46 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/element-call#25