资源描述
数字信号处理课程设计报告
数字信号与处理课程设计报告
1、 课程设计题目:按时间抽选(DIT)的基-2IFFT算法的C实现
学号:08113126
学生姓名:徐思凯
班 级:081131
专 业:信息工程
指导教师:饶志华
2011年 6月 19 日
目 录
一.数字信号处理的简介 - 2 -
二.课程设计的目的与要求 - 2 -
三.傅立叶变换的逆变换 - 2 -
四.IFFT的计算方法 - 3 -
五.课程设计代码 - 4 -
六.程序结果 - 8 -
一.数字信号处理的简介
数字信号处理的主要对象是数字信号,且是采用运算的方法达到处理目的,因此,其实现方法不同于模拟信号的实现方法,基本上可以分为两种实现方法,即软件实现方法和硬件实现的方法。而硬件实现指的是选用合适的DSP芯片,配有适合芯片语言及任务要求的软件,实现某种信号处理功能的一种方法。数字信号处理的特点1.灵活性2.高精度和高稳定性3.便于大规模集成4.对数字信号可以存储、运算;系统可以获得高性能指标
二.课程设计的目的与要求
通过本课程设计进一步巩固数字信号处理的基本概念、理论、分析方法和实现方法;能掌握的基本理论和分析方法方面的知识得到进一步扩展;能有效地将理论和实际紧密结合;增强软件编程实现能力和解决实际问题的能力, 要求能够熟练地用Matlab语言编写数字信号处理的应用程序。
三.傅立叶变换的逆变换
对一个给定的傅里叶变换,求其相应原函数f(t)的运算,即傅立叶变换的逆变换对向量(或直接对矩阵的行或列)进行离散傅立叶逆变换的函数的调用方法是:
Y=ifft(X,n,dim)
函数对X进行离散傅立叶逆变换。其中X、n、dim的意义及用法和离散傅立叶变换函数fft完全相同。
举例
A=[3,2,1,1;-5,1,0,1;3,2,1,5];
fftA=fft(A) %求A的列向量的傅立叶变换
fftA2=fft(A,4,2) %求A的行向量的傅立叶变换
ifft(fftA) %对矩阵fftA的列向量进行傅立叶逆变换,结果应等于A
ifft(fftA2,4,2) %对矩阵fftA2的行向量进行傅立叶逆变换,其结果应等于A
DX=diff(X) 计算向量X的向前差分,DX(i)=X(i+1)-X(i),0<i<n。
DX=diff(X,n) 计算X的n阶向前差分,diff(X,2)=diff(diff(X))。
DX=diff(A,n,dim)计算矩阵A的n阶差分,dim=1时(缺省状态),按列计算差分,dim=2, 按行计算差分。
四.IFFT的计算方法
FFT算法同样可以应用于IDFT的计算,称为快速傅里叶反变换,简写为IFFT。前述DFT和IDFT公式为
比较上面两式,可以看出,只要把DFT公式中的系数改为,并乘以系数1/N,就可用FFT算法来计算IDFT,这就得到了IFFT的算法。
当把时间抽选FFT算法用于 IFFT计算时,由于原来输入的时间序列x(n)现在变为频率序列X(k),原来是将x(n)偶奇分的,而现在变成对X(k)进行偶奇分了,因此这种算法改称为频率抽选IFFT算法。类似地,当把频率抽选FFT算法用于计算IFFT时,应该称为时间抽选IFFT算法。
在IFFT计算中经常把常量1/N分解成M个1/2连乘,即1/N=(1/2)M,并且在M级的迭代运算中,每级的运算都分别乘 上一个1/2因子。图3.29表示的是时间抽选IFFT流程图。
五.课程设计代码
#include <stdio.h>
#include <math.h> /*调用系统函数*/
#include <stdlib.h> /*动态存储*/
#include <time.h>
#define N 1024
typedef struct /*定义复数类型*/
{
double real;
double img;
}
complex; /*定义结构体类型为复数类型,声明新类型名为complex*/
complex x[N], *W; /*想x[n]为输入序列,*w为指向complex的数据指针*/
int size_x=0; /*输入序列的大小,在本程序中仅限2的次幂*/
double PI; / *圆周率*/
/*主函数*/
int main(){
int i,method,s;
void fft(); /*快速傅里叶变换*/
void ifft(); /*逆快速傅里叶变换*/
void initW(); /*初始化变换核*/
void change(); /*变址,将x[n]倒置*/
void add(complex ,complex ,complex *); /*复数加法*/
void mul(complex ,complex ,complex *); /*复数乘法*/
void sub(complex ,complex ,complex *); /*复数减法*/
void divi(complex ,complex ,complex *); /*复数除法*/
void output(); /*输出结果*/
void input(); /*随机输入时调用*/
typedef struct COMPLEX // 复数结构体
{
double Real;
double Imag;
} Complex;
void FFT1D(Complex* pTD, Complex* pFD, unsigned int nGrade); // 一维 FFT 变换
void IFFT1D(Complex* pFD, Complex* pTD, unsigned int nGrade); // 一维 IFFT 变换
void FFT1D(Complex* pTD, Complex* pFD, unsigned int nGrade) // 一维 FFT 变换
{
Complex *W, *X1, *X2, *X;
Complex TempComplex;
unsigned int i, j, k;
unsigned int bfsize, p;
unsigned int nCount = 1 << nGrade;
double dAngle;
W = new Complex[nCount >> 1]; // 分配内存空间
X1 = new Complex[nCount];
X2 = new Complex[nCount];
for(i = 0; i < (nCount >> 1); i++) // 计算加权系数
{
dAngle = PI * 2.0 * i / nCount;
W[i].Real = cos(dAngle);
W[i].Imag = - sin(dAngle);
}
memcpy(X1, pTD, sizeof(Complex) * nCount); // 内存拷贝
for(k = 0; k < nGrade; k++) // 采用蝶形算法进行快速傅立叶变换
{
for(j = 0; j < (unsigned int) (1 << k); j++)
{
bfsize = 1 << (nGrade - k);
for(i = 0; i < bfsize / 2; i++)
{
p = j * bfsize;
X2[i + p].Real = X1[i + p].Real + X1[i + p + bfsize / 2].Real;
X2[i + p].Imag = X1[i + p].Imag + X1[i + p + bfsize / 2].Imag;
TempComplex.Real = X1[i + p].Real - X1[i + p + bfsize / 2].Real;
TempComplex.Imag = X1[i + p].Imag - X1[i + p + bfsize / 2].Imag;
X2[i + p + bfsize / 2].Real = TempComplex.Real * W[i * (1 << k)].Real - TempComplex.Imag * W[i * (1 << k)].Imag;
X2[i + p + bfsize / 2].Imag = TempComplex.Real * W[i * (1 << k)].Imag + TempComplex.Imag * W[i * (1 << k)].Real;
}
}
X = X1;
X1 = X2;
X2 = X;
}
for(j = 0; j < nCount; j++)
{
p = 0;
for(i = 0; i < nGrade; i++)
{
if (j & (1 << i))
{
p += 1 << (nGrade - i - 1);
}
}
pFD[j].Real = X1[p].Real;
pFD[j].Imag = X1[p].Imag;
}
delete[] W;
delete[] X1;
delete[] X2;
}
void IFFT1D(Complex* pFD, Complex* pTD, unsigned int nGrade) // 一维 IFFT 变换
{
Complex *W, *X1, *X2, *X;
Complex TempComplex;
unsigned int i, j, k;
unsigned int bfsize, p;
unsigned int nCount = 1 << nGrade;
double dAngle;
W = new Complex[nCount >> 1]; // 分配内存空间
X1 = new Complex[nCount];
X2 = new Complex[nCount];
// 计算加权系数
for(i = 0; i < (nCount >> 1); i++)
{
dAngle = PI * 2.0 * i / nCount;
W[i].Real = cos(dAngle);
W[i].Imag = sin(dAngle);
}
memcpy(X1, pFD, sizeof(Complex) * nCount); // 内存拷贝
for(k = 0; k < nGrade; k++) // 采用蝶形算法进行快速傅立叶变换
{
for(j = 0; j < (unsigned int) (1 << k); j++)
{
bfsize = 1 << (nGrade - k);
for(i = 0; i < bfsize / 2; i++)
{
p = j * bfsize;
X2[i + p].Real = X1[i + p].Real + X1[i + p + bfsize / 2].Real;
X2[i + p].Imag = X1[i + p].Imag + X1[i + p + bfsize / 2].Imag;
TempComplex.Real = X1[i + p].Real - X1[i + p + bfsize / 2].Real;
TempComplex.Imag = X1[i + p].Imag - X1[i + p + bfsize / 2].Imag;
X2[i + p + bfsize / 2].Real = TempComplex.Real * W[i * (1 << k)].Real - TempComplex.Imag * W[i * (1 << k)].Imag;
X2[i + p + bfsize / 2].Imag = TempComplex.Real * W[i * (1 << k)].Imag + TempComplex.Imag * W[i * (1 << k)].Real;
}
}
X = X1;
X1 = X2;
X2 = X;
}
for(j = 0; j < nCount; j++) // 重新排序
{
p = 0;
for(i = 0; i < nGrade; i++)
{
if (j & (1 << i))
{
p += 1 << (nGrade - i - 1);
}
}
pTD[j].Real = X1[p].Real / (double) nCount;
pTD[j].Imag = X1[p].Imag / (double) nCount;
}
delete[] W;
delete[] X1;
delete[] X2;
}
六.程序结果
心得和经验
做课程设计是为了加深我们对平时学习的理论知识的理解,在理论和实验教学基础上进一步巩固所学基本理论和提高应用所学知识并加以综合应用的能力,培养学生将所学知识应用于实际的思想,提高分析和解决问题的能力,增强学生的综合能力,开发学生的智力,激发学生的创新精神,为毕业设计和以后工作打下必要基础。
这次为期一周的数字信号处理课程设计,使我们弄明白了不少的知识,也学到了不少的东西。首先我们认识到了Visual C++工具箱的强大的功能和方便的操控性,通过软件可以使设计简化,运算简单,而且可以使设计者腾出时间来把重点放在一些困难概念的理解和掌握上。Visual C++的功能很强大,可用于电子,通信,图像等领域的信号处理与系统设计。要精通Visual C++并不是件很容易的事,这得花较多的时间来研究和分析。通过使用软件,我们不仅加深了对书本知识的了解,还将理论与实际相结合,提高了自己实际思考问题、独立分析问题、冷静解决问题的能力,对数字信号处理这门课也更加充满了兴趣。设计滤波器是数字信号处理中最为重要的应用之一,因此学好滤波器的设计及分析,对于我们大学生来说是十分重要的。
- 9 -
展开阅读全文