<!-- canonical: https://jmrplens.github.io/phonometry/es/guides/psychoacoustic-annoyance/ -->
Source: https://jmrplens.github.io/phonometry/es/guides/psychoacoustic-annoyance/

Lo *molesto* que resulta un sonido depende de algo más que de su sonoridad.
Fastl y Zwicker, *Psychoacoustics: Facts and Models*, combinan cuatro
sensaciones psicoacústicas (**sonoridad**, **nitidez**, **aspereza** e
**intensidad de fluctuación**) en una única **molestia psicoacústica** `PA`, un
escalar que crece con la sonoridad y se eleva aún más cuando el sonido es agudo,
áspero o fluctúa lentamente. Esta página cubre el modelo exacto de `PA`
(Ecs 16.2–16.4), la **intensidad de fluctuación** que consume, tanto la forma
cerrada para ruido de banda ancha modulado en amplitud (Ec. 10.2) como el modelo
de señal de Osses et al. (2016), y la utilidad que deriva las cuatro sensaciones
a partir de una grabación.

<details>
<summary>Mostrar el código de esta figura</summary>

```python

from phonometry import psychoacoustics

n5 = np.linspace(4.0, 60.0, 200)
profiles = [
    ("Base neutra: S = 1.75 acum, F = R = 0", 1.75, 0.0, 0.0),
    ("Sonido agudo: S = 3.5 acum", 3.5, 0.0, 0.0),
    ("Áspero + fluctuante: F = 1.2 vacil, R = 0.7 asper", 2.0, 1.2, 0.7),
]
fig, ax = plt.subplots()
for label, s, f, r in profiles:
    pa = [psychoacoustics.psychoacoustic_annoyance(v, s, f, r).annoyance for v in n5]
    ax.plot(n5, pa, label=label)

ex = psychoacoustics.psychoacoustic_annoyance(30.0, 2.0, 0.5, 0.3)
ax.plot([30.0], [ex.annoyance], "o", label=f"Ejemplo resuelto (PA = {ex.annoyance:.2f})")
ax.set_xlabel("Sonoridad percentil N5 [sonios]")
ax.set_ylabel("Molestia psicoacústica PA")
ax.legend()
plt.show()
```

</details>

## 1. Las cuatro sensaciones

La molestia psicoacústica se apoya en cuatro sensaciones auditivas, cada una con
su propio modelo y unidad en la biblioteca:

- **Sonoridad**: la sonoridad percentil `N5` (la sonoridad superada el 5 % del
  tiempo), en **sonios**, del modelo Zwicker variable en el tiempo de la ISO
  532-1 (`loudness_zwicker`, véase [Sonoridad](/phonometry/es/guides/loudness/)).
- **Nitidez** `S`, en **acum**: el balance espectral hacia las altas
  frecuencias, DIN 45692 (`sharpness_din`).
- **Aspereza** `R`, en **asper**: la dureza de la modulación de amplitud rápida
  (~70 Hz), modelo de Sottek ECMA-418-2 (`roughness_ecma`).
- **Intensidad de fluctuación** `F`, en **vacil**: la sensación de fluctuación
  lenta (~4 Hz) de la sonoridad (§3 más abajo).

## 2. Molestia psicoacústica (Ecs 16.2–16.4)

El modelo exacto (Fastl y Zwicker Ec. 16.2; origen Widmann 1992) escala `N5` por
un factor que crece con la ponderación de nitidez `wS` y la ponderación combinada
de aspereza/fluctuación `wFR`:

$$
PA = N_5\left(1 + \sqrt{w_S^2 + w_{FR}^2}\right), \qquad
w_S = (S - 1{,}75)\,0{,}25\,\lg(N_5 + 10)\ \ (S > 1{,}75\ \mathrm{acum}), \qquad
w_{FR} = \frac{2{,}18}{N_5^{0{,}4}}\,(0{,}4\,F + 0{,}6\,R).
$$

`wS` es cero para `S ≤ 1,75 acum` (la nitidez solo añade molestia por encima de
ese umbral); `wFR` pondera la aspereza con más peso que la intensidad de
fluctuación (0,6 frente a 0,4). `psychoacoustic_annoyance` toma las cuatro
magnitudes directamente y devuelve la molestia junto con las dos ponderaciones
intermedias:

```python
from phonometry import psychoacoustics

res = psychoacoustics.psychoacoustic_annoyance(30.0, 2.0, 0.5, 0.3)   # N5, S, F, R
print(round(res.annoyance, 4))   # 37.0478
print(round(res.w_s, 4), round(res.w_fr, 4))   # 0.1001 0.2125

res.plot()   # PA junto a sus ponderaciones wS y wFR (necesita matplotlib)
```

La figura de arriba barre `PA` frente a `N5` para tres perfiles: una base neutra
(`S = 1,75 acum`, `F = R = 0`, de modo que `PA = N5`), un sonido agudo y un
sonido áspero y fluctuante, ambos elevados sobre la base, con el ejemplo
resuelto marcado.

### 2.1 A partir de una señal (estimación de ingeniería)

`psychoacoustic_annoyance_from_signal` es una utilidad que deriva las cuatro
sensaciones a partir de una señal de presión calibrada y las combina: `N5` de la
sonoridad Zwicker variable en el tiempo de la ISO 532-1, `S` de la nitidez DIN
45692, `R` de la aspereza de Sottek ECMA-418-2 y `F` del modelo de señal de
intensidad de fluctuación.

```python
from phonometry import psychoacoustics

res = psychoacoustics.psychoacoustic_annoyance_from_signal(x, fs, field="free")
print(res.annoyance, res.n5, res.sharpness, res.roughness, res.fluctuation_strength)

res.plot()   # la misma vista PA / wS / wFR, ahora con las cuatro sensaciones derivadas
```

:::caution
**Advertencia sobre la mezcla de modelos.** Este compuesto mezcla familias de
modelos: `N5` y `S` de la familia Zwicker, `R` de Sottek y `F` de Osses. El
modelo `PA` se calibró con sensaciones de la familia Zwicker, así que trate la
utilidad de señal como una *estimación de ingeniería*. Para resultados exactos y
reproducibles, calcule las cuatro magnitudes con los modelos en los que confíe y
páselas directamente a `psychoacoustic_annoyance` (la función de cuatro
argumentos es el modelo exacto).
:::

## 3. Intensidad de fluctuación

La **intensidad de fluctuación** `F` (vacil) cuantifica la percepción de la
fluctuación *lenta* de la sonoridad. Como la aspereza, es una sensación de paso
de banda de la frecuencia de modulación, pero su máximo se sitúa aproximadamente
un orden de magnitud más abajo, en `fmod ≈ 4 Hz` en lugar del máximo de la
aspereza en ~70 Hz. Por definición, un tono de 1 kHz a 60 dB, modulado en
amplitud al 100 % a 4 Hz, produce `1 vacil`. Esta página cubre los modelos de
Fastl y Zwicker; la intensidad de fluctuación normativa del modelo de Sottek
(cláusula 9 de ECMA-418-2) está en
[Métricas de calidad sonora](/phonometry/es/guides/sound-quality/).

<details>
<summary>Mostrar el código de esta figura</summary>

```python

from phonometry import psychoacoustics

# Forma cerrada exacta (Ec. 10.2), ruido de banda ancha AM a 60 dB, modulación 100 %:
fmod = np.logspace(np.log10(0.5), np.log10(32.0), 240)
f_bbn = [psychoacoustics.fluctuation_strength_am_noise(60.0, 1.0, fm) for fm in fmod]

# Modelo de señal de Osses 2016 sobre un tono AM de 1 kHz / 70 dB en el mismo barrido:
fs = 48000
t = np.arange(int(2.0 * fs)) / fs
carrier = np.sin(2 * np.pi * 1000 * t)
fm_tone = [1.0, 2.0, 4.0, 8.0, 16.0, 32.0]
f_tone = []
for fm in fm_tone:
    am = (1.0 + np.sin(2 * np.pi * fm * t)) * carrier
    am = am / np.sqrt(np.mean(am ** 2)) * 2e-5 * 10 ** (70 / 20)
    f_tone.append(psychoacoustics.fluctuation_strength(am, float(fs)).fluctuation_strength)

fig, ax = plt.subplots()
ax.semilogx(fmod, f_bbn, label="Ruido de banda ancha AM (forma cerrada)")
ax2 = ax.twinx()
ax2.plot(fm_tone, f_tone, "s--", color="tab:green", label="Tono AM (modelo de señal)")
ax.axvline(4.0, ls="--", color="0.4")
ax.set_xlabel("Frecuencia de modulación f_mod [Hz]")
ax.set_ylabel("Intensidad de fluctuación F [vacil]")
h1, l1 = ax.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax.legend(h1 + h2, l1 + l2, loc="upper right")
plt.show()
```

</details>

### 3.1 Forma cerrada para ruido de banda ancha AM (Ec. 10.2)

Para ruido de banda ancha modulado sinusoidalmente en amplitud, Fastl y Zwicker
dan una forma cerrada (Ec. 10.2) en función del factor de modulación `m`, el
nivel `L` y la frecuencia de modulación `fmod`:

$$
F = \frac{5{,}8\,(1{,}25\,m - 0{,}25)\,[0{,}05\,(L/\mathrm{dB}) - 1]}
{(f_{mod}/5\,\mathrm{Hz})^2 + (4\,\mathrm{Hz}/f_{mod}) + 1{,}5}\ \ \mathrm{vacil}.
$$

El denominador es el paso de banda a `4 Hz`: alcanza su mínimo cerca de
`fmod ≈ 3,7 Hz` y crece a ambos lados. El resultado se limita a `0` (la sensación
desaparece por debajo de ~20 dB o `m < 0,2`). Esta forma exacta es el valor a
citar para el ruido de banda ancha AM.

```python
from phonometry import psychoacoustics

print(round(psychoacoustics.fluctuation_strength_am_noise(60.0, 1.0, 4.0), 4))   # 3.6943 vacil
```

### 3.2 El modelo de señal de Osses 2016

`fluctuation_strength` implementa el modelo de señal de Osses et al. (2016):
construye un patrón de excitación sobre 47 filtros auditivos, extrae la
modulación de envolvente de `~4 Hz` por banda, la pondera y la combina, y devuelve
la `F` global (vacil) junto con la intensidad de fluctuación específica sobre el
eje de Bark y la traza dependiente del tiempo.

```python
from phonometry import psychoacoustics

res = psychoacoustics.fluctuation_strength(x, fs)
print(res.fluctuation_strength)   # vacil
res.plot()   # intensidad de fluctuación específica F′(z) sobre el eje de Bark (requiere matplotlib)
```

<details>
<summary>Mostrar el código de esta figura</summary>

```python

from phonometry import psychoacoustics

# El estímulo tipo referencia: un tono de 1 kHz a 70 dB SPL, modulado en
# amplitud al 100 % a 4 Hz, donde la sensación es máxima.
fs = 48000
t = np.arange(int(2.0 * fs)) / fs
am = (1.0 + np.sin(2 * np.pi * 4.0 * t)) * np.sin(2 * np.pi * 1000 * t)
am = am / np.sqrt(np.mean(am ** 2)) * 2e-5 * 10 ** (70 / 20)
res = psychoacoustics.fluctuation_strength(am, float(fs))
print(round(res.fluctuation_strength, 2))    # 1.09 vacil

# En una línea: la intensidad de fluctuación específica sobre el eje de Bark.
res.plot(language="es")
plt.show()

# O dibuja f'(z) a mano con los arrays que ya lleva el resultado:
fig, ax = plt.subplots()
ax.fill_between(res.bark_axis, res.specific, alpha=0.3)
ax.plot(res.bark_axis, res.specific)
ax.set_xlabel("Razón de banda crítica z [Bark]")
ax.set_ylabel("Intensidad de fluctuación específica [vacil/Bark]")
plt.show()
```

</details>

La sensación se queda donde está la energía modulada, en las bandas críticas
en torno a la portadora, y por eso la forma cerrada de §3.1 y el modelo de
señal divergen para ruido de **banda ancha** modulado: allí la modulación se
reparte por todo el eje de Bark y el modelo banda a banda acumula más de la
que admite la forma cerrada única.

:::note
**Sin norma numérica.** La intensidad de fluctuación no tiene norma ISO/IEC. Esta
es una implementación clean-room a partir del artículo de Osses 2016, calibrada
para que el tono AM de `1 kHz / 60 dB / m = 1 / 4 Hz` marque `1,00 vacil` por
construcción, y contrastada con los valores de la literatura de la Tabla 1 de
Osses 2016 y con la referencia abierta SQAT (usada solo como oráculo numérico).
En el barrido de tono AM a `70 dB` `fmod ∈ {1, 2, 4, 8, 16, 32} Hz` da
`[0,40, 0,79, 1,09, 1,05, 0,17, 0,09]` vacil frente a la literatura
`[0,39, 0,84, 1,25, 1,30, 0,36, 0,06]` (`r` de Pearson `= 0,98`, máximo correcto a
`4 Hz`, dentro de ~2,1×). La exactitud para tonos FM no se persigue explícitamente.
Para **ruido de banda ancha AM** el modelo de señal sobreestima el nivel absoluto
(reparte la energía modulada entre las bandas); cite la forma cerrada
`fluctuation_strength_am_noise` (§3.1) para ese estímulo.
:::

## Qué cubre esta guía

**Cubierto.** Fastl y Zwicker, en *Psychoacoustics: Facts and Models*, dan el
modelo exacto de `PA`, Ecs 16.2-16.4 (origen Widmann 1992), que ejecuta
`psychoacoustic_annoyance`. También dan la forma cerrada para ruido de banda
ancha AM, Ec. 10.2, que ejecuta `fluctuation_strength_am_noise`. El modelo de
señal de Osses et al. (2016) para la intensidad de fluctuación se ejecuta
como `fluctuation_strength`, contrastado con los valores de su Tabla 1 y con
la referencia SQAT. `psychoacoustic_annoyance_from_signal` deriva las cuatro
magnitudes a partir de una señal (`N5` Zwicker de la ISO 532-1, `S` de la DIN
45692, `R` de ECMA-418-2) y las combina con el modelo exacto.

**No cubierto.** El modelo de Osses 2016 no persigue explícitamente su
exactitud para tonos FM. Aquí solo se validan estímulos AM. El front-end
también se aparta del planteamiento exacto del artículo (tramas de 2 s,
solape del 90 %, umbral absoluto de audición). Como resultado, un tono
estacionario de 1 kHz marca unos 0,09 vacil en vez de 0, y el ruido de banda
ancha estacionario marca unos 0,4 vacil. Para el ruido de banda ancha AM,
cite `fluctuation_strength_am_noise` (§3.1) en vez de `fluctuation_strength`,
que sobreestima ese estímulo. La intensidad de fluctuación normativa del
modelo de Sottek de la cláusula 9 de ECMA-418-2 no está implementada en esta
página: está en
[Métricas de calidad sonora](/phonometry/es/guides/sound-quality/).

## Véase también

- Referencia de la API: [`psychoacoustics.psychoacoustic_annoyance`](/phonometry/es/reference/api/psychoacoustics/psychoacoustic-annoyance/) y [`psychoacoustics.fluctuation_strength`](/phonometry/es/reference/api/psychoacoustics/fluctuation-strength/).
