Théorie des Filtres IIR : Filtrage Numérique IIR
L’Objectif est de réaliser le filtre d’ordre 4 ( 2 Stages ) évoqué dans Filtrage Numérique IIR
Après avoir déterminé les coefficients du filtre IIR, l’algorithme à appliquer au sein du processeur est du type :
\( y[n]=\sum_{i=0}^{N}b[i].x[n-i]-\sum_{i=1}^{N}a[i].y[n-i] \)
Pour un Filtre d’ordre 2 :
\( y[n]=b_{0}.x[n]+b_{1}.x[n-1]+b_{2}.x[n-2]-a_{1}.y[n-1]-a_{2}.y[n-2] \)
|
|
Mise en Oeuvre
typedef struct
{
uint16_t numStages;
float32_t *pState;
float32_t *coef;
} arm_iir_instance_f32;
int IIR_filt_f32(arm_iir_instance_f32 *S, float* x, float* y)
{
unsigned int i;
float *wn_1_ptr,*wn_2_ptr,*coef_ptr;
float output=0.0;
float wn,wn_1,wn_2;
coef_ptr = S->coef; /* coefficient pointer */
wn_1_ptr = S->pState; /* first history */
wn_2_ptr = wn_1_ptr + 1; /* next history */
output = *x * (*coef_ptr++);
for (i = 0 ; i < S->numStages; i++)
{
wn_1 = *wn_1_ptr; /* history values */
wn_2 = *wn_2_ptr;
output = output - wn_1 * (*coef_ptr++);
wn = output - wn_2 * (*coef_ptr++); /* poles */
output = wn + wn_1 * (*coef_ptr++);
output = output + wn_2 * (*coef_ptr++); /* zeros */
*wn_2_ptr++ = *wn_1_ptr;
*wn_1_ptr++ = wn;
wn_1_ptr++;
wn_2_ptr++;
}
*y = output;
return 0;
}
Pour un filtre IIR d’ordre 4 ( numStage = 2 ), on rangera les coefficients dans un tableau de la manière suivante :
\( H(z)=k.\frac{1 + S_0\alpha_1 . z^{-1} + S_0\alpha_2 . z^{-2}}{1 + S_0\beta_1 . z^{-1} + S_0\beta_2 . z^{-2}}.\frac{1 + S_1\alpha_1 . z^{-1} + S_1\alpha_2 . z^{-2}}{1 + S_1\beta_1 . z^{-1} + S_1\beta_2 . z^{-2}} \)
\( H(z)=k.\frac{z^2 + S_0\alpha_1 . z + S_0\alpha_2 }{z^2 + S_0\beta_1 . z + S_0\beta_2 }.\frac{z^2 + S_1\alpha_1 . z + S_1\alpha_2 }{z^2 + S_1\beta_1 . z + S_1\beta_2 } \)
tab_coeff[0] : k
tab_coeff[1] : S0_beta1
tab_coeff[2] : S0_beta2
tab_coeff[3] : S0_alpha1
tab_coeff[4] : S0_alpha2
tab_coeff[5] : S1_beta1
tab_coeff[6] : S1_beta2
tab_coeff[7] : S1_alpha1
tab_coeff[8] : S1_alpha2
L’initialisation du filtre IIR se fait avec :
IIR_init_f32( &ARM_IIR_F32, 2, tab_coeff, tab_history, 1);
Le calcul de l’échantillon de sortie du filtre pour chaque nouvel échantillon d’entrée se fait avec la fonction IIR_filt_f32(arm_iir_instance_f32 *S, float* x, float* y)
x_sample_f et y_sample_f sont de type float32_t, ainsi on aura :
void BSP_AUDIO_SAI_Interrupt_CallBack()
{
float32_t x_sample_f;
float32_t y_sample_f;
BSP_LED_On(LED1);
x_sample_f=(float32_t)rx_sample_L;
// SIGNAL PROCESSING ALGORITHM
IIR_filt_f32(&ARM_IIR_F32, &x_sample_f, &y_sample_f);
tx_sample_L = (int16_t)y_sample_f ;
tx_sample_R = tx_sample_L;
BSP_LED_Off(LED1);
return;
}
Q1. Tester la fonction IIR_filt_f32() avec des coefficients de filtres calculés par le script python synthese_iir_ordre4.py
REMARQUE : la fonction signal.iirfilter permet de calculer les coefficients de tout type de filtre IIR. ( cf gene_coeffs_IIR.py )
Q2. Compléter et tester la fonction IIR_calc_coeff_f32() afin de calculer les coefficients du filtre IIR d’ordre 4 pour une fréquence de coupure souhaitée.
Q3. Réaliser un synthétiseur à synthèse soustractive à base de filtre IIR. Les paramètres k et Q doivent pouvoir être réglables avec un potentiomètre du clavier maître.