打印

授之以渔: 几个例子弄清复立叶变换的应用

[复制链接]
楼主: highgear
手机看帖
扫描二维码
随时随地手机跟帖
81
xuyiyi| | 2010-9-1 11:23 | 只看该作者 回帖奖励 |倒序浏览
帮顶, highgear老师请继续。

使用特权

评论回复
82
粉丝| | 2010-9-1 12:27 | 只看该作者
楼主仅描述了博立叶变换的原理皮毛,贴出来的是PC机上的程序实现,离单片机实现还相差十万八千里。
FFT的单片机实现有很多的技术细节,用汇编有汇编的细节,用C有C的细节。就等于小波变换一样,知道原理与实现是两码事。

使用特权

评论回复
83
xuyiyi| | 2010-9-1 12:38 | 只看该作者
这么漂亮的楼,怎么看见一只苍蝇在飞?

谁放进来的?拖出去砍了~~~  :@

使用特权

评论回复
84
sinanjj| | 2010-9-1 19:17 | 只看该作者
我先mark下,


有空再看

使用特权

评论回复
85
highgear|  楼主 | 2010-9-1 22:16 | 只看该作者
本帖最后由 highgear 于 2010-9-1 23:16 编辑

首先, 我贴出的DFT程序都是我自己写的, 而且有汇编的版本。 大家已经看到了, c 版本完全使用了16-bit 整数乘法, 32-bit 加法以及少量的移位操作除法(主要是 %,用于非 2的次方的 N) 可以完全避开。 可以设定在每次定时中断里采样后计算, 由于递推, 计算量很低(2个16bit乘法, 2个32bit 加法)。 唯一的问题是, 必须使用定点 scale 转换以避免浮点运算, 这不如直接使用浮点直观, 对没有处理经验的程序员可能是一个挑战。虽然演示程序为了通用起见用了 PC, 但是dft 算法程序用在 avr, 51等 8-bit mcu 是完完全全没有问题的。不要再说出单片机不能实现的胡话出来。

FFT程序我也有汇编的版本,  C/C++ 版本也是采用了16-bit 整数乘法, 32-bit 加法以及少量的移位操作, 效率很高, 不过在  8-bit  mcu 上可能用不上, 因为, 数据窗口点数少了, 用 dft 更好,  数据窗口点数多了, 8-bit mcu 上太慢, 不实用。 因此我就不介绍了。

最后, 我贴出我用 matlab 做的变速不变调的算法验证程序, 作为结束。

简单的讲一讲原理:
下面的程序使用了短时博立叶变换(short time fourier transform),  窗口函数为 hamming。
1) 短时博立叶变换, 这里的片断 segment = N/4, 数据被分割为 0 到  N-1,  N/4 to N+N/4-1, N/2 to N+N/2-1, 依次类推。
2) 做 fft, 计算出幅度和相位。
3)计算新的幅度和相位。幅度通过插植, 相位得把  wt 计入: da(2: (1 + NX/2)) = (2*pi*segment) ./ (NX ./ (1: (NX/2)));
4)用新的幅度和相位产生新的复数, 加窗并作 ifft 生成变速后的音频数据。
 
SPEED = 2;

[in_rl, fs] = wavread('C:\windows\Media\Windows XP Startup.wav');
in = in_rl(:, 1)';
sizeOfData = length(in);

N = 2048;
segment = N/4;
window = hamming(N)';
X = zeros((1+ N/2), 1 + fix((sizeOfData - N)/segment));
c = 1;
for i = 0: segment: (sizeOfData - N)
      fftx = fft(window .* in((i+1): (i+N)));
      X(:, c) = fftx(1: (1+N/2))';
     c = c + 1;
end;

[Xrows, Xcols] = size(X);
NX = 2 * (Xrows - 1);
Y = zeros(Xrows, round((Xcols - 1) / SPEED));

da = zeros(1, NX/2+1);
da(2: (1 + NX/2)) = (2*pi*segment) ./ (NX ./ (1: (NX/2)));
phase = angle(X(:, 1));
c = 1;
for i = 0: SPEED: (Xcols-2)
       X1 = X(:, 1 + floor(i));
      X2 = X(:, 2 + floor(i));
      df = i - floor(i);
      magnitude = (1-df) * abs(X1) + df * (abs(X2));
      dangle = angle(X2) - angle(X1);
      dangle = dangle - da' - 2 * pi * round(dangle/(2*pi));
      Y(:, c) = magnitude .* exp(j * phase);
      phase = phase + da' + dangle;
      c = c + 1;
end

[Yrows, Ycols] = size(Y);
out = zeros(1, N + (Ycols - 1) * segment );
c = 1;
for i = 0: segment: (segment * (Ycols-1))
       Yc = Y(:, c)';
       Ynew = [Yc, conj(Yc((N/2): -1: 2))];
       out((i+1): (i+N)) = out((i+1)i+N)) + real(ifft(Ynew)) .* window;
      c = c + 1;
end;

wavplay(out, fs);


申明:以上的**和程序都是原创, 可以使用,但请不要任意转载。

使用特权

评论回复
86
highgear|  楼主 | 2010-9-1 23:03 | 只看该作者
纯技术的帖子里, 本来不想引入非技术的东西。

不过宇宙粉丝飞船作为 av 斑竹, 说出 “仅知道取样电阻上的电压,而不知道取样电阻的阻值,如何求功率???神仙也求不出来!“ , 还算可以谅解;但是在看了我公布的程序(我认为已经做的够简单, 够清晰, 本来也是为朋友的学生准备的), 竟然认为 “离单片机实现还相差十万八千里“, 呵呵, 实在对不起我的程序, 对不起党,对不起人民, 对不起21ic.

使用特权

评论回复
87
原野之狼| | 2010-9-1 23:32 | 只看该作者
群众的眼睛是雪亮的

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
xuyiyi + 1
88
望断云山| | 2010-9-2 01:02 | 只看该作者
专业打酱油的专程前来支持 highgear !

使用特权

评论回复
89
xuyiyi| | 2010-9-2 10:10 | 只看该作者
呵呵, 顶!

俺们菜鸟要对得起highgear 老师的程序, 对得起党,对得起人民, 对得起21ic,对得起成千上万21ic家的网友。

顶一千遍!顶一万遍!

使用特权

评论回复
90
xuyiyi| | 2010-9-2 10:12 | 只看该作者
群众的眼睛是雪亮的
原野之狼 发表于 2010-9-1 23:32



群众的眼睛是雪亮的,但小狼的眼睛不够雪亮~~~

这么好的贴子不给穿裤子,你那权力准备用在何地方?;P

使用特权

评论回复
91
lost1421| | 2010-9-2 11:02 | 只看该作者
FFT的变换结果在实际应用中有何意义?除了能看到有哪些频率的信号,还有什么用?

使用特权

评论回复
92
RUNNER| | 2010-9-2 11:12 | 只看该作者
呵呵, 顶!

俺们菜鸟要对得起highgear 老师的程序, 对得起党,对得起人民, 对得起21ic,对得起成千上万21ic家的网友。

顶一千遍!顶一万遍!

使用特权

评论回复
93
123jj| | 2010-9-2 11:50 | 只看该作者
好贴要顶,

顶一千遍!顶一万遍!

使用特权

评论回复
94
lpf336| | 2010-9-2 13:58 | 只看该作者
顶一下

使用特权

评论回复
95
ok2001| | 2010-9-2 14:18 | 只看该作者
太好了,终于看到有注重数学的帖子, 很多“技巧”,“窍门”其实都是源于数学和物理的应用。作电子行业,特别是搞设计工作,没有数学基础,的确行之不远。对于新手,与其经常关注“使用了什么高超的控制芯片,用过多少不同的单片机,会多少门编译器,熟悉多少重编程语音”,还不如真正得弄懂:e^(jωt) = cos(ωt) + j sin(ωt) ---欧拉,又见欧拉,看看这个等式:e^iπ+1=0,耐人寻味,令人遐想!!!

使用特权

评论回复
96
lyb_ab| | 2010-9-2 17:26 | 只看该作者
顶一下!

使用特权

评论回复
97
lxyppc| | 2010-9-2 21:21 | 只看该作者
纯技术的帖子里, 本来不想引入非技术的东西。

不过宇宙粉丝飞船作为 av 斑竹, 说出 “仅知道取样电阻上的电压,而不知道取样电阻的阻值,如何求功率???神仙也求不出来!“ , 还算可以谅解;但是在看了我公布 ...
highgear 发表于 2010-9-1 23:03


消化不好的人需要吃流食
如果再嚼碎一点,吃下去就感觉不到食物原有的味道了

使用特权

评论回复
98
ttlasong| | 2010-9-2 23:23 | 只看该作者
几个例子弄清复立叶变换的应用

使用特权

评论回复
99
aihe| | 2010-9-3 00:35 | 只看该作者
100楼
坚决顶楼主

使用特权

评论回复
100
123jj| | 2010-9-3 08:11 | 只看该作者
100楼!

坚决顶楼主。顶顶顶!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则