WAV 文件做FFT变换
本帖最后由 zwj512 于 2014-4-20 19:25 编辑平台:ARM9QT4.5
小弟现在可以解析WAV文件
采样率是44Khz16bit双声道PCM编码
我现在想做FFT 变换 我是直接把WAV的16bit数据作为一个点 进行FFT变换呢还是需要别的步骤?
我只做一个声道的FFT PCM存储数据的时候是高低字节反着存储我用不用 变换一下再做FFT ?
而且16bit的数据有点大运算有点慢我现在是只读取 低字节进行FFT 变换 这样可取不 ?
我现在FFT变换后 频谱有些乱我进行的256点变换 一般正常的话 是低频到高频逐渐降低
而且我的FFT点数 低于256时程序运行时 就会出现内存错误不懂。。。
我的不是这样的 有做过这方面的大神吗 谢谢指点
下面是FFT程序 有懂的大神帮看看
#ifndef FILTER_H
#define FILTER_H
/*********************************************************************
快速福利叶变换C函数
函数简介:此函数是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依
赖硬件。此函数采用联合体的形式表示一个复数,输入为自然顺序的复
数(输入实数是可令复数虚部为0),输出为经过FFT变换的自然顺序的
复数
使用说明:使用此函数只需更改宏定义FFT_N的值即可实现点数的改变,FFT_N的
应该为2的N次方,不满足此条件时应在后面补0
函数调用:FFT(s);
时 间:2010-2-20
版 本:Ver1.0
参考文献:
**********************************************************************/
#include<math.h>
#define PI 3.1415926535897932384626433832795028841971 //定义圆周率值
#define FFT_N 128 //定义福利叶变换的点数
struct compx {float real,imag;}; //定义一个复数结构
struct compx s;
//FFT输入和输出:从S开始存放,根据大小自己定义
/*******************************************************************
函数原型:struct compx EE(struct compx b1,struct compx b2)
函数功能:对两个复数进行乘法运算
输入参数:两个以联合体定义的复数a,b
输出参数:a和b的乘积,以联合体的形式输出
*******************************************************************/
struct compx EE(struct compx a,struct compx b)
{
struct compx c;
c.real=a.real*b.real-a.imag*b.imag;
c.imag=a.real*b.imag+a.imag*b.real;
return(c);
}
/*******************************************************************
//定义复数求模
********************************************************************/
float cmplxabs(struct compx a)
{
float b;
b=sqrt(a.real*a.real+a.imag*a.imag);
return(b);
}
/*****************************************************************
函数原型:void FFT(struct compx *xin,int N)
函数功能:对输入的复数组进行快速傅里叶变换(FFT)
输入参数:*xin复数结构体组的首地址指针,struct型
*****************************************************************/
void FFT(struct compx *xin)
{
int f,m,nv2,nm1,i,k,l,j=0;
struct compx u,w,t;
nv2=FFT_N/2; //变址运算,即把自然顺序变成倒位序,采用雷德算法
nm1=FFT_N-1;
for(i=0;i<nm1;i++)
{
if(i<j) //如果i<j,即进行变址
{
t=xin;
xin=xin;
xin=t;
}
k=nv2; //求j的下一个倒位序
while(k<=j) //如果k<=j,表示j的最高位为1
{
j=j-k; //把最高位变成0
k=k/2; //k/2,比较次高位,依次类推,逐个比较,直到某个位为0
}
j=j+k; //把0改为1
}
{
int le,lei,ip; //FFT运算核,使用蝶形运算完成FFT运算
f=FFT_N;
for(l=1;(f=f/2)!=1;l++) //计算l的值,即计算蝶形级数
;
for(m=1;m<=l;m++) // 控制蝶形结级数
{ //m表示第m级蝶形,l为蝶形级总数l=log(2)N
le=2<<(m-1); //le蝶形结距离,即第m级蝶形的蝶形结相距le点
lei=le/2; //同一蝶形结中参加运算的两点的距离
u.real=1.0; //u为蝶形结运算系数,初始值为1
u.imag=0.0;
w.real=cos(PI/lei); //w为系数商,即当前系数与前一个系数的商
w.imag=-sin(PI/lei);
for(j=0;j<=lei-1;j++) //控制计算不同种蝶形结,即计算系数不同的蝶形结
{
for(i=j;i<=FFT_N-1;i=i+le) //控制同一蝶形结运算,即计算系数相同蝶形结
{
ip=i+lei; //i,ip分别表示参加蝶形运算的两个节点
t=EE(xin,u); //蝶形运算,详见公式
xin.real=xin.real-t.real;
xin.imag=xin.imag-t.imag;
xin.real=xin.real+t.real;
xin.imag=xin.imag+t.imag;
}
u=EE(u,w); //改变系数,进行下一个蝶形运算
}
}
}
}
#endif // FILTER_H
1)WAV文件的16bitPCM有两种存储方式,即大端方式和小端方式,通过你的描述,估计是小端方式。如果是小端方式而且在X86系统中使用C语言进行数据处理,可用采用一个short int指针来进行读取。
2)对于X86系统,16bit数据不大,运算也不慢。如果是ARM,在运算的时候,要充分利用移位指令计算。如果是DSP,我就不多说了,一般TI、ADI或飞思卡尔都会提供一些标准算法库,自己写也不难。如果你是在8位机上实现FFT,则要充分考虑机器的运算能力,一般情况下256点FFT在44K下实时变换这样的运算负荷,对于一般的8位机基本完不成,除非外部配合FPGA或DSP来完成。
3)对于16bit数据,只取低字节是不对的,如果声音数据有超过-128~+127范围的,则计算完全错误,同时降低了分析的动态范围,不可取。
4)使用FFT的蝶形变换后,输出的复数是倒位序,你需要重新对虚实部进行排列。
5)以后问算法的时候,最好告知大家你的运算平台,否则很难回答你的提问。 你自己生成一个1K正弦波来做FFT不就知道了。 MARK
正在做这方面的东西 dellric 发表于 2014-4-20 16:43
1)WAV文件的16bitPCM有两种存储方式,即大端方式和小端方式,通过你的描述,估计是小端方式。如果是小端方 ...
谢谢我在ARM9上跑用QT4.5写的程序 我开始也是用的 short int 读取数据 进行FFT变换 256点速度跟不上来 而且我求出的复数取模后 还会有负数出现的情况(我用16bit数据)
我用FFT的时候点数如果低于 256点 比如128点 系统就会出现内存错误 我也不知道怎么回事 Jordan?? 发表于 2014-4-20 16:50
MARK
正在做这方面的东西
做的怎么样啦 指点一下啊 zwj512 发表于 2014-4-20 18:16
做的怎么样啦 指点一下啊
我用的是fftw库
自己写的效果没这么好 Jordan?? 发表于 2014-4-20 19:52
我用的是fftw库
自己写的效果没这么好
fftw库qt下可以用吗 zwj512 发表于 2014-4-20 20:33
fftw库qt下可以用吗
我就是用在qt下...... Jordan?? 发表于 2014-4-20 21:26
我就是用在qt下......
我已安装好啦明天试试有问题请教你啊 Jordan?? 发表于 2014-4-20 16:50
MARK
正在做这方面的东西
我交叉编译器 4.3.3编译时 有这个错误 怎么解决啊我试试了 FFTW3 FFTW2 一样的效果
zwj512 发表于 2014-4-21 09:30
我交叉编译器 4.3.3编译时 有这个错误 怎么解决啊我试试了 FFTW3 FFTW2 一样的效果
...
静态链接?加上-static 看看吧
Jordan?? 发表于 2014-4-21 09:36
静态链接?加上-static 看看吧
我生成的库文件 没有.so文件 是不这个问题你有吗给我传一个 谢谢 zwj512 发表于 2014-4-21 09:41
我生成的库文件 没有.so文件 是不这个问题你有吗给我传一个 谢谢
会不会是你编译选项错了?
我的是在BBB上直接本地编译的,静态库库和动态库都有
要不你在pro文件里加上
TEMPLATE = lib
CONFIG += staticlib Jordan?? 发表于 2014-4-21 09:46
会不会是你编译选项错了?
我的是在BBB上直接本地编译的,静态库库和动态库都有
要不你在pro文件里加上
照你的办法成功啦没错啦但是我只有静态库我也是 ./configmake make install啊 不知怎么回事 我这样做 不会影响程序运行结果吧 zwj512 发表于 2014-4-21 09:53
照你的办法成功啦没错啦但是我只有静态库我也是 ./configmake make install啊 不知怎么回事...
不会,静态链接理论上还快一些呢{:lol:} Jordan?? 发表于 2014-4-21 09:57
不会,静态链接理论上还快一些呢
哈哈谢谢你啦 你不是在linux下安装的吧在linux下好像就没有 动态库啊 zwj512 发表于 2014-4-21 10:00
哈哈谢谢你啦 你不是在linux下安装的吧在linux下好像就没有 动态库啊
/usr/lib下一大堆动态库 路过学习学习。 Jordan?? 发表于 2014-4-21 10:04
/usr/lib下一大堆动态库
大侠有几个问题
1. 我的是16bit的 我用short int读回来的数据 用高低字节互换吗然后再FFT
2. FFTW里面的数据类型可以是float,那我读回来的数据 还用别的处理吗还是直接强制类型转换然后FFT zwj512 发表于 2014-4-21 12:48
大侠有几个问题
1. 我的是16bit的 我用short int读回来的数据 用高低字节互换吗然后再FFT
2. FF ...
{:lol:} 我不是什么大侠。。。
应该是要高低字节互换的..
我也在折腾这些 Jordan?? 发表于 2014-4-21 13:11
我不是什么大侠。。。
应该是要高低字节互换的..
我也在折腾这些
按你的方式 生成的是 .a 文件没有可执行文件求助 zwj512 发表于 2014-4-21 14:35
按你的方式 生成的是 .a 文件没有可执行文件求助
将库添加到工程中即可。。
不会添加的话我也没办法了 Jordan?? 发表于 2014-4-21 15:05
将库添加到工程中即可。。
不会添加的话我也没办法了
好吧我解决啦生成动态库啦
页:
[1]