分享

[数字信号处理]IIR滤波器基础

 XeonGate 2022-12-06 发布于江苏

1.IIR滤波器构造

          之前在介绍FIR滤波器的时候,我们提到过,IIR滤波器的单位冲击响应是无限的!用差分方程来表达一个滤波器,应该是下式这个样子的。
          
        这个式子是N次差分方程的表达式。我们明显可以看出,计算输出y(n)的时候,需要以前的输出值与输入值。换言之,这个可能表达式还有反馈环节。当 为0的时候,这个滤波器由于没有反馈,其单位冲击响应是有限的,是FIR滤波器。当 不为0是时候,是IIR滤波器。

2.直接I型IIR滤波器

        就如同之前所说一样,我们考虑这样一个滤波器。
 
        很明显,这是一个1阶才差分方程。由于 不为0,这是一个1阶IIR滤波器的差分方程。为了方便观察,我们将其画系统成框图。

        很明显的,要实现这个滤波器,我们需要2个单位的存储空间,用来存储过去的输入值与输出值。这样的话,考虑N阶的滤波器,我们就需要2N个存储单元。这种结构被称作直接I型结构。

3.直接II型IIR滤波器

       我们先观察上图的直接I型滤波器,将其视为有两个较小系统串联而成的系统。由于是串联,那么,顺序必定不影响输入输出结果,那么,我们将其调整一下位置。得到就像下图一样的一个新的系统。

        然后,我们可以发现,其实,这个系统完全没有必要使用两个延迟算子,可以合并使用。将其延迟算子合并,那么,可以得到下面这样一个系统。

        这个系统与之前的直接I型系统一样,拥有完全相同的输入输出特性。并且,节省了一半的延迟算子。实现这个滤波器所需要的存储空间为N。

3.直接II型IIR滤波器的实现(C语言)


#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <string.h>


double IIR_Filter(double *a, int Lenth_a,
                  double *b, int Lenth_b,
                  double Input_Data,
                  double *Memory_Buffer) 
{
    int Count;
    double Output_Data = 0; 
    int Memory_Lenth = 0;
    
    if(Lenth_a >= Lenth_b) Memory_Lenth = Lenth_a;
    else Memory_Lenth = Lenth_b;
    
    Output_Data += (*a) * Input_Data;  //a(0)*x(n)             
    
    for(Count = 1; Count < Lenth_a ;Count++)
    {
        Output_Data -= (*(a + Count)) *
                       (*(Memory_Buffer + (Memory_Lenth - 1) - Count));                                       
    } 
    
    //------------------------save data--------------------------// 
    *(Memory_Buffer + Memory_Lenth - 1) = Output_Data;
    Output_Data = 0;
    //----------------------------------------------------------// 
    
    for(Count = 0; Count < Lenth_b ;Count++)
    {    	
        Output_Data += (*(b + Count)) *
                       (*(Memory_Buffer + (Memory_Lenth - 1) - Count));      
    }
    
    //------------------------move data--------------------------// 
    for(Count = 0 ; Count < Memory_Lenth -1 ; Count++)
    {
    	*(Memory_Buffer + Count) = *(Memory_Buffer + Count + 1);
    }
    *(Memory_Buffer + Memory_Lenth - 1) = 0;
    //-----------------------------------------------------------//

    return (double)Output_Data; 
}



int main(void)
{    
    double a[] = {1   , 0.5554 ,0.1542 };   
    double b[] = {0   ,      0 ,0.1542 };	
   
    int Lenth_a = sizeof(a)/sizeof(double);
    int Lenth_b = sizeof(b)/sizeof(double);
    int Memory_Lenth = 0;
    
    if(Lenth_a >= Lenth_b) Memory_Lenth = Lenth_a;
    else Memory_Lenth = Lenth_b;
    
    printf("Memory Lenth : %d  \n" , Memory_Lenth); 
   
    double Input = 0 ;
    double Output = 0;
    
    double *Memory_Buffer;
    Memory_Buffer = (double *) malloc(sizeof(double)*Memory_Lenth);  
    memset(Memory_Buffer,
           0,
           sizeof(double)*Memory_Lenth);
    

    FILE* Input_Data;
    FILE* Output_Data;
     
    Input_Data = fopen("input.dat","r"); 
    Output_Data= fopen("output.txt","w"); 
    
    while(1)
    {
        if(fscanf(Input_Data, "%lf", &Input) == EOF)  break;
        
        Output = IIR_Filter( a, Lenth_a,
                             b, Lenth_b,
                             Input,
                             Memory_Buffer);

        fprintf(Output_Data,"%lf,",Output);
        
    	//printf("Output:  %lf \n" ,Output);
    }	
    
    printf("Finish \n");

    return (int)1;
}

        当然,这里的参数还是随意设置的。之后我会就IIR的滤波器的间接设计与直接设计,进行详细的说明。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多