Skip to content

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 Polynomial con evaluación y búsqueda de raíces
  • Clase TransferFunction base para H(z) y H(s)
  • Especialización BiquadTransferFunction con 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

  1. Pole-Zero Analysis
  2. Poles determine resonances and stability
  3. Zeros determine nulls in frequency response
  4. Distance to unit circle ↔ resonance strength

  5. Stability Criteria

  6. Z-domain: All poles must satisfy |pole| < 1
  7. S-domain: All poles must satisfy Re(pole) < 0
  8. Poles on/outside unit circle → unbounded output

  9. Filter Design

  10. Pole angle relates to filter's center frequency
  11. Q factor controls pole distance to unit circle
  12. Zeros at z=-1 → lowpass, zeros at z=+1 → highpass

  13. Frequency Response

  14. Evaluated on unit circle: z = e^jω
  15. ω = 2πf/fs (normalized frequency)
  16. 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