广义互相关求信号时延 JAVA实现
来源:互联网 发布:电脑优化提速 编辑:程序博客网 时间:2024/06/03 23:00
最近在做一个声音测量距离的系统,平台为Android,要用广义互相关来求信号的时延。
里面用到了FFT,FFT是参考这位仁兄的:
http://blog.csdn.net/syrchina/article/details/6670517
如何通过FFT求信号时延看这里:
http://zlgc.seu.edu.cn/jpkc2/ipkc/signal/new/course/two/2-6-11.htm
废话不多说了:上代码,下面的是FFT的
public class FFT {private int N_FFT=0;//傅里叶变换的点数private int M_of_N_FFT=0;//蝶形运算的级数,N = 2^Mprivate int Npart2_of_N_FFT=0;//创建正弦函数表时取PI的1/2private int Npart4_of_N_FFT=0;//创建正弦函数表时取PI的1/4private float SIN_TABLE_of_N_FFT [] = null;private static final double PI = 3.14159265358979323846264338327950288419716939937510;public FFT(int FFT_N){Init_FFT(FFT_N);}public Complex[] complexLization(float data[]){Complex[] w = new Complex[data.length];for(int i=0;i<data.length;i++){w[i].real = data[i];w[i].imag = 0.0f;}return w;}public float[] magnitude(Complex[] data){float[] r = new float[data.length];for(int i=0;i<data.length;i++){r[i] = (float) Math.sqrt(data[i].real * data[i].real + data[i].imag * data[i].imag);}return r;}//初始化FFT程序//N_FFT是 FFT的点数,必须是2的次方private void Init_FFT(int N_of_FFT){ int i=0; int temp_N_FFT=1; N_FFT = N_of_FFT;//傅里叶变换的点数 ,必须是 2的次方 M_of_N_FFT = 0;//蝶形运算的级数,N = 2^M for (i=0; temp_N_FFT<N_FFT; i++) { temp_N_FFT = 2*temp_N_FFT; M_of_N_FFT++; } //printf("\n%d\n",M_of_N_FFT); Npart2_of_N_FFT = N_FFT/2;//创建正弦函数表时取PI的1/2 Npart4_of_N_FFT = N_FFT/4;//创建正弦函数表时取PI的1/4 //data_of_N_FFT = (ptr_complex_of_N_FFT)malloc(N_FFT * sizeof(complex_of_N_FFT)); //data_of_N_FFT = //ptr_complex_of_N_FFT SIN_TABLE_of_N_FFT=NULL; //SIN_TABLE_of_N_FFT = (ElemType *)malloc((Npart4_of_N_FFT+1) * sizeof(ElemType)); SIN_TABLE_of_N_FFT = new float[Npart4_of_N_FFT+1]; CREATE_SIN_TABLE();//创建正弦函数表}//创建正弦函数表private void CREATE_SIN_TABLE(){ int i=0; for (i=0; i<=Npart4_of_N_FFT; i++) { SIN_TABLE_of_N_FFT[i] = (float) Math.sin(PI*i/Npart2_of_N_FFT);//SIN_TABLE[i] = sin(PI2*i/N); }}private float Sin_find(float x){ int i = (int)(N_FFT*x); i = i>>1; if (i>Npart4_of_N_FFT)//注意:i已经转化为0~N之间的整数了! { //不会超过N/2 i = Npart2_of_N_FFT - i;//i = i - 2*(i-Npart4); } return SIN_TABLE_of_N_FFT[i];}private float Cos_find(float x){ int i = (int)(N_FFT*x); i = i>>1; if (i<Npart4_of_N_FFT)//注意:i已经转化为0~N之间的整数了! { //不会超过N/2 //i = Npart4 - i; return SIN_TABLE_of_N_FFT[Npart4_of_N_FFT - i]; } else//i>Npart4 && i<N/2 { //i = i - Npart4; return -SIN_TABLE_of_N_FFT[i - Npart4_of_N_FFT]; }}private void ChangeSeat(Complex DataInput[]){ int nextValue,nextM,i,k,j=0; Complex temp; nextValue=N_FFT/2; //变址运算,即把自然顺序变成倒位序,采用雷德算法 nextM=N_FFT-1; for (i=0;i<nextM;i++) { if (i<j)//如果i<j,即进行变址 { temp=DataInput[j]; DataInput[j]=DataInput[i]; DataInput[i]=temp; } k=nextValue; //求j的下一个倒位序 while (k<=j)//如果k<=j,表示j的最高位为1 { j=j-k;//把最高位变成0 k=k/2;//k/2,比较次高位,依次类推,逐个比较,直到某个位为0 } j=j+k;//把0改为1 }}//FFT运算函数public void FFT(Complex []data){ int L=0,B=0,J=0,K=0; int step=0, KB=0; //ElemType P=0; float angle; Complex W = new Complex(); Complex Temp_XX = new Complex(); ChangeSeat(data);//变址 //CREATE_SIN_TABLE(); for (L=1; L<=M_of_N_FFT; L++) { step = 1<<L;//2^L B = step>>1;//B=2^(L-1) for (J=0; J<B; J++) { //P = (1<<(M-L))*J;//P=2^(M-L) *J angle = (float)J/B;//这里还可以优化 W.imag = -Sin_find(angle);//用C++该函数课声明为inline W.real = Cos_find(angle);//用C++该函数课声明为inline //W.real = cos(angle*PI); //W.imag = -sin(angle*PI); for (K=J; K<N_FFT; K=K+step) { KB = K + B; //Temp_XX = XX_complex(data[KB],W); //用下面两行直接计算复数乘法,省去函数调用开销 Temp_XX.real = data[KB].real * W.real-data[KB].imag*W.imag; Temp_XX.imag = W.imag*data[KB].real + data[KB].imag*W.real; data[KB].real = data[K].real - Temp_XX.real; data[KB].imag = data[K].imag - Temp_XX.imag; data[K].real = data[K].real + Temp_XX.real; data[K].imag = data[K].imag + Temp_XX.imag; } } }}//IFFT运算函数public void IFFT(Complex []data){ int L=0,B=0,J=0,K=0; int step=0, KB=0; //ElemType P=0; float angle=0.0f; Complex W = new Complex(); Complex Temp_XX = new Complex(); ChangeSeat(data);//变址 //CREATE_SIN_TABLE(); for (L=1; L<=M_of_N_FFT; L++) { step = 1<<L;//2^L B = step>>1;//B=2^(L-1) for (J=0; J<B; J++) { //P = (1<<(M-L))*J;//P=2^(M-L) *J angle = (float)J/B;//这里还可以优化 W.imag = Sin_find(angle);//用C++该函数课声明为inline W.real = Cos_find(angle);//用C++该函数课声明为inline //W.real = cos(angle*PI); //W.imag = -sin(angle*PI); for (K=J; K<N_FFT; K=K+step) { KB = K + B; //Temp_XX = XX_complex(data[KB],W); //用下面两行直接计算复数乘法,省去函数调用开销 Temp_XX.real = data[KB].real * W.real-data[KB].imag*W.imag; Temp_XX.imag = W.imag*data[KB].real + data[KB].imag*W.real; data[KB].real = data[K].real - Temp_XX.real; data[KB].imag = data[K].imag - Temp_XX.imag; data[K].real = data[K].real + Temp_XX.real; data[K].imag = data[K].imag + Temp_XX.imag; } } }}}下面的是一个辅助类:
public class Complex {public float real;public float imag;public Complex(){this.real = 0;this.imag = 0;}}
下面是自相关求解过程源码:
public class Correlation {private Complex[] s1 = null;private Complex[] s2 = null;private int lag = 0;public Correlation(float sig1[] , float sig2[]){int maxLen = sig1.length > sig2.length ? sig1.length : sig2.length;maxLen = (int) (Math.log(maxLen)/Math.log(2.0)) + 1;//求出FFT的幂次maxLen = (int) Math.pow(2, maxLen);s1 = new Complex[maxLen];s2 = new Complex[maxLen];for(int i=0;i<maxLen;i++){//这一步已经完成了补零的工作了s1[i] = new Complex();s2[i] = new Complex();}for(int i=0;i<sig1.length;i++){s1[i].real = sig1[i];//System.out.println(s1[i].real);}for(int i=0;i<sig2.length;i++){s2[i].real = sig2[i];//System.out.println(s2[i].real);}//求出信号的FFTfloat[] rr = new float[maxLen];FFT fft = new FFT(maxLen);fft.FFT(s1);fft.FFT(s2);conj(s2);mul(s1,s2);fft.IFFT(s1);float max = s1[maxLen-1].real;for(int i=0;i>maxLen;i++){if(s1[i].real > max){lag = i;max = s1[i].real;}//System.out.println(s1[i].real);}}public int getLag(){return lag;}//求两个复数的乘法,结果返回到第一个输入public void mul(Complex[] s1,Complex[] s2){float temp11=0,temp12=0;float temp21=0,temp22=0;for(int i=0;i<s1.length;i++){temp11 = s1[i].real ; temp12 = s1[i].imag;temp21 = s2[i].real ; temp22 = s2[i].imag;s1[i].real = temp11 * temp21 - temp12 * temp22;s1[i].imag = temp11 * temp22 + temp21 * temp12;//s1[i].real = s1[i].real * s2[i].real - s1[i].imag * s2[i].imag;//s1[i].imag = s1[i].real * s2[i].imag + s1[i].imag * s2[i].real;}}//求信号的共轭public void conj(Complex s[]){for(int i=0;i<s.length;i++){s[i].imag = 0.0f - s[i].imag;}}}下面的是测试代码:
public class Test {public static void main(String args[]){//fft的测试函数代码/*int f0 = 10;int fs = 100;int FFT_LENGHT = 512;float[] testdata = new float[FFT_LENGHT];Complex[] r = new Complex[FFT_LENGHT*2];for(int i=0;i<r.length;i++){r[i] = new Complex();}FFT fft = new FFT(FFT_LENGHT*2);for(int i=0;i<FFT_LENGHT;i++){r[i].real = (float) Math.sin(2*3.1415926*i*f0/fs);r[i].imag = 0.0f;//testdata[i] = (float) Math.sin(2*3.1415926*i*f0/fs);}//r = fft.complexLization(testdata);fft.FFT(r);testdata = fft.magnitude(r);for(int i=0;i<FFT_LENGHT;i++){System.out.println(testdata[i]);}*///测试互相关函数int f0=10;int fs=150;int K = 50;int lag = 50;int dataLength = 16;float[] s1 = new float[dataLength];float[] s2 = new float[dataLength*2];for(int i=0;i<dataLength;i++){//s1[i] = (float) Math.sin(2*3.14*(i*2.0/K/fs+f0)*i/fs);s1[i] = (float) Math.sin(2*3.14*f0*i/fs);//System.out.println(s1[i]);}for(int i=0;i<dataLength*1;i++){s2[i] = 0;}for(int i=dataLength*1;i<dataLength*2;i++){s2[i] = s1[i-dataLength*1];}Correlation correlation = new Correlation(s1, s2);//System.out.println("结果:"+correlation.getLag());}}
再来个对应结果的图吧:
从图从左往右数,最高的刚好是第16个点,再看看测试代码里面的两个信号就知道刚好延迟了一个信号周期,刚好16个点,结果太完美了。
先写到这里,后面有 成果了再上传其它的代码。
0 0
- 广义互相关求信号时延 JAVA实现
- 信号互相关及其应用
- 信号处理:自相关和互相关
- 自相关与互相关在matlab中实现
- 自相关与互相关在matlab中实现
- Cross correlation/互相关
- 归一化互相关算法
- 求教:两个向量求互相关性,用Matlab画出图像后,应该如何分析?
- 广义表操作 (Java实现)——广义表深度、广义表长度、打印广义表信息
- 实现广义表求表头和表尾的运算
- 广义表及其Java代码实现
- 互相关信息和归一化互相关信息
- C语言做互相关
- 互相关法提取基音
- 两个序列的互相关
- 互相关与卷积关系
- java 实现文件互相copy
- 广义表求深度
- js格式化时间
- 第十五周(项目二)——用文件保存学生的名单。
- 设计模式----抽象工厂模式
- 使用 lsof 查找打开的文件
- Socket通信实验总结
- 广义互相关求信号时延 JAVA实现
- n 个元素顺序入栈,则可能的出栈序列有多少种?
- leetcode——Longest Substring Without Repeating Characters 求链表中无重复字符的最大字串长度(AC)
- All in All
- POJ3254 Corn fiedls
- void用法的总结
- Unix调试的瑞士军刀:lsof
- Web For Pentester 阅读笔记(1)
- GIT远程中央版本库配置