Bancos de filtros
phonometry soporta varios tipos de filtro, cada uno con su propia función de transferencia característica. Todos los bancos sitúan sus puntos de −3 dB en los bordes de banda de ANSI S1.11, de modo que los niveles por banda son comparables entre arquitecturas.
Bandas de octava fraccionaria: las matemáticas
Sección titulada «Bandas de octava fraccionaria: las matemáticas»IEC 61260-1:2014 construye cada banda a partir de la razón de octava en base 10 (es decir, “una octava” no es exactamente 2). Para la fracción de banda , las frecuencias centrales y los bordes de banda siguen (5.2-5.5):
de modo que cada banda de tercio de octava abarca — diez bandas por década, y por eso las frecuencias nominales (25, 31,5, 40 …) se repiten escaladas por 10. phonometry diseña cada banda como una cascada SOS cuyos puntos de −3 dB caen exactamente en y en todas las arquitecturas — para Chebyshev II, Elíptico y Bessel eso exige pre-deformar (pre-warping) el mapeo analítico de los bordes de banda en lugar de confiar en la parametrización por defecto de SciPy.
Decimación multitasa
Sección titulada «Decimación multitasa»Una banda de tercio de octava de 25 Hz a 48 kHz abarca unos 5,8 Hz — el 0,024 % de Nyquist — con coeficientes tan rígidos que se vuelven numéricamente inestables. El banco lo evita filtrando las bandas bajas a una frecuencia decimada:
Parámetros de octavefilter() / OctaveFilterBank
Sección titulada «Parámetros de octavefilter() / OctaveFilterBank»| Parámetro | Tipo | Unidades | Rango / por defecto | Notas |
|---|---|---|---|---|
x | array 1D o 2D | unidades digitales | no vacío | 2D es [channels, samples] |
fs | int | Hz | > 0 | |
fraction | int | — | por defecto 1; habitual 3; cualquier b ≥ 1 | Bandas por octava = b |
order | int | — | por defecto 6 | Orden SOS por banda |
limits | lista [lo, hi] | Hz | por defecto [12, 20000] | Rango de análisis |
filter_type | str | — | 'butter' (por defecto), 'cheby1', 'cheby2', 'ellip', 'bessel' | Ver la comparación más abajo |
ripple / attenuation | float | dB | requerido por los tipos cheby/ellip | Rizado de banda de paso / atenuación de banda eliminada |
show | bool | — | por defecto False | Dibuja la respuesta del banco (requiere matplotlib) |
sigbands | bool | — | por defecto False | Devuelve también las señales temporales por banda |
zero_phase | bool | — | por defecto False | Filtrado adelante-atrás (offline) |
stateful / steady_ic (clase) | bool | — | por defecto False | Estado en streaming; consulta Procesado por bloques |
verify_filter_class(bank) comprueba el banco diseñado contra los límites de
aceptación de la Tabla 1 de IEC 61260-1 e informa de la clase (1, 2 o None si queda fuera de ambas) con los
márgenes por banda.
Comparación de filtros y zoom
Sección titulada «Comparación de filtros y zoom»Usamos secciones de segundo orden (SOS) en todos los filtros para garantizar la estabilidad numérica. La siguiente gráfica compara las arquitecturas centrándose en el punto de cruce a −3 dB.


| Tipo | Nombre | Ejemplo de uso | Ideal para |
|---|---|---|---|
butter | Butterworth | octavefilter(x, fs, filter_type='butter') | Medición acústica general. |
cheby1 | Chebyshev I | octavefilter(x, fs, filter_type='cheby1', ripple=0.1) | Caída más abrupta a costa de rizado. |
cheby2 | Chebyshev II | octavefilter(x, fs, filter_type='cheby2', attenuation=60) | Banda de paso plana con ceros en la banda atenuada. |
ellip | Elíptico | octavefilter(x, fs, filter_type='ellip', ripple=0.1, attenuation=60) | Máxima selectividad. |
bessel | Bessel | octavefilter(x, fs, filter_type='bessel') | Preservar la forma de los transitorios. |
Galería de respuestas del banco
Sección titulada «Galería de respuestas del banco»Vista espectral completa de los bancos para octava (1/1) y tercio de octava (1/3).
| Arquitectura | Octava 1/1 (fraction=1) | Octava 1/3 (fraction=3) |
|---|---|---|
| Butterworth | ![]() ![]() | ![]() ![]() |
| Chebyshev I | ![]() ![]() | ![]() ![]() |
| Chebyshev II | ![]() ![]() | ![]() ![]() |
| Elíptico | ![]() ![]() | ![]() ![]() |
| Bessel | ![]() ![]() | ![]() ![]() |
Uso y ejemplos por tipo de filtro
Sección titulada «Uso y ejemplos por tipo de filtro»1. Butterworth (butter)
Sección titulada «1. Butterworth (butter)»El filtro Butterworth es conocido por su banda de paso máximamente plana. Es la elección estándar para mediciones acústicas donde no se admite rizado dentro de las bandas de frecuencia.
from phonometry import octavefilter# Medición estándar por defectospl, freq = octavefilter(x, fs, filter_type='butter')2. Chebyshev I (cheby1)
Sección titulada «2. Chebyshev I (cheby1)»Los filtros Chebyshev tipo I ofrecen una caída más abrupta que Butterworth a cambio de rizado en la banda de paso. Útiles cuando se necesita alta selectividad cerca de las frecuencias de corte.
# Selectividad con 0.1 dB de rizado en la banda de pasospl, freq = octavefilter(x, fs, filter_type='cheby1', ripple=0.1)3. Chebyshev II (cheby2)
Sección titulada «3. Chebyshev II (cheby2)»También llamado Chebyshev inverso, tiene banda de paso plana y rizado en la
banda atenuada. Ofrece una caída más rápida que Butterworth sin afectar a la
señal en la banda de paso. Los bordes de la banda atenuada se colocan
automáticamente para que los puntos de −3 dB caigan en los bordes de banda
(attenuation debe ser > 3.01 dB).
# Banda de paso plana con 60 dB de atenuaciónspl, freq = octavefilter(x, fs, filter_type='cheby2', attenuation=60)4. Elíptico (ellip)
Sección titulada «4. Elíptico (ellip)»Los filtros elípticos (Cauer) tienen la transición más corta (caída más abrupta) para un orden dado. Presentan rizado tanto en la banda de paso como en la atenuada.
# Máxima selectividad para aislamiento extremo entre bandasspl, freq = octavefilter(x, fs, filter_type='ellip', ripple=0.1, attenuation=60)5. Bessel (bessel)
Sección titulada «5. Bessel (bessel)»Los filtros Bessel están optimizados para una respuesta de fase lineal y un retardo de grupo mínimo. Preservan la forma de las ondas filtradas (transitorios) mejor que ningún otro tipo, pero tienen la caída más lenta.
# Ideal para análisis de pulsos y preservación de transitoriosspl, freq = octavefilter(x, fs, filter_type='bessel')6. Linkwitz-Riley (linkwitz_riley)
Sección titulada «6. Linkwitz-Riley (linkwitz_riley)»Diseñado específicamente para crossovers de audio. Los filtros Linkwitz-Riley (típicamente de 4.º orden, aunque se admite cualquier orden par) permiten dividir una señal en bandas que, al sumarse, producen una respuesta en magnitud perfectamente plana y sin diferencia de fase entre bandas en el cruce.
from phonometry import linkwitz_riley# Dividir la señal en bandas grave y aguda a 1000 Hzlow, high = linkwitz_riley(signal, fs, freq=1000, order=4)# Reconstrucción: low + high == signal (respuesta plana)

Verificar la clase IEC 61260-1
Sección titulada «Verificar la clase IEC 61260-1»verify_filter_class comprueba cada banda de un banco contra los límites de
aceptación de IEC 61260-1:2014 (Tabla 1, con el mapeo de breakpoints a
fraccionales y la interpolación logarítmica de la norma) e informa de la clase
por banda con su margen en dB:
from phonometry import OctaveFilterBank, verify_filter_class
bank = OctaveFilterBank(fs=48000, fraction=3, order=6)result = verify_filter_class(bank)print(result["overall_class"]) # 1, 2 o Noneprint(result["bands"][0]) # {'freq': ..., 'class': 1, 'margin_class1_db': ...}

La respuesta del Butterworth de orden 6 (azul) serpentea entre las regiones prohibidas: debe atenuar al menos la máscara roja fuera de la banda y no más que la morada dentro de ella.
Con parámetros por defecto (orden 6), Butterworth cumple clase 1.
Chebyshev II se queda en clase 2 — limitado exactamente por su attenuation=60
frente a los 70 dB exigidos en el stopband lejano (sube attenuation para
alcanzar clase 1). Chebyshev I, Elíptico y Bessel no cumplen los límites de
clase con orden 6: el rizado de banda de paso (cheby1/ellip) y la caída lenta
(bessel) violan la máscara.
Descomposición de la señal y estabilidad
Sección titulada «Descomposición de la señal y estabilidad»Con sigbands=True puedes recuperar las componentes en el dominio del tiempo de
cada banda. Esto permite análisis avanzados o comparar cómo afectan distintas
arquitecturas (p. ej. Butterworth vs Chebyshev) a la fase y al transitorio.
import numpy as npfrom phonometry import octavefilter
# 1. Generar una señal (suma de 250 Hz y 1000 Hz)fs = 48000t = np.linspace(0, 0.5, int(fs * 0.5), endpoint=False)y = np.sin(2 * np.pi * 250 * t) + np.sin(2 * np.pi * 1000 * t)
# 2. Comparar arquitecturas (Butterworth vs Chebyshev II)spl_b, freq, xb_butter = octavefilter(y, fs=fs, fraction=1, sigbands=True, filter_type='butter')spl_c2, _, xb_cheby2 = octavefilter(y, fs=fs, fraction=1, sigbands=True, filter_type='cheby2')
# 'xb_butter' y 'xb_cheby2' contienen las señales por banda en el dominio del tiempo

La gráfica compara las respuestas de Butterworth (azul, línea continua) y Chebyshev II (rojo, discontinua). El panel inferior muestra la respuesta al impulso, destacando las diferencias de estabilidad y decaimiento transitorio.
El retardo de grupo, cuantificado
Sección titulada «El retardo de grupo, cuantificado»El retardo de grupo de la banda de octava de 1 kHz muestra el compromiso directamente: Bessel se mantiene casi plano en la banda de paso (los transitorios sobreviven), mientras que Chebyshev I y el Elíptico pagan su caída abrupta con fuertes picos de retardo en los bordes de banda.


Filtrado de fase cero
Sección titulada «Filtrado de fase cero»Para análisis offline puedes eliminar por completo el retardo de grupo:
zero_phase=True filtra cada banda hacia delante y hacia atrás
(scipy.signal.sosfiltfilt), manteniendo las señales por banda alineadas con la
entrada. La atenuación efectiva se duplica y la opción es incompatible con el
procesado por bloques (stateful).
from phonometry import OctaveFilterBank
bank = OctaveFilterBank(fs=48000, fraction=3)spl, freq, xb = bank.filter(y, sigbands=True, zero_phase=True)

El filtrado causal retrasa la ráfaga según el retardo de grupo del filtro; el filtrado de fase cero la mantiene alineada con la entrada.



















