---
title: "Sonoridad de programa y pico verdadero (BS.1770 / R 128)"
description: "El algoritmo de sonoridad de programa de la Rec. UIT-R BS.1770-5 y la práctica de normalización de EBU R 128: ponderación K, sonoridad integrada con puertas en LUFS, los medidores momentáneo y de corto plazo del modo EBU de Tech 3341, el rango de sonoridad de Tech 3342 y el nivel de pico verdadero por sobremuestreo en dBTP."
references:
  - type: standard
    organization: "International Telecommunication Union"
    year: 2023
    title: "Algorithms to measure audio programme loudness and true-peak audio level"
    designation: "Recomendación UIT-R BS.1770-5 (11/2023)"
    url: "https://www.itu.int/rec/R-REC-BS.1770"
    note: "El prefiltro de ponderación K (Anexo 1, Tablas 1-2), la sonoridad ponderada por canal y las puertas en dos etapas (Anexo 1, Fórmulas 1-7, Tabla 3), las directrices de estimación del pico verdadero (Anexo 2 y la cota de infravaloración de su Adjunto 1) y las ponderaciones de canal dependientes de la posición para sistemas de sonido avanzados (Anexo 3, Tablas 4-5)."
  - type: standard
    organization: "European Broadcasting Union"
    year: 2023
    title: "Loudness normalisation and permitted maximum level of audio signals"
    designation: "EBU R 128"
    url: "https://tech.ebu.ch/publications/r128"
    note: "El nivel objetivo de −23,0 LUFS, el techo de −1 dBTP y la práctica de normalización."
  - type: standard
    organization: "European Broadcasting Union"
    year: 2023
    title: "Loudness metering: 'EBU Mode' metering to supplement loudness normalisation"
    designation: "EBU Tech 3341"
    url: "https://tech.ebu.ch/publications/tech3341"
    note: "Las escalas temporales momentánea/corto plazo/integrada (M/S/I) del modo EBU, validadas frente a las señales sintetizables de requisitos mínimos de su Tabla 1 con sus tolerancias oficiales."
  - type: standard
    organization: "European Broadcasting Union"
    year: 2023
    title: "Loudness range: A measure to supplement loudness normalisation"
    designation: "EBU Tech 3342"
    url: "https://tech.ebu.ch/publications/tech3342"
    note: "El algoritmo del rango de sonoridad (LRA), su implementación de referencia y sus señales de prueba, validado frente a las señales de su Tabla 1 con ±1 LU."
  - type: standard
    organization: "European Broadcasting Union"
    year: 2023
    title: "Guidelines for production of programmes in accordance with EBU R 128"
    designation: "EBU Tech 3343"
    url: "https://tech.ebu.ch/publications/tech3343"
    note: "La práctica de producción alrededor de los números de esta página."
  - type: article
    authors: ["Steinmetz, C. J.", "Reiss, J. D."]
    year: 2021
    title: "pyloudnorm: A simple yet flexible loudness meter in Python"
    journal: "150.ª Convención de la AES"
    url: "https://github.com/csteinmetz1/pyloudnorm"
    note: "Una implementación independiente de BS.1770, útil como contraste."
---

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

La **Rec. UIT-R BS.1770-5** define cómo miden la sonoridad de un programa la
radiodifusión y el streaming: **ponderación K**, potencia cuadrática media en
**bloques de 400 ms con puertas** y suma ponderada por canal, expresada en
**LKFS/LUFS**. **EBU R 128** construye encima la práctica de normalización
(todo programa se nivela a **−23,0 LUFS** con un techo de pico verdadero de
**−1 dBTP**), y sus documentos compañeros EBU Tech 3341 y Tech 3342 añaden el
medidor en *modo EBU* (sonoridad momentánea, de corto plazo e integrada) y el
*rango de sonoridad* (LRA). phonometry implementa la cadena completa en el
espacio de nombres `broadcast` y valida cada señal de prueba EBU
sintetizable con su tolerancia oficial.

## 1. La ponderación K y la medida de sonoridad (Anexo 1)

La señal atraviesa primero un prefiltro de dos etapas: un realce de agudos
de ~+4 dB que modela la cabeza como una esfera rígida y después el paso alto
RLB. Su concatenación es la **ponderación K**. La sonoridad en un intervalo
es la suma ponderada por canal de las potencias cuadráticas medias $z_i$
(Fórmula 2):

$$
L_K = -0.691 + 10 \log_{10} \sum_i G_i\, z_i \quad \text{LKFS},
$$

donde la constante cancela la ganancia de la ponderación K a 997 Hz y $G_i$
pondera cada canal (1,0 los canales frontales, 1,41 los envolventes, LFE
excluido, Tabla 3). La Recomendación ancla la escala: un seno de 997 Hz a
0 dB FS en un canal frontal marca −3,01 LKFS. La unidad se escribe LKFS en
la UIT y LUFS en la EBU; son idénticas, y 1 LU es 1 dB.

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

fs = 48000
t = np.arange(20 * fs) / fs
x = np.zeros((5, t.size))                     # L, R, C, Ls, Rs
x[0] = np.sin(2 * np.pi * 997.0 * t)          # 0 dB FS en el canal izquierdo
print(round(broadcast.integrated_loudness(x, fs), 2))   # -3.01  LKFS
```

Los coeficientes de los biquads están tabulados a 48 kHz (Tablas 1-2) y a
esa frecuencia se devuelven literalmente; cualquier otra frecuencia los
rederiva a través del prototipo analógico para que la respuesta coincida con
la especificación (dentro de 0,02 dB a 32 kHz y por encima; las frecuencias
por debajo de 16 kHz se rechazan):

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

(b1, a1), (b2, a2) = broadcast.k_weighting_coefficients(48000)
print(b1)   # [ 1.53512486 -2.69169619  1.19839281]  (Tabla 1, literal)
y = broadcast.k_weighting(np.random.default_rng(0).standard_normal(48000),
                          48000)              # la propia señal filtrada
```

`k_weighting_response` evalúa esos mismos biquads como función de
transferencia y devuelve un `KWeightingResponse` inmutable que lleva la
magnitud combinada (`magnitude_db`) y las dos etapas (`shelf_db`,
`highpass_db`) sobre una rejilla de frecuencia logarítmica; su `.plot()`
dibuja la respuesta, con el realce de cabeza esférica de +4 dB y la caída
del paso alto RLB:

<ThemeImage
  src="https://raw.githubusercontent.com/jmrplens/phonometry/main/.github/images/k_weighting_response_es.svg"
  alt="Respuesta en frecuencia de magnitud de la ponderación K en un eje de frecuencia logarítmico: la curva azul combinada cae por debajo de unos pocos cientos de hercios a través del paso alto RLB y sube hasta una meseta de +4 dB por encima de 2 kHz fijada por el realce de cabeza esférica, con las dos etapas dibujadas como curvas acompañantes tenues"
  width="96%"
/>

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

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

broadcast.k_weighting_response(48000).plot(language="es")
plt.show()
```

</details>

## 2. Las puertas y la sonoridad de programa

La sonoridad **integrada** (de programa) divide la medición en bloques de
400 ms con solape del 75 % y les aplica dos puertas (Fórmulas 3-7): los
bloques por debajo del umbral absoluto de **−70 LKFS** se descartan; la
sonoridad de los supervivientes menos 10 LU fija el **umbral relativo**, y
los bloques por encima de ambas puertas definen el resultado. Las puertas
evitan que los pasajes silenciosos largos (ambientes, pausas, colas de
aplausos) arrastren hacia abajo el nivel del primer plano:

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

fs = 48000
def tono(nivel_dbfs, segundos):
    t = np.arange(int(segundos * fs)) / fs
    return 10 ** (nivel_dbfs / 20) * np.sin(2 * np.pi * 1000.0 * t)

# 10 s de programa a -23 dBFS seguidos de 30 s de ambiente silencioso.
x = np.concatenate([tono(-23.0, 10.0), tono(-50.0, 30.0)])
res = broadcast.program_loudness(np.vstack([x, x]), fs)
print(round(res.integrated, 1))            # -23.1  LUFS (la cola se descarta)
print(round(res.relative_threshold, 1))    # -39.0  LUFS
```

Una media sin puertas sobre los mismos 40 s quedaría cerca de −29 LUFS: las
puertas son lo que hace que los programas de gran rango de sonoridad casen
en antena. EBU R 128 normaliza este valor integrado a **−23,0 LUFS**; cuando
el objetivo no es alcanzable en la práctica (programas en directo, por
ejemplo) se permite una tolerancia de ±1,0 LU, y los flujos de control de
calidad admiten ±0,2 LU por error de medida.

## 3. Modo EBU: momentánea, corto plazo, integrada

EBU Tech 3341 define las tres escalas temporales de un medidor conforme, y
una sola llamada las calcula todas:

* **Momentánea (M)**: ventana deslizante de 400 ms, sin puertas;
* **Corto plazo (S)**: ventana deslizante de 3 s, sin puertas;
* **Integrada (I)**: la sonoridad de programa con puertas anterior,

más **Max M** y **Max S**, el pico verdadero y el LRA:

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

fs = 48000
def tono(nivel_dbfs, segundos):
    t = np.arange(int(segundos * fs)) / fs
    return 10 ** (nivel_dbfs / 20) * np.sin(2 * np.pi * 1000.0 * t)

# Caso de prueba 3 de EBU Tech 3341: escalones de -36 / -23 / -36 dBFS.
x = np.concatenate([tono(-36.0, 10.0), tono(-23.0, 60.0), tono(-36.0, 10.0)])
res = broadcast.program_loudness(np.vstack([x, x]), fs)
print(round(res.integrated, 1), round(res.max_momentary, 1),
      round(res.max_short_term, 1))         # -23.0 -23.0 -23.0
```

El `ProgramLoudnessResult` congelado lleva las series M y S con sus ejes de
tiempo, los máximos, los umbrales, el LRA con sus bordes percentiles, los
picos verdaderos por canal y las ponderaciones de canal; su `.plot()` dibuja
la traza de sonoridad del programa:

<ThemeImage
  src="https://raw.githubusercontent.com/jmrplens/phonometry/main/.github/images/program_loudness_es.svg"
  alt="Medición EBU R 128 de un programa sintético de un minuto con secciones de ambiente, diálogo, música y fundido: la sonoridad momentánea gris respira alrededor de la traza azul de corto plazo, la sonoridad integrada discontinua roja cae exactamente sobre el objetivo de -23 LUFS y una banda sombreada marca el rango de sonoridad entre sus percentiles 10 y 95"
  width="96%"
  loading="eager"
/>

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

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

fs = 48000
rng = np.random.default_rng(1770)
sos = signal.butter(2, 2000.0, fs=fs, output="sos")
trozos = []
for nivel, segundos in [(-38, 8), (-23, 16), (-17, 12), (-25, 16), (-45, 8)]:
    ruido = signal.sosfilt(sos, rng.standard_normal(int(segundos * fs)))
    ruido /= np.sqrt(np.mean(ruido ** 2))
    t = np.arange(ruido.size) / fs
    vaiven = 1 + 0.22 * np.sin(2 * np.pi * 0.9 * t) \
        + 0.14 * np.sin(2 * np.pi * 2.83 * t + 1.0)
    trozos.append(10 ** (nivel / 20) * ruido * vaiven)
x = np.concatenate(trozos)

# Normalizar el programa al objetivo de R 128 y medirlo.
ganancia = -23.0 - broadcast.integrated_loudness(np.vstack([x, x]), fs)
x *= 10 ** (ganancia / 20)
broadcast.program_loudness(np.vstack([x, x]), fs).plot()
plt.show()
```

</details>

## 4. Rango de sonoridad (EBU Tech 3342)

El **rango de sonoridad** cuantifica cuánto varía la sonoridad en una escala
temporal macroscópica, en LU. Es la separación entre los **percentiles 10 y
95** de la distribución de sonoridad de corto plazo tras una puerta en
cascada: un umbral absoluto de −70 LUFS y después un umbral relativo
**−20 LU** por debajo del nivel de lo que sobrevivió (deliberadamente más
profundo que los −10 LU de la medida integrada, para que el primer plano
silencioso pero real siga contando). Los percentiles impiden que un disparo
aislado o un fundido inflen el valor:

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

fs = 48000
def tono(nivel_dbfs, segundos):
    t = np.arange(int(segundos * fs)) / fs
    return 10 ** (nivel_dbfs / 20) * np.sin(2 * np.pi * 1000.0 * t)

# Caso de prueba 1 de EBU Tech 3342: 20 s a -20 dBFS y 20 s a -30 dBFS.
x = np.concatenate([tono(-20.0, 20.0), tono(-30.0, 20.0)])
res = broadcast.program_loudness(np.vstack([x, x]), fs)
print(round(res.loudness_range, 1))         # 10.0  LU
```

`loudness_range()` también está disponible de forma independiente sobre
cualquier vector de sonoridad de corto plazo, siguiendo la implementación de
referencia de Tech 3342 (incluida su indexación de percentiles por rango más
cercano). La EBU no recomienda el LRA para programas de menos de un minuto:
demasiado pocas ventanas de 3 s.

## 5. Pico verdadero (Anexo 2)

Los picos por muestra engañan: el máximo verdadero de la forma de onda
reconstruida cae en general *entre* muestras, y un medidor de pico por
muestra infravalora 3 dB un tono a $f_s/4$ con la fase desafortunada (peor
caso $20\log_{10}\cos(\pi f_{\mathrm{norm}}/n)$ para una razón de
sobremuestreo $n$). Por eso el Anexo 2 de BS.1770-5 mide el **pico
verdadero** sobre la señal sobremuestreada hasta al menos 192 kHz (4× a
48 kHz), en **dBTP** (dB respecto al 100 % de la escala completa):

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

fs = 48000
t = np.arange(fs) / fs
# Un tono a fs/4 a plena escala cuyos picos caen justo entre muestras.
x = np.sin(2 * np.pi * (fs / 4) * t + np.pi / 4)
print(round(float(broadcast.true_peak_level(x, fs, oversample=1)), 2))  # -3.01
print(round(float(broadcast.true_peak_level(x, fs)), 2))                #  0.12
```

El interpolador recupera la excursión entre muestras que la rejilla de
muestreo perdió (el residuo de +0,12 dB es rizado de interpolación de los
bordes abruptos del tono, dentro de la tolerancia de +0,2/−0,4 dB que deben
cumplir los medidores en modo EBU). EBU R 128 limita la producción a
**−1 dBTP**; los códecs de distribución suelen necesitar más margen. Es la
misma maquinaria de pico sobremuestreado que sostiene el `lc_peak` ponderado
C de [Niveles integrados y estadísticos](/phonometry/es/guides/levels/).

## 6. Programas multicanal y el Anexo 3

Con 1, 2, 5 o 6 canales las ponderaciones de la Tabla 3 se aplican solas
(orden de canales `L, R, C, Ls, Rs`, o `L, R, C, LFE, Ls, Rs` con el LFE
excluido). Para cualquier otra disposición de altavoces (22.2, 4+7+0 y el
resto de sistemas de sonido avanzados de BS.2051), el Anexo 3 deriva la
ponderación de cada canal de la posición de su altavoz: 1,41 (+1,5 dB) para
los altavoces laterales de la capa media (60° ≤ |acimut| ≤ 120°,
|elevación| < 30°), 1,0 en el resto:

```python
from phonometry import broadcast

print(broadcast.channel_weight(110.0, 0.0))    # 1.41  (M+110, lateral)
print(broadcast.channel_weight(110.0, 35.0))   # 1.0   (U+110, capa superior)
pesos = broadcast.channel_weight([0, 30, -30, 90, -90], [0, 0, 0, 0, 0])
# -> [1. 1. 1. 1.41 1.41]; se pasa como program_loudness(..., weights=pesos)
```

El audio basado en objetos (Anexo 4) se mide renderizando primero a una
configuración de altavoces y midiendo el render; el renderizado en sí queda
fuera de este alcance.

## Informe de EBU R 128 (`.report()`)

`ProgramLoudnessResult.report(path)` renderiza una ficha PDF de una página con
el formato de una hoja de conformidad de entrega para radiodifusión: la línea
de norma base, un bloque opcional de metadatos, una tabla de conformidad a todo
lo ancho (`Métrica | Medido | Objetivo / Límite | Resultado`) y, debajo, la
gráfica de sonoridad frente al tiempo a todo lo ancho (el propio `.plot()` del
resultado, con las trazas momentánea y de corto plazo, la línea de la integrada
y la banda del LRA). El veredicto lo determinan **solo** la sonoridad integrada
y el pico verdadero máximo; el rango de sonoridad y los máximos
momentáneo/corto plazo se muestran como filas informativas (una raya en la
columna Resultado, nunca un color de cumple/no cumple). Un número único
enmarcado `I = X LUFS (LRA = Y LU, TP máx = Z dBTP)`, un veredicto combinado
CUMPLE/NO CUMPLE y un pie con el descargo fijo cierran la hoja.

La disposición apilada (tabla de conformidad arriba, gráfica debajo) difiere
del cuerpo estrecho de dos paneles de las demás fichas porque la tabla de
conformidad necesita cuatro columnas y la traza de sonoridad frente al tiempo
es apaisada. 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` proporcionado se interpreta como la sonoridad de programa
objetivo en LUFS (por defecto los −23,0 LUFS de EBU R 128), y la ficha cumple
cuando la sonoridad integrada está dentro de la tolerancia de R 128
seleccionada y el pico verdadero es igual o inferior a −1,0 dBTP. La
tolerancia sigue el argumento `tolerance`: el valor por defecto `"qc"` aplica
el margen de ±0,2 LU por errores de medida del punto i) de R 128 (flujos de
trabajo de sonoridad como el control de calidad), y `"live"` aplica la
tolerancia de ±1,0 LU del punto h), permitida solo cuando el nivel objetivo no
es alcanzable en la práctica (por ejemplo, programas en directo); la regla
aplicada y su punto de R 128 se imprimen en la ficha. El veredicto se evalúa
sobre la sonoridad redondeada a los 0,1 LU mostrados, de modo que los números
impresos nunca pueden contradecirlo. 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("loudness_fiche_es.pdf", language="es")`.

```python
from phonometry import broadcast, ReportMetadata

res = broadcast.program_loudness(x, fs)   # un programa estéreo terminado
res.report(
    "loudness_fiche.pdf",
    metadata=ReportMetadata(
        specimen="Secuencia de tonos de referencia",
        measurement_standard="EBU R 128",
        laboratory="Laboratorio de referencia Phonometry",
        requirement=-23.0,                # sonoridad de programa objetivo (LUFS)
    ),
)                                          # I (LUFS), LRA (LU), pico verdadero (dBTP)
```

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

<ReportPreview
	name="ebu_r128_loudness_example"
	title="Informe de ejemplo de sonoridad de programa EBU R 128 (PDF)"
	description="Ficha de conformidad de sonoridad de programa de una página: un bloque de metadatos, una tabla de conformidad de cuatro columnas con la sonoridad integrada y el pico verdadero máximo como veredicto y el rango de sonoridad y los máximos momentáneo/corto plazo como filas informativas, la gráfica de sonoridad frente al tiempo a todo lo ancho, el número único enmarcado I = -23.0 LUFS (LRA = 10.0 LU, TP máx = -20.4 dBTP) y un veredicto CUMPLE frente al objetivo de -23.0 LUFS con la tolerancia de control de calidad por defecto de ±0,2 LU del punto i) de EBU R 128."
	caption="Ficha de conformidad de sonoridad de programa (ProgramLoudnessResult.report), I en LUFS con LRA en LU y pico verdadero en dBTP."
/>

## 7. Validación

Cada señal sintetizable de "requisitos mínimos" de EBU Tech 3341 (casos 1-6
y 9-23) y de Tech 3342 (casos 1-4) se ejecuta en la batería de tests con su
tolerancia oficial (±0,1 LU en sonoridad, +0,2/−0,4 dB en pico verdadero,
±1 LU en LRA), junto con el ancla de 997 Hz y la cota de infravaloración en
forma cerrada del Anexo 2, Adjunto 1. Los casos 7-8 y los casos 5-6 del LRA
usan material de programa auténtico distribuido por la EBU y no son
sintetizables; se ejecutan contra el conjunto oficial de pruebas de sonoridad
de la EBU (descargado de la propia EBU, cuya licencia cubre solo pruebas
técnicas, así que el audio nunca se incorpora al repositorio) y los cuatro
pasan dentro de tolerancia; las series de sonoridad por bloques medidas de
esos ficheros se incorporan como datos simples, de modo que las etapas de
gating y LRA de estos casos se ejecutan también en todas partes sin el
audio. El medidor independiente
[pyloudnorm](https://github.com/csteinmetz1/pyloudnorm) es un contraste útil
con grabaciones reales; no se usó como fuente de esta implementación.
