---
title: "Niveles integrados y estadísticos"
description: "Leq, LAeq, percentiles L10/L50/L90, LCpeak/SEL y dosis de ruido (IEC 61252), Lden y niveles de evaluación (ISO 1996-1), y espectrogramas de octava."
references:
  - type: standard
    organization: "International Electrotechnical Commission"
    year: 2013
    title: "Electroacoustics — Sound level meters — Part 1: Specifications"
    designation: "IEC 61672-1:2013"
    url: "https://webstore.iec.ch/en/publication/5708"
    note: "La balística de envolvente Fast/Slow/Impulse que sustenta los niveles percentiles, el pico ponderado C del apartado 5.13 (verificado contra las ráfagas de tono de la Tabla 5) y el nivel de exposición sonora verificado contra la columna LAE de la Tabla 4."
  - type: standard
    organization: "International Electrotechnical Commission"
    year: 1993
    title: "Electroacoustics — Specifications for personal sound exposure meters"
    designation: "IEC 61252:1993"
    url: "https://webstore.iec.ch/en/publication/5054"
    note: "La exposición sonora E en Pa²h y el nivel normalizado a 8 h LEX,8h (≡ LEP,d), anclados en 3,2 Pa²h ⇔ exactamente 90 dB. Revisada después como IEC 61252:2025 (https://webstore.iec.ch/en/publication/68929); la primera edición es la implementada."
  - type: standard
    organization: "International Organization for Standardization"
    year: 2016
    title: "Acoustics — Description, measurement and assessment of environmental noise — Part 1: Basic quantities and assessment procedures"
    designation: "ISO 1996-1:2016"
    url: "https://www.iso.org/standard/59765.html"
    note: "Lden (3.6.4), Ldn (3.6.5) y el nivel de evaluación compuesto de jornada completa del apartado 6.5 (Fórmulas 5-6, ajustes de la Tabla A.1)."
  - type: book
    authors: ["Kinsler, L. E.", "Frey, A. R.", "Coppens, A. B.", "Sanders, J. V."]
    year: 2000
    title: "Fundamentals of acoustics"
    edition: "4.ª ed."
    publisher: "Wiley"
    url: "https://www.wiley.com/en-us/Fundamentals+of+Acoustics%2C+4th+Edition-p-9780471847892"
    note: "Las definiciones de presión sonora, energía y nivel que sostienen Leq, SEL y las medidas de dosis (ISBN 978-0-471-84789-2)."
---

import ThemeImage from '../../../../components/ThemeImage.astro';

Métricas de ruido ambiental calculadas directamente sobre la señal cruda
(calibrada).

## Leq y LAeq

El nivel continuo equivalente integra la presión al cuadrado durante el tiempo
de medición:

$$
L_{eq} = 10\log_{10}\left(\frac{1}{T}\int_0^T \frac{p^2(t)}{p_0^2}\ dt\right) \text{ dB}, \qquad p_0 = 20\ \mu\text{Pa}
$$

y $L_{Aeq}$ es la misma integral tras ponderar A la señal. $L_N$ es el nivel
superado el $N\ \%$ del tiempo: el percentil $(100-N)$ de la distribución del
nivel con ponderación temporal.

```python
import numpy as np
from phonometry import metrology

# recording: una captura de micrófono calibrada (Pa) — grabada con tu cadena de medición. Sintetizada aquí para que la guía funcione por sí sola.
fs = 48000
recording = 0.2 * np.sin(2 * np.pi * 1000 * np.arange(fs) / fs)
sensitivity = 1.0                                    # calibration_factor (ver Calibración)

# Nivel continuo equivalente de toda la grabación
level = metrology.leq(recording, calibration_factor=sensitivity)

# Leq ponderado A (la métrica estándar de ruido ambiental)
la = metrology.laeq(recording, fs, calibration_factor=sensitivity)
```

Ambas aceptan señales 1D (devuelven un escalar) o arrays 2D
`[channels, samples]` (devuelven un nivel por canal), y admiten `dbfs=True` para
análisis digital a fondo de escala (la calibración no aplica en modo dBFS).

¿Por qué la media *energética* y no la media aritmética de los valores en dB?
Porque las dosis sonoras se suman como energía: dos periodos a 60 dB y 80 dB no
promedian 70 dB; la mitad a 80 dB domina y $L_{eq}$ = 77 dB. Promediar
decibelios directamente subestima cualquier ruido fluctuante. $L_{eq}$ es el
nivel del sonido *estacionario* que transporta la misma energía que el real,
fluctuante, y por eso las normativas se redactan en términos de él.

La misma regla gobierna cualquier combinación de niveles: niveles de periodo
en un valor de día completo, posiciones de micrófono en un promedio de sala,
mediciones repetidas en una media. Combina energías,
`10 * np.log10(np.mean(10 ** (L / 10)))`, nunca los valores en dB. El error
de la media aritmética es unilateral (siempre lee de menos) y crece con la
dispersión, así que no se cancela con muchas mediciones: con valores
repartidos en 10 dB ya cuesta un par de decibelios. Las pocas fórmulas
normativas que sí promedian decibelios directamente son aproximaciones
deliberadas y lo declaran (ISO 1996-2 ofrece una como sustituto de la
incertidumbre por mediciones repetidas y avisa de que se infla cuando los
niveles se dispersan más de 3 dB, ver la sección de incertidumbre más abajo);
en todo lo demás, energía.

### Parámetros de `leq()` / `laeq()`

| Parámetro | Tipo / forma | Unidades | Rango / valor por defecto | Notas |
| :--- | :--- | :--- | :--- | :--- |
| `x` | array 1D o 2D | unidades digitales (o Pa si está calibrada) | no vacío | 2D es `[channels, samples]`; devuelve un nivel por canal |
| `fs` | int | Hz | > 0 (solo `laeq`) | `leq` no necesita frecuencia de muestreo (integral RMS pura) |
| `calibration_factor` | float | Pa por unidad digital | por defecto `1.0` | De `sensitivity()` |
| `dbfs` | bool | — | por defecto `False` | `True`: 0 dBFS = seno RMS a fondo de escala; ignora la calibración |

## Niveles percentiles (LN)

`ln_levels` calcula niveles estadísticos a partir de la envolvente con
ponderación temporal: **L10** es el nivel superado el 10 % del tiempo (picos de
eventos), **L50** la mediana y **L90** el nivel de fondo.

```python
import numpy as np
from phonometry import metrology

# Un tono constante da L10 = L50 = L90; los percentiles solo cuentan algo con un
# nivel *fluctuante*. Sintetizamos 3 s alternando entre medio segundo tranquilo
# y otro ~10 dB más fuerte para que los estadísticos se separen.
fs = 48000
rng = np.random.default_rng(0)
segment = fs // 2                                  # 0.5 s por nivel
quiet = 0.02 * rng.standard_normal(segment)        # fondo
loud = 0.06 * rng.standard_normal(segment)         # eventos ~10 dB más fuertes
varying = np.tile(np.concatenate([quiet, loud]), 3)

stats = metrology.ln_levels(varying, fs, n=(10, 50, 90), weighting="A")
print(f"LA10={stats[10]:.1f}  LA50={stats[50]:.1f}  LA90={stats[90]:.1f} dB")
# LA10=66.6  LA50=65.2  LA90=58.5 dB  -> L10 (eventos) > L50 (mediana) > L90 (fondo)
```

<ThemeImage src="https://raw.githubusercontent.com/jmrplens/phonometry/main/.github/images/ln_levels_example_es.svg" alt="Historia del nivel Fast de un ruido fluctuante con los niveles estadísticos L10, L50 y L90 marcados" width="80%" loading="eager" />

*L10 sigue los picos de los eventos, L50 el nivel mediano y L90 el fondo.*

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

```python
import numpy as np
import matplotlib.pyplot as plt
from phonometry import metrology

# La señal fluctuante del ejemplo de ln_levels: 0.5 s de fondo alternando
# con 0.5 s de eventos ~10 dB más fuertes, repetido 3 veces
fs = 48000
rng = np.random.default_rng(0)
segment = fs // 2
quiet = 0.02 * rng.standard_normal(segment)
loud = 0.06 * rng.standard_normal(segment)
varying = np.tile(np.concatenate([quiet, loud]), 3)

# Envolvente cuadrática media Fast -> nivel frente al tiempo, y los percentiles
envelope = metrology.time_weighting(varying, fs, mode="fast")
level_t = 10 * np.log10(np.maximum(envelope, 1e-12) / (2e-5) ** 2)
stats = metrology.ln_levels(varying, fs, n=(10, 50, 90))
t = np.arange(varying.size) / fs

fig, ax = plt.subplots()
ax.plot(t, level_t, linewidth=0.8, label="Nivel Fast Lp(t)")
for i, (n_value, style) in enumerate([(10, "--"), (50, "-"), (90, "-.")], 1):
    ax.axhline(float(stats[n_value]), color=f"C{i}", linestyle=style,
               label=f"L{n_value} = {stats[n_value]:.1f} dB")
ax.set(xlabel="Tiempo [s]", ylabel="Nivel [dB]")
ax.legend(loc="lower right")
plt.show()
```

</details>

Opciones: `mode` selecciona la ponderación temporal de la envolvente (`'fast'`, `'slow'`,
`'impulse'`), `weighting` aplica antes la ponderación A/C, y
`calibration_factor`/`dbfs` se comportan como en `leq`. El transitorio de ataque
del integrador (~5τ) se descarta antes de calcular los percentiles, de modo que
la rampa inicial de asentamiento no cuenta en los percentiles bajos.

Formalmente, $L_N$ es el percentil $(100-N)$ de la distribución del nivel con
ponderación temporal: la grabación se convierte primero en una envolvente de
nivel frente a tiempo (Fast por defecto), y $L_{10}$ es el valor de la
envolvente superado el 10 % del tiempo. Eso hace que la *elección de la
ponderación temporal forme parte de la métrica*: un $L_{10}$ con envolvente
Slow es sistemáticamente más bajo que con una Fast en ruido impulsivo, por lo
que las normativas siempre indican la ponderación temporal.

### Leer Leq frente a los percentiles

$L_{eq}$ y la familia $L_N$ responden preguntas distintas sobre el mismo
historial de niveles. $L_{eq}$ es una media energética, así que los momentos más
ruidosos la dominan: un solo segundo a 100 dB eleva el $L_{eq}$ de una hora
por lo demás estable a 60 dB hasta unos 66 dB, mientras que $L_{90}$,
$L_{50}$ e incluso $L_{10}$ apenas se mueven (un evento de un segundo ocupa
mucho menos del 10 % de la hora). Los percentiles son estadísticos de rango,
robustos frente a eventos raros por construcción. En la práctica:

- **$L_{eq}$ (y $L_{Aeq}$)** es la métrica de dosis: las normativas, la
  exposición y los modelos de molestia se escriben con ella precisamente
  *porque* se niega a ignorar los eventos ruidosos raros.
- **$L_{90}$** estima el nivel residual (de fondo) bajo una fuente
  intermitente, que es como lo usa el Anexo I de ISO 1996-2.
- **$L_{10}$** sigue los picos de los eventos; la separación
  $L_{10} - L_{90}$ es un indicador rápido de intermitencia.
- **$L_{eq} - L_{50}$** mide lo "picudo" que es el historial: en ruido
  estacionario casi coinciden, y cuanto más fluctúa el nivel más sube
  $L_{eq}$ por encima de la mediana (para una distribución gaussiana de
  niveles con desviación típica $\sigma$ dB,
  $L_{eq} \approx L_{50} + 0{,}115\,\sigma^2$).

Una precaución: los percentiles no se combinan. Dos horas con $L_{90}$
conocidos no dan el $L_{90}$ de las dos horas con ninguna fórmula;
recalcúlalo sobre la envolvente conjunta. Los valores de $L_{eq}$, en cambio,
se combinan exactamente promediando energías ponderadas por el tiempo, que es
lo que hace `composite_rating_level` más abajo.

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

| Parámetro | Tipo / forma | Unidades | Rango / valor por defecto | Notas |
| :--- | :--- | :--- | :--- | :--- |
| `x` | array 1D o 2D | unidades digitales | no vacío | 2D devuelve diccionarios por canal |
| `fs` | int | Hz | > 0 | Lo necesita el detector de envolvente |
| `n` | tupla de ints | % | por defecto `(10, 50, 90)` | Cualquier porcentaje de excedencia, p. ej. `(1, 5, 95)` |
| `mode` | str | — | `'fast'` (por defecto), `'slow'`, `'impulse'` | Ponderación temporal IEC 61672-1 de la envolvente |
| `weighting` | str o None | — | `'A'`, `'C'`, `'G'`, `'Z'`, `None` (por defecto) | Ponderación frecuencial previa a la envolvente |
| `calibration_factor` / `dbfs` | float / bool | — | como `leq` | Misma semántica que en `leq()` |

## Métricas de pico, evento y ocupacionales

```python
import numpy as np
from phonometry import metrology

# recording: una captura de micrófono calibrada (Pa) — grabada con tu cadena de medición. Sintetizada aquí para que la guía funcione por sí sola.
fs = 48000
recording = 0.2 * np.sin(2 * np.pi * 1000 * np.arange(fs) / fs)
sensitivity = 1.0                                    # calibration_factor (ver Calibración)

# Pico ponderado C (IEC 61672-1 §5.13): los límites de acción laborales usan esto
peak = metrology.lc_peak(recording, fs, calibration_factor=sensitivity)

# Un único evento de ruido y una muestra de jornada (fragmentos de una grabación real)
event = recording
shift_sample = recording

# Nivel de exposición sonora: nivel del evento normalizado a 1 s (LAE)
lae = metrology.sel(event, fs, weighting="A", calibration_factor=sensitivity)

# Dosis diaria de ruido (IEC 61252): exposición en Pa²·h y LEX,8h / LEP,d
E = metrology.sound_exposure(shift_sample, fs, duration_hours=8, calibration_factor=sensitivity)
lex = metrology.lex_8h(shift_sample, fs, duration_hours=8, calibration_factor=sensitivity)
```

`lc_peak` está verificado contra las respuestas de referencia de ciclo
único/semiciclo de la Tabla 5 de IEC 61672-1:2013, `sel` contra la columna LAE
de la Tabla 4, y las funciones de dosis contra las anclas de IEC 61252
(3,2 Pa²h ↔ exactamente 90 dB). `lc_peak` sobremuestrea (polifásico) la señal
ponderada C por `oversample` (por defecto `8`) antes de tomar el máximo,
recuperando el verdadero pico inter-muestra: un máximo en rejilla subestima los
tonos de HF sostenidos hasta ~1,15 dB (un tono de 8 kHz a 48 kHz tiene solo
6 muestras/ciclo). Usa `oversample=1` para detectar el pico en la rejilla
original. Con `duration_hours`, la entrada se trata como muestra representativa
de ese periodo de exposición; sin él, la entrada es el evento completo.

### SEL: comparar eventos de distinta duración

Un paso de tren de 4 s y otro de 30 s no pueden compararse solo por su
$L_{Aeq}$: el evento más largo entrega más energía al mismo nivel. El **nivel
de exposición sonora** comprime la energía del evento *completo* en
exactamente un segundo:

$$
L_E = L_{eq,T} + 10\log_{10}\frac{T}{T_0}, \qquad T_0 = 1\ \text{s}
$$

de modo que los eventos de cualquier duración resultan directamente
comparables, y $N$ eventos idénticos se suman como $+10\log_{10}N$. Es el
bloque básico de los modelos de ruido aeroportuario y ferroviario.

<ThemeImage src="https://raw.githubusercontent.com/jmrplens/phonometry/main/.github/images/sel_concept_es.svg" alt="Historia del nivel del paso de un vehículo con su Leq sobre el evento completo y el bloque SEL de un segundo con la misma energía" width="80%" />

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

```python
import numpy as np
import matplotlib.pyplot as plt
from phonometry import metrology

# El paso de un vehículo: ruido bajo una envolvente de energía gaussiana (análisis en dBFS)
fs = 48000
t = np.arange(int(8.0 * fs)) / fs
rng = np.random.default_rng(11)
x = 0.3 * np.exp(-0.5 * ((t - 4.0) / 1.1) ** 2) * rng.standard_normal(t.size)

level = 10 * np.log10(np.maximum(metrology.time_weighting(x, fs, mode="fast"), 1e-12))
l_sel = float(metrology.sel(x, fs, dbfs=True))
l_eq = float(metrology.leq(x, dbfs=True))
print(f"Leq = {l_eq:.1f} dBFS, SEL = {l_sel:.1f} dBFS")
# Leq = -16.6 dBFS, SEL = -7.6 dBFS -> el bloque de 1 s lleva la energía del evento

fig, ax = plt.subplots()
ax.plot(t, level, linewidth=1.0, label="Nivel Fast del evento")
ax.hlines(l_eq, 0, 8, color="C2", linestyle="--",
          label=f"Leq sobre el evento completo = {l_eq:.1f} dBFS")
ax.fill_between([3.5, 4.5], -55, l_sel, color="C1", alpha=0.25)
ax.hlines(l_sel, 3.5, 4.5, color="C1", linewidth=2,
          label=f"SEL = {l_sel:.1f} dBFS: la misma energía en 1 s")
ax.set(xlabel="Tiempo [s]", ylabel="Nivel [dBFS]", ylim=(-55, l_sel + 6))
ax.legend(loc="lower left")
plt.show()
```

</details>

### Dosis de ruido: exposición sonora y LEX,8h

Las normativas laborales limitan la *dosis* diaria, no el nivel. IEC 61252 la
expresa como **exposición sonora** $E$ en pascales al cuadrado por hora (la
integral temporal de la presión ponderada A al cuadrado) y el **nivel
normalizado a 8 h** equivalente:

$$
E = \int_0^T p_A^2(t)\ dt \quad [\text{Pa}^2\text{h}], \qquad
L_{EX,8h} = 10\log_{10}\frac{E}{8\ \text{h} \cdot p_0^2}
$$

El ancla que conviene memorizar: **3,2 Pa²h ⇔ exactamente 90 dB durante 8 h**
(la suite de CI lo verifica). La mitad de dosis son −3 dB; el doble de
duración al mismo nivel son +3 dB.

### Parámetros de pico / evento / dosis

| Función | Parámetros clave | Devuelve | Ancla normativa |
| :--- | :--- | :--- | :--- |
| `lc_peak(x, fs, calibration_factor=1.0, dbfs=False)` | `dbfs=True` referencia el *pico* a fondo de escala (`1.0`), no el RMS | LCpeak [dB] | IEC 61672-1 §5.13, ráfagas de tono de la Tabla 5 |
| `sel(x, fs, weighting=None, ...)` | `weighting='A'` da el LAE | SEL [dB] | IEC 61672-1 Tabla 4 (columna LAE) |
| `sound_exposure(x, fs, duration_hours=None, ...)` | `duration_hours` trata `x` como muestra de ese periodo | E [Pa²h] | IEC 61252 |
| `lex_8h(x, fs, duration_hours=None, ...)` | misma semántica de muestreo | LEX,8h [dB] | IEC 61252 (≡ LEP,d) |

`lex_8h` califica *una* grabación; componer una jornada laboral completa a
partir de muestras por tarea o por función, con el presupuesto normativo de
incertidumbre de la ISO 9612, continúa en
[Exposición al ruido en el trabajo](/phonometry/es/guides/occupational-exposure/).

## Ruido ambiental: Lden, Ldn y niveles de evaluación (ISO 1996-1)

La evaluación regulatoria del ruido pondera más las tardes y las noches.
`lden()` implementa el nivel día-tarde-noche de ISO 1996-1:2016 (3.6.4:
+5 dB tarde, +10 dB noche, periodos 12/4/8 h por defecto, ajustables porque
cada país los define distinto), `ldn()` la variante día-noche (3.6.5) y
`composite_rating_level()` el compuesto general de jornada completa del
apartado 6.5 (Fórmulas 5-6) para periodos arbitrarios con ajustes por fuente o
carácter (Tabla A.1: p. ej. +5 dB impulsivo regular, +12 dB altamente
impulsivo, +3 a +6 dB tonos prominentes):

```python
from phonometry import environmental

l = environmental.lden(63.2, 58.1, 51.4)                      # desde LAeq por periodo
r = environmental.composite_rating_level([(63.2, 12, 0.0),    # día
                            (58.1, 4, 5.0),     # tarde (+5)
                            (51.4, 8, 10.0)])   # noche (+10) == environmental.lden
```

<ThemeImage src="https://raw.githubusercontent.com/jmrplens/phonometry/main/.github/images/lden_profile_es.svg" alt="Perfil LAeq urbano sintético de 24 horas con las bandas de día, tarde y noche, los niveles por periodo ponderados con +5 y +10 dB y el Lden resultante" width="80%" />

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

```python
import numpy as np
import matplotlib.pyplot as plt
from phonometry import environmental

# LAeq horario sintético de una vía urbana (dB), horas 00 a 23
laeq_h = np.array([48, 46, 45, 45, 46, 50, 56, 64, 66, 65, 63, 63,
                   64, 63, 63, 64, 65, 66, 65, 64, 63, 62, 61, 50], dtype=float)

def period_leq(idx):
    return 10 * np.log10(np.mean(10 ** (laeq_h[idx] / 10)))  # media energética

ld = period_leq(np.arange(7, 19))                # día 07-19
le = period_leq(np.arange(19, 23))               # tarde 19-23
ln_ = period_leq(np.r_[23, np.arange(0, 7)])     # noche 23-07
l_den = environmental.lden(ld, le, ln_)
print(f"Lden = {l_den:.1f} dB")   # Lden = 64.3 dB

fig, ax = plt.subplots()
ax.axvspan(19, 23, color="C1", alpha=0.15)                                # tarde
ax.axvspan(23, 24, color="C0", alpha=0.15); ax.axvspan(0, 7, color="C0", alpha=0.15)
ax.step(np.arange(25), np.r_[laeq_h, laeq_h[-1]], where="post",
        color="0.3", label="LAeq horario")
ax.hlines(ld, 7, 19, color="C2", linestyle="--", label="Ldía (+0 dB)")
ax.hlines(le + 5, 19, 23, color="C1", linestyle="--", label="Ltarde + 5 dB")
ax.hlines([ln_ + 10, ln_ + 10], [23, 0], [24, 7], color="C0",
          linestyle="--", label="Lnoche + 10 dB")
ax.hlines(l_den, 0, 24, color="C3", linewidth=2, label=f"Lden = {l_den:.1f} dB")
ax.set(xlabel="Hora del día", ylabel="Nivel [dB]", xlim=(0, 24))
ax.legend(loc="upper left", fontsize=8, ncol=2)
plt.show()
```

</details>

### Parámetros de `lden()` / `ldn()` / `composite_rating_level()`

| Función | Parámetros clave | Notas |
| :--- | :--- | :--- |
| `lden(lday, levening, lnight, hours=(12, 4, 8))` | LAeq por periodo [dB]; `hours` debe sumar 24 | +5 dB tarde, +10 dB noche (3.6.4) |
| `ldn(lday, lnight, hours=(15, 9))` | | +10 dB noche (3.6.5) |
| `composite_rating_level(periods)` | iterable de `(level_db, hours, adjustment_db)` | Fórmulas generales (5)-(6); ajustes según la Tabla A.1 |

Dónde pones el micrófono cambia el número: ISO 1996-2 fija las posiciones del receptor y sus correcciones de fachada. El diagrama es contexto de medida; aplica las correcciones a tus niveles antes del análisis:

<ThemeImage src="https://raw.githubusercontent.com/jmrplens/phonometry/main/.github/images/diagram_env_measurement_es.svg" alt="Posiciones de medida de ruido ambiental según ISO 1996-2: campo libre, a 2 m de la fachada y enrasado, con sus correcciones" width="92%" />

Combínalo con `laeq()` por periodo para ir de grabaciones a Lden, y con los
veredictos `tone_to_noise_ratio()` / `prominence_ratio()` de
[Tonos discretos prominentes](/phonometry/es/guides/tone-prominence/) para
justificar ajustes tonales.

## Determinación de niveles: ajuste tonal, ruido residual e incertidumbre (ISO 1996-2)

ISO 1996-2:2017 es la parte de **determinación**: cómo el nivel medido se
convierte en nivel de valoración y se reporta con su incertidumbre. La *suma* del
nivel de valoración y las penalizaciones por periodo están en ISO 1996-1 (arriba);
ISO 1996-2 aporta el ajuste tonal, la corrección de ruido residual y el
presupuesto de incertidumbre.

**Ajuste tonal (método de ingeniería, Anexo C).** A partir del nivel tonal
sumado en energía $L_{pt}$ y el nivel de ruido enmascarante $L_{pn}$ en la banda
crítica alrededor de un tono, la audibilidad sobre el umbral de enmascaramiento es
$\Delta L_{ta} = L_{pt} - L_{pn} + 2 + \lg[1 + (f_c/502)^{2.5}]$ dB (Fórmula (C.3)),
y el ajuste es $K_t = 0$ para $\Delta L_{ta} < 4$, $K_t = \Delta L_{ta} - 4$ para
$4 \le \Delta L_{ta} \le 10$ y $K_t = 6$ por encima (Fórmulas (C.4)–(C.6)). El
ancho de banda crítico es 100 Hz hasta 500 Hz y el 20 % de $f_c$ por encima
(Tabla C.1). El **método de cribado** en tercios de octava (`tonal_seeking_survey`)
marca una banda que supera a ambas vecinas en 15/8/5 dB (baja/media/alta), y
`tonal_adjustment_from_mean_audibility` mapea la audibilidad media de ISO/PAS 20065
a $K_t$ (Tabla J.1).

<ThemeImage src="https://raw.githubusercontent.com/jmrplens/phonometry/main/.github/images/tonal_audibility_es.svg" alt="Ajuste tonal Kt de ISO 1996-2 como función a tramos de la audibilidad tonal: cero por debajo de 4 dB, creciendo linealmente hasta 6 dB entre 4 y 10 dB, y 6 dB por encima, con los cuatro ejemplos resueltos del Anexo C.5 y un tono de rango medio marcados" width="80%" />

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

```python
import matplotlib.pyplot as plt
from phonometry import environmental

# ISO 1996-2:2007 Anexo C.5, Ejemplo 2 (dos tonos cerca de 400 Hz):
res = environmental.assess_tonal_audibility(tone_level=54.1, masking_noise_level=45.2,
                              centre_frequency=430.0)
print(res.audibility, res.adjustment)   # ΔLta ≈ 11,1 dB -> Kt = 6 dB
res.plot()
plt.show()
```
</details>

**Corrección de ruido residual (Cláusula 10.4).** `residual_sound_correction()`
aplica $L = 10\lg(10^{L'/10} - 10^{L_\text{res}/10})$ (Fórmula (16)). Con un
residual dentro de 3 dB del nivel medido no se permite corrección alguna: el
valor reportable es entonces el nivel medido *sin corregir* $L'$, como cota
superior del sonido específico (expuesto como `reportable_upper_bound`, con
`reliable=False`). `gaussian_residual_level()` estima el residual a partir de
niveles percentiles (Anexo I) y rechaza ordenaciones de percentiles
invertidas.

**Incertidumbre de medición (Cláusula 4, Anexo F).**
`combined_standard_uncertainty()` forma $u = \sqrt{\sum (c_j u_j)^2}$ (Fórmula (2))
y `environmental_expanded_uncertainty()` aplica $k = 2$ (95 %) o $k = 1.3$ (80 %);
`residual_correction_uncertainty()` lleva la sensibilidad de la corrección residual
(Fórmulas (F.7)/(F.8)) y `uncertainty_from_repeated_measurements()` la
incertidumbre típica de mediciones repetidas: la vía primaria en el dominio
de energía (Fórmulas (17)+(19)), con el sustituto en niveles de la Nota 2
(Fórmula (20)) reportado al lado como `approximate_uncertainty` y un aviso
cuando los niveles se dispersan más de 3 dB, donde el sustituto se infla
groseramente.

```python
from phonometry import environmental

kt = environmental.assess_tonal_audibility(54.1, 45.2, 430.0).adjustment      # 6 dB
corr = environmental.residual_sound_correction(measured_level=58.0, residual_level=50.0)
u = environmental.combined_standard_uncertainty([0.59, 0.3, 2.0, 0.40, 0.38])  # 2,18 dB (G.2)
environmental.expanded_uncertainty(u)                            # 4,36 dB (k = 2)
```

## Espectrograma de octavas (niveles vs tiempo)

Análisis de octava fraccional en tiempo corto: un nivel por banda y ventana,
alineado en el tiempo entre bandas.

```python
import numpy as np
from phonometry import metrology

# recording: una captura de micrófono calibrada (Pa) — grabada con tu cadena de medición. Sintetizada aquí para que la guía funcione por sí sola.
fs = 48000
recording = 0.2 * np.sin(2 * np.pi * 1000 * np.arange(fs) / fs)

bank = metrology.OctaveFilterBank(fs=48000, fraction=3)
levels, freq, times = bank.spectrogram(recording, window_time=0.125, overlap=0.5)
# levels: (bandas, ventanas) — listo para pcolormesh(times, freq, levels)
```

<ThemeImage src="https://raw.githubusercontent.com/jmrplens/phonometry/main/.github/images/spectrogram_example_es.webp" alt="Espectrograma en tercios de octava de un barrido logarítmico con dos ráfagas de tono" width="80%" />

*Un barrido logarítmico y dos ráfagas de tono, resueltos en el tiempo y en
bandas normalizadas de tercio de octava.*

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

```python
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import chirp
from phonometry import metrology

# Barrido logarítmico de 80 Hz -> 8 kHz más dos ráfagas de tono, con algo de ruido
fs = 48000
t = np.arange(int(4.0 * fs)) / fs
x = 0.5 * chirp(t, f0=80, t1=4.0, f1=8000, method="logarithmic")
x[int(1.0 * fs):int(1.3 * fs)] += np.sin(2 * np.pi * 4000 * t[: int(0.3 * fs)])
x[int(2.5 * fs):int(2.8 * fs)] += np.sin(2 * np.pi * 250 * t[: int(0.3 * fs)])
x += 0.01 * np.random.default_rng(42).standard_normal(t.size)

bank = metrology.OctaveFilterBank(fs=fs, fraction=3, order=6, limits=[50.0, 12000.0])
levels, freq, times = bank.spectrogram(x, window_time=0.125, overlap=0.5)

fig, ax = plt.subplots()
mesh = ax.pcolormesh(times, freq, levels, shading="auto")
ax.set_yscale("log")
ax.set(xlabel="Tiempo [s]", ylabel="Frecuencia [Hz]")
fig.colorbar(mesh, label="Nivel [dB]")
plt.show()
```

</details>

- Una entrada multicanal `(channels, samples)` devuelve `(channels, bands, frames)`.
- `times` contiene el centro de cada ventana en segundos.
- `mode='peak'` da niveles de pico por ventana en lugar de RMS.
- `zero_phase=True` filtra las bandas hacia delante y atrás para que el retardo
  de grupo por banda no desplace las ventanas (solo análisis offline).

### Parámetros de `OctaveFilterBank.spectrogram()`

| Parámetro | Tipo | Unidades | Rango / valor por defecto | Notas |
| :--- | :--- | :--- | :--- | :--- |
| `x` | array 1D o 2D | unidades digitales | no vacío | 2D devuelve `(channels, bands, frames)` |
| `window_time` | float | s | > 0; por defecto `0.125` | Longitud de la ventana (0,125 s replica Fast) |
| `overlap` | float | — | 0 ≤ overlap < 1; por defecto `0.5` | Fracción de solape entre ventanas (0 = sin solape) |
| `mode` | str | — | `'rms'` (por defecto) o `'peak'` | Detector por ventana |
| `detrend` | bool | — | por defecto `True` | Elimina el offset DC de cada banda antes del nivel (mejora la precisión en graves) |
| `zero_phase` | bool | — | por defecto `False` | Filtrado hacia delante y atrás (solo offline) |
| `calibration_factor` / `dbfs` | — | — | solo constructor | Se fijan en `OctaveFilterBank(...)`, no por llamada |

Consulta [Calibración y dBFS](/phonometry/es/guides/calibration/) para
convertir unidades digitales a SPL físico, y
[Ponderación temporal](/phonometry/es/guides/time-weighting/) para los
detalles de la envolvente. Las estrategias ocupacionales de la ISO 9612
continúan en
[Exposición al ruido en el trabajo](/phonometry/es/guides/occupational-exposure/),
los veredictos de prominencia tonal de ECMA-418-1 en
[Tonos discretos prominentes](/phonometry/es/guides/tone-prominence/), y las
curvas isofónicas de ISO 226 viven con las métricas de percepción en
[Sonoridad](/phonometry/es/guides/loudness/). Que un único Leq sea un
resumen justo de una medición es, de entrada, una cuestión de
estacionariedad: los tests de
[calificación de datos](/phonometry/es/guides/data-qualification/) la
responden objetivamente a partir de medias cuadráticas por segmento.

## Véase también

- Referencia de la API: [`metrology.levels`](/phonometry/es/reference/api/levels/levels/), [`environmental.measurement`](/phonometry/es/reference/api/environment/measurement/) y [`environmental.rating`](/phonometry/es/reference/api/environment/rating/).
