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

El **nivel efectivo de ruido percibido (EPNL)** es la métrica de certificación
acústica de las aeronaves de transporte. Condensa una historia temporal
espectral de tercio de octava (cada medio segundo) de un sobrevuelo en un único
número, en EPNdB, mediante cinco pasos del **Anexo 16 de la ICAO, Vol. I,
Apéndice 2**. Esta página cubre las cuatro primitivas que construyen la métrica
y el verificador de sistema de medida IEC 61265. Cada magnitud se valida contra
los ejemplos trabajados del Manual Técnico Ambiental (ETM) Vol. I, ICAO
Doc 9501.

## Molestia percibida y PNL

Cada uno de los 24 niveles de banda de tercio de octava (50 Hz–10 kHz) se
convierte en una **molestia** percibida en noys mediante la ley analítica a
trozos de la Tabla A2-3, y se combinan en la molestia total
`N = 0.85·n_max + 0.15·Σn` y el nivel de ruido percibido
`PNL = 40 + (10/lg2)·lg N`.

```python
from phonometry import aircraft

noys = aircraft.perceived_noisiness(spl)      # noys por banda (spl = 24 niveles, dB)
pnl = aircraft.perceived_noise_level(spl)      # PNdB
```

## Corrección tonal

Las irregularidades espectrales (tonos de ventilador/turbina) se penalizan con
una **corrección tonal** `C`, hallada con el método de pendientes ("encircling"):
las pendientes se suavizan a un espectro de fondo `SPL''`, el exceso tonal
`F = SPL − SPL''` por encima de 1,5 dB se mapea a un factor de corrección
(división de frecuencia en 500 Hz / 5000 Hz, con tope de 6⅔ dB) y se toma el
máximo sobre las bandas. La implementación reproduce exactamente el ejemplo del
turbofán de la Tabla 3-7 del ETM Vol. I (`C = 2,0 dB` en 2500 Hz).

```python
from phonometry import aircraft

c = aircraft.tone_correction(spl)              # dB; se suma al PNL para dar PNLT
```

## EPNL

Sobre el sobrevuelo, `PNLT = PNL + C`, su máximo es `PNLTM`, y la métrica integra
`PNLT` sobre la ventana de 10 dB por debajo (los registros más cercanos a
`PNLTM − 10` a cada lado) normalizada a 10 s, de modo que `EPNL = PNLTM + D` con
la corrección por duración `D`.

```python
from phonometry import aircraft

# spectra: un array (K, 24) de niveles de tercio de octava muestreado cada dt s
res = aircraft.effective_perceived_noise_level(spectra, dt=0.5)
print(res.epnl, res.pnltm, res.duration_correction, res.band_limits)
res.plot()   # historia temporal PNL/PNLT (requiere matplotlib)
```

`effective_perceived_noise_level` devuelve un `EPNLResult` con el `pnl` por
registro, la `tone_correction`, el `pnlt`, el máximo `pnltm`, la
`duration_correction`, el `epnl` y los `band_limits` de 10 dB por debajo. El
ejemplo del método integrado en condiciones de referencia de la Tabla 4-4 del
ETM Vol. I se reproduce como `EPNL = 92,6 EPNdB`.

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

```python

from phonometry import aircraft

k, dt = 41, 0.5
idx = np.arange(k)
shape = 15.0 * np.exp(-((np.log10(aircraft.NOY_BANDS) - np.log10(400.0)) ** 2) / 0.5)
gain = 30.0 * np.exp(-((idx - 20.0) ** 2) / (2 * 5.0**2)) - 5.0
spectra = (55.0 + shape)[None, :] + gain[:, None]
spectra[:, 17] += 12.0 * np.exp(-((idx - 20.0) ** 2) / (2 * 6.0**2))  # tono de ventilador 2500 Hz
aircraft.effective_perceived_noise_level(spectra, dt).plot(language="es")
```

</details>

### Informe EPNL de ICAO (`.report()`)

`EPNLResult.report(path)` renderiza una ficha PDF de una página con el formato de
una hoja de datos de certificación de ruido de aeronaves: la línea de base
normativa (Anexo 16 de la ICAO, Vol. I, Apéndice 2), un bloque opcional de metadatos de
cabecera al estilo TCDSN (aeronave, fabricante / titular del certificado de tipo,
solicitante, punto de medida), una tabla de métricas de las magnitudes
intermedias informativas (el máximo `PNLTM`, la corrección por duración `D`, la
ventana de registros de 10 dB por debajo y, cuando no es cero, el ajuste por
reparto de bandas) sobre la gráfica apaisada a todo el ancho de `PNLT` frente al
tiempo (el propio `.plot()` del resultado), el número único `EPNL = X EPNdB` en
caja, una fila de veredicto Nivel | Límite | Margen cuando se aporta un límite de
certificación, una franja estática de condiciones de referencia (25 °C, 70 % HR,
nivel del mar, viento nulo, ISA) y un pie con el descargo fijo. Usa el mismo
contenedor `ReportMetadata` y el mismo motor de renderizado que la
[ficha de aislamiento de ISO 717](/phonometry/es/guides/insulation-field/#informe-de-iso-717-report);
un `requirement` aportado se lee como el límite de certificación EPNL en EPNdB
(el EPNL cumple si es igual o inferior), y `metadata=None` produce una ficha de
predicción ligera sin fila de veredicto. El renderizado necesita reportlab
(`pip install phonometry[report]`); solo se admite `engine="reportlab"`. La
ficha se genera en inglés por defecto; pasa `language="es"` para una ficha en
español (cadenas fijas traducidas y coma como separador decimal), p. ej.
`res.report("epnl_fiche_es.pdf", language="es")`. La ficha es un resultado EPNL
calculado y no es un certificado oficial de ruido de un Estado; no reproduce
ningún TCDSN.

```python
from phonometry import effective_perceived_noise_level, ReportMetadata

# spectra: un array (K, 24) de niveles de tercio de octava muestreado cada dt s
res = effective_perceived_noise_level(spectra, dt=0.5)
res.report(
    "ficha_epnl.pdf",
    metadata=ReportMetadata(
        specimen="Transporte bimotor turbofán de ejemplo",
        manufacturer="Empresa Aeronáutica de Ejemplo",
        measurement_standard="ICAO Annex 16 Vol I Amendment 14 Chapter 4",
        laboratory="Laboratorio de referencia Phonometry",
        requirement=101.0,          # límite de certificación EPNL (EPNdB)
    ),
)                                   # EPNL (EPNdB) con PNLTM y D
```

La ficha de ejemplo se regenera con `make reports` y se conserva renderizada en
el repositorio; pulsa la vista previa para abrir el PDF.

## Verificación del sistema de medida (IEC 61265)

`verify_aircraft_noise_system` comprueba el rendimiento medido contra las
tolerancias de la IEC 61265:1995: los límites de respuesta direccional del
micrófono (Tabla 1) y los límites escalares de respuesta en frecuencia,
linealidad y resolución. El filtrado de tercio de octava lo cubre la
verificación de clase 2 de filtros IEC 61260 de la librería.

```python
from phonometry import metrology

report = metrology.verify_aircraft_noise_system(
    directional={4000.0: {30: 0.4, 60: 0.9, 90: 1.9, 120: 2.4, 150: 2.4}},
    frequency_response={1000.0: 1.2},
)
print(report["passed"], report["checks"])
```

## Absorción atmosférica (SAE ARP 5534)

Corregir un sobrevuelo medido a condiciones atmosféricas de referencia requiere
la atenuación en bandas de 1/3 de octava sobre el trayecto. El coeficiente de
tono puro es el de ISO 9613-1 (idéntico, según ARP 5534 §3.1) que da
`air_attenuation`; `sae_band_attenuation` añade el **método SAE** (ARP 5534
§3.2.2) que mapea la atenuación de trayecto de tono puro medio de banda
`δ_t = α·s` a la atenuación de banda `δ_B`, consistente con el método exacto
mucho más allá del límite de 50 dB del método aproximado.

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

```python

from phonometry import aircraft

freqs = 1000.0 * 10.0 ** (np.arange(-13, 11) / 10.0)   # tercios 50 Hz-10 kHz
fig, ax = plt.subplots()
# continua: atenuación de banda SAE, discontinua: tono puro medio de banda
for s in (1000.0, 7620.0):
    att = aircraft.sae_band_attenuation(freqs, s, temperature=25.0, relative_humidity=70.0)
    line, = ax.semilogx(att.frequency, att.band_attenuation, marker="o",
                        markersize=3, label=f"Banda SAE ({s:.0f} m)")
    ax.semilogx(att.frequency, att.midband_attenuation, "--", alpha=0.6,
                color=line.get_color())
ax.set(xlabel="Frecuencia [Hz]", ylabel="Atenuación [dB]",
       title="Absorción atmosférica aeronáutica a 25 °C, 70% HR")
ax.grid(True, which="both", alpha=0.3)
ax.legend()
plt.show()
```

</details>

```python

from phonometry import aircraft

freqs = 1000.0 * 10.0 ** (np.arange(-13, 11) / 10.0)   # tercios 50 Hz–10 kHz
att = aircraft.sae_band_attenuation(freqs, path_length=7620.0,
                              temperature=25.0, relative_humidity=70.0)
att.plot()   # banda frente a tono puro medio de banda (requiere matplotlib)
```

Válido ~6–32 °C, 20–95 % HR (ventana 14 CFR Part 36), hasta 7620 m, recíproco.

## Ruido de aeropuerto: el motor NPD (ECAC Doc 29)

El método de ruido de aeropuerto de ECAC Doc 29 describe la aeronave con tablas
**nivel-potencia-distancia (NPD)**. `npd_level` lee el nivel de evento
(`LAmax`/`SEL`) para una potencia y distancia arbitrarias, interpolando
linealmente en potencia (Ec. 4-3) y log-linealmente en distancia oblicua
(Ec. 4-4).

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

```python

from phonometry import aircraft

# Una tabla NPD esquemática: SEL frente a distancia oblicua para dos empujes.
powers = [12000.0, 20000.0]
distances = [200.0, 400.0, 630.0, 1000.0, 2000.0, 4000.0, 6300.0, 10000.0]
levels = [[98.5, 92.0, 88.2, 83.6, 76.8, 69.4, 63.9, 56.8],
          [107.2, 100.9, 97.2, 92.7, 86.0, 78.5, 72.9, 65.6]]

fig, ax = plt.subplots()
for p in (20000.0, 12000.0):
    curve = aircraft.npd_curve(powers, distances, levels, power=p)
    line, = ax.semilogx(curve.distance, curve.level, label=f"P = {p:.0f} N")
    ax.semilogx(curve.table_distances, curve.table_levels, "o", markersize=4,
                color=line.get_color())
ax.set(xlabel="Distancia oblicua [m]", ylabel="Nivel de evento [dB]",
       title="Curvas nivel-potencia-distancia (ECAC Doc 29)")
ax.grid(True, which="both", alpha=0.3)
ax.legend()
plt.show()
```

</details>

```python
from phonometry import aircraft

powers = [12000.0, 20000.0]
distances = [200.0, 400.0, 1000.0, 2000.0, 6300.0, 10000.0]
levels = [[98.5, 92.0, 83.6, 76.8, 63.9, 56.8],
          [107.2, 100.9, 92.7, 86.0, 72.9, 65.6]]
aircraft.npd_curve(powers, distances, levels, power=20000.0).plot()
```

Es el motor NPD que sustenta el método.

## Contornos de ruido de aeropuerto (evento único)

El cálculo de evento único trocea la trayectoria en segmentos y corrige el nivel
base NPD por segmento (§4.3-4.5): `impedance_adjustment` (T, p),
`lateral_attenuation` (β,ℓ), `engine_installation_correction` (φ, montaje),
`duration_correction`, la fracción de segmento finito `noise_fraction` y, detrás
de los segmentos de rodaje de despegue, `start_of_roll_directivity` (ΔSOR).
`event_level` los ensambla y suma en `SEL`/`LAmax`, y `noise_contour` lo evalúa
sobre una malla en tierra (marca los segmentos de rodaje con una máscara
`ground_roll`).

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

```python

from phonometry import aircraft

# Tablas NPD (SEL y LAmax) de una aeronave, dos ajustes de potencia.
powers = [8000.0, 12000.0]
distances = [60.0, 120.0, 240.0, 480.0, 960.0, 1920.0, 3840.0, 7680.0]
sel = [[98.0, 92.0, 86.0, 80.0, 74.0, 68.0, 62.0, 56.0],
       [104.0, 98.0, 92.0, 86.0, 80.0, 74.0, 68.0, 62.0]]
lmax = [[94.0, 88.0, 82.0, 76.0, 70.0, 64.0, 58.0, 52.0],
        [100.0, 94.0, 88.0, 82.0, 76.0, 70.0, 64.0, 58.0]]

# Despegue: rodaje a lo largo de +x y después un ascenso constante.
xs = np.linspace(0.0, 18000.0, 40)
z = np.clip((xs - 1500.0) * 0.11, 0.0, 2500.0)
power = np.where(xs < 3000.0, 12000.0, 10000.0)
path = np.column_stack([xs, np.zeros_like(xs), z, power, np.full_like(xs, 82.3)])

contour = aircraft.noise_contour(path, powers, distances, sel, lmax,
                                 x=np.linspace(-2500.0, 20000.0, 56),
                                 y=np.linspace(-6000.0, 6000.0, 44))
contour.plot(language="es")   # huella SEL de evento único (requiere matplotlib)
plt.show()
```

</details>

El mecanismo que explica estas correcciones de suelo es la interferencia de dos
caminos: la onda directa y su reflexión en el suelo. Abajo, una fuente de
400 Hz a 1,5 m sobre un plano rígido forma el patrón de lóbulos, con la fuente
imagen dibujada como fantasma bajo el suelo y un receptor situado en un mínimo
de interferencia.

La directividad de inicio de rodaje es la radiación trasera lobulada del ruido
de chorro: máxima hacia un acimut ψ ≈ 120° respecto al morro, y decreciente al
través (ψ = 90°) y directamente detrás (ψ = 180°).

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

```python

from phonometry import aircraft

az = np.linspace(90.0, 270.0, 361)              # semicírculo trasero
psi = np.where(az <= 180.0, az, 360.0 - az)     # ΔSOR es simétrico izquierda/derecha
jet = [aircraft.start_of_roll_directivity(p, 300.0, "jet") for p in psi]
prop = [aircraft.start_of_roll_directivity(p, 300.0, "turboprop") for p in psi]

ax = plt.subplot(projection="polar")
ax.set_theta_zero_location("N")                 # morro arriba, acimut horario
ax.set_theta_direction(-1)
ax.plot(np.radians(az), jet, label="Reactor turbofán")
ax.plot(np.radians(az), prop, label="Turbohélice")
ax.set_rlim(-16.0, 0.0)                         # eje radial: dB respecto al través
ax.legend(loc="lower center")
plt.show()
```

</details>

```python

from phonometry import aircraft

powers = [8000.0, 12000.0]; distances = [60.0, 240.0, 960.0, 3840.0]
sel = [[98.0, 86.0, 74.0, 62.0], [104.0, 92.0, 80.0, 68.0]]
lmax = [[94.0, 82.0, 70.0, 58.0], [100.0, 88.0, 76.0, 64.0]]
xs = np.linspace(0.0, 18000.0, 40)
path = np.column_stack([xs, np.zeros_like(xs), np.clip((xs-1500)*0.11, 0, 2500),
                        np.where(xs < 3000, 12000.0, 10000.0), np.full_like(xs, 82.3)])
aircraft.noise_contour(path, powers, distances, sel, lmax,
                 x=np.linspace(-2500, 20000, 60), y=np.linspace(-6000, 6000, 48)).plot()
```

Validado contra el workbook de referencia de ECAC Doc 29 5ª ed. Vol 3 Parte 1:
la geometría de segmento, la atenuación lateral, la instalación del motor, la
fracción de ruido y la directividad de inicio de rodaje (turbofán y turbohélice)
reproducen los valores de referencia con < 0,01 dB, y la suma energética de
segmentos coincide con el `SEL` de referencia.

El modelo cubre también el rodaje de aterrizaje (máscara `landing_roll`:
fracción de ruido reducida Ec. 4-21b, geometría al extremo más cercano, sin
término de directividad), el ángulo de alabeo por segmento (`bank`, positivo
con el ala de estribor arriba; el ángulo de depresión es φ = β + ε para
observadores a estribor de la traza y φ = β − ε para observadores a babor,
§4.5.2), la geometría lateral §4.5.5 al extremo más cercano detrás
del rodaje de despegue, la velocidad media Ec. 4-13b en segmentos de pista y el
suelo recomendado de 30 m en las consultas NPD. Siete eventos de receptor del
workbook de referencia se reproducen end-to-end en la suite de tests.

## Qué cubre esta guía

**Cubierto.** El Anexo 16 de la ICAO, Vol. I, Apéndice 2: la molestia
percibida y el PNL de la Tabla A2-3 (`perceived_noisiness`,
`perceived_noise_level`), la corrección tonal por el método de pendientes
(`tone_correction`, que reproduce el ejemplo del turbofán de la Tabla 3-7 del
ETM Vol. I) y la cadena EPNL completa (`effective_perceived_noise_level`, que
reproduce el ejemplo de la Tabla 4-4 del ETM Vol. I). Las tolerancias del
sistema de medida de la IEC 61265:1995 mediante `verify_aircraft_noise_system`.
La absorción atmosférica en banda de la SAE ARP 5534 mediante
`sae_band_attenuation`. La cadena de ruido de aeropuerto de evento único de
ECAC Doc 29 (`npd_curve`, `event_level`, `noise_contour`), validada con menos
de 0,01 dB de diferencia frente al workbook de referencia de la Doc 29 5.ª ed.
Vol. 3 Parte 1.

**No cubierto.** `verify_aircraft_noise_system` comprueba las tolerancias de
la IEC 61265:1995, no la edición sucesora de 2018. La cadena de ruido de
aeropuerto solo construye contornos de evento único: no ensambla los índices
acumulados multievento (una suma al estilo Lden sobre un calendario de vuelos
completo) que un estudio completo de contornos de ruido de la Doc 29 necesita
además de estos niveles de evento único.

## Véase también

- Referencia de la API: [`aircraft.aircraft_noise`](/phonometry/es/reference/api/aeroacoustics/aircraft-noise/), [`aircraft.airport_noise`](/phonometry/es/reference/api/aeroacoustics/airport-noise/) y [`aircraft.atmospheric_absorption`](/phonometry/es/reference/api/aeroacoustics/atmospheric-absorption/).
