不是科研狗,基础理论薄弱,写的比较匆忙,有理解有误的地方还请理解和指正。 最近接触音视频处理比较多,就遇到了采集的音频数据有噪音的情况。可不可以用傅里叶变换去除音频噪音呢?在此之前,我对傅里叶变换的概念只有一句话,“时域转频域的一个玩意儿”。我将音频时域转为频域,再去除噪音的频段,不就达到去噪的效果吗? 嗯,试试就逝世。 可以参考这篇 举个大家常用的例子,两个向量,a,b在坐标系中表示,可以变换为一组坐标。 比如想求c点坐标,在图中是不好处理的问题,但是变换后,c=a+b=(2+1,1+2)=(3,3) ,在数上就很好处理了。总之,一个问题不好处理的时候,换个思路(变换),就能迎刃而解。嗯嗯,有点像线性代数的味道。 时域和频域一一对应,通过频域可以变换为时域 傅里叶变换有许多类型,通常不加前缀说的是连续傅里叶变换,离散傅里叶变换常用在计算机处理上,在此之上进行算法改进,降低时间复杂度,叫快速傅里叶变换。 所以啊,傅里叶就提出了这句话:任何周期函数都由多个不同的正弦波(sin和cos)叠加构成(满足狄里赫利条件情况下) 正弦波自己给自己内积为1,自己和别人内积为0,也就是sin(nwt),cos(nwt)都是标准正交基,再加上常量1, 任何的周期函数都可以用着三个表示 。所以呢,只需要将时域的f(t)分别和各种标准正交基做内积,等于0代表没有该正弦波,否则存在该分量。 线性代数:在空间中找到一组向量,他们的内积为0,自身的模为1时,称这组向量为标准正交基,空间中的任意向量都可以由这些标准正交基构成。 嗯,你需要学习到晚上2点[手动滑稽] 但上图的f(t)没有和各种正弦波做内积啊,而是和e^-iwt 做内积。其实这是欧拉公式将正弦波与指数之间进行了变换,本质上上图公式就是和各种正弦波做内积。现在就说说欧拉公式。 回顾下初中知识 离散傅里叶变换可以参考这篇 1,从文件读取8000个音频数据,由于现实中的音频没有虚部,所以只设置实部。 3,离散傅里叶逆变换就是X(k)乘上e^(j2tkn/N),也就是实部虚部都为正 4,下图公式求幅度 完整代码
写在前面
网上大佬们写的傅里叶公式推导,证明已经很多了(瑟瑟发抖),我这里主要是讲傅里叶的应用,不涉及公式证明,而是直接拿起公式使用。
由于自己获取知识也是看大佬们博文理解学习得来的,所以图片中多少有一些是别人的图,不过我附上了别人的链接。
看完这篇你能收获到:
1 傅里叶变换的原理
2 傅里叶变换在音频的应用
3 离散傅里叶变换处理音频的C语言代码及讲解背景
嗯,经过几天的折腾,效果(上图为原始音频信号,下图为在频域去掉高频正交基后的音频信号)
结论:
1,有点效果,但噪音只是变小了,没有去除。使用的是DFT,还有待改进。
2,琢磨了一段时间,还有诸多地方没有理解到,傅里叶变换是需要长期研究和推敲的学问。把自己理解到的知识点做下笔记,以后要走图像处理什么的路子,再来细细研究吧。一 什么是傅里叶变换(分析)?
在回答这个问题的时候,我们需要先知道什么是变换?为什么要变换?(1)什么是变换?
(2)为什么变换?
傅里叶变换的思路就是时域和频域的相互变换。二 时域和频域
傅里叶变换类型
对于时域是周期性连续的函数进行变换叫傅里叶级数
对于时域是非周期连续的函数进行变换叫傅里叶变换
三傅里叶级数(Fourier Series)
如图,频域由若干个正弦波构成,时域的矩形波可以由多个正弦波叠加构成(当正弦波个数趋向无穷大,逼近为矩形波,有点极限的赶脚)
周期函数其实说的就是时域信号,多个不同的正弦波说的是频域的信号。
当然,如上图所示,一个正弦波的确定,需要知道他的相位,振幅和角频率,所以时域转频域得到的是一系列的初相,振幅和角频率。
傅里叶说的这句话写成公式就是
又或者可以这样写
这个公式该这么理解呢?这就需要知道正弦波的正交性。(1)正弦波的正交性
什么是标准正交基
什么是内积?
三傅里叶变换公式
(1) 欧拉公式
数系
自然数:1,2,3,4。。。
整数:-1,1,-2,2.。。。
有理数:-1,2,2/3,4/5.。。
无理数:根号2等
这些一起就构成了实数,如图 实数轴。
但遇到x^2=-1这样的解,用实数就无法解决了,引入虚数。虚数+实数=复数,如图为复平面,任意点可以用a+bi 来表示
在复平面上画圆,由三角公式,可以求得a点为cosx+i *sinx。
复平面上乘法的意义:
乘-1,逆时针旋转180度。乘-i ,逆时针旋转90度,复数乘法如图
现在就可以 拿出欧拉公式了
公式推导就是使用的泰勒公式,e,sin,cos都是十大必背泰勒展开式,两边展开是相等的。
到这里就打住吧,总之我们到这里能知道傅里叶变换公式e^iwt其实就是与各个sin,cos做内积。具体欧拉公式讲解可以看这篇
欧拉公式讲解
欧拉恒等式
也就是角度到达180度时候,又回到实数轴
离散傅里叶变换(DFT)
离散傅里叶变换讲解
离散和连续的区别在于,连续是积分而离散是求和
原理,如下图,a,b图是待检测信号,c,d是3个周期的正弦信号,很显然a图含有正弦波,e=ac,将e图的各点相加,很显然值是正的,这就说明a图含频率为3的正弦波,f=bd,显然将f图中各点相加结果约等于0了,说明b图不含有周期为3的正弦波
在计算机中用这个公式更好处理一点
n和N是在一个正弦周期内采样N个点,采样间隔为2piN,n用来步进,一次步进2piN,最后进行累加求和,就得出了X(k)最后 离散傅里叶变换完整代码
2,离散傅里叶变换关键处
temp的re就是对应上图公式的cos,同理im就是对应上图的sin,每个X[k]进行累加求和 for (int k = 0; k < N; k++) { X[k].re = 0; X[k].im = 0; for (int n = 0; n < N; n++) { temp.re = (float)cos(2 * pi*k*n / N); temp.im = -(float)sin(2 * pi*k*n / N); X[k] = complexadd(X[k], complexMult(x[n], temp)); } }
temp.re = (float)cos(2 * pi*k*n / N); temp.im = (float)sin(2 * pi*k*n / N); x[k] = complexadd(x[k], complexMult(X[n], temp));
在代码中表示printf("%d ", int(2.0/N*sqrt(X[k].re*X[k].re + X[k].im*X[k].im))); //打印的为幅度
#include <stdio.h> #include <math.h> #define pi 3.1415926 struct complex { float re; float im; }; complex complexadd(complex a, complex b) { //复数加 complex rt; rt.re = a.re + b.re; rt.im = a.im + b.im; return rt; } complex complexMult(complex a, complex b) { //复数乘 complex rt; rt.re = a.re*b.re - a.im*b.im; rt.im = a.im*b.re + a.re*b.im; return rt; } complex complexSet(complex *a, short *b, int N)//复数设置 { for (int i = 0; i < N; i++) { a[i].re = b[i]; a[i].im = 0; } } //离散傅里叶变换 //X[]标识变换后频域,x[]为时域采样信号 void dft(complex X[], complex x[], int N) { complex temp; int k, n; for (int k = 0; k < N; k++) { X[k].re = 0; X[k].im = 0; for (int n = 0; n < N; n++) { temp.re = (float)cos(2 * pi*k*n / N); temp.im = -(float)sin(2 * pi*k*n / N); X[k] = complexadd(X[k], complexMult(x[n], temp)); } printf("%d ", int(2.0/N*sqrt(X[k].re*X[k].re + X[k].im*X[k].im))); //打印的为幅度 if (k >= 6000)//去除高频信号 { X[k].re = 0.0; X[k].im = 0.0; } } } //离散傅里叶逆变换 //X[]标识变换后频域,x[]为时域采样信号 void idft(complex X[], complex x[], int N) { complex temp; //int k, n; for (int k = 0; k < N; k++) { x[k].re = 0; x[k].im = 0; for (int n = 0; n < N; n++) { temp.re = (float)cos(2 * pi*k*n / N); temp.im = (float)sin(2 * pi*k*n / N); x[k] = complexadd(x[k], complexMult(X[n], temp)); } x[k].re /= N; x[k].im /= N; } } #define N 8000//采样率为8000 int main() { complex samples[N], X[N], x[N]; //原始数据,变换后的频域数据,逆变换后的时域数据 FILE *fp; FILE *fp2; short buf[N]; int re=0; fp=fopen("./ttt.pcm", "rb"); fp2 = fopen("./trans.pcm", "wb"); if (!fp ||!fp2) { printf("I could not open file.n"); return 1; } else { while (fread(buf, sizeof(short)*N,1 , fp) > 0)//末尾数据忽略 { complexSet(samples, buf, N); dft(X, samples, N); idft(X, x, N); for (int i = 0; i < N; i++) { buf[i] = x[i].re; } fwrite(buf, sizeof(short)*N,1 , fp2); } } fclose(fp); fclose(fp2); return 0; }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算