Conectar un nodo a un AudioParam SUMA a su automatizacion; no la escala. El modulador de AM colgaba de `envelope.gain`, asi que su profundidad se mantenia CONSTANTE mientras la envolvente se movia: el tremolo ni crecia con el ataque ni moria con la caida, y alli donde la automatizacion bajaba de la profundidad el parametro CRUZABA CERO — modulacion en anillo, no tremolo. MEDIDO con render offline del grafo real, viejo contra nuevo: caso cuerpo RMS cola PICO corte A commit neutral (control) 0.242 -> 0.242 0.149 -> 0.149 0.0002 (igual) B signal neutral 0.332 -> 0.275 0.145 -> 0.088 0.0666 -> 0.0002 C commit + risk 0.243 -> 0.200 0.263 -> 0.103 ~0 D commit.subtle + threat 0.143 -> 0.018 0.333 -> 0.009 ~0 - B: el clic del cierre de cada aviso/error desaparece (x333 menos amplitud en el corte). Era el tick audible al final de TODOS los earcons de `signal`. - C: la cola dejaba +76% de pico sobre el control; ahora muere por debajo, que es lo que una cola debe hacer. El sustain no se toca (ahi el tremolo ES el percepto de rugosidad buscado). - D: el caso grave. `commit.subtle` (gain 0.03) cargado con `threat` (roughness 0.5) salia a RMS 0.143 — SIETE VECES su nivel declarado, con inversiones de polaridad. Ahora sale a 0.018, su nivel de diseño. Escenario real: un item de menu destructivo con intent="threat". - A: el control sin AM no se mueve ni un digito. El fix no toca lo que no debe. LA FORMA. Etapa de ganancia en serie entre el filtro y la envolvente, con valor base `1 - depth` y el modulador sobre su propio `.gain`: el factor es `(1 - depth) + depth*sin`, que hace pico en 1 —el tremolo nunca ANADE nivel— y multiplica la envolvente, asi que silencio por cualquier cosa es silencio. `depth` clampeada a 0.5 para que `1 - 2*depth >= 0`: invertir polaridad es otro efecto. Y deja de escalarse por `gainScale`: siendo un ratio ya es relativa por construccion, que es justo lo que el comentario viejo perseguia a mano («scaling both keeps the timbre and only moves the volume»). CONTRAPARTIDA DECLARADA: los earcons con rugosidad bajan 1.6-2.7 dB de nivel medio (B: -1.6 dB de cuerpo, -2.7 dB de pico), porque el AM ya no suma nivel. Es correccion, no perdida — pero es un cambio perceptual real en la familia `signal` y en todo `risk`/`threat`. Si el autor quiere recalibrar los gains base, es una decision de catalogo aparte. GUARD. `engine-sound.test.ts` sustituye el test que fijaba la propiedad vieja (la profundidad escalada por gainScale) por el que fija la invariante que de verdad importa: NADA puede conectarse al AudioParam de la envolvente, y la etapa en serie vale `1 - depth`. Verificado en ROJO (al reconectar el modulador a `envelope.gain` falla con su mensaje). El fallo colateral que aparecio al hacerlo —el test de la voz desconocida avisando dos veces— era cascada: al fallar el assert no corre `dispose()`, el AudioContext queda vivo y el siguiente test recibe el aviso de «segundo contexto». Doctrina: `sema.md` (sintesis) y `arts/sound/README.md` (voces) describen ahora la etapa en serie y por que nunca se parchea un modulador sobre `envelope.gain`. VERIFICADO: sonido + sema 244/244 · check 76 = base 75 + 1 del fichero huerfano `__adv-verify-haptic-dead.test.ts` (sin trackear, sin borrar sin instruccion) · docs:check 0/616 · el dev server sirve el fix (comprobado por fetch del modulo) · prettier: los dos ficheros eran limpios en HEAD y quedan limpios. Cierra el hallazgo S-06 de AUDIT-sema-2026-08-05. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>alpha-0.1-dir-prefs
parent
24d30ee1a8
commit
316452263f
Loading…
Reference in new issue