Ir al contenido

Acústica de salas

Normas aplicables: ISO 3382ISO 18233ISO 354Referencias: Kuttruff 2016Schroeder 1965Hak et al. 2012

La acústica de salas parte de una única medición: la respuesta al impulso (RI) entre una fuente y un receptor. Fíltrala en bandas e intégrala, y da el tiempo de reverberación, la claridad y la inteligibilidad del habla: todo sobre el campo sonoro dentro de un único recinto. Esta página sigue esa cadena en orden de medición: adquirir la RI (ISO 18233), convertirla en parámetros de sala (ISO 3382-1/2), métricas espaciales del habla para oficinas diáfanas (ISO 3382-3) y, cerrando el ciclo, la absorción acústica de un material en una cámara reverberante (ISO 354). Para el aislamiento acústico entre recintos (la misma RI medida a ambos lados de un cerramiento) consulta la guía complementaria Medición del aislamiento en campo e índices.

1. Adquisición de la respuesta al impulso (ISO 18233)

Sección titulada «1. Adquisición de la respuesta al impulso (ISO 18233)»

Una sala se comporta, con buena aproximación, como un sistema lineal e invariante en el tiempo, así que todo sobre ella está contenido en su RI. Podrías disparar una pistola y grabar la cola, pero una excitación determinista reproducida por un altavoz y deconvolucionada recupera la misma RI con 20–30 dB más de relación señal-ruido efectiva (ISO 18233). Se proporcionan dos excitaciones.

Barrido sinusoidal exponencial (ESS, Anexo B). La frecuencia instantánea crece exponencialmente,

de modo que el tiempo invertido por octava es constante y la excitación imita al ruido rosa (energía constante por banda de octava fraccionaria). La RI se recupera mediante división espectral lineal (con relleno de ceros, no circular),

con un pequeño término de Tikhonov que protege los extremos de banda donde el barrido tiene poca energía. Como un barrido de grave a agudo sitúa la distorsión armónica en tiempos de llegada negativos, la distorsión se separa limpiamente de la RI lineal y se descarta conservando solo la parte causal. El método "farina" llega al mismo resultado convolucionando la grabación con el filtro inverso analítico; supone que el barrido de referencia se generó con la amplitud y el desvanecimiento por defecto, así que usa el método espectral con un barrido de amplitud distinta de la unidad o con desvanecimiento personalizado.

Secuencia de longitud máxima (MLS, Anexo A). Una secuencia binaria de orden N y longitud cuya autocorrelación circular es una delta casi perfecta; la RI se obtiene de la correlación cruzada circular del periodo grabado con la secuencia. La MLS excita con amplitud constante y es rápida de promediar, pero es más sensible a la varianza temporal (corrientes de aire, deriva de temperatura) y no admite tanta potencia como un barrido. Prefiere el barrido para salas y cerramientos; recurre a la MLS cuando la excitación deba ser periódica o el hardware favorezca una señal de dos niveles.

Cadena de medición indirecta ISO 18233: una excitación (barrido ESS o MLS) alimenta un altavoz en la sala, un micrófono capta la respuesta y la deconvolución (correlación o filtro inverso) recupera la respuesta al impulsoCadena de medición indirecta ISO 18233: una excitación (barrido ESS o MLS) alimenta un altavoz en la sala, un micrófono capta la respuesta y la deconvolución (correlación o filtro inverso) recupera la respuesta al impulso
import numpy as np
from scipy.signal import fftconvolve
from phonometry import room
fs = 48000
# Un barrido de 3 s, 20 Hz - 20 kHz es una buena excitación de sala de banda ancha
# sweep: excitación que reproduces por el altavoz
sweep = room.sweep_signal(fs, 20.0, 20000.0, 3.0)
# Deconvoluciona la respuesta grabada para recuperar la respuesta al impulso
system = np.zeros(fs); system[100] = 1.0; system[2000] = 0.4 # directo + reflexión
# recorded: captura de micrófono del barrido reproducido (aquí simulada por convolución con una sala sintética)
recorded = fftconvolve(sweep, system)
ir = room.impulse_response(recorded, sweep, fs, method="spectral")
print(int(np.argmax(np.abs(ir)))) # 100: sonido directo recuperado
ir.plot() # forma de onda + envolvente de Schroeder (figura de abajo)
# Variante de filtro inverso de Farina (necesita la banda del barrido)
ir_f = room.impulse_response(recorded, sweep, fs, method="farina", f_range=(20.0, 20000.0))
# MLS periódica: excita con >= 2 periodos, promedia, correlaciona
mls = room.mls_signal(16) # longitud 2**16 - 1 = 65535
rec = fftconvolve(np.tile(mls, 2), system)[: 2 * mls.size]
ir_m = room.mls_impulse_response(rec, mls)
print(int(np.argmax(np.abs(ir_m)))) # 100

sweep_signal/mls_signal devuelven arrays simples, listos para escribir en un WAV y reproducir. impulse_response/mls_impulse_response devuelven ahora un ImpulseResponseResult, un sustituto directo del array de la RI (np.asarray(ir), la indexación y ir.size siguen funcionando, de modo que room_parameters(ir, fs) no cambia) que además guarda la frecuencia de muestreo y el método y añade un .plot(). Dos excitaciones más de la literatura de medición de funciones de transferencia - los pares complementarios de Golay con deconvolución exactamente libre de ruido, y los barridos conformados a un espectro objetivo arbitrario - viven en la guía de medición de sistemas y devuelven los mismos tipos de resultado.

Las dos excitaciones. El barrido exponencial desplaza su energía hacia frecuencias altas a lo largo de toda la señal, mientras que la MLS es una secuencia de dos niveles con espectro plano, visible como la magnitud casi constante de la derecha.

Señales de excitación ISO 18233: la forma de onda del barrido sinusoidal exponencial y su espectrograma con el ascenso exponencial de frecuencia, y una secuencia de longitud máxima con su espectro de magnitud planoSeñales de excitación ISO 18233: la forma de onda del barrido sinusoidal exponencial y su espectrograma con el ascenso exponencial de frecuencia, y una secuencia de longitud máxima con su espectro de magnitud plano
Ver el código de esta figura
from phonometry import room
from phonometry import plot_excitation
fs = 48000
sweep = room.sweep_signal(fs, 50.0, 20000.0, 1.0) # excitación ESS
mls = room.mls_signal(12).astype(float) # longitud 2**12 - 1
# Una línea: forma de onda + espectrograma (barrido), secuencia + espectro (MLS)
plot_excitation(sweep, fs, kind="sweep")
plot_excitation(mls, fs, kind="mls")
# A mano: el espectrograma del barrido y el espectro de magnitud de la MLS
import numpy as np
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
ax1.specgram(sweep, NFFT=1024, Fs=fs, noverlap=512)
ax1.set(xlabel="Tiempo [s]", ylabel="Frecuencia [Hz]", title="Espectrograma del barrido")
spec = np.abs(np.fft.rfft(mls))
freqs = np.fft.rfftfreq(mls.size, d=1.0 / fs)
ax2.semilogx(freqs[1:], 20 * np.log10(spec[1:] / np.median(spec[1:])))
ax2.set(xlabel="Frecuencia [Hz]", ylabel="Magnitud [dB]", title="Espectro de la MLS (plano)")

La respuesta al impulso recuperada. Deconvolucionar la grabación da la RI de banda ancha: el sonido directo, las reflexiones tempranas discretas y la cola difusa que decae. Su .plot() muestra la forma de onda arriba y la envolvente log-magnitud con la curva de decaimiento de energía de Schroeder abajo: el decaimiento recto cuya pendiente se convierte en el tiempo de reverberación del §2.

Un barrido exponencial cruza una sala dibujada mientras se construye el espectrograma de la grabación, con las reflexiones discretas apareciendo como copias retardadas de la cresta principal; después el filtro inverso colapsa toda la grabación en la respuesta al impulso.

Descargar la animación (WebM)

Un barrido exponencial cruza una sala dibujada mientras se construye el espectrograma de la grabación, con las reflexiones discretas apareciendo como copias retardadas de la cresta principal; después el filtro inverso colapsa toda la grabación en la respuesta al impulso.

Descargar la animación (WebM)

Respuesta al impulso de la sala recuperada: la forma de onda normalizada con el sonido directo y las reflexiones etiquetadas, y debajo la envolvente log-magnitud en dB con la curva de decaimiento de energía de SchroederRespuesta al impulso de la sala recuperada: la forma de onda normalizada con el sonido directo y las reflexiones etiquetadas, y debajo la envolvente log-magnitud en dB con la curva de decaimiento de energía de Schroeder
Ver el código de esta figura
import numpy as np
from scipy.signal import fftconvolve
from phonometry import room
fs = 48000
sweep = room.sweep_signal(fs, 20.0, 20000.0, 1.5)
# Una sala sintética: sonido directo + dos reflexiones + cola difusa que decae
system = np.zeros(int(0.7 * fs))
system[80], system[1400], system[3100] = 1.0, 0.5, 0.32
ir = room.impulse_response(fftconvolve(sweep, system), sweep, fs, length=system.size)
# Una línea: forma de onda + log-magnitud / decaimiento de Schroeder
ir.plot(language="es")
# A mano: la envolvente log-magnitud normalizada en dB
import matplotlib.pyplot as plt
h = np.asarray(ir)
t = np.arange(h.size) / fs
plt.plot(t, 20 * np.log10(np.abs(h) / np.max(np.abs(h))))
plt.ylim(-80, 5)
plt.xlabel("Tiempo [s]"); plt.ylabel("Nivel re pico [dB]")

Dónde medir. Una RI caracteriza un único par fuente–receptor; un parámetro de sala se obtiene promediando sobre varios. ISO 3382-1 (espacios para interpretación) pide al menos dos posiciones de fuente y micrófonos separados m entre sí, m de cualquier superficie, a m (altura de oído sentado); ISO 3382-2 fija el número mínimo de posiciones de fuente, de micrófono y de combinaciones fuente–micrófono según el grado de exactitud (control / ingeniería / precisión) y pide posiciones de micrófono que eviten las colocaciones simétricas.

Configuración de medición de acústica de salas: una planta de la sala en vista superior con dos posiciones de fuente (altavoz) y seis posiciones de micrófono con las reglas de separación de ISO 3382-1, y la tabla de ISO 3382-2 con el número mínimo de posiciones para los grados de control, ingeniería y precisiónConfiguración de medición de acústica de salas: una planta de la sala en vista superior con dos posiciones de fuente (altavoz) y seis posiciones de micrófono con las reglas de separación de ISO 3382-1, y la tabla de ISO 3382-2 con el número mínimo de posiciones para los grados de control, ingeniería y precisión

Promediar entre posiciones. El parámetro por banda que se informa es la media aritmética sobre todas las combinaciones fuente-micrófono, y la dispersión entre posiciones es parte de la respuesta, no ruido: indícala junto a la media siempre que supere la diferencia apenas perceptible (DAP) del parámetro (§2), porque una sala puede cumplir un objetivo en promedio mientras butacas concretas quedan muy fuera de él. Cuatro errores de colocación sesgan la propia media:

  • Posiciones correlacionadas. Micrófonos a menos de 2 m entre sí muestrean casi el mismo campo sonoro dos veces, así que el promedio parece más estable de lo que es. El mínimo de 1 m a cualquier superficie evita, a su vez, el refuerzo de presión junto a un contorno (y el filtro en peine de la animación de más abajo) que colorea todo lo que graba un micrófono demasiado cercano.

El sonido directo y una reflexión del suelo llegan al micrófono; al cambiar la altura del micrófono varía el retardo entre los dos caminos y el filtro en peine de la respuesta en frecuencia se mueve con él, y por eso importa la posición de medición cerca de superficies reflectantes.

Descargar la animación (WebM)

El sonido directo y una reflexión del suelo llegan al micrófono; al cambiar la altura del micrófono varía el retardo entre los dos caminos y el filtro en peine de la respuesta en frecuencia se mueve con él, y por eso importa la posición de medición cerca de superficies reflectantes.

Descargar la animación (WebM)

  • Colocaciones simétricas. En una sala geométricamente simétrica, las posiciones especulares reciben patrones de reflexión especulares; promediarlas no añade información nueva. Por eso la ISO 3382-2 pide posiciones que no caigan sobre líneas de simetría.
  • Demasiado cerca de la fuente. Dentro del campo directo el EDT se desploma y el C80 se satura hacia arriba haga lo que haga la sala. La ISO 3382-2 mantiene por ello cada micrófono al menos a de la fuente, con una estimación del tiempo de reverberación esperado (unos 2,2 m para un aula de 200 m³ con 0,5 s esperados).
  • La lotería de baja frecuencia. Por debajo de la frecuencia de Schroeder (§2) cada banda contiene solo un puñado de modos propios, y un micrófono sobre un nodo de uno de ellos ve un decaimiento distinto que otro sobre un antinodo. La dispersión de las bandas de 63-125 Hz entre posiciones es estructuralmente mayor; el remedio son más posiciones, no una excitación más larga.

Parámetros de sweep_signal() / inverse_filter()

Sección titulada «Parámetros de sweep_signal() / inverse_filter()»
ParámetroTipoUnidadesRango / valor por defectoNotas
fsintHz> 0Frecuencia de muestreo
f1floatHz> 0, en/por debajo de la banda más bajaFrecuencia inicial del barrido
f2floatHzf1 < f2 <= fs/2Frecuencia final del barrido
secondsfloatscualquiera; mayor ⇒ más SNRDuración del barrido
amplitudefloatpor defecto 1.0Amplitud de pico
fadefloat[0, 0.5), por defecto 0.01Fracción de fundido medio Hann (elimina transitorios de inicio/fin)
ParámetroTipoUnidadesRango / valor por defectoNotas
recordedarray 1Dcualquierano vacíoRespuesta del sistema grabada
referencearray 1Dcualquierano vacíoEl barrido emitido
fsintHz> 0Frecuencia de muestreo
methodstr'spectral' (por defecto) / 'farina''farina' requiere f_range
f_range(float, float)Hzpor defecto None(f1, f2) del barrido (solo Farina)
regularizationfloatpor defecto 1e-6Término de Tikhonov como fracción de la energía espectral de pico
lengthint, opcionalmuestraspor defecto len(recorded)Muestras de RI causal a devolver
return_fullboolpor defecto FalseDevuelve la secuencia completa (distorsión en la cola)

mls_signal(order) toma un entero order en 2–20 (longitud de secuencia ); mls_impulse_response(recorded, mls, length=None) necesita que recorded abarque un número entero de periodos de MLS.

2. Análisis del decaimiento y parámetros de sala (ISO 3382-1/2)

Sección titulada «2. Análisis del decaimiento y parámetros de sala (ISO 3382-1/2)»

La RI se filtra en bandas de octava (o de tercio de octava) y cada banda se convierte en una curva de decaimiento mediante la integración inversa de Schroeder de la RI al cuadrado:

Integrar hacia atrás elimina la fluctuación que afecta a la RI al cuadrado en bruto y produce una curva suave cuya pendiente es la tasa de decaimiento. El ruido de fondo haría que se estabilizara, así que la integración se trunca donde la recta de decaimiento ajustada cruza el suelo de ruido y la cola que falta se compensa suponiendo un decaimiento exponencial.

Los tiempos de reverberación provienen de un ajuste lineal por mínimos cuadrados sobre un rango de evaluación, extrapolado a una caída completa de 60 dB, : EDT de 0 a −10 dB (reverberación percibida), T20 de −5 a −25 dB y T30 de −5 a −35 dB. Los repartos de energía en una frontera temprano/tardío dan la claridad y la definición,

con ms → C50 (habla) y ms → C80 (música), más el tiempo central . Cada parámetro tiene una diferencia apenas perceptible (ISO 3382-1 Tabla A.1: EDT 5 %, C80 1 dB, D50 0,05, Ts 10 ms) que fija con qué precisión merece la pena informarlo.

La energía de la cola de la respuesta al impulso al cuadrado se rellena desde el final mientras la integral hacia atrás avanza hacia t = 0, y la curva de decaimiento de Schroeder emerge en un eje inferior, terminando con las rectas de regresión T20 y T30.

Descargar la animación (WebM)

La energía de la cola de la respuesta al impulso al cuadrado se rellena desde el final mientras la integral hacia atrás avanza hacia t = 0, y la curva de decaimiento de Schroeder emerge en un eje inferior, terminando con las rectas de regresión T20 y T30.

Descargar la animación (WebM)

Respuesta al impulso al cuadrado con su curva de decaimiento integrada hacia atrás de Schroeder, y las ventanas de regresión EDT, T20 y T30 marcadasRespuesta al impulso al cuadrado con su curva de decaimiento integrada hacia atrás de Schroeder, y las ventanas de regresión EDT, T20 y T30 marcadas

La RI al cuadrado dentada (gris) se integra hasta la curva suave de Schroeder (azul); las ventanas EDT, T20 y T30 se ajustan sobre esa curva y cada una se extrapola a un decaimiento de 60 dB.

import numpy as np
from phonometry import room
fs = 48000
# Decaimiento de pendiente única con T = 1 s: p^2 = exp(-13.8155 t) (60/ln(10)/13.8155 = 1)
t = np.arange(fs) / fs
# ir: respuesta al impulso de sala medida; aquí la sustituye un decaimiento sintético de pendiente única.
ir = np.concatenate([np.zeros(10), np.exp(-13.8155 * t / 2.0)])
time, level = room.decay_curve(ir, fs) # curva de Schroeder (0 dB en t = 0)
res = room.room_parameters(ir, fs, limits=None) # banda única de banda ancha
print(round(float(res.t30[0]), 2)) # 1.0 s
print(round(float(res.c80[0]), 2)) # 3.05 dB
print(round(float(res.d50[0]), 3)) # 0.499
print(round(float(res.ts[0]) * 1000, 0)) # 72 ms
# Bandas de octava 125 Hz - 4 kHz (por defecto en ISO 3382-1); usa fraction=3 para tercios
octaves = room.room_parameters(ir, fs)
print(octaves.frequency) # ~[126, 251, 501, 1000, 1995, 3981]
print(octaves.t30_valid) # indicadores de rango dinámico por banda
octaves.plot() # barras EDT/T20/T30 + C50/C80 por banda (requiere matplotlib)
room.decay_curve(ir, fs).plot() # curva de Schroeder con los ajustes EDT/T20/T30
Ver el código de esta figura
import matplotlib.pyplot as plt
import numpy as np
from phonometry import room
fs = 48000
# Decaimiento de pendiente única con T = 1 s: p^2 = exp(-13.8155 t) (60/ln(10)/13.8155 = 1)
t = np.arange(fs) / fs
# ir: respuesta al impulso de sala medida; aquí la sustituye un decaimiento sintético de pendiente única.
ir = np.concatenate([np.zeros(10), np.exp(-13.8155 * t / 2.0)])
time, level = room.decay_curve(ir, fs) # curva de Schroeder (0 dB en t = 0)
# En una línea — la curva de Schroeder con los ajustes rectos EDT/T20/T30:
decay = room.decay_curve(ir, fs) # un DecayCurve (se sigue desempaquetando como time, level)
decay.plot(language="es")
plt.show()
# A mano, el decaimiento es solo la curva de Schroeder; marca los niveles de evaluación:
fig, ax = plt.subplots()
ax.plot(time, level, color="#1f77b4", label="Curva de Schroeder")
for db in (-5.0, -25.0, -35.0): # bordes de la ventana de evaluación T20 / T30
ax.axhline(db, ls=":", alpha=0.4)
ax.set_xlabel("Tiempo [s]")
ax.set_ylabel("Nivel re régimen permanente [dB]")
ax.set_ylim(top=3.0)
ax.legend()
plt.show()

Para este decaimiento de pendiente única, EDT, T20 y T30 devuelven todos ≈ 1,0 s, y los parámetros de energía coinciden con sus formas cerradas (C80 = 3,05 dB, D50 = 0,499, Ts = 72 ms). Una sala real tiene una pendiente inicial más pronunciada, así que EDT < T30.

Sobre un decaimiento real, dependiente de la frecuencia, el .plot() por bandas es el resumen de trabajo de toda la medición: los tiempos de caída como barras agrupadas por octava (bandas no válidas rayadas) sobre un segundo panel con C50 y C80.

Parámetros por banda ISO 3382 de una respuesta al impulso sintética de sala: barras agrupadas de EDT, T20 y T30 por banda de octava que caen de unos 1,4 s a 125 Hz a 0,7 s a 4 kHz, sobre un segundo panel donde C50 y C80 suben con la frecuenciaParámetros por banda ISO 3382 de una respuesta al impulso sintética de sala: barras agrupadas de EDT, T20 y T30 por banda de octava que caen de unos 1,4 s a 125 Hz a 0,7 s a 4 kHz, sobre un segundo panel donde C50 y C80 suben con la frecuencia

Una sala cuyo tiempo de reverberación cae de 1,4 s a 125 Hz a 0,7 s a 4 kHz, la firma típica de una sala amueblada cuya absorción crece con la frecuencia; la claridad sube a medida que el decaimiento se acorta.

Mostrar el código de esta figura
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
from phonometry import room
# Una RIR sintética con decaimiento dependiente de la frecuencia: portadoras
# de ruido por banda de octava cuyo T60 cae de 1,4 s a 125 Hz a 0,7 s a 4 kHz.
fs = 48000
rng = np.random.default_rng(3382)
t = np.arange(int(1.6 * fs)) / fs
ir = np.zeros_like(t)
for fc, t60 in [(125.0, 1.4), (250.0, 1.25), (500.0, 1.1),
(1000.0, 1.0), (2000.0, 0.85), (4000.0, 0.7)]:
sos = signal.butter(4, [fc / np.sqrt(2), fc * np.sqrt(2)],
btype="bandpass", fs=fs, output="sos")
carrier = signal.sosfilt(sos, rng.standard_normal(t.size))
ir += carrier * np.exp(-3.0 * np.log(10.0) / t60 * t)
# Una línea: barras EDT/T20/T30 por banda + C50/C80 (requiere matplotlib).
octaves = room.room_parameters(ir, fs)
octaves.plot(language="es")
plt.show()
# A mano: el espectro de T30 desde los campos del resultado.
fig, ax = plt.subplots()
ax.bar(np.arange(octaves.t30.size), octaves.t30)
ax.set_xticks(np.arange(octaves.t30.size))
ax.set_xticklabels([f"{f:g}" for f in octaves.frequency])
ax.set_xlabel("Frecuencia central de banda de octava [Hz]")
ax.set_ylabel("T30 [s]")
plt.show()

Leer EDT, T20 y T30 unos contra otros. Los tres tiempos extrapolan el mismo decaimiento de 60 dB desde ventanas distintas, así que su desacuerdo lleva información:

  • T20 ≈ T30 (curvatura por debajo del 10 %): el decaimiento se acerca a una única pendiente recta en ambas ventanas de evaluación, algo compatible con un campo difuso (aunque no lo demuestra), y cualquiera de los dos tiempos puede representar “el” tiempo de reverberación de la banda.
  • T30 > T20 (curvatura por encima del 10 %): el decaimiento se comba, con la energía tardía decayendo más despacio que la temprana. Las causas habituales son volúmenes acoplados (una puerta abierta a un pasillo o a una escalera, un anfiteatro profundo o una caja escénica devolviendo energía) y una absorción muy desigual que deja reverberante un eje de la sala. Ningún número único describe ese decaimiento: informa de ambas ventanas junto con la curvatura, y trata con recelo las predicciones estadísticas, porque su hipótesis de campo difuso ha fallado a la vista.
  • EDT lejos de T20/T30: el EDT se ajusta donde aún dominan el sonido directo y las primeras reflexiones, así que varía de butaca en butaca mientras el T30 apenas se mueve. Un EDT por debajo del T30 dice que la posición recibe mucha energía temprana (cerca de la fuente, bajo un reflector): la sala suena allí más seca de lo que sugiere su T30, porque la reverberación percibida sigue al EDT. Un EDT por encima del T30 en una butaca apunta a un eco o a una superficie focalizante que concentra allí energía tardía.

Cuánto decaimiento permite el suelo de ruido. Una ventana de ajuste vale lo que el rango de decaimiento que tiene debajo. La relación impulso-ruido (INR) es la distancia de nivel entre el pico de la RI filtrada en banda y su suelo de ruido; la ventana de ajuste más un margen de seguridad debe caber dentro de ella, que es el requisito ISO 3382 de al menos 35 dB de rango útil de decaimiento para T20 y 45 dB para T30. Un rango escaso sesga el tiempo ajustado hacia arriba, hacia la cola plana que el suelo de ruido impone a la curva de decaimiento, y el sesgo crece en silencio antes de que el ajuste falle a la vista (Hak, Wenmaekers y van Luxemburg, 2012). room_parameters informa del dynamic_range por banda y endurece los límites de aceptación a 46 dB (T20) y 54 dB (T30) antes de marcar un valor como válido, de modo que el sesgo residual de truncado y compensación de un tiempo marcado válido quede dentro de la DAP del 5 %. Cuando una banda no supera su indicador, el orden de remedios es: usa T20 en lugar de T30 (su ventana necesita 10 dB menos de rango según los mínimos ISO, 8 dB con los límites endurecidos); sube la INR en la adquisición, porque duplicar la longitud del barrido o el número de promedios síncronos gana 3 dB cada vez; y solo entonces recurre al EDT, nunca a un ajuste estirado dentro del ruido.

Por debajo de la frecuencia de Schroeder estas estadísticas de caída dejan de contar toda la historia: el campo lo gobiernan modos propios discretos. La simulación siguiente excita la misma sala rígida de 5 m por 3,5 m en su modo (2,1) y después entre dos modos; en resonancia un patrón de onda estacionaria con líneas nodales fijas crece hasta dominar el mapa de presión RMS, fuera de resonancia la sala sigue respondiendo, pero el campo forzado se mantiene débil y nunca se organiza en ese patrón nodal (2,1).

Simulación FDTD 2D de una sala rígida de 5 por 3,5 metros excitada en el modo (2,1) de 84 Hz y en una frecuencia fuera de modo, lado a lado. En resonancia un patrón de onda estacionaria con líneas nodales fijas crece hasta dominar el mapa de presión RMS; fuera de resonancia la respuesta forzada se mantiene débil y nunca se organiza en esa estructura nodal.

Descargar la animación (WebM)

Simulación FDTD 2D de una sala rígida de 5 por 3,5 metros excitada en el modo (2,1) de 84 Hz y en una frecuencia fuera de modo, lado a lado. En resonancia un patrón de onda estacionaria con líneas nodales fijas crece hasta dominar el mapa de presión RMS; fuera de resonancia la respuesta forzada se mantiene débil y nunca se organiza en esa estructura nodal.

Descargar la animación (WebM)

ParámetroTipoUnidadesRango / valor por defectoNotas
irarray 1Dcualquierano silenciosoRespuesta al impulso medida
fsintHz> 0Frecuencia de muestreo
limits(float, float) o NoneHzpor defecto (125.0, 4000.0)Límites de centros de banda; None = banda única de banda ancha
fractionint1 (octava, por defecto) / 3 (tercio)Fracción de ancho de banda
zero_phasebooldefecto FalseFiltrado de octava hacia delante y atrás (NOTA de ISO 3382-2, 7.3, que relaja a ); elimina el retardo de grupo del filtro antes de la integración inversa y reduce aproximadamente a la mitad el sesgo de T30 corto a 125 Hz (~+4,9 % → +2,4 % con = 0,2 s). decay_curve también lo acepta

Devuelve un RoomAcousticsResult: frequency (centros de banda, o None en banda ancha), edt/t20/t30 (s), c50/c80 (dB), d50, ts (s), dynamic_range (dB), los indicadores edt_valid/t20_valid/t30_valid (ISO 3382-1, 5.3.3: ruido ≥ 25 dB por debajo del pico para EDT, endurecido a 46 dB para T20 y 54 dB para T30 para que el sesgo de compensación de cola de un valor marcado como válido quede dentro de la DAP del 5 %) y curvature % (valores por encima del 10 % señalan un decaimiento no recto). decay_curve(ir, fs, band=None, fraction=1, zero_phase=False) devuelve solo la curva (time, level) para una banda o la respuesta de banda ancha.

RoomAcousticsResult.report(path) genera una ficha PDF de una página con el formato de un informe de medición de acústica de salas (un espacio para espectáculos según la ISO 3382-1:2009 o una sala ordinaria según la ISO 3382-2:2008, ambos evaluados por el método de la respuesta al impulso integrada): una línea de norma base, un bloque opcional de metadatos de cabecera, la tabla de parámetros por bandas a ancho completo (, , EDT, , , , ) sobre la gráfica de tiempos de caída por banda del propio resultado (.plot()), el resultado enmarcado del tiempo de reverberación de frecuencias medias (la media de los de las octavas de 500 Hz y 1000 Hz, el descriptor habitual de la sala) con el EDT de medias al lado, y un pie con el descargo de responsabilidad fijo. La ISO 3382-1/-2 son normas de caracterización sin apto/no apto intrínseco, por lo que solo aparece una fila de veredicto cuando se aporta un tiempo de reverberación de medias objetivo mediante el campo requirement de los metadatos (ReportMetadata(requirement=...), leído como el máximo aceptable, la forma habitual de un límite de aula u oficina diáfana). Un resultado de banda ancha no tiene octavas de 500 Hz / 1000 Hz que promediar, de modo que su recuadro y su veredicto recurren al de banda ancha sin afirmación de “500-1000 Hz”. Usa el mismo contenedor ReportMetadata y el mismo motor de renderizado que la ficha de absorción ISO 11654; los campos específicos de sala room_volume, source_positions y receiver_positions rellenan la cabecera (la ISO 3382 exige indicar el volumen de la sala y el número de posiciones de fuente y de micrófono), junto con test_room (el nombre de la sala), specimen (la descripción de la sala y su estado de ocupación), area, instrumentation, temperature, relative_humidity, pressure, measurement_standard, test_date, laboratory, operator, report_id y notes. Al pasar metadata=None se obtiene una ficha de caracterización mínima. 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 separador decimal de coma).

from phonometry import room, ReportMetadata
result = room.room_parameters(ir, fs) # bandas de octava 125 Hz - 4 kHz
result.report(
"ficha_sala.pdf",
metadata=ReportMetadata(
specimen="Auditorio pequeño, desocupado, totalmente amueblado",
test_room="Auditorio A",
room_volume=2830.0, area=340.0,
source_positions=2, receiver_positions=8,
measurement_standard="ISO 3382-1",
temperature=21.0, relative_humidity=45.0,
laboratory="Laboratorio de referencia Phonometry",
requirement=1.3, # añade un veredicto frente a un T_mid objetivo
),
) # T_mid + la tabla de parámetros por banda

La ficha de ejemplo se regenera con make reports y se mantiene renderizada en el repositorio; haz clic en la vista previa para abrir el PDF.

Informe de ejemplo de parámetros acústicos de salas ISO 3382 (PDF)

Ficha de acústica de salas de una página: una cabecera de metadatos (cliente, sala, descripción, volumen de la sala, superficie del suelo, posiciones de fuente y de micrófono, instrumentación, temperatura, humedad y presión), la tabla de parámetros por bandas de octava (T20, T30, EDT, C50, C80, D50 y Ts de 125 Hz a 4 kHz) sobre la gráfica de barras de tiempos de caída por banda, el tiempo de reverberación de medias enmarcado T_mid = 1,15 s con el EDT de medias al lado, y un veredicto CUMPLE frente al objetivo de 1,3 s.

Descargar el informe (PDF)

Ficha de parámetros acústicos de salas (RoomAcousticsResult.report), T_mid y la tabla por banda.

La acústica de oficinas diáfanas trata de la privacidad del habla: con qué rapidez el habla de un hablante se desvanece hasta la ininteligibilidad a medida que uno se aleja. Los niveles y el STI se miden a lo largo de una fila de puestos de trabajo (al menos 4 posiciones, preferiblemente 6–10), y cuatro magnitudes de un solo número resumen la sala. La tasa de decaimiento espacial del habla ponderada A es la pendiente del nivel frente a , escalada a una cifra por duplicación usando solo las posiciones de 2–16 m,

con Lp,A,S,4m leído en la misma recta a 4 m. La distancia de distracción rD (STI = 0,50) y la distancia de privacidad rP (STI = 0,20) provienen de una regresión lineal del STI frente a la distancia. Las buenas oficinas empujan rD por debajo de ~5 m; las malas dejan el habla molesta más allá de 10 m.

Línea de medición de oficina diáfana ISO 3382-3 desde la fuente a 1 m a lo largo de posiciones de 2 m a 16 m, que alimenta las cuatro magnitudes de índice único D2,S, Lp,A,S,4m, rD y rPLínea de medición de oficina diáfana ISO 3382-3 desde la fuente a 1 m a lo largo de posiciones de 2 m a 16 m, que alimenta las cuatro magnitudes de índice único D2,S, Lp,A,S,4m, rD y rP
import numpy as np
from phonometry import room
r = np.array([2.0, 4.0, 6.0, 8.0, 12.0, 16.0]) # distancias al hablante (m)
lp = 65.0 - 7.0 * np.log2(r) # nivel de habla ponderado A (dB)
sti = 0.70 - 0.03 * r # STI por posición
m = room.open_plan_metrics(r, lp, sti)
print(round(m.d2s, 1), round(m.lp_as_4m, 1)) # 7.0 dB, 51.0 dB
print(round(m.rd, 1), round(m.rp, 1)) # 6.7 m, 16.7 m
m.plot() # la regresión de decaimiento espacial de la figura de abajo
Decaimiento espacial en oficina abierta: nivel de habla ponderado A y STI frente a la distancia a la fuente en eje logarítmico, con la regresión D2,S, el marcador Lp,A,S,4m a 4 m y los cruces de distancia rD y rPDecaimiento espacial en oficina abierta: nivel de habla ponderado A y STI frente a la distancia a la fuente en eje logarítmico, con la regresión D2,S, el marcador Lp,A,S,4m a 4 m y los cruces de distancia rD y rP
Ver el código de esta figura
import matplotlib.pyplot as plt
import numpy as np
from phonometry import room
r = np.array([2.0, 4.0, 6.0, 8.0, 12.0, 16.0]) # distancias al hablante (m)
lp = 65.0 - 7.0 * np.log2(r) # nivel de habla ponderado A (dB)
sti = 0.70 - 0.03 * r # STI por posición
m = room.open_plan_metrics(r, lp, sti)
# En una línea: la regresión D2,S reconstruida con los campos del resultado,
# con los cruces rD / rP marcados (la figura superior añade además los puntos
# medidos y el eje de STI):
m.plot(language="es")
plt.show()
import matplotlib.pyplot as plt
import numpy as np
from phonometry import room
r = np.array([2.0, 4.0, 6.0, 8.0, 12.0, 16.0]) # distancias al hablante (m)
lp = 65.0 - 7.0 * np.log2(r) # nivel de habla ponderado A (dB)
sti = 0.70 - 0.03 * r # STI por posición
m = room.open_plan_metrics(r, lp, sti)
# Decaimiento espacial: Lp,A,S medido frente a la distancia en eje logarítmico,
# la regresión D2,S reconstruida con los campos del resultado, y el STI con los
# cruces rD / rP en un eje gemelo:
b = -m.d2s / np.log10(2.0) # pendiente de la regresión frente a lg(r)
a = m.lp_as_4m - b * np.log10(4.0) # ordenada desde el nivel a 4 m
rr = np.logspace(np.log10(2.0), np.log10(16.0), 100)
fig, ax = plt.subplots()
ax.semilogx(r, lp, "o", label="Lp,A,S medido")
ax.semilogx(rr, a + b * np.log10(rr), "--", label=f"D2,S = {m.d2s:.1f} dB")
ax.plot(4.0, m.lp_as_4m, "D", label=f"Lp,A,S,4m = {m.lp_as_4m:.0f} dB")
ax.set_xlabel("Distancia al hablante r [m]")
ax.set_ylabel("Nivel de habla ponderado A [dB]")
ax.set_xlim(1.8, 20.0)
twin = ax.twinx()
twin.semilogx(r, sti, "s-", color="#2ca02c", label="STI")
twin.axvline(m.rd, ls=":", color="#2ca02c")
twin.axvline(m.rp, ls=":", color="#9467bd")
twin.annotate(f"rD = {m.rd:.1f} m", (m.rd, 0.52))
twin.annotate(f"rP = {m.rp:.1f} m", (m.rp, 0.22))
twin.set_ylabel("STI")
twin.set_ylim(0.0, 1.0)
lines, labels = ax.get_legend_handles_labels()
tl, tlab = twin.get_legend_handles_labels()
ax.legend(lines + tl, labels + tlab, loc="best")
plt.show()
ParámetroTipoUnidadesRango / valor por defectoNotas
positions_marray 1Dm≥ 4 posiciones, todas > 0Distancias fuente-receptor
spl_a_speecharray 1DdBmisma longitudNivel de habla ponderado A Lp,A,S,n por posición
sti_valuesarray 1Dmisma longitudSTI por posición (método completo de IEC 60268-16)

Devuelve un OpenPlanResult con d2s, lp_as_4m, rd y rp; su .plot() redibuja la regresión de decaimiento espacial del apartado 6.2 a partir de esos cuatro campos y marca rd / rp. d2s/lp_as_4m son nan si menos de dos posiciones caen en 2–16 m; rd/rp son nan cuando el STI no decrece con la distancia. El STI por posición puede medirse a su vez con las herramientas STIPA de la guía del índice de transmisión del habla.

OpenPlanResult.report(path) renderiza una ficha PDF de una página con el formato de un informe de medición de privacidad acústica en oficinas diáfanas: la línea de norma base, un bloque de cabecera de metadatos opcional, una tabla compacta de las cuatro magnitudes de número único del apartado 4 (, , la distancia de distracción y la distancia de privacidad ) apilada sobre la gráfica de decaimiento espacial a todo el ancho del resultado (.plot(), la regresión del apartado 6.2 en el eje logarítmico de distancia con la lectura a 4 m y los cruces / marcados, la curva al estilo de la Figura 3), el enmarcado con las demás magnitudes al lado, y un pie con el descargo fijo. La ISO 3382-3 caracteriza un espacio en lugar de definir un apto/no apto intrínseco, por lo que la fila de veredicto aparece solo cuando se suministra una tasa de decaimiento espacial objetivo a través del campo requirement de los metadatos (ReportMetadata(requirement=...), interpretada como el mínimo aceptable en dB, según los intervalos de calidad informativos del Anexo A donde un mayor decaimiento espacial es mejor; la sala cumple igualando o superando el objetivo). Usa el mismo contenedor ReportMetadata y el mismo motor de renderizado que la ficha de acústica de salas ISO 3382-1/-2; los campos propios de oficinas diáfanas area (superficie del suelo), source_positions y receiver_positions (el número de posiciones de medición) rellenan la cabecera, junto con client, test_room (la oficina o zona), specimen (la descripción y el estado de amueblamiento), instrumentation, temperature, relative_humidity, pressure, measurement_standard, test_date, laboratory, operator, report_id y notes. Al pasar metadata=None se obtiene una ficha de caracterización simple. La ficha incrusta la gráfica de decaimiento espacial, por lo que el renderizado necesita tanto reportlab como matplotlib (pip install "phonometry[report,plot]"); solo se admite engine="reportlab". La ficha se renderiza en inglés por defecto; pasa language="es" para una ficha en español (cadenas fijas traducidas y separador decimal de coma).

import numpy as np
from phonometry import room, ReportMetadata
r = np.array([2.0, 3.0, 4.0, 6.0, 8.0, 11.0, 16.0]) # distancias al hablante (m)
lp = 62.0 - 7.0 * np.log2(r) # nivel de habla ponderado A (dB)
sti = 0.65 - 0.03 * r # STI por posición
result = room.open_plan_metrics(r, lp, sti)
result.report(
"ficha_oficina_diafana.pdf",
metadata=ReportMetadata(
test_room="Oficina diáfana B",
specimen="Amueblada, desocupada, con ruido de fondo",
area=420.0, source_positions=2, receiver_positions=7,
measurement_standard="ISO 3382-3",
temperature=22.0, relative_humidity=45.0,
laboratory="Laboratorio de referencia Phonometry",
requirement=7.0, # añade un veredicto frente a un D2,S objetivo
),
language="es",
) # D2,S + Lp,A,S,4m, rD, rP y la curva de decaimiento

La ficha de ejemplo se regenera con make reports y se mantiene renderizada en el repositorio; haz clic en la vista previa para abrir el PDF.

Informe de ejemplo de acústica de oficinas diáfanas ISO 3382-3 (PDF)

Ficha de oficina diáfana de una página: una cabecera de metadatos (cliente, oficina/zona, descripción, superficie del suelo, posiciones de fuente y de medición, instrumentación, temperatura, humedad y presión), la tabla de las cuatro magnitudes de número único (D2,S = 7,0 dB por duplicación, Lp,A,S,4m = 48,0 dB, rD = 5,0 m, rP = 15,0 m) sobre la gráfica de decaimiento espacial en un eje logarítmico de distancia con la regresión de D2,S, la lectura a 4 m y los cruces rD y rP, el D2,S enmarcado, y un veredicto CUMPLE frente al objetivo de 7,0 dB.

Descargar el informe (PDF)

Ficha de acústica de oficinas diáfanas (OpenPlanResult.report): D2,S, Lp,A,S,4m, rD, rP y la curva de decaimiento espacial.

El área de absorción acústica equivalente A que gobierna R', L'n, la corrección ambiental K2 de ISO 3744 y el término de absorción de ISO 3741 se mide a su vez en una cámara reverberante (ISO 354). Mide el tiempo de reverberación de la cámara vacía () y de nuevo con la muestra de ensayo instalada (); la absorción de la muestra es la diferencia de las dos áreas de Sabine, y dividiendo por el área cubierta se obtiene el coeficiente de absorción:

con a partir de la temperatura del aire de la cámara en °C (válida 15–30 °C) y el coeficiente de atenuación en potencia del aire (por defecto 0; convierte un de ISO 9613-1 en dB/m con attenuation_from_alpha). Como los efectos de borde y difracción pueden dispersar más energía de la que intercepta el área plana de la muestra, puede superar 1,0 y nunca se satura (ISO 354 Cláusula 3.7).

import numpy as np
from phonometry import materials
# Tiempos de reverberación en tercios de octava de una sala de 200 m^3, vacía (T1)
# y con una muestra absorbente de 10.8 m^2 instalada (T2).
t1 = np.array([5.0, 4.0, 3.0])
t2 = np.array([3.0, 2.5, 2.0])
a_empty = materials.absorption_area(t1, volume=200.0, temperature=20.0)
print(np.round(a_empty, 2)) # [ 6.45 8.06 10.75] m^2
alpha = materials.absorption_coefficient(t1, t2, volume=200.0, sample_area=10.8,
temperature1=20.0)
print(np.round(alpha, 3)) # [0.398 0.448 0.498]

T1 y T2 son exactamente los tiempos de reverberación que devuelve room_parameters, así que una medición de decaimiento ISO 3382-2 de la sala vacía y tratada fluye directamente a absorption_coefficient. Un volumen de sala por debajo del mínimo de 150 m³ o un área de muestra fuera de 10–12 m² genera un AbsorptionWarning de aviso; el resultado se devuelve igualmente.

Parámetros de absorption_area() / absorption_coefficient()

Sección titulada «Parámetros de absorption_area() / absorption_coefficient()»
ParámetroTipoUnidadesRango / valor por defectoNotas
t60 / t1, t2array 1Ds> 0Tiempo(s) de reverberación; t1 vacía, t2 con la muestra
volumefloat> 0Volumen de la sala V (aviso por debajo de 150 m³)
sample_areafloat> 0Área S que cubre la muestra (solo coeficiente)
temperature / temperature1, temperature2float°Cpor defecto 20.0, 15–30Fija c vía Ec. (6); temperature2 por defecto es temperature1
speed_of_sound (…1, …2)float, opcionalm/s> 0Sobrescribe la c derivada de la temperatura
m (m1, m2)float o array 1D1/m≥ 0, por defecto 0Coeficiente de atenuación en potencia del aire

absorption_area() devuelve el área de absorción acústica equivalente A (m²) con la forma de t60; absorption_coefficient() devuelve alpha_s; attenuation_from_alpha(alpha) convierte un alpha de ISO 9613-1 (dB/m) a m.

Cubierto. Los anexos A y B de la ISO 18233:2006, la adquisición de la respuesta al impulso por MLS y por barrido exponencial de room.mls_signal/room.sweep_signal y room.impulse_response/room.mls_impulse_response; la ISO 3382-1:2009 (apartado 5.3.3 de integración regresiva, las fórmulas de parámetros del anexo A y los requisitos de posición/separación) y la ISO 3382-2:2008 (apartado 6, los recuentos de posiciones por grado de precisión y el criterio de rango dinámico del apartado 5.3.3), calculados por room.room_parameters/room.decay_curve: EDT, T20, T30, C50, C80, D50, Ts y las marcas de validez y curvatura por banda; las magnitudes de oficina diáfana del apartado 4 y los apartados 6.2/6.3 de la ISO 3382-3:2012 (, , , ) de room.open_plan_metrics; y la absorción en cámara reverberante de los apartados 4 y 8.1 de la ISO 354:2003 mediante materials.absorption_area y materials.absorption_coefficient.

No cubierto. El anexo A de la ISO 3382-1 también define la fuerza acústica y los parámetros binaurales LF/LFC e IACC; phonometry implementa solo la familia de reverberancia y claridad citada arriba (EDT, T20, T30, C50, C80, D50, Ts). La STI por posición de la ISO 3382-3 se toma como entrada de open_plan_metrics en lugar de calcularse dentro de la función: mídela con las herramientas STIPA de la guía del Índice de Transmisión de la Palabra. Los requisitos de calificación de la sala de la ISO 354 (anexo A: número de posiciones de altavoz y micrófono, elementos difusores) no se comprueban; absorption_area/absorption_coefficient solo convierten un par / ya medido y emiten un aviso cuando el volumen de la sala o el área de la muestra caen fuera de los límites del apartado 6.

  • Aislamiento acústico en campo, en laboratorio y de predicción: el aislamiento acústico entre recintos en campo, laboratorio y predicción, y su incertidumbre de medición.
  • Potencia acústica: los métodos de LW que consumen el área de absorción de ISO 354 (el K2 de ISO 3744 y el término de absorción de ISO 3741).
  • Índice de transmisión del habla: la medición STI/STIPA que alimenta los sti_values de oficinas diáfanas.
  • Sonoridad y Métricas de calidad sonora: la sonoridad, el sharpness y las demás métricas de percepción de lo que entrega la sala.
  • Bancos de filtros: los filtros de octava fraccionaria IEC 61260 usados para las curvas de decaimiento por banda y los espectros de aislamiento.
  • Niveles: el promediado en energía y las métricas de nivel que sustentan los niveles de las salas emisora/receptora.
  • Teoría: la integración de Schroeder, las ventanas de regresión y la derivación de la curva de referencia.
  • Informe de conformidad: los decaimientos en forma cerrada y las definiciones de parámetros frente a los que se validan las implementaciones de ISO 18233 / ISO 3382 / ISO 354.
  • Referencia de la API: room.room_acoustics, room.room_ir y room.open_plan.

Cada banda de la respuesta al impulso se convierte en una curva de decaimiento mediante la integración inversa de Schroeder de la RI al cuadrado, y una recta ajustada por mínimos cuadrados sobre un rango de evaluación se extrapola a una caída completa de 60 dB, (ISO 3382-1/2): EDT de 0 a −10 dB (reverberación percibida), T20 de −5 a −25 dB y T30 de −5 a −35 dB.

¿Cuánto rango de decaimiento necesito para un T20 o T30 válido?

Sección titulada «¿Cuánto rango de decaimiento necesito para un T20 o T30 válido?»

La ventana de ajuste más un margen de seguridad debe caber dentro de la relación impulso-ruido, la distancia de nivel entre el pico de la RI filtrada en banda y su suelo de ruido: la ISO 3382 exige al menos 35 dB de rango útil de decaimiento para T20 y 45 dB para T30. Un rango escaso sesga el tiempo ajustado hacia arriba, así que room_parameters endurece sus indicadores de validez a 46 dB y 54 dB, manteniendo el sesgo dentro de la DAP del 5 %.

¿Mido la respuesta al impulso de la sala con un barrido sinusoidal o con una MLS?

Sección titulada «¿Mido la respuesta al impulso de la sala con un barrido sinusoidal o con una MLS?»

Ambos son métodos de deconvolución de ISO 18233 que recuperan la respuesta al impulso con 20–30 dB más de relación señal-ruido efectiva que una fuente impulsiva. Prefiere el barrido sinusoidal exponencial (Anexo B): sitúa la distorsión armónica en tiempos de llegada negativos, donde se descarta. Usa la MLS (Anexo A) cuando la excitación deba ser periódica o el hardware favorezca una señal de dos niveles; es más sensible a la varianza temporal.