05_03_03_transfer_functions - Estado del Proyecto¶
✅ COMPLETADO¶
Fecha de completación: 2025-10-10
📊 Métricas Finales¶
- Tests: 34/34 pasando ✅
- Cobertura: 100% ✅
- Líneas de código: ~1,400 LOC
- Ejemplos funcionales: 2
- Documentación: Completa
🎯 Objetivos Alcanzados¶
1. Sistema de Transfer Functions ✅¶
- Clase
Polynomialcon evaluación y búsqueda de raíces - Clase
TransferFunctionbase para H(z) y H(s) - Especialización
BiquadTransferFunctioncon factory methods - Normalización automática
- Soporte para dominios Z y S
2. Análisis Matemático ✅¶
- Cálculo de polos (
poles()) - Cálculo de ceros (
zeros()) - Verificación de estabilidad Z-domain: |pole| < 1
- Verificación de estabilidad S-domain: Re(pole) < 0
- Evaluación en puntos arbitrarios
- Datos para pole-zero plots
3. Análisis de Frecuencia ✅¶
- Respuesta en frecuencia (magnitud y fase)
- Evaluación en círculo unitario (e^jω)
- Salida en dB o lineal
- DC gain (H(z=1))
- Nyquist response (H(z=-1))
4. Factory Methods ✅¶
-
BiquadTransferFunction.lowpass(fc, Q, fs) -
BiquadTransferFunction.highpass(fc, Q, fs) - Coeficientes basados en Audio EQ Cookbook
- Almacenamiento de coeficientes originales
5. Suite de Tests ✅¶
TestPolynomial (5 tests): - test_polynomial_str - test_polynomial_evaluate - test_polynomial_roots - test_polynomial_constant - test_polynomial_empty_roots
TestTransferFunction (19 tests): - test_tf_normalization - test_tf_str_representation - test_tf_zeros - test_tf_poles - test_tf_evaluate - test_tf_evaluate_at_pole - test_stability_z_domain_stable - test_stability_z_domain_unstable - test_stability_s_domain_stable - test_stability_s_domain_unstable - test_dc_gain - test_nyquist_response - test_frequency_response - test_frequency_response_db - test_frequency_response_requires_sample_rate - test_frequency_response_only_z_domain - test_pole_zero_plot_data
TestBiquadTransferFunction (8 tests): - test_biquad_initialization - test_biquad_lowpass_creation - test_biquad_highpass_creation - test_biquad_lowpass_dc_gain - test_biquad_highpass_dc_gain - test_biquad_stability - test_biquad_frequency_response_shape - test_biquad_has_2_poles_2_zeros
TestEdgeCases (3 tests): - test_zero_denominator_coefficient - test_very_high_q_filter - test_dc_gain_s_domain_error - test_nyquist_s_domain_error
6. Ejemplos Funcionales ✅¶
-
filter_analysis.py- Análisis completo de filtros -
pole_zero_comparison.py- Comparación de posiciones pole-zero - Visualización ASCII de plano-Z
- Demostración de filtros estables e inestables
🏗️ Arquitectura Implementada¶
transfer_function.py
├── Domain (Enum)
│ ├── Z_DOMAIN
│ ├── S_DOMAIN
│ └── FREQUENCY
│
├── Polynomial
│ ├── coefficients: List[float]
│ ├── __str__()
│ ├── evaluate(z) → complex
│ └── roots() → List[complex]
│
├── TransferFunction
│ ├── numerator: Polynomial
│ ├── denominator: Polynomial
│ ├── domain: Domain
│ ├── sample_rate: Optional[float]
│ │
│ ├── zeros() → List[complex]
│ ├── poles() → List[complex]
│ ├── evaluate(point) → complex
│ ├── is_stable() → (bool, str)
│ ├── frequency_response(freqs, in_db) → (mag, phase)
│ ├── dc_gain() → float
│ ├── nyquist_response() → float
│ └── pole_zero_plot_data() → Dict
│
└── BiquadTransferFunction(TransferFunction)
├── b0, b1, b2: float (feedforward)
├── a1, a2: float (feedback)
│
├── @classmethod lowpass(fc, Q, fs)
└── @classmethod highpass(fc, Q, fs)
📈 Resultados de Ejemplo¶
Lowpass Filter (fc=1kHz, Q=0.707, fs=48kHz)¶
H(z) = (0.0039*z^2 + 0.0078*z + 0.0039) / (1.0000*z^2 + -1.8153*z + 0.8310)
Poles: 0.9077 ± 0.0845j (|pole| = 0.9116)
Zeros: -1.0000 (double zero at Nyquist)
Stability: ✓ STABLE (All poles inside unit circle)
DC Gain: 1.000000 (-0.00 dB)
@ 1kHz: 0.707107 (-3.01 dB) ← cutoff frequency
@ 5kHz: 0.037150 (-28.58 dB)
Efecto del Q Factor¶
Q=0.5 → |pole| = 0.8770 (distance to unit circle: 0.123)
Q=0.7 → |pole| = 0.9116 (distance to unit circle: 0.088)
Q=1.0 → |pole| = 0.9367 (distance to unit circle: 0.063)
Q=5.0 → |pole| = 0.9870 (distance to unit circle: 0.013) ← resonant
Q=10.0 → |pole| = 0.9935 (distance to unit circle: 0.007) ← very resonant
🔧 Tecnologías Utilizadas¶
- Python 3.12 con type hints
- NumPy para álgebra (roots, evaluación compleja)
- unittest para testing
- dataclasses para estructuras
- Enum para dominios
📝 Fórmulas Implementadas¶
Audio EQ Cookbook (Biquad)¶
ω0 = 2π·fc/fs
α = sin(ω0)/(2Q)
# Lowpass:
b0 = (1 - cos(ω0))/2
b1 = 1 - cos(ω0)
b2 = (1 - cos(ω0))/2
a1 = -2·cos(ω0)
a2 = 1 - α
# Highpass:
b0 = (1 + cos(ω0))/2
b1 = -(1 + cos(ω0))
b2 = (1 + cos(ω0))/2
(same a1, a2)
Frequency Response¶
# For z ∈ unit circle:
z = e^(j·2π·f/fs)
H(f) = N(z)/D(z)
|H(f)| = |H(f)| # magnitude
∠H(f) = arg(H(f)) # phase
🎓 Conceptos DSP Demostrados¶
- Pole-Zero Analysis
- Poles determine resonances and stability
- Zeros determine nulls in frequency response
-
Distance to unit circle ↔ resonance strength
-
Stability Criteria
- Z-domain: All poles must satisfy |pole| < 1
- S-domain: All poles must satisfy Re(pole) < 0
-
Poles on/outside unit circle → unbounded output
-
Filter Design
- Pole angle relates to filter's center frequency
- Q factor controls pole distance to unit circle
-
Zeros at z=-1 → lowpass, zeros at z=+1 → highpass
-
Frequency Response
- Evaluated on unit circle: z = e^jω
- ω = 2πf/fs (normalized frequency)
- DC: ω=0 (z=1), Nyquist: ω=π (z=-1)
🔗 Integración¶
Este módulo se integra con: - 05_03_01_equation_database: Transfer functions en entradas de algoritmos - 05_03_02_signal_flow_diagrams: TF derivadas de signal flow graphs - 05_03_04_numerical_specs (siguiente): Especificaciones numéricas de filtros
🚀 Próximos Pasos¶
Módulo completado. Continuar con: - TAREA 5: 05_03_04_numerical_specs - TAREA 6: 05_03_05_algorithm_templates
📚 Referencias¶
- Audio EQ Cookbook by Robert Bristow-Johnson
- Digital Signal Processing by Oppenheim & Schafer
- NumPy Documentation - polynomial roots