源:FIR数字滤波器C语言

1.单位冲击响应与频响

就如同之前所说的一样,使用下图所示的单位冲击响应,所设计的滤波器,是无法实现的。

现在,让我们看看其这个滤波器的频响。所谓频响,就是计算其单位冲击响应的离散时间傅里叶变换,

我们可以看出,这个滤波器的频响的计算结果是实数,并没有虚数部分。也就是,其相位谱一直是0,也就意味着,这个滤波器输入与输出之间没有延迟,这种相位特性称为0延迟相位特性。

但是,这个滤波器无法是无法实现的。我们实际计算一下该滤波器的输入输出,就可以明白。

这个滤波器在计算的过程中,需要过去的值和未来的值。未来的值是不可预测的,所以,这个滤波器无法实现。为了使得这个滤波器可以实现,我们只好移动其单位冲击响应,使得其不再需要未来的值。比如,就像下面这样移动。

这样的话,这个滤波器就可以实现了,我们只需要记录其40个过去的输入值和现在的输入值。但是,由于移动了其单位冲击响应,会不会对频响产生什么影响呢,我们来看看。

为了更好的说明问题,L去代替之前例子中的20。

移动之后频响,我们根据上面式子可以得出两个结论:1,移动不会对幅度谱产生影响。2,,移动会对相位产生一个延迟,这个延迟主要取决于移动的长度,移动的长度越长,延迟越大。但是,这个移动是线性的。

因此,我们把这个移动的相位特性称为,线性相位特性。到这里,我们移动后的,因果的,可实现的滤波器的单位冲击响应,如下所示。

2.窗函数实现的FIR滤波器代码(C语言)

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

3.频响的问题

按照上面程序,参数如下设定。

运行程序,我们就实现了一个FIR滤波器。我们使用Matlab做出其频响。

好了,这里可以看出,从其幅度特性看来,我们确实实现了一个低通滤波器。但是,相位特性就比较奇怪(为了方便看出问题,我已经进行了解卷绕,至于什么是解卷绕,为什么要解卷绕,之后会说)。

那么,问题来了!按照道理来说,这个FIR滤波器应该是拥有线性相位特性的,但是为什么这里的线性相位特性确不是一条直线!在接近于阻带起始频率的地方,有什么会震荡?这个问题,之后再解决吧。

[数字信号处理]相位特性解卷绕   <-----------戳我

4.实际的滤波效果

为了验证效果,我们输入实际的信号看看。这里,我们选择采样周期为10ms(0.1ms,2014.10.3日修正),那么,其通带频率和阻带起始频率为

为了验证其性质,我选择了1KHz和3KHz的频率混合,最终输出。输入的波形如下。

其输出波形是如下。

红色的“+”是Matlab计算的结果,黑的o是我用C语言实现的滤波器的计算结果,蓝的*号是1KHz的信号,也就是希望的输出。可以看出,这个滤波器有一定的延迟,但是滤波效果还是不错。

博客地址:http://blog.csdn.net/thnh169/

单位冲击响应与频响以及FIR实现代码(C语言)(转)的更多相关文章

  1. 离散系统频响特性函数freqz()

    MATLAB提供了专门用于求离散系统频响特性的函数freqz(),调用freqz()的格式有以下两种: l        [H,w]=freqz(B,A,N) B和A分别为离散系统的系统函数分子.分母 ...

  2. RDA EQ&频响曲线

    相关数据: FAC->Audio->EQ Setting EQ Band - Gain Frequency Q Factor 1.5 FAC->Audio->PEQ // En ...

  3. px单位html5响应式方案

    移动端h5响应式方案最近这几年用得最多的最多的就是rem方案了.这个需要计算根元素的font-size来实现响应式. 但这种方案也有一个缺点,那就是font-size不为整数的时候一些字体使用rem单 ...

  4. 【转载】基于vw等viewport视区相对单位的响应式排版和布局

    文章转载自 张鑫旭-鑫空间-鑫生活 http://www.zhangxinxu.com/wordpress/ 原文链接:http://www.zhangxinxu.com/wordpress/?p=5 ...

  5. 响应面分析 | response surface analysis | R代码

    先开题,慢慢补充. 参考: 什么是响应面(RSM)分析 Response-Surface Methods in R, Using rsm In-class Examples with R Code R ...

  6. 在AD转换中的过采样和噪声形成

    1. 直接量化的过采样AD转换 此类系统的模型可以用下图表示. 图中xa(t)是输入信号,e(t)是量化引入的噪声,xd[n]是最终得到的数字信号,包含分量xda和xde. 对于M倍过采样,信号与量化 ...

  7. 转载 iir直接i型和直接ii型滤波器

    1.IIR滤波器构造           之前在介绍FIR滤波器的时候,我们提到过,IIR滤波器的单位冲击响应是无限的!用差分方程来表达一个滤波器,应该是下式这个样子的.                ...

  8. OpenCL Workshop 1 —— 数字音频滤波

    Introduction 这两年深度学习大火,Cuda跟着吃红利,OpenCL发展也很快.虽然OpenCL不是事实上的标准,但是作为开放标准,适应性是很强的,除了显卡之外,CPU/FPGA上都可以执行 ...

  9. 转载:EQ

    https://blog.csdn.net/qiumingjian/article/details/46326269 https://blog.csdn.net/sszhouplus/article/ ...

随机推荐

  1. 关于SVN更新注意

    SVN更新时其实大部分都可以直接更新但是只有在 当然为0就没有事但是如果不是0的话就要注意了表示你修改的和别人修改了相同的文件先点开 次文件然后看看那些不一样主要看如果是这样就直接点更新就好了,如果有 ...

  2. java int和Integer的区别

    今天偶然和同学讨论到int和Integer的区别是,发现自己对这个问题了解的并不是很清楚,而且有些概念还是错的,所以在这对int和Integer的区别做一个总结. int与integer的区别从大的方 ...

  3. 2016-3-6.16:43------------js开始

    -------------------------------------------------------------------

  4. Ubuntu下载工具 uget+aria2

    一.安装. uget和aria2都可以在“软件中心”中安装,但是版本太老啦,无法发挥作用,所以最好还是在终端中添加ppa进行安装: 1.uget的安装:  sudo add-apt-repositor ...

  5. elasticearch 安装

    1.elasticsearch需要安装jdk1.7以上 2.在ubuntu下不能以root运行,需要建立专门账号 添加组 root@ubuntu:~/Downloads/elasticsearch-/ ...

  6. Compress a folder using powershell

    There are many ways to compress a folder using powershell: Method 1: Using System.IO.Compression and ...

  7. Linux 监控文件事件

    某些应用程序需要对文件或者目录进行监控,来侦测其是否发生了某些事件.Linux很贴心的为我们提供了inotify API,也是Linux的专有. inotify API 在使用之前一定要有一个inot ...

  8. 【转载】linux环境下为firefox/chrome浏览器安装flash player

    本文转载自 http://blog.sina.com.cn/s/blog_6ad624380102v1xf.html     firefox安装flash player的方法: 先到adobe网站上下 ...

  9. C# 双引号的输出

    Console.WriteLine("\"a little list.\"");

  10. 转: window中使用PSFTP/WinSCP实现SFTP上传下载

    sftp 服务器:  dbmonitor 1.sftp属于交互式的,所以你得缓存下命令#!/bin/shsftp -o Port=3322 root@172.16.1.21:/opt << ...