Ir al contenido

Métricas de calidad sonora

Normas aplicables: DIN 45692ECMA-418Referencias: Fastl y Zwicker 2007

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.

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):

con hasta 15,8 Bark y creciendo exponencialmente a partir de ahí, y 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 derivada queda dentro de la ventana normativa 0,105–0,115).

Ponderación de nitidez g(z) de DIN 45692 frente a la razón de banda crítica en eje logarítmico, comparando las curvas DIN, von Bismarck y Aures con los codos de 15,8 y 15 Bark marcadosPonderación de nitidez g(z) de DIN 45692 frente a la razón de banda crítica en eje logarítmico, comparando las curvas DIN, von Bismarck y Aures con los codos de 15,8 y 15 Bark marcados
Mostrar el código de esta figura
import matplotlib.pyplot as plt
import numpy as np
# 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()
import numpy as np
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.

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.

import numpy as np
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
Tonalidad específica media de ECMA-418-2 sobre las 53 bandas Bark_HMS para un tono de 1 kHz a 40 dB SPL: la tonalidad se concentra en un único pico en la banda crítica del tono, hacia 9 Bark_HMS, y cae casi a cero en el resto, integrando T = 1,00 tu_HMSTonalidad específica media de ECMA-418-2 sobre las 53 bandas Bark_HMS para un tono de 1 kHz a 40 dB SPL: la tonalidad se concentra en un único pico en la banda crítica del tono, hacia 9 Bark_HMS, y cae casi a cero en el resto, integrando T = 1,00 tu_HMS
Mostrar el código de esta figura
import matplotlib.pyplot as plt
import numpy as np
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()

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ámetroTipoUnidadesRango / valor por defectoNotas
signal_inarray 1DPano vacíoSeñal de presión calibrada
fsfloatHz> 0Se remuestrea a 48 kHz internamente si es necesario
fieldstr'free' (por defecto) / 'diffuse'Filtro del oído externo/medio
f_lowfloat, opcionalHzpor defecto NoneBorde inferior de una banda de usuario para la búsqueda de T(l)
f_highfloat, opcionalHzpor defecto NoneBorde 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.

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.

import numpy as np
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
Demostración de calidad sonora ECMA-418-2: un sonido tonal puntúa alta tonalidad y aspereza casi nula, mientras que un sonido modulado en amplitud a 70 Hz puntúa alta aspereza y baja tonalidadDemostración de calidad sonora ECMA-418-2: un sonido tonal puntúa alta tonalidad y aspereza casi nula, mientras que un sonido modulado en amplitud a 70 Hz puntúa alta aspereza y baja tonalidad
Mostrar el código de esta figura
import matplotlib.pyplot as plt
import numpy as np
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()
ParámetroTipoUnidadesRango / valor por defectoNotas
signal_inarray 1DPano vacíoSeñal de presión calibrada
fsfloatHz> 0Se remuestrea a 48 kHz internamente si es necesario
fieldstr'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

Sección titulada «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).

import numpy as np
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
Percepción de modulación lenta vs rápida de ECMA-418-2: la intensidad de fluctuación forma un paso de banda sobre la frecuencia de modulación con máximo cerca de 4 a 6 Hz mientras que la aspereza de los mismos tonos de 1 kHz modulados en amplitud tiene su máximo cerca de 70 HzPercepción de modulación lenta vs rápida de ECMA-418-2: la intensidad de fluctuación forma un paso de banda sobre la frecuencia de modulación con máximo cerca de 4 a 6 Hz mientras que la aspereza de los mismos tonos de 1 kHz modulados en amplitud tiene su máximo cerca de 70 Hz
Mostrar el código de esta figura
import matplotlib.pyplot as plt
import numpy as np
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()
ParámetroTipoUnidadesRango / valor por defectoNotas
signal_inarray 1DPano vacíoSeñal de presión calibrada
fsfloatHz> 0Se remuestrea a 48 kHz internamente si es necesario
fieldstr'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; esta métrica de la cláusula 9 es la contraparte normativa del modelo de Sottek.

Consulta Tonos discretos prominentes para los veredictos TNR/PR de ECMA-418-1, el índice de transmisión del habla para el STI/STIPA, y Teoría para la matemática subyacente.

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 que permite la nota al pie 47. La sonoridad de ECMA-418-2 que comparte este front-end está en Sonoridad, y los modelos de intensidad de fluctuación de Fastl y Zwicker, en Molestia psicoacústica.