"""Pont audio → animation : calcule un niveau de volume normalisé. Unité pure (numpy seulement) — aucune dépendance matérielle, testable sans micro. """ import numpy as np def compute_rms(frames): """Niveau RMS d'un bloc audio float32, normalisé et borné dans [0.0, 1.0]. frames : tableau numpy 1-D d'échantillons float32 (typiquement dans [-1, 1]). Retourne 0.0 pour un bloc vide ou silencieux. """ if frames.size == 0: return 0.0 rms = float(np.sqrt(np.mean(np.square(frames, dtype="float64")))) return min(1.0, max(0.0, rms)) def shape_level(rms, gain): """Met en forme un niveau RMS brut pour l'animation : amplifie et borne dans [0, 1]. Les RMS vocaux sont faibles (~0.02–0.15) ; appliqués tels quels, le cercle bouge à peine. On applique un gain puis une courbe en racine carrée : les niveaux faibles sont boostés (forte réactivité à voix normale) tout en restant bornés à 1.0 (pas de saturation visuelle). gain=0 → toujours 0 (aucune réaction). """ boosted = max(0.0, rms) * gain shaped = boosted ** 0.5 return min(1.0, max(0.0, shaped))