05_22_06_stability_validator - El Guardián de la Estabilidad Numérica¶
PROPÓSITO¶
El sistema de seguridad del Coefficient Calculator. Verifica que todos los coeficientes calculados resulten en sistemas estables, previene denormals, valida precisión numérica, y detecta potenciales overflow/underflow. Es el auditor que previene explosiones numéricas antes de que lleguen al procesamiento de audio.
Responsabilidad: Garantizar 100% de coeficientes estables y numéricamente seguros antes de su uso.
ESTRUCTURA¶
05_22_06_stability_validator/
├── include/
│ ├── stability_validator.hpp # Validador principal
│ └── validation_result.hpp # Estructura de resultados
├── src/
│ ├── pole_zero_analysis.cpp # Análisis de polos y zeros
│ ├── denormal_prevention.cpp # Prevención de denormals
│ └── precision_validation.cpp # Validación de precisión
├── tests/
│ ├── test_unstable_filters.cpp # Tests con filtros inestables
│ └── test_denormal_detection.cpp # Tests de denormals
├── examples/
│ └── validate_custom_filter.cpp # Ejemplo de validación
└── README.md
API PRINCIPAL¶
StabilityValidator¶
class StabilityValidator {
public:
struct ValidationResult {
bool is_stable;
bool has_denormal_risk;
bool sufficient_precision;
std::string error_message;
};
// Validación completa
ValidationResult validate_filter(const BiquadCoeffs& coeffs);
// Verificaciones individuales
bool poles_inside_unit_circle(const BiquadCoeffs& coeffs);
bool finite_frequency_response(const BiquadCoeffs& coeffs);
bool denormal_risk(const BiquadCoeffs& coeffs);
bool sufficient_precision(const BiquadCoeffs& coeffs);
// Correcciones automáticas
void apply_denormal_prevention(BiquadCoeffs& coeffs);
void upgrade_precision(BiquadCoeffs& coeffs);
};
PROCESO DE VALIDACIÓN¶
Coeficientes Calculados
↓
┌────────────────────────┐
│ Check 1: Poles │ → ¿Están dentro del círculo unitario?
│ |poles| < 1 │ NO → FILTRO INESTABLE ❌
└────────────────────────┘
↓ SÍ
┌────────────────────────┐
│ Check 2: Frequency │ → ¿Gain finito en todas las frecuencias?
│ Response Finite │ NO → RESPUESTA INFINITA ❌
└────────────────────────┘
↓ SÍ
┌────────────────────────┐
│ Check 3: Denormals │ → ¿Coeficientes muy pequeños?
│ Risk Detection │ SÍ → Aplicar prevención ⚠️
└────────────────────────┘
↓
┌────────────────────────┐
│ Check 4: Precision │ → ¿Precisión suficiente?
│ Validation │ NO → Upgrade a double/long double ⚠️
└────────────────────────┘
↓
COEFICIENTES VALIDADOS ✅
ANÁLISIS DE POLOS Y ZEROS¶
Teoría¶
Para un filtro biquad:
El denominador define los polos del sistema. Para estabilidad, los polos deben estar dentro del círculo unitario en el plano Z:
Los polos se calculan resolviendo:
DENORMALS: EL ENEMIGO INVISIBLE¶
¿Qué son los denormals?¶
Números de punto flotante extremadamente pequeños (< 1e-38 para float) que causan degradación masiva de performance (hasta 100x más lento) en algunas CPUs.
Detección¶
bool denormal_risk(const BiquadCoeffs& c) {
const double DENORMAL_THRESHOLD = 1e-30;
return (abs(c.b0) < DENORMAL_THRESHOLD ||
abs(c.b1) < DENORMAL_THRESHOLD ||
abs(c.b2) < DENORMAL_THRESHOLD ||
abs(c.a1) < DENORMAL_THRESHOLD ||
abs(c.a2) < DENORMAL_THRESHOLD);
}
Prevención¶
void apply_denormal_prevention(BiquadCoeffs& c) {
const double DENORMAL_OFFSET = 1e-30;
// Añadir offset microscópico a b0 (no audible)
c.b0 += DENORMAL_OFFSET;
// Compensar con DC blocker si necesario
// (mantiene respuesta en frecuencia correcta)
}
EJEMPLO DE USO¶
#include "stability_validator.hpp"
#include "filter_coefficient_calculator.hpp"
// Calcular coeficientes
FilterCoefficientCalculator<double> calc;
auto coeffs = calc.butterworth_lpf(20000.0, 100.0, 44100.0); // Q muy alto
// Validar
StabilityValidator validator;
auto result = validator.validate_filter(coeffs);
if (!result.is_stable) {
std::cerr << "❌ Filtro inestable: " << result.error_message << "\n";
// NO usar estos coeficientes
} else if (result.has_denormal_risk) {
std::cout << "⚠️ Denormal risk detectado, aplicando prevención...\n";
validator.apply_denormal_prevention(coeffs);
}
// Ahora es seguro usar los coeficientes
CASOS PATOLÓGICOS A DETECTAR¶
Filtro Inestable¶
BiquadCoeffs unstable;
unstable.b0 = 1.0;
unstable.b1 = 0.0;
unstable.b2 = 0.0;
unstable.a1 = -1.5; // Polo fuera del círculo unitario
unstable.a2 = 0.8;
// poles = 0.75 ± 0.66i → |pole| = 1.0 → INESTABLE
Q Extremadamente Alto¶
// Q = 1000 @ 10kHz @ 44.1kHz
// Produce polos muy cerca del círculo unitario
// Sensible a errores de precisión numérica
Frecuencia cerca de Nyquist¶
TAREAS DE DESARROLLO¶
- Implementar StabilityValidator class
- Implementar pole-zero analysis con solver de polinomios
- Implementar denormal detection y prevention
- Implementar frequency response validation
- Implementar precision validation
- Implementar upgrade automático de precisión
- Tests con filtros inestables conocidos
- Tests con casos patológicos (Q alto, freq cerca Nyquist)
- Benchmarks de overhead de validación (<5% del cálculo)
- Documentación de teoría de estabilidad
MÉTRICAS DE CALIDAD¶
✅ 100% de filtros inestables detectados ✅ 0 denormals en producción (todos prevenidos) ✅ Overhead de validación < 5% del tiempo de cálculo ✅ Test coverage > 95% (crítico para seguridad)
REFERENCIAS¶
- Teoría de Estabilidad: "Digital Signal Processing" - Oppenheim & Schafer
- Denormals: "Avoiding Denormals" - Intel Optimization Manual
- Pole-Zero Analysis: "Understanding Digital Signal Processing" - Lyons
Sin este módulo, coeficientes incorrectos llegarían al procesamiento de audio causando crashes, distorsión, o CPU spikes aleatorios.