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

Dos sonidos igual de sonoros pueden diferir aún en cuán *afilados*, cuán
*tonales*, cuán *ásperos* o cuán *fluctuantes* son. Esta página cubre las
métricas de calidad sonora que complementan a la sonoridad: el sharpness
(DIN 45692) y la tonalidad, la aspereza y la intensidad de fluctuación de
ECMA-418-2 del modelo de Sottek. La sonoridad, incluida la de ECMA-418-2 que
comparte el mismo front-end auditivo, está en
[Sonoridad](/phonometry/es/guides/loudness/).

## Sharpness en acum (DIN 45692)

Dos sonidos pueden ser igual de sonoros y aun así uno se percibe más
"afilado" (siseante, metálico) porque su sonoridad se sitúa más arriba en la
escala Bark. El sharpness es el primer momento del patrón de sonoridad
específica ponderado por g(z):

$$
S = k\ \frac{\int_0^{24} N'(z)\ g(z)\ z\ dz}{\int_0^{24} N'(z)\ dz}\ \text{acum}
$$

con $g(z) = 1$ hasta 15,8 Bark y creciendo exponencialmente a partir de ahí, y
$k$ normalizada para que el sonido de referencia (ruido de ancho de banda
crítico a 1 kHz, 60 dB) sea exactamente **1,00 acum** (DIN 45692 apartado 6;
la $k = 0{,}108$ derivada queda dentro de la ventana normativa 0,105–0,115).

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

```python

# Ponderación de nitidez g(z) de DIN 45692: Ec. (1) más las variantes informativas del Anexo B
z = np.arange(1, 241) * 0.1                     # bins de Bark, 0.1 .. 24.0
g_din = np.where(z > 15.8, 0.15 * np.exp(0.42 * (z - 15.8)) + 0.85, 1.0)
g_bis = np.where(z > 15.0, 0.2 * np.exp(0.308 * (z - 15.0)) + 0.8, 1.0)
n = 4.0                                         # Aures depende de la sonoridad total (sonos)
g_aures = 0.078 * np.exp(0.171 * z) / z * (n / np.log(n * 0.05 + 1.0))

fig, ax = plt.subplots()
ax.semilogy(z, g_din, label="DIN 45692 g(z)")
ax.semilogy(z, g_bis, "--", label="von Bismarck (Anexo B)")
ax.semilogy(z, g_aures, "-.", label="Aures (Anexo B, N = 4 sonos)")
ax.axvline(15.8, linestyle=":", color="0.5")    # codo DIN: g crece a partir de 15.8 Bark
ax.set(xlabel="Razón de banda crítica z [Bark]", ylabel="Ponderación g(z)")
ax.grid(True, which="both", alpha=0.3)
ax.legend()
plt.show()
```

</details>

```python

from phonometry import psychoacoustics

# Una grabación y su calibración para que la guía funcione por sí sola
fs = 48000
x = 0.2 * np.sin(2 * np.pi * 1000 * np.arange(fs) / fs)   # cualquier grabación (unidades digitales)
sens = 1.0                                                # calibration_factor a pascales

s = psychoacoustics.sharpness_din(x, fs, calibration_factor=sens)      # acum
s_aures = psychoacoustics.sharpness_din(x, fs, method="aures")          # variante del Anexo B
```

CI verifica los valores objetivo de la Tabla A.2 (desde 0,38 acum a 250 Hz
hasta 2,82 acum a 4 kHz) dentro de la tolerancia del 5 % / 0,05 acum de la
norma.

## Tonalidad (ECMA-418-2)

Una componente tonal (un silbido, el tono de paso de pala de un ventilador)
destaca incluso a bajo nivel. ECMA-418-2 la cuantifica a partir de la **función
de autocorrelación** (ACF) de la señal rectificada de cada banda: una componente
periódica (tonal) mantiene una ACF alta a retardo no nulo, y la relación entre
sonoridad tonal y de ruido impulsa la tonalidad específica T′(z). El valor único
T se da en **tu_HMS**, calibrado de modo que un tono de 1 kHz/40 dB sea
≈ 1 tu_HMS; el resultado también sigue la frecuencia tonal f_ton por banda.

```python

from phonometry import psychoacoustics

fs = 48000
t = np.arange(int(1.2 * fs)) / fs
x = np.sqrt(2) * 2e-5 * 10 ** (40 / 20) * np.sin(2 * np.pi * 1000 * t)

res = psychoacoustics.tonality_ecma(x, fs, field="free")
peak = int(np.argmax(res.specific_tonality))
print(f"T = {res.tonality:.3f} tu_HMS")                    # 1.000 tu_HMS
print(f"f_ton = {res.tonal_frequencies[peak]:.0f} Hz")     # 999 Hz

res.plot()   # tonalidad específica media T'(z) + T(l) dependiente del tiempo
```

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

```python

from phonometry import psychoacoustics

# El ancla de calibración: un tono de 1 kHz a 40 dB SPL vale cerca de 1 tu_HMS.
fs = 48000
t = np.arange(int(1.2 * fs)) / fs
x = np.sqrt(2) * 2e-5 * 10 ** (40 / 20) * np.sin(2 * np.pi * 1000 * t)
res = psychoacoustics.tonality_ecma(x, fs, field="free")

# En una línea: al pasar unos ejes se dibuja solo el panel de tonalidad específica.
fig, ax = plt.subplots()
res.plot(ax=ax, language="es")
plt.show()

# O dibuja T'(z) a mano frente a la escala de razón de banda crítica:
fig, ax = plt.subplots()
ax.fill_between(res.bark, res.specific_tonality, alpha=0.3, color="#d62728")
ax.plot(res.bark, res.specific_tonality, color="#d62728")
ax.set_xlabel("Razón de banda crítica z [Bark_HMS]")
ax.set_ylabel("Tonalidad específica T' [tu_HMS]")
plt.show()
```

</details>

Esa concentración es lo que distingue un sonido tonal de uno de banda ancha
con la misma sonoridad: la etapa de autocorrelación encuentra una componente
periódica en una banda y casi nada en las demás. Un ventilador con tono de paso
de pala y su serie armónica muestra varios picos así; un siseo muestra un
patrón plano y bajo. Llamar a `.plot()` sin ejes añade el panel de `T(l)`
dependiente del tiempo, que es donde aparece un tono intermitente.

### Parámetros de `tonality_ecma()`

| Parámetro | Tipo | Unidades | Rango / valor por defecto | Notas |
| :--- | :--- | :--- | :--- | :--- |
| `signal_in` | array 1D | Pa | no vacío | Señal de presión calibrada |
| `fs` | float | Hz | > 0 | Se remuestrea a 48 kHz internamente si es necesario |
| `field` | str | — | `'free'` (por defecto) / `'diffuse'` | Filtro del oído externo/medio |
| `f_low` | float, opcional | Hz | por defecto `None` | Borde inferior de una banda de usuario para la búsqueda de T(l) |
| `f_high` | float, opcional | Hz | por defecto `None` | Borde superior de la banda de usuario |

Devuelve un `EcmaTonality`: `tonality` (T, tu_HMS), `specific_tonality`
(T′(z), 53 bandas), `bark`, `centre_frequencies`, `tonal_frequencies`
(f_ton,z), `time`, `tonality_vs_time` (T(l)), `tonal_frequency_vs_time`,
`field`.

## Aspereza (ECMA-418-2): capacidad nueva

La aspereza es la sensación áspera y zumbante de una modulación de amplitud
rápida (aproximadamente 20–300 Hz, con máximo cerca de 70 Hz): la cualidad de
un ralentí diésel o de un altavoz distorsionado. Es una **métrica nueva** en
phonometry. ECMA-418-2 extrae la envolvente de cada banda, pondera su espectro
de modulación por la tasa y la profundidad de modulación, y correlaciona la
modulación entre bandas; el resultado R se da en **asper**. El sonido de
referencia (portador de 1 kHz, modulado en amplitud al 100 % a 70 Hz, nivel
global de 60 dB SPL) se define como 1 asper; esta implementación de sala
limpia devuelve 0,9999 asper con la constante de calibración tabulada c_R
(Fórmula 104) usada **sin** reajustarla hacia atrás al objetivo.

```python

from phonometry import psychoacoustics

fs = 48000
t = np.arange(int(2.0 * fs)) / fs
x = (1.0 + np.cos(2 * np.pi * 70 * t)) * np.sin(2 * np.pi * 1000 * t)
x *= 2e-5 * 10 ** (60 / 20) / np.sqrt(np.mean(x**2))   # nivel global de 60 dB SPL

res = psychoacoustics.roughness_ecma(x, fs, field="free")
print(f"R = {res.roughness:.4f} asper")   # 0.9999 asper (referencia: 1 asper)

res.plot()   # aspereza R(l50) dependiente del tiempo + mapa de calor de aspereza específica
```

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

```python

from phonometry import psychoacoustics

fs = 48000
t = np.arange(int(2.0 * fs)) / fs
amp = np.sqrt(2) * 2e-5 * 10 ** (60 / 20)

# Un tono puro (tonal, suave) frente a un tono modulado en amplitud a 70 Hz
# (áspero), ambos normalizados a un nivel global de 60 dB SPL:
tone = amp * np.sin(2 * np.pi * 1000 * t)
rough = (1.0 + np.cos(2 * np.pi * 70 * t)) * np.sin(2 * np.pi * 1000 * t)
rough *= 2e-5 * 10 ** (60 / 20) / np.sqrt(np.mean(rough**2))

scores = {
    "Tono puro": (psychoacoustics.tonality_ecma(tone, fs).tonality, psychoacoustics.roughness_ecma(tone, fs).roughness),
    "Tono AM 70 Hz": (psychoacoustics.tonality_ecma(rough, fs).tonality, psychoacoustics.roughness_ecma(rough, fs).roughness),
}
labels = list(scores)
tonal = [scores[k][0] for k in labels]
rough_v = [scores[k][1] for k in labels]
xpos = np.arange(len(labels))
fig, ax = plt.subplots()
ax.bar(xpos - 0.2, tonal, 0.4, label="Tonalidad [tu_HMS]")
ax.bar(xpos + 0.2, rough_v, 0.4, label="Aspereza [asper]")
ax.set_xticks(xpos)
ax.set_xticklabels(labels)
ax.legend()
plt.show()
```

</details>

### Parámetros de `roughness_ecma()`

| Parámetro | Tipo | Unidades | Rango / valor por defecto | Notas |
| :--- | :--- | :--- | :--- | :--- |
| `signal_in` | array 1D | Pa | no vacío | Señal de presión calibrada |
| `fs` | float | Hz | > 0 | Se remuestrea a 48 kHz internamente si es necesario |
| `field` | str | — | `'free'` (por defecto) / `'diffuse'` | Filtro del oído externo/medio |

Devuelve un `EcmaRoughness`: `roughness` (R, asper, el percentil 90 de
R(l50)), `specific_roughness` (R′(z), 53 bandas), `bark`, `centre_frequencies`,
`time`, `roughness_vs_time` (R(l50)), `specific_roughness_vs_time`
(array de (n_times, 53)), `field`.

## Intensidad de fluctuación (ECMA-418-2): nueva capacidad

La intensidad de fluctuación es la sensación lenta y ondulante de la
modulación de amplitud o de frecuencia por debajo de unos 20 Hz: una
sirena, tonos batientes, el habla al ritmo silábico. Es la contraparte lenta
de la aspereza: el mismo modelo auditivo separa la modulación de la
envolvente en un paso de banda lento con máximo cerca de 4 Hz (intensidad de
fluctuación, en **vacil_HMS**) y otro rápido con máximo cerca de 70 Hz
(aspereza). La cláusula 9 de ECMA-418-2 analiza la envolvente de cada banda
con análisis espectral de alta resolución (HSA), un ajuste por mínimos
cuadrados de pares de líneas espectrales del núcleo de la ventana que
resuelve tasas de modulación muy por debajo del ancho de bin de la DFT, con
ventanas de análisis dependientes de la envolvente que omiten los periodos
más silenciosos, y después pondera el complejo armónico dominante y lo
escala con una sonoridad específica basada en el HSA. El sonido de
referencia (portadora de 1 kHz, modulada en amplitud al 100 % a 4 Hz, nivel
global de 60 dB SPL) se define como 1 vacil_HMS; esta implementación de
sala limpia converge a 0,9958 vacil_HMS a los 12 s con la constante de
calibración tabulada c_F (fórmula 163) usada **sin** reajustarla al objetivo
(el ejemplo de 8 s de abajo imprime 0,9957). Una señal cuyo valor único F
supera 0,2 vacil_HMS tiene una intensidad de fluctuación *prominente*
(cláusula 9.2).

```python

from phonometry import psychoacoustics

fs = 48000
t = np.arange(int(8.0 * fs)) / fs
x = (1.0 + np.cos(2 * np.pi * 4 * t)) * np.sin(2 * np.pi * 1000 * t)
x *= 2e-5 * 10 ** (60 / 20) / np.sqrt(np.mean(x**2))   # 60 dB SPL globales

res = psychoacoustics.fluctuation_strength_ecma(x, fs, field="free")
print(f"F = {res.fluctuation_strength:.4f} vacil_HMS")   # 0,9957 vacil_HMS (referencia: 1 vacil_HMS)

res.plot()   # F(l50) temporal + mapa de calor de la específica
```

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

```python

from phonometry import psychoacoustics

fs = 48000
t = np.arange(int(3.0 * fs)) / fs
carrier = np.sin(2 * np.pi * 1000 * t)

def am_tone(fmod):
    # AM del 100 % a un nivel global de 60 dB SPL (convención de las cláusulas 7/9)
    x = (1.0 + np.sin(2 * np.pi * fmod * t)) * carrier
    return x * 2e-5 * 10 ** (60 / 20) / np.sqrt(np.mean(x**2))

fm_slow = [0.5, 1, 2, 4, 8, 16, 32]
fm_fast = [20, 40, 70, 100, 150, 200]
f_vals = [psychoacoustics.fluctuation_strength_ecma(am_tone(fm), fs).fluctuation_strength
          for fm in fm_slow]
r_vals = [psychoacoustics.roughness_ecma(am_tone(fm), fs).roughness for fm in fm_fast]

fig, ax = plt.subplots()
ax.semilogx(fm_slow, f_vals, "o-", label="Intensidad de fluctuación F [vacil_HMS]")
ax.semilogx(fm_fast, r_vals, "s-", label="Aspereza R [asper]")
ax.set(xlabel="Frecuencia de modulación [Hz]", ylabel="F [vacil_HMS] / R [asper]")
ax.legend()
plt.show()
```

</details>

### Parámetros de `fluctuation_strength_ecma()`

| Parámetro | Tipo | Unidades | Rango / valor por defecto | Notas |
| :--- | :--- | :--- | :--- | :--- |
| `signal_in` | array 1D | Pa | no vacío | Señal de presión calibrada |
| `fs` | float | Hz | > 0 | Se remuestrea a 48 kHz internamente si es necesario |
| `field` | str | — | `'free'` (por defecto) / `'diffuse'` | Filtro del oído externo/medio |

Devuelve un `EcmaFluctuationStrength`: `fluctuation_strength` (F, vacil_HMS, el
percentil 90 de F(l50)), `specific_fluctuation_strength` (F′(z), 53 bandas),
`bark`, `centre_frequencies`, `time`, `fluctuation_strength_vs_time`
(F(l50)), `specific_fluctuation_strength_vs_time` (array de (n_times, 53)),
`field`.

Los modelos de intensidad de fluctuación de Fastl y Zwicker (forma cerrada
para ruido de banda ancha AM y el modelo de señal de Osses 2016) están en
[Molestia psicoacústica](/phonometry/es/guides/psychoacoustic-annoyance/);
esta métrica de la cláusula 9 es la contraparte normativa del modelo de
Sottek.

Consulta [Tonos discretos prominentes](/phonometry/es/guides/tone-prominence/)
para los veredictos TNR/PR de ECMA-418-1, el
[índice de transmisión del habla](/phonometry/es/guides/speech-transmission/)
para el STI/STIPA, y [Teoría](/phonometry/es/reference/theory/perception/) para la
matemática subyacente.

## Qué cubre esta guía

**Cubierto.** La DIN 45692:2009 mediante `sharpness_din()`: la ponderación del
apartado 6 sobre el patrón de sonoridad específica de ISO 532-1, más las
variantes informativas de von Bismarck y Aures del Anexo B, con los valores
objetivo de la Tabla A.2 comprobados en CI. La ECMA-418-2:2025 sobre el
front-end auditivo común del apartado 5: las etapas de salida de tonalidad del
apartado 6.2 (`tonality_ecma()`), la cadena de aspereza del apartado 7
(`roughness_ecma()`) y la intensidad de fluctuación por HSA del apartado 9
(`fluctuation_strength_ecma()`). Cada una usa la constante de calibración
tabulada de la norma, no un ajuste inverso al sonido de referencia.

**No cubierto.** Los tres puntos de entrada de ECMA-418-2 son monoaurales: las
combinaciones binaurales de media cuadrática de la Fórmula 112 (apartado
7.1.11) y la Fórmula 170 (apartado 9.1.15) no están implementadas, así que
analiza cada canal por separado. La ponderación de entropía opcional del
apartado 7.1.6 necesita una señal externa de velocidad de giro y queda fuera,
igual que el ajuste de ±0,25 % de $c_F$ que permite la nota al pie 47. La
sonoridad de ECMA-418-2 que comparte este front-end está en
[Sonoridad](/phonometry/es/guides/loudness/), y los modelos de intensidad de
fluctuación de Fastl y Zwicker, en
[Molestia psicoacústica](/phonometry/es/guides/psychoacoustic-annoyance/).

## Véase también

- Referencia de la API: [`psychoacoustics.sharpness`](/phonometry/es/reference/api/psychoacoustics/sharpness/), [`psychoacoustics.tonality_ecma`](/phonometry/es/reference/api/psychoacoustics/tonality-ecma/), [`psychoacoustics.roughness_ecma`](/phonometry/es/reference/api/psychoacoustics/roughness-ecma/) y [`psychoacoustics.fluctuation_strength_ecma`](/phonometry/es/reference/api/psychoacoustics/fluctuation-strength-ecma/).
