小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

FIR數(shù)字濾波器C語言

 XeonGate 2022-12-07 發(fā)布于江蘇

https://blog.csdn.net/syrchina/article/details/11731325

1.單位沖擊響應(yīng)與頻響

        就如同之前所說的一樣,使用下圖所示的單位沖擊響應(yīng),所設(shè)計(jì)的濾波器,是無法實(shí)現(xiàn)的。


         現(xiàn)在,讓我們看看其這個(gè)濾波器的頻響。所謂頻響,就是計(jì)算其單位沖擊響應(yīng)的離散時(shí)間傅里葉變換,


       我們可以看出,這個(gè)濾波器的頻響的計(jì)算結(jié)果是實(shí)數(shù),并沒有虛數(shù)部分。也就是,其相位譜一直是0,也就意味著,這個(gè)濾波器輸入與輸出之間沒有延遲,這種相位特性稱為0延遲相位特性。

        但是,這個(gè)濾波器無法是無法實(shí)現(xiàn)的。我們實(shí)際計(jì)算一下該濾波器的輸入輸出,就可以明白。


        這個(gè)濾波器在計(jì)算的過程中,需要過去的值和未來的值。未來的值是不可預(yù)測的,所以,這個(gè)濾波器無法實(shí)現(xiàn)。為了使得這個(gè)濾波器可以實(shí)現(xiàn),我們只好移動其單位沖擊響應(yīng),使得其不再需要未來的值。比如,就像下面這樣移動。


        這樣的話,這個(gè)濾波器就可以實(shí)現(xiàn)了,我們只需要記錄其40個(gè)過去的輸入值和現(xiàn)在的輸入值。但是,由于移動了其單位沖擊響應(yīng),會不會對頻響產(chǎn)生什么影響呢,我們來看看。


       為了更好的說明問題,L去代替之前例子中的20。

       移動之后頻響,我們根據(jù)上面式子可以得出兩個(gè)結(jié)論:1,移動不會對幅度譜產(chǎn)生影響。2,,移動會對相位產(chǎn)生一個(gè)延遲,這個(gè)延遲主要取決于移動的長度,移動的長度越長,延遲越大。但是,這個(gè)移動是線性的。

       因此,我們把這個(gè)移動的相位特性稱為,線性相位特性。到這里,我們移動后的,因果的,可實(shí)現(xiàn)的濾波器的單位沖擊響應(yīng),如下所示。


2.窗函數(shù)實(shí)現(xiàn)的FIR濾波器代碼(C語言)

  1. #include <stdio.h>  
  2. #include <math.h>  
  3. #include <malloc.h>  
  4. #include <string.h>  
  5.   
  6.   
  7. #define   pi         (3.1415926)  
  8.   
  9. /*-------------Win Type----------------*/  
  10. #define   Hamming    (1)  
  11.   
  12.   
  13.   
  14. double Input_Data[] =   
  15. {  
  16. 0.000000 , 0.896802 , 1.538842 , 1.760074 ,  1.538842 ,  1.000000 ,  0.363271 , -0.142040 , -0.363271 , -0.278768,  
  17. 0.000000 , 0.278768 , 0.363271 , 0.142020 , -0.363271 , -1.000000 , -1.538842 , -1.760074 , -1.538842 , -0.896802,  
  18. 0.000000 , 0.896802 , 1.538842 , 1.760074 ,  1.538842 ,  1.000000 ,  0.363271 , -0.142040 , -0.363271 , -0.278768,  
  19. 0.000000 , 0.278768 , 0.363271 , 0.142020 , -0.363271 , -1.000000 , -1.538842 , -1.760074 , -1.538842 , -0.896802,  
  20. 0.000000 , 0.896802 , 1.538842 , 1.760074 ,  1.538842 ,  1.000000 ,  0.363271 , -0.142040 , -0.363271 , -0.278768,  
  21. 0.000000 , 0.278768 , 0.363271 , 0.142020 , -0.363271 , -1.000000 , -1.538842 , -1.760074 , -1.538842 , -0.896802,  
  22. 0.000000 , 0.896802 , 1.538842 , 1.760074 ,  1.538842 ,  1.000000 ,  0.363271 , -0.142040 , -0.363271 , -0.278768,  
  23. 0.000000 , 0.278768 , 0.363271 , 0.142020 , -0.363271 , -1.000000 , -1.538842 , -1.760074 , -1.538842 , -0.896802,  
  24. 0.000000 , 55  
  25. };  
  26.   
  27.   
  28.   
  29.   
  30. double sinc(double n)  
  31. {  
  32.     if(0==n) return (double)1;  
  33.     else return (double)(sin(pi*n)/(pi*n));  
  34. }  
  35.    
  36. int Unit_Impulse_Response(int N,double w_c,  
  37.                           int Win_Type,  
  38.                           double *Output_Data)  
  39. {  
  40.     signed int Count = 0;   
  41.     
  42.     for(Count = -(N-1)/2;Count <= (N-1)/2;Count++)  
  43.     {  
  44.         *(Output_Data+Count+((N-1)/2)) = (w_c/pi)*sinc((w_c/pi)*(double)(Count));  
  45.         //printf("%d %lf  ",Count+((N-1)/2)+1,*(Output_Data+Count+((N-1)/2)));  
  46.         //if(Count%4 == 0) printf("\n");  
  47.     }     
  48.       
  49.       
  50.     switch (Win_Type)  
  51.     {  
  52.           
  53.         case Hamming:   printf("Hamming \n");  
  54.                         for(Count = -(N-1)/2;Count <= (N-1)/2;Count++)  
  55.                 {  
  56.                     *(Output_Data+Count+((N-1)/2)) *= (0.54 + 0.46 * cos((2*pi*Count)/(N-1)));  
  57.                     //printf("%d %lf  ",Count+((N-1)/2)+1,*(Output_Data+Count+((N-1)/2)));  
  58.                     //if(((Count+1)%5 == 0)&&(Count != -20)) printf("\n");  
  59.             }   
  60.                         break;  
  61.                           
  62.                           
  63.         default:        printf("default Hamming \n");  
  64.                         for(Count = -(N-1)/2;Count <= (N-1)/2;Count++)  
  65.                 {  
  66.                     *(Output_Data+Count+((N-1)/2)) *= (0.54 + 0.46 * cos((2*pi*Count)/(N-1)));  
  67.                     //printf("%d %lf  ",Count+((N-1)/2)+1,*(Output_Data+Count+((N-1)/2)));  
  68.                     //if(((Count+1)%5 == 0)&&(Count != -20)) printf("\n");  
  69.             }   
  70.           
  71.                         break;  
  72.     }  
  73.       
  74.     return (int)1;  
  75. }  
  76.   
  77.   
  78. void Save_Input_Date (double Scand,  
  79.                       int    Depth,  
  80.                       double *Input_Data)  
  81. {  
  82.     int Count;  
  83.     
  84.     for(Count = 0 ; Count < Depth-1 ; Count++)  
  85.     {  
  86.         *(Input_Data + Count) = *(Input_Data + Count + 1);  
  87.     }  
  88.       
  89.     *(Input_Data + Depth-1) = Scand;  
  90. }  
  91.   
  92.   
  93.   
  94. double Real_Time_FIR_Filter(double *b,  
  95.                             int     b_Lenth,  
  96.                             double *Input_Data)  
  97. {      
  98.     int Count;  
  99.     double Output_Data = 0;  
  100.       
  101.     Input_Data += b_Lenth - 1;    
  102.       
  103.     for(Count = 0; Count < b_Lenth ;Count++)  
  104.     {         
  105.             Output_Data += (*(b + Count)) *  
  106.                             (*(Input_Data - Count));                           
  107.     }           
  108.       
  109.     return (double)Output_Data;  
  110. }  
  111.   
  112.   
  113.   
  114.   
  115.   
  116. int main(void)  
  117. {  
  118.     double w_p = pi/10;  
  119.     double w_s = pi/5;  
  120.     double w_c = (w_s + w_p)/2;  
  121.     printf("w_c =  %f \n" , w_c);  
  122.       
  123.     int N = 0;    
  124.     N = (int) ((6.6*pi)/(w_s - w_p) + 0.5);  
  125.     if(0 == N%2) N++;      
  126.     printf("N =  %d \n" , N);      
  127.     
  128.     double *Impulse_Response;          
  129.     Impulse_Response = (double *) malloc(sizeof(double)*N);    
  130.     memset(Impulse_Response,  
  131.            0,  
  132.            sizeof(double)*N);  
  133.              
  134.     Unit_Impulse_Response(N,w_c,  
  135.                           Hamming,  
  136.                           Impulse_Response);         
  137.   
  138.     double *Input_Buffer;  
  139.     double Output_Data = 0;  
  140.     Input_Buffer = (double *) malloc(sizeof(double)*N);    
  141.     memset(Input_Buffer,  
  142.            0,  
  143.            sizeof(double)*N);  
  144.     int Count = 0;  
  145.       
  146.     FILE *fs;   
  147.     fs=fopen("FIR_Data.txt","w");   
  148.       
  149.     while(1)  
  150.     {     
  151.         if(Input_Data[Count] == 55) break;  
  152.            
  153.         Save_Input_Date (Input_Data[Count],  
  154.                      N,  
  155.                      Input_Buffer);  
  156.          
  157.         Output_Data = Real_Time_FIR_Filter(Impulse_Response,  
  158.                                            N,  
  159.                                            Input_Buffer);  
  160.                           
  161.             
  162.         fprintf(fs,"%lf,",Output_Data);  
  163.         //if(((Count+1)%5 == 0)&&(Count != 0))  fprintf(fs,"\r\n");   
  164.      
  165.         Count++;  
  166.     }  
  167.             
  168.     /*---------------------display--------------------------------      
  169.     for(Count = 0; Count < N;Count++) 
  170.     { 
  171.         printf("%d %lf  ",Count,*(Input_Buffer+Count)); 
  172.         if(((Count+1)%5 == 0)&&(Count != 0)) printf("\n");            
  173.     }       
  174.     */    
  175.       
  176.     fclose(fs);  
  177.     printf("Finish \n");  
  178.     return (int)0;  
  179. }  


3.頻響的問題

        按照上面程序,參數(shù)如下設(shè)定。

   

        運(yùn)行程序,我們就實(shí)現(xiàn)了一個(gè)FIR濾波器。我們使用Matlab做出其頻響。

        

        好了,這里可以看出,從其幅度特性看來,我們確實(shí)實(shí)現(xiàn)了一個(gè)低通濾波器。但是,相位特性就比較奇怪(為了方便看出問題,我已經(jīng)進(jìn)行了解卷繞,至于什么是解卷繞,為什么要解卷繞,之后會說)。

       那么,問題來了!按照道理來說,這個(gè)FIR濾波器應(yīng)該是擁有線性相位特性的,但是為什么這里的線性相位特性確不是一條直線!在接近于阻帶起始頻率的地方,有什么會震蕩?這個(gè)問題,之后再解決吧。

      [數(shù)字信號處理]相位特性解卷繞   <-----------戳我

4.實(shí)際的濾波效果

       為了驗(yàn)證效果,我們輸入實(shí)際的信號看看。這里,我們選擇采樣周期為10ms,那么,其通帶頻率和阻帶起始頻率為


       為了驗(yàn)證其性質(zhì),我選擇了1KHz和3KHz的頻率混合,最終輸出。輸入的波形如下。


      其輸出波形是如下。

        紅色的“+”是Matlab計(jì)算的結(jié)果,黑的o是我用C語言實(shí)現(xiàn)的濾波器的計(jì)算結(jié)果,藍(lán)的*號是1KHz的信號,也就是希望的輸出。可以看出,這個(gè)濾波器有一定的延遲,但是濾波效果還是不錯(cuò)。

       from: http://blog.csdn.net/thnh169/

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多