单位冲击响应与频响以及FIR实现代码(C语言)(转)
1.单位冲击响应与频响
就如同之前所说的一样,使用下图所示的单位冲击响应,所设计的滤波器,是无法实现的。
现在,让我们看看其这个滤波器的频响。所谓频响,就是计算其单位冲击响应的离散时间傅里叶变换,
我们可以看出,这个滤波器的频响的计算结果是实数,并没有虚数部分。也就是,其相位谱一直是0,也就意味着,这个滤波器输入与输出之间没有延迟,这种相位特性称为0延迟相位特性。
但是,这个滤波器无法是无法实现的。我们实际计算一下该滤波器的输入输出,就可以明白。
这个滤波器在计算的过程中,需要过去的值和未来的值。未来的值是不可预测的,所以,这个滤波器无法实现。为了使得这个滤波器可以实现,我们只好移动其单位冲击响应,使得其不再需要未来的值。比如,就像下面这样移动。
这样的话,这个滤波器就可以实现了,我们只需要记录其40个过去的输入值和现在的输入值。但是,由于移动了其单位冲击响应,会不会对频响产生什么影响呢,我们来看看。
为了更好的说明问题,L去代替之前例子中的20。
移动之后频响,我们根据上面式子可以得出两个结论:1,移动不会对幅度谱产生影响。2,,移动会对相位产生一个延迟,这个延迟主要取决于移动的长度,移动的长度越长,延迟越大。但是,这个移动是线性的。
因此,我们把这个移动的相位特性称为,线性相位特性。到这里,我们移动后的,因果的,可实现的滤波器的单位冲击响应,如下所示。
2.窗函数实现的FIR滤波器代码(C语言)
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <string.h> #define pi (3.1415926) /*-------------Win Type----------------*/
#define Hamming (1) double Input_Data[] =
{
0.000000 , 0.896802 , 1.538842 , 1.760074 , 1.538842 , 1.000000 , 0.363271 , -0.142040 , -0.363271 , -0.278768,
0.000000 , 0.278768 , 0.363271 , 0.142020 , -0.363271 , -1.000000 , -1.538842 , -1.760074 , -1.538842 , -0.896802,
0.000000 , 0.896802 , 1.538842 , 1.760074 , 1.538842 , 1.000000 , 0.363271 , -0.142040 , -0.363271 , -0.278768,
0.000000 , 0.278768 , 0.363271 , 0.142020 , -0.363271 , -1.000000 , -1.538842 , -1.760074 , -1.538842 , -0.896802,
0.000000 , 0.896802 , 1.538842 , 1.760074 , 1.538842 , 1.000000 , 0.363271 , -0.142040 , -0.363271 , -0.278768,
0.000000 , 0.278768 , 0.363271 , 0.142020 , -0.363271 , -1.000000 , -1.538842 , -1.760074 , -1.538842 , -0.896802,
0.000000 , 0.896802 , 1.538842 , 1.760074 , 1.538842 , 1.000000 , 0.363271 , -0.142040 , -0.363271 , -0.278768,
0.000000 , 0.278768 , 0.363271 , 0.142020 , -0.363271 , -1.000000 , -1.538842 , -1.760074 , -1.538842 , -0.896802,
0.000000 ,
}; double sinc(double n)
{
if(==n) return (double);
else return (double)(sin(pi*n)/(pi*n));
} int Unit_Impulse_Response(int N,double w_c,
int Win_Type,
double *Output_Data)
{
signed int Count = ; for(Count = -(N-)/;Count <= (N-)/;Count++)
{
*(Output_Data+Count+((N-)/)) = (w_c/pi)*sinc((w_c/pi)*(double)(Count));
//printf("%d %lf ",Count+((N-1)/2)+1,*(Output_Data+Count+((N-1)/2)));
//if(Count%4 == 0) printf("\n");
} switch (Win_Type)
{ case Hamming: printf("Hamming \n");
for(Count = -(N-)/;Count <= (N-)/;Count++)
{
*(Output_Data+Count+((N-)/)) *= (0.54 + 0.46 * cos((*pi*Count)/(N-)));
//printf("%d %lf ",Count+((N-1)/2)+1,*(Output_Data+Count+((N-1)/2)));
//if(((Count+1)%5 == 0)&&(Count != -20)) printf("\n");
}
break; default: printf("default Hamming \n");
for(Count = -(N-)/;Count <= (N-)/;Count++)
{
*(Output_Data+Count+((N-)/)) *= (0.54 + 0.46 * cos((*pi*Count)/(N-)));
//printf("%d %lf ",Count+((N-1)/2)+1,*(Output_Data+Count+((N-1)/2)));
//if(((Count+1)%5 == 0)&&(Count != -20)) printf("\n");
} break;
} return (int);
} void Save_Input_Date (double Scand,
int Depth,
double *Input_Data)
{
int Count; for(Count = ; Count < Depth- ; Count++)
{
*(Input_Data + Count) = *(Input_Data + Count + );
} *(Input_Data + Depth-) = Scand;
} double Real_Time_FIR_Filter(double *b,
int b_Lenth,
double *Input_Data)
{
int Count;
double Output_Data = ; Input_Data += b_Lenth - ; for(Count = ; Count < b_Lenth ;Count++)
{
Output_Data += (*(b + Count)) *
(*(Input_Data - Count));
} return (double)Output_Data;
} int main(void)
{
double w_p = pi/;
double w_s = pi/;
double w_c = (w_s + w_p)/;
printf("w_c = %f \n" , w_c); int N = ;
N = (int) ((6.6*pi)/(w_s - w_p) + 0.5);
if( == N%) N++;
printf("N = %d \n" , N); double *Impulse_Response;
Impulse_Response = (double *) malloc(sizeof(double)*N);
memset(Impulse_Response,
,
sizeof(double)*N); Unit_Impulse_Response(N,w_c,
Hamming,
Impulse_Response); double *Input_Buffer;
double Output_Data = ;
Input_Buffer = (double *) malloc(sizeof(double)*N);
memset(Input_Buffer,
,
sizeof(double)*N);
int Count = ; FILE *fs;
fs=fopen("FIR_Data.txt","w"); while()
{
if(Input_Data[Count] == ) break; Save_Input_Date (Input_Data[Count],
N,
Input_Buffer); Output_Data = Real_Time_FIR_Filter(Impulse_Response,
N,
Input_Buffer); fprintf(fs,"%lf,",Output_Data);
//if(((Count+1)%5 == 0)&&(Count != 0)) fprintf(fs,"\r\n"); Count++;
} /*---------------------display--------------------------------
for(Count = 0; Count < N;Count++)
{
printf("%d %lf ",Count,*(Input_Buffer+Count));
if(((Count+1)%5 == 0)&&(Count != 0)) printf("\n");
}
*/ fclose(fs);
printf("Finish \n");
return (int);
}
3.频响的问题
按照上面程序,参数如下设定。
运行程序,我们就实现了一个FIR滤波器。我们使用Matlab做出其频响。
好了,这里可以看出,从其幅度特性看来,我们确实实现了一个低通滤波器。但是,相位特性就比较奇怪(为了方便看出问题,我已经进行了解卷绕,至于什么是解卷绕,为什么要解卷绕,之后会说)。
那么,问题来了!按照道理来说,这个FIR滤波器应该是拥有线性相位特性的,但是为什么这里的线性相位特性确不是一条直线!在接近于阻带起始频率的地方,有什么会震荡?这个问题,之后再解决吧。
[数字信号处理]相位特性解卷绕 <-----------戳我
4.实际的滤波效果
为了验证效果,我们输入实际的信号看看。这里,我们选择采样周期为10ms(0.1ms,2014.10.3日修正),那么,其通带频率和阻带起始频率为
为了验证其性质,我选择了1KHz和3KHz的频率混合,最终输出。输入的波形如下。
其输出波形是如下。
红色的“+”是Matlab计算的结果,黑的o是我用C语言实现的滤波器的计算结果,蓝的*号是1KHz的信号,也就是希望的输出。可以看出,这个滤波器有一定的延迟,但是滤波效果还是不错。
博客地址:http://blog.csdn.net/thnh169/
单位冲击响应与频响以及FIR实现代码(C语言)(转)的更多相关文章
- 离散系统频响特性函数freqz()
MATLAB提供了专门用于求离散系统频响特性的函数freqz(),调用freqz()的格式有以下两种: l [H,w]=freqz(B,A,N) B和A分别为离散系统的系统函数分子.分母 ...
- RDA EQ&频响曲线
相关数据: FAC->Audio->EQ Setting EQ Band - Gain Frequency Q Factor 1.5 FAC->Audio->PEQ // En ...
- px单位html5响应式方案
移动端h5响应式方案最近这几年用得最多的最多的就是rem方案了.这个需要计算根元素的font-size来实现响应式. 但这种方案也有一个缺点,那就是font-size不为整数的时候一些字体使用rem单 ...
- 【转载】基于vw等viewport视区相对单位的响应式排版和布局
文章转载自 张鑫旭-鑫空间-鑫生活 http://www.zhangxinxu.com/wordpress/ 原文链接:http://www.zhangxinxu.com/wordpress/?p=5 ...
- 响应面分析 | response surface analysis | R代码
先开题,慢慢补充. 参考: 什么是响应面(RSM)分析 Response-Surface Methods in R, Using rsm In-class Examples with R Code R ...
- 在AD转换中的过采样和噪声形成
1. 直接量化的过采样AD转换 此类系统的模型可以用下图表示. 图中xa(t)是输入信号,e(t)是量化引入的噪声,xd[n]是最终得到的数字信号,包含分量xda和xde. 对于M倍过采样,信号与量化 ...
- 转载 iir直接i型和直接ii型滤波器
1.IIR滤波器构造 之前在介绍FIR滤波器的时候,我们提到过,IIR滤波器的单位冲击响应是无限的!用差分方程来表达一个滤波器,应该是下式这个样子的. ...
- OpenCL Workshop 1 —— 数字音频滤波
Introduction 这两年深度学习大火,Cuda跟着吃红利,OpenCL发展也很快.虽然OpenCL不是事实上的标准,但是作为开放标准,适应性是很强的,除了显卡之外,CPU/FPGA上都可以执行 ...
- 转载:EQ
https://blog.csdn.net/qiumingjian/article/details/46326269 https://blog.csdn.net/sszhouplus/article/ ...
随机推荐
- CI 路由设置
$route['news/show/(:num)']='news/show/$1'; 前边是匹配 网址 后边是 指定控制器 在application/config/文件夹下有routes.p ...
- android:editable is deprecated: Use an <EditText> to make it editable
问题:android:editable is deprecated: Use an to make it editable 意思:Android的:编辑是反对:使用<</span> ...
- C++:bitset类的使用
#include <iostream> #include <bitset> using namespace std; int main() { //初始化一个bitmap , ...
- discuz!迁移指南
转自:http://jingyan.baidu.com/article/f7ff0bfc77114b2e26bb1390.html 曾经在本地搭建过一个discuz!论坛,现在买了域名和服务器,那么怎 ...
- 第20章 数据库操作----JDBC概述
JDBC是一种可用于执行SQL语句的Java API(Application Programming Interface,应用程序设计接口),是连接数据库和Java应用程序的纽带. 1.JDBC-OD ...
- 转 android学习—— context 和 getApplicationContext()
在android中常常会遇到与context有关的内容 浅论一下context : 在语句 AlertDialog.Builder builder = new AlertDialog.Builder( ...
- C#排列组合类
//----------------------------------------------------------------------------- // // 算法:排列组合类 // // ...
- C#入门经典(2-重置窗体布局,界面介绍,错误列表)
- axis-运行bat报错问题
仇玮浡说我的位置不对,我仔细一看,果然,端口号错了... 发现了 我以前用的都是8088 现在的tomcat是8080 看得到8088 没觉得奇怪.. 成功之后的样子 总结:多仔细检查配置文件,如果 ...
- Windows Embedded CE 6.0 下载地址和序列号
Windows Embedded CE 6.0 下载地址和序列号 安装起来特麻烦 程序下载地址 http://download.microsoft.com/download/a/0/9/a09e587 ...