码迷,mamicode.com
首页 > 其他好文 > 详细

CZT变换(chirp z-transform)

时间:2018-05-20 14:12:34      阅读:439      评论:0      收藏:0      [点我收藏+]

标签:https   技术分享   说明   关闭   call   opened   size   abs   text   

作者:桂。

时间:2018-05-20  12:04:24

链接:http://www.cnblogs.com/xingshansi/p/9063131.html 


前言

相比DFT,CZT是完成频谱细化的一种思路,本文主要记录CZT的C代码实现。

一、代码实现

原理主要参考MATLAB接口:

技术分享图片

对应C代码实现:

Complex.c

技术分享图片
/*=============================
                          Chirp-Z Transform
=============================*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "Complex.h"
#include "FFT.h"

void CZT(comp* x, int  N, comp A, comp W, comp *xCZT, int  M);
void main()
{
    int i;
    int N,M;

    double PI;
    double A0,Theta0;
    double W0,Phi0;

    comp* x;
    comp* xCZT;
    comp A,W;

    PI = 3.1415926;

    N = 5;              //信号长度
    M = 10;            //chirp-z 变换输出长度
    x = (comp *)calloc(N,sizeof(comp));
    xCZT  = (comp *)calloc(M,sizeof(comp));
    for (i = 0;i < N; i++)
    {
        x[i].re=(float)(i-3);
        x[i].im = 0.0;
    }

    A0 = 1.0;                   //起始抽样点z0的矢量半径长度
    Theta0 = 0.0;             //起始抽样点z0的相角
    A.re = (float)(A0*cos(Theta0));
    A.im = (float)(A0*sin(Theta0));

    Phi0 = 2.0*PI/M;      //两相邻抽样点之间的角度差
    W0 = 1.0;                  //螺线的伸展率
    W.re = (float)(W0*cos(-Phi0));
    W.im = (float)(W0*sin(-Phi0));


    CZT(x,N,A,W,xCZT,M);

    printf("The Original Signal:\n");
    for (i = 0; i<N; i++)
    {
        printf("%10.4f",x[i].re);
        printf("%10.4f\n",x[i].im);
    }

    printf("The Chirp-Z Transfrom:\n");
    for (i = 0 ;i<M ;i++)
    {
        printf("%10.4f",xCZT[i].re);
        printf("%10.4f\n",xCZT[i].im);
    }

}


/*----------------函数说明----------------------
Name: CZT
Function: Chirp-Z Transform
Para:  x[in][out]:待变换信号                            N[in]:信号长度
         A[in]:                                                       W[in]:
         M[in]:Chirp-Z变换输出长度
--------------------------------------------*/
void CZT(comp* x, int  N, comp A, comp W, comp* xCZT, int  M)
{
    int i;
    int L;

    comp* h;
    comp* g;
    comp* pComp;
    comp tmp,tmp1,tmp2;

    i=1;
    do 
    {
        i*=2;
    } while (i<N+M-1);
    L = i;

    h = (comp*)calloc(L,sizeof(comp));
    g = (comp*)calloc(L,sizeof(comp));
    pComp = (comp*)calloc(L,sizeof(comp));

    for (i = 0; i<N; i++)
    {
        tmp1 = cpow(A,-i);
        tmp2 = cpow(W, i*i/2.0);
        tmp = cmul(tmp1,tmp2);
        g[i] = cmul(tmp,x[i]);
    }
    for (i = N;i<L; i++)
    {
        g[i] =czero();
    }

    FFT(g,L,1);

    for (i = 0;i<=M-1;i++)
    {
        h[i] = cpow(W, -i*i/2.0);
    }
    for (i=M; i<=L-N;i++)
    {
        h[i] =czero();
    }
    for (i = L-N+1; i<=L;i++)
    {
        h[i] = cpow(W,-(L-i)*(L-i)/2.0);
    }

    FFT(h,L,1);

    for (i = 0; i<L; i++)
    {
        pComp[i] = cmul(h[i],g[i]);
    }

    FFT(pComp,L,-1);         //IDFT

    for (i = 0; i<M;i++)
    {
        tmp = cpow(W,i*i/2.0);
        xCZT[i] = cmul(tmp,pComp[i]);
    }


}
View Code

Complex.h

技术分享图片
/*===========================
Define comp as complex type
cmplx     c = (a,b)
cmul     c=a*b
conjg    c=a‘
cabs1    f=|a|
cabs2    f=|a|**2
cadd     c=a+b
csub     c=a-b
czero    c=(0.0,0.0)
===========================*/
#ifndef COMPLEX_H
#define COMPLEX_H
#include <math.h>
typedef  struct xy
{
    float re;
    float im;
}comp;
comp cmplx(float a,float b);
comp cmul(comp a,comp b);
comp conjg(comp a);
float cabs1(comp a);
float cabs2(comp a);
comp cadd(comp a,comp b);
comp csub(comp a,comp b);
comp czero();
comp cpow(comp a,double n);
float arg(comp a);

#endif
View Code

CZT.c

技术分享图片
/*=============================
                          Chirp-Z Transform
=============================*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "Complex.h"
#include "FFT.h"

void CZT(comp* x, int  N, comp A, comp W, comp *xCZT, int  M);
void main()
{
    int i;
    int N,M;

    double PI;
    double A0,Theta0;
    double W0,Phi0;

    comp* x;
    comp* xCZT;
    comp A,W;

    PI = 3.1415926;

    N = 5;              //信号长度
    M = 10;            //chirp-z 变换输出长度
    x = (comp *)calloc(N,sizeof(comp));
    xCZT  = (comp *)calloc(M,sizeof(comp));
    for (i = 0;i < N; i++)
    {
        x[i].re=(float)(i-3);
        x[i].im = 0.0;
    }

    A0 = 1.0;                   //起始抽样点z0的矢量半径长度
    Theta0 = 0.0;             //起始抽样点z0的相角
    A.re = (float)(A0*cos(Theta0));
    A.im = (float)(A0*sin(Theta0));

    Phi0 = 2.0*PI/M;      //两相邻抽样点之间的角度差
    W0 = 1.0;                  //螺线的伸展率
    W.re = (float)(W0*cos(-Phi0));
    W.im = (float)(W0*sin(-Phi0));


    CZT(x,N,A,W,xCZT,M);

    printf("The Original Signal:\n");
    for (i = 0; i<N; i++)
    {
        printf("%10.4f",x[i].re);
        printf("%10.4f\n",x[i].im);
    }

    printf("The Chirp-Z Transfrom:\n");
    for (i = 0 ;i<M ;i++)
    {
        printf("%10.4f",xCZT[i].re);
        printf("%10.4f\n",xCZT[i].im);
    }

}


/*----------------函数说明----------------------
Name: CZT
Function: Chirp-Z Transform
Para:  x[in][out]:待变换信号                            N[in]:信号长度
         A[in]:                                                       W[in]:
         M[in]:Chirp-Z变换输出长度
--------------------------------------------*/
void CZT(comp* x, int  N, comp A, comp W, comp* xCZT, int  M)
{
    int i;
    int L;

    comp* h;
    comp* g;
    comp* pComp;
    comp tmp,tmp1,tmp2;

    i=1;
    do 
    {
        i*=2;
    } while (i<N+M-1);
    L = i;

    h = (comp*)calloc(L,sizeof(comp));
    g = (comp*)calloc(L,sizeof(comp));
    pComp = (comp*)calloc(L,sizeof(comp));

    for (i = 0; i<N; i++)
    {
        tmp1 = cpow(A,-i);
        tmp2 = cpow(W, i*i/2.0);
        tmp = cmul(tmp1,tmp2);
        g[i] = cmul(tmp,x[i]);
    }
    for (i = N;i<L; i++)
    {
        g[i] =czero();
    }

    FFT(g,L,1);

    for (i = 0;i<=M-1;i++)
    {
        h[i] = cpow(W, -i*i/2.0);
    }
    for (i=M; i<=L-N;i++)
    {
        h[i] =czero();
    }
    for (i = L-N+1; i<=L;i++)
    {
        h[i] = cpow(W,-(L-i)*(L-i)/2.0);
    }

    FFT(h,L,1);

    for (i = 0; i<L; i++)
    {
        pComp[i] = cmul(h[i],g[i]);
    }

    FFT(pComp,L,-1);         //IDFT

    for (i = 0; i<M;i++)
    {
        tmp = cpow(W,i*i/2.0);
        xCZT[i] = cmul(tmp,pComp[i]);
    }


}
View Code

FFT.c

技术分享图片
#include "FFT.h"

void FFT(comp *data,int FFTn,int inverse)
{
    comp      u,w,t;
    double     temp1,temp2;
    double     pi;
    int       i,j,k,l,ip;
    int       le,le1,m;

    pi=3.1415926f;
    m=0;
    while(FFTn != (0x0001<<m)) m++;
    for(i=0,j=0; i<FFTn-1; i++)
    {
        if(i<j)
        {
            t=data[j];
            data[j]=data[i];
            data[i]=t;
        }
        k=FFTn/2;
        while(k<=j)
        {
            j-=k;
            k/=2;
        }
        j+=k;
    }
    le=1;
    for(l=0; l<m; l++ )
    {
        le*=2;
        le1=le/2;
        u.re=(float)1.0;
        u.im=(float)0.0;
        w.re=(float)cos(pi/le1);
        w.im=(float)(inverse*sin(pi/le1));
        for(j=0; j<le1; j++)
        {
            for(i=j; i<FFTn; i+=le)
            {
                ip=i+le1;
                t.re=data[ip].re*u.re-data[ip].im*u.im;
                t.im=data[ip].re*u.im+data[ip].im*u.re;
                data[ip].re=data[i].re-t.re;
                data[ip].im=data[i].im-t.im;
                data[i].re+=t.re;
                data[i].im+=t.im;
             }
            temp1=u.re;
            temp2=u.im;
            u.re=(float)(temp1*w.re-temp2*w.im);
            u.im=(float)(temp1*w.im+temp2*w.re);
        }
    }
    if(inverse>0) return;
    for(i=0; i<FFTn; i++)
    {
        data[i].re/=FFTn;
        data[i].im/=FFTn;
    }
    return;
}
View Code

FFT.h

技术分享图片
#ifndef    _FFT1_H_
#define    _FFT1_H_

#include "Complex.h"
//========================================
//功能:    实现FFT
//输入:    data[in][out]: 数据指针;  FFTn[in]:FFT点数; 
//            inverse[in]:正反FFT标志位:1,正FFT;-1,逆FFT
void FFT(comp *data,int FFTn,int inverse);

#endif
View Code

二、仿真测试

参数设置:

技术分享图片

结果对比:

  • matlab

技术分享图片

  • C

 技术分享图片

利用CZT对信号进行频率估计:

 频率细化直接查找:

技术分享图片

仿真code:

clc;clear all;close all;
fs = 1000;
f0 = 201.3;
t = [0:199]/fs;
sig = (sin(2*pi*t*f0));
% %存入txt
% fp=fopen(‘data.txt‘,‘a‘);%‘A.txt‘为文件名;‘a‘为打开方式:在打开的文件末端添加数据,若文件不存在则创建。
% fprintf(fp,‘%f ‘,sig);%fp为文件句柄,指定要写入数据的文件。注意:%d后有空格。
% fclose(fp);%关闭文件。

f1 = 190;
f2 = 210;
m = 100;
w = exp(-1j*2*pi*(f2-f1)/(m*fs));
a = exp(1j*2*pi*f1/fs);
y = czt(sig,m,w,a);
[val,pos] = max(abs(y));
fre_est = (pos-1)*(f2-f1)/m+f1;
y1 = fft(sig);
figure()
subplot 211
plot(linspace(f1,f2,length(y)),abs(y));
hold on;
scatter(fre_est,abs(y(pos)),‘r*‘);
subplot 212
plot(t/max(t)*fs,abs(y1))

  一个基本应用,频率精确测量:一种卫星信号载波频率精确估计算法.pdf

CZT变换(chirp z-transform)

标签:https   技术分享   说明   关闭   call   opened   size   abs   text   

原文地址:https://www.cnblogs.com/xingshansi/p/9063131.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!