www.pudn.com > readaudioshow.rar > SpectrumThread.cpp


//--------------------------------------------------------------------------- 
#include  
#pragma hdrstop 
#include  
#include "SpectrumThread.h" 
#pragma package(smart_init) 
const double    PI=3.14159265; 
 
//--------------------------------------------------------------------------- 
__fastcall SpectrumThread::SpectrumThread(bool CreateSuspended, TPaintBox *in, int ic) : 
    TThread(CreateSuspended) 
{ 
    count=ic; 
    view=in; 
    data=new short[ic * 2]; 
    WaveR=new double[ic]; 
    WaveI=new double[ic]; 
    busy=false; 
} 
 
//--------------------------------------------------------------------------- 
__fastcall SpectrumThread::~SpectrumThread(void) 
{ 
    delete[] data; 
    delete[] WaveR; 
    delete[] WaveI; 
} 
 
//--------------------------------------------------------------------------- 
void SpectrumThread::Process(short *idata) 
{ 
    if(!busy) 
    { 
        memcpy(data, idata, 2 * count * sizeof(short)); 
        Resume(); 
    } 
} 
 
//--------------------------------------------------------------------------- 
void SpectrumThread::SetMousePoint(int x, int y) 
{ 
    if(!busy) 
    { 
        point.x=x; 
        point.y=y; 
    } 
} 
 
//--------------------------------------------------------------------------- 
void __fastcall SpectrumThread::Execute(void) 
{ 
    //---- Place thread code here ---- 
    while(!Terminated) 
    { 
        FillBuffer(); 
    } 
} 
 
//--------------------------------------------------------------------------- 
void __fastcall SpectrumThread::FillBuffer(void) 
{ 
    long    zerolevel=view->ClientHeight - 30; 
    int     i, dx, freq; 
    double  ts=static_cast(view->ClientWidth) / static_cast(count) * 2; 
    busy=true; 
    view->Canvas->Lock(); 
    view->Canvas->Brush->Color=clBlack; 
    view->Canvas->Pen->Color=clWhite; 
    view->Canvas->Rectangle(0, 0, view->ClientWidth, view->ClientHeight); 
    view->Canvas->Pen->Color=clYellow; 
    view->Canvas->MoveTo(0, zerolevel); 
    view->Canvas->LineTo(view->ClientWidth, zerolevel); 
 
    dx=view->ClientWidth / 22; 
    for(long i=dx; i < view->ClientWidth - dx; i+=dx) 
    { 
        view->Canvas->TextOutA(i - 12, zerolevel + 2, IntToStr(i / dx) + "kHz"); 
    } 
 
    freq=point.x * 22050 / view->ClientWidth; 
    view->Canvas->TextOutA(view->ClientWidth - 50, 10, IntToStr(freq) + "Hz"); 
    memset(WaveI, 0, count * sizeof(double)); 
 
    for(i=0; i < count; i++) 
    { 
        WaveR[i]=data[i * 2]; 
    } 
 
    FFT(WaveR, WaveI, count, 1); 
    view->Canvas->Pen->Color=clAqua; 
    view->Canvas->MoveTo(0, zerolevel - sqrt(WaveR[0] * WaveR[0] + WaveI[0] * WaveI[0]) / count * 2); 
    for(i=1; i < count / 2; i++) 
    { 
        view->Canvas->LineTo(i * ts, zerolevel - sqrt(WaveR[i] * WaveR[i] + WaveI[i] * WaveI[i]) / count * 2); 
    } 
 
    memset(WaveI, 0, count * sizeof(double)); 
 
    for(i=0; i < count; i++) 
    { 
        WaveR[i]=data[i * 2 + 1]; 
    } 
 
    FFT(WaveR, WaveI, count, 1); 
    view->Canvas->Pen->Color=clRed; 
    view->Canvas->MoveTo(0, zerolevel - sqrt(WaveR[0] * WaveR[0] + WaveI[0] * WaveI[0]) / count * 2); 
    for(i=1; i < count / 2; i++) 
    { 
        view->Canvas->LineTo(i * ts, zerolevel - sqrt(WaveR[i] * WaveR[i] + WaveI[i] * WaveI[i]) / count * 2); 
    } 
 
    view->Canvas->Unlock(); 
    busy=false; 
    Suspend(); 
} 
 
//--------------------------------------------------------------------------- 
void __fastcall SpectrumThread::fft1(double *br, double *bi, int il, const double *st, const double *ct) 
{ 
    //the size of br,bi should be equal to il. 
 
    //and size of st and ct no less than il. 
    int is=il >> 1; 
    int mpx=0; 
    int ic=1; 
    int ia; 
 
    while(is) 
    { 
        is>>=1; 
        mpx++; 
    } 
 
    is=il; 
 
    for(ia=1; ia <= mpx; ia++) 
    { 
        int ib; 
        int ka=0; 
        is>>=1; 
        for(ib=1; ib <= ic; ib++) 
        { 
            int in=1; 
            int k; 
            for(k=1; k <= is; k++) 
            { 
                int     j1=ka + k; 
                int     j2=j1 + is; 
                double  xr=br[j1]; 
                double  xi=bi[j1]; 
                double  yr=br[j2]; 
                double  yi=bi[j2]; 
                br[j1]=xr + yr; 
                bi[j1]=xi + yi; 
                xr-=yr; 
                xi-=yi; 
                br[j2]=xr * ct[in] - xi * st[in]; 
                bi[j2]=xr * st[in] + xi * ct[in]; 
                in+=ic; 
            } 
 
            ka+=is << 1; 
        } 
 
        ic<<=1; 
    } 
} 
 
/* */ 
void __fastcall SpectrumThread::binrv(double *bc, int il, const int *lb) 
{ 
    int is=il - 1; 
    int i; 
    for(i=2; i <= is; i++) 
    { 
        int ig=lb[i]; 
        if(ig <= i) continue; 
 
        double  xx=bc[i]; 
        bc[i]=bc[ig]; 
        bc[ig]=xx; 
    } 
} 
 
/* */ 
void __fastcall SpectrumThread::brtab(int *lbr, int il) 
{ 
    int is=il >> 1; 
    int mpx=0; 
    while(is) 
    { 
        is>>=1; 
        mpx++; 
    } 
 
    int ln; 
    for(ln=1; ln <= il; ln++) 
    { 
        int j1=ln - 1; 
        int ibord=0; 
        for(int k=1; k <= mpx; k++) 
        { 
            int j2=j1 >> 1; 
            ibord=ibord * 2 + (j1 - 2 * j2); 
            j1=j2; 
        } 
 
        lbr[ln]=ibord + 1; 
    } 
} 
 
/* */ 
void __fastcall SpectrumThread::cstab(double *st, double *ct, int il, int ity) 
{ 
    double  yy; 
    yy= -PI * 2.0 / il; 
    if(ity < 0) yy= -yy; 
 
    int     l; 
    double  ang=0.0; 
    for(l=1; l <= il; l++) 
    { 
        st[l]=sin(ang); 
        ct[l]=cos(ang); 
        ang+=yy; 
    } 
} 
 
/* */ 
void __fastcall SpectrumThread::FFT(double *br, double *bi, int n, int ity) 
//ity>0 forward ,ity<0 backward 
 
//n=pow(2,m); 
 
//Here br and bi start from 0. 
{ 
    double  *ct, *st; 
    int     *il; 
    if(n <= 0) return; 
 
    double  invsqrtn=1.0 / sqrt(n); 
    ct= (double *)malloc(sizeof(double) * n) - 1; 
    st= (double *)malloc(sizeof(double) * n) - 1; 
    cstab(st, ct, n, ity); 
    il= (int *)malloc(sizeof(int) * n) - 1; 
    brtab(il, n); 
    fft1(br - 1, bi - 1, n, st, ct); 
    binrv(br - 1, n, il); 
    binrv(bi - 1, n, il); 
    for(int i=0; i < n; i++) 
    { 
        br[i]*=invsqrtn; 
        bi[i]*=invsqrtn; 
    } 
 
    free(il + 1); 
    free(ct + 1); 
    free(st + 1); 
}