C语言编写DFT计算程序, 并绘制幅度谱

一、什么是DFT?
离散傅里叶变换(Discrete Fourier Transform,缩写为DFT),是傅里叶变换在时域和频域上都呈离散的形式,将信号的时域采样变换为其DTFT的频域采样。在形式上,变换两端(时域和频域上)的序列是有限长的,而实际上这两组序列都应当被认为是离散周期信号的主值序列。即使对有限长的离散信号作DFT,也应当将其看作其周期延拓的变换。在实际应用中通常采用快速傅里叶变换计算DFT

二、DFT的公式
离散傅里叶变化定义为
X ( k ) = ∑ n = 0 N − 1 x ( n ) W N n k , k = 0 , 1 , … , N − 1 X(k)=\sum_{n=0}^{N-1} x(n) W_{N}^{n k}, k=0,1, \ldots, N-1 X(k)=n=0N1x(n)WNnk,k=0,1,,N1

其中, W N n k W_{N}^{n k} WNnk为旋转因子,特此说明,其计算公式为 W N n k = e − j 2 π N n k , N = 0 , 1 μ , … , N − 1 W_{N}^{n k}=e^{-j \frac{2 \pi}{N} n k}, \mathrm{N}=0,1_{\mu}, \ldots, \mathrm{N}-1 WNnk=ejN2πnk,N=0,1μ,,N1
1.利用欧拉公式 e j θ = cos ⁡ θ + j sin ⁡ θ e^{j \theta}=\cos \theta+j \sin \theta ejθ=cosθ+jsinθ得: X ( k ) = ∑ n = 0 N − 1 x ( n ) cos ⁡ ( 2 π N k n ) − j x ( n ) sin ⁡ ( 2 π N k n ) X(k)=\sum_{n=0}^{N-1} x(n) \cos \left(\frac{2 \pi}{N} k n\right)-j x(n) \sin \left(\frac{2 \pi}{N} k n\right) X(k)=n=0N1x(n)cos(N2πkn)jx(n)sin(N2πkn)
2.幅值得计算
asin ⁡ ( x ) + b cos ⁡ ( x ) = a 2 + b 2 sin ⁡ ( x + arctanb ⁡ / a ) \operatorname{asin}(x)+b \cos (x)=\sqrt{a^{2}+b^{2}} \sin (x+\operatorname{arctanb} / a) asin(x)+bcos(x)=a2+b2 sin(x+arctanb/a)

三,DFT源程序
抽样点为:64
原始序列为:
0.6*sin(2*pi*500*i)+0.6*sin(2*pi*50*i)



#include <stdio.h>
#include <stdlib.h>
#include <math.h> 

#define pi 3.14159
#define N 64

typedef struct
{
	double real;
	double imag;
}complex;

void Wn(int ,int ,int ,complex *);//定义旋转因子
void c_jiafa(complex ,complex ,complex *); //复数加法运算 
void c_chengfa(complex ,complex ,complex *); //复数乘法运算

int main()
{
	double y[N];
	complex A[N],a[N],f[N]; //a[N]为输入的信号,A[N]是DFT后的序列 
	for(int i=0;i<N;i++) //提供初始信号 
	{
		a[i].real=0.6*sin(2*pi*500*i)+0.6*sin(2*pi*50*i);//0.6*sin(2*pi*500*i)+0.6*sin(2*pi*50*i)
		a[i].imag=0;
	}
	
	
	for(int k=0;k<N;k++)
	{
		//int n;
		complex sum={0,0};
		for(int n=0;n<N;n++)
		{
			complex wn,t;
			Wn(N,n,k,&wn);
			c_chengfa(a[n],wn,&t);
			c_jiafa(sum,t,&sum);
		}
		A[k].real=sum.real;
		A[k].imag=sum.imag;
	} 
	
	for(int i=0;i<N;i++)//幅值计算
	{
		y[i]=sqrt(A[i].real*A[i].real+A[i].imag*A[i].imag);
		printf("%d\t%lf\n",i,y[i]);
	}
	system("pause");
	return 0;
}

void Wn(int n1,int i,int k,complex *Wn) //定义旋转因子 
{
	//用欧拉公式分成实部和虚部 
	Wn->real=cos(2*pi*i*k/n1);
	Wn->imag=-sin(2*pi*i*k/n1);
}

void c_jiafa(complex a,complex b,complex *c) //复数加法运算 
{
	c->real=a.real+b.real; 
	c->imag=a.imag+b.imag;
}

void c_chengfa(complex a,complex b,complex *c) //复数乘法运算
{
	c->real=a.real*b.real-a.imag*b.imag;
	c->imag=a.real*b.imag+a.imag*b.real;
}

四,程序编译,产生dat文件
在这里插入图片描述

五,gnuplot绘图
在这里插入图片描述
结果为:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐维康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值