设计需求

  • 根据离散傅里叶变换的原始公式和自己编写复数计算函数进行离散傅里叶变换
  • 对10000个点的加有噪声或干净的正弦波的数据进行离散傅里叶变换,生成10000个点的复数数据序列到文本文件中。
  • 数据格式为实部+虚部,用空格或逗号隔开。

实现思路

离散傅里叶变换的公式如下:
X(k)=∑n=0N−1x(n)exp⁡(−j2πNnk)=∑n=0N−1x(n)WNnk\begin{aligned} X(k)&=\sum_{n=0}^{N-1}x(n)\exp(-j\frac{2\pi}{N}nk)\\ &=\sum_{n=0}^{N-1}x(n)W_N^nk \end{aligned} X(k)​=n=0∑N−1​x(n)exp(−jN2π​nk)=n=0∑N−1​x(n)WNn​k​
带入欧拉公式
eix=cos⁡x+i(sin⁡x)e^{ix}=\cos x+i(\sin x)eix=cosx+i(sinx)
得到:
X(k)=∑n=0N−1x(n)cos⁡(2πNkn)−jx(n)sin⁡(2πNkn)X(k)=\sum_{n=0}^{N-1}x(n)\cos (\frac{2\pi}{N}kn)-jx(n)\sin (\frac{2\pi}{N}kn)X(k)=n=0∑N−1​x(n)cos(N2π​kn)−jx(n)sin(N2π​kn)
幅值计算:
y(k)=a2+b2y(k)=\sqrt{a^2+b^2}y(k)=a2+b2​

DFT源代码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define pi 3.14159
typedef struct
{double real;//实部double imag;//虚部
}complex;
//复数加法
void complex_add(complex a, complex b, complex *c)
{c -> real = a.real + b.real;c -> imag = a.imag + b.imag;
}
//复数乘法
void complex_mul(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;
}
//求模
double complex_mod(complex a)
{double c = 0;c = pow(a.real * a.real + a.imag + a.imag, 0.5);return c;
}
int data_len(FILE*fp){int len = 0,c;while ((c = fgetc(fp)) != EOF)if (c == '\n'){len++;}return len;
}
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);
}
int main(int argc, char* argv[])
{//检查命令行参数正确与否if (argc != 4){printf("用法:程序名 输入文件 输出文件 采样点数\n");printf("程序名:编译后后的.exe名称\n");printf("输入文件:所需进行计算的信号文件\n");printf("输出文件:计算后输出的文件名\n");printf("采样点数:所需计算的采样点数\n");return -1;}FILE* fp1 = fopen(argv[1], "r");int N = atoi(argv[2]);//定义采样点数FILE* fp2 = fopen(argv[2], "w");int len = 0;double data = 0;//检查文件能否被打开if (fp1 == NULL){printf("file error!\n");return -1;}//检测文件行数len = data_len(fp1);complex x[len];//原序列complex X[len];//DFT后的序列double y[len];//幅值printf("data len:%d\n",len);rewind(fp1);//拷贝文件内容char* str = (char*)malloc(sizeof(char) * len);for(int i = 0;i < len; i++)//把数据取出来{fscanf(fp1, "%s", str);if (feof(fp1)) break;data = atof(str);x[i].real = data;x[i].imag = 0;}for(int j =0;j <len; j++)//{//旋转因子计算complex sum = {0,0};for(int n = 0;n < len; n++){complex wn,t;Wn(len,n,j,&wn);complex_mul(x[n],wn,&t);complex_add(sum,t,&sum);}X[j].real = sum.real;X[j].imag = sum.imag;fprintf(fp2,"%lf %lf\n",X[j].real,X[j].imag);}// for(int k=0;k < len; k++)//幅值计算// {// double t = k/len;// y[k] = sqrt(X[k].real * X[k].real// + X[k].imag * X[k].imag);// fprintf(fp2,"%lf %lf\n",t,y[k]);// }printf("success");fclose(fp1);fclose(fp2);return 0;
}

在tcc中编译文件并运行

打开result1.txt,查看数据

将数据导入gnuplot中绘制频谱图

在MATLAB中验证结果

MATLAB中的代码如下

clear;
close all;
x = load('wave.txt');%读取数据
N = length(x);%检查矩阵的长度
a = zeros(N,1);%建立N行0矩阵,存放实部数据
b = zeros(N,1);%建立N行0矩阵,存放虚部数据
for k=0:N-1for i=0:N-1b(k+1)=b(k+1)+x(i+1)*sin((2*pi*k*i)/N);%虚部a(k+1)=a(k+1)+x(i+1)*cos((2*pi*k*i)/N);%实部endc(k+1)=sqrt(a(k+1)^2+b(k+1)^2);%求幅度
end
t=(0:1:N-1);%时间数据
plot(t,c);%画频谱图
axis([0,300,0,5000]);

C语言进行离散傅里叶DFT变换~MATLAB验证相关推荐

  1. idft重建图像 matlab_利用 MATLAB 编程,打开一幅图像,对其进行 DFT 变换,并置其不同区域内的系数为零,进行 IDFT ,观察其输出效果。_学小易找答案...

    [连线题]请对正确的快键键连线 [判断题]板书是指教师在课堂黑板或白板上书写,将教学内容形象.直观.简洁地传授给学生.清晰.流畅.快速的粉笔书写是课堂板书的基本功. [其它]利用 MATLAB 编程, ...

  2. Matlab验证DFT频移特性

    DFT频移特性如下所示: 证明思路:设置随机序列x=[2,1,9,0,7,8,1,3] 通过DFT变换得到对应频谱--频域移动3个单位--做IDFT变换得到频谱移动后的实部+虚部 通过欧拉公式验证对应 ...

  3. Matlab截取语音信号做DFT变换

    1,首先就是要选择一段wav格式的音频文件,网络上找到的wav文件时间太长,因此需要对其进行时域上的分割,截取一小段来进行实验. 2,截取信号代码 clc clear [x,fs]=audioread ...

  4. dft对称性 matlab实验,数字信号处理实验指导书(审)

    (0???2?)上对X(ej?)均匀采样得到 ?X(k)?X(ej?) ??2?k/N??n???x(n)e?j2?kn/N 0?k?N?1 可以看到X(k)也是频域上的有限长序列,长度为N.序列X( ...

  5. 利用卷积定理进行信道估计 + 深入探究 DFT 与 matlab 中的 fft 用法

    文章目录 1 背景 2 DFT & FFT 公式级别解析 2.1 DFT / IDFT 2.2 FFT 3 利用卷积定理进行信道估计 1 背景 最近尝试用时域卷积定理来进行信道估计 假设 TX ...

  6. Opencv——DFT变换(实现两个Mat的卷积以及显示Mat的频域图像)

    DFT原理:(单变量离散傅里叶变换) 数学基础: 任何一个函数都可以转换成无数个正弦和余弦函数的和的形式. 通常观察傅里叶变换后的频域函数可以获得两个重要的信息:幅频曲线和相频曲线. 在数字图像处理中 ...

  7. 沃尔什哈达玛变换Matlab,哈达玛变换矩阵-数字图像处理.ppt

    哈达玛变换矩阵-数字图像处理 3.1 二维离散傅里叶变换(DFT) 3.1.1 二维连续傅里叶变换 二维连续函数 f (x, y)的傅里叶变换定义如下: 设 是独立变量 的函数,且在 上绝对可积,则定 ...

  8. matlab第七章符号对象,MATLAB语言:第七章 MATLAB符号计算

    <MATLAB语言:第七章 MATLAB符号计算>由会员分享,可在线阅读,更多相关<MATLAB语言:第七章 MATLAB符号计算(33页珍藏版)>请在人人文库网上搜索. 1. ...

  9. matlab验证线性卷积与圆周卷积的关系

    数字信号处理实验 一.线性卷积和圆周卷积的关系 1.线性卷积 设X1为N1点的有限长序列,X2为N2点的有限长序列(0 < n < N2) 则两序列的线性卷积为: 线性卷积y1(n)的长度 ...

最新文章

  1. CUDA 7 Stream流简化并发性
  2. topcoder srm 495 div1
  3. mysql的字符集编码_MySQL的字符编码设置
  4. 服务器升级内存跟cpu之后性能更差,云服务器cpu重要还是内存重要
  5. VTK:PolyData之CleanPolyData
  6. VHDL编码器和译码器的设计
  7. 简答String类的操作特点以及static方法的注意事项
  8. csv导入sqlite(python)
  9. 注册测绘师学习笔记(二)
  10. Tekla插件(材料备料定尺工具)
  11. PC端如何跟手机端兼容
  12. [lua]紫猫lua教程-命令宝典-L1-01-02. 变量
  13. 毕达哥拉斯定理a^2 + b^2 =c^2
  14. 计算机网络第七版--概述知识点总结
  15. java根据指定字符开头_Java如何检查以特定单词开头的字符串?
  16. 泊松过程1 | 定义与基本性质
  17. 武汉2022专技公需课必修答案
  18. 手机显示服务器迁移中是什么意思,服务器迁移注意什么?什么是服务器迁移?...
  19. LeetCode 71-80题
  20. 数据库基本知识-总结

热门文章

  1. python与人工智能的关系_python和人工智能之间的关系是什么?老男孩Python人工智能...
  2. WebSocket 详解
  3. html的head中的常见元素
  4. hibernate hql语句 投影查询的三种方式
  5. Appium Desktop介绍-xcodebuild failed with code 65 问题解决
  6. hystrix源码小贴士之Yammer Publisher
  7. Linux下磁盘监控及系统版本-CPU-内存等查看
  8. centos7下nginx配置
  9. Android使用百度地图定位
  10. 后台服务器控件点击跳转另一页面显示本页面