From 9a47508d2d37fa8e3d73192bd94b2606d6f69759 Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Wed, 8 Apr 2026 17:19:20 +0200 Subject: [PATCH] fix: lower RMS normalization target from -23/-20 to -27 dBFS Training clips at -23 LUFS measure -25 to -31 dBFS RMS (avg ~-27). Normalizing output to -23 dBFS was 4-8 dB too loud, causing saturation on clips with high crest factor and peaks near 0 dBFS. Co-Authored-By: Claude Sonnet 4.6 --- nodes/selva_lora_trainer.py | 2 +- nodes/selva_sampler.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nodes/selva_lora_trainer.py b/nodes/selva_lora_trainer.py index 9bbb434..c763661 100644 --- a/nodes/selva_lora_trainer.py +++ b/nodes/selva_lora_trainer.py @@ -139,7 +139,7 @@ def _eval_sample(generator, feature_utils_orig, dataset, seq_cfg, device, dtype, elif audio.dim() == 3 and audio.shape[1] != 1: audio = audio.mean(dim=1, keepdim=True) - target_rms = 10 ** (-23.0 / 20.0) # -23 dBFS matches training data + target_rms = 10 ** (-27.0 / 20.0) # -27 dBFS matches measured RMS of training clips rms = audio.pow(2).mean().sqrt().clamp(min=1e-8) audio = audio * (target_rms / rms) peak = audio.abs().max().clamp(min=1e-8) diff --git a/nodes/selva_sampler.py b/nodes/selva_sampler.py index b9fe4be..cd9362a 100644 --- a/nodes/selva_sampler.py +++ b/nodes/selva_sampler.py @@ -36,8 +36,8 @@ class SelvaSampler: "tooltip": "Normalize output level. Uses RMS normalization to target_lufs rather than peak normalization, so level matches typical audio content.", }), "target_lufs": ("FLOAT", { - "default": -20.0, "min": -40.0, "max": -6.0, "step": 1.0, - "tooltip": "Target RMS level in dBFS when normalize=True. -20 matches typical processed audio. Increase toward -14 for louder output, decrease toward -30 for quieter.", + "default": -27.0, "min": -40.0, "max": -6.0, "step": 1.0, + "tooltip": "Target RMS level in dBFS when normalize=True. -27 matches the measured RMS of LUFS-normalized training clips. Increase toward -20 for louder output.", }), }, } @@ -49,7 +49,7 @@ class SelvaSampler: CATEGORY = SELVA_CATEGORY DESCRIPTION = "Generates audio from video features using SelVA's flow matching ODE. Supports text prompts and negative prompts via classifier-free guidance." - def generate(self, model, features, prompt, negative_prompt, duration, steps, cfg_strength, seed, normalize=True, target_lufs=-20.0): + def generate(self, model, features, prompt, negative_prompt, duration, steps, cfg_strength, seed, normalize=True, target_lufs=-27.0): import dataclasses from selva_core.model.flow_matching import FlowMatching