Mercurial > hg > x
view wavelet.cpp @ 1:6422640a802f
first upload
author | Wen X <xue.wen@elec.qmul.ac.uk> |
---|---|
date | Tue, 05 Oct 2010 10:45:57 +0100 |
parents | |
children | fc19d45615d1 |
line wrap: on
line source
//--------------------------------------------------------------------------- #include <math.h> #include <mem.h> #include "wavelet.h" #include "matrix.h" //--------------------------------------------------------------------------- /* function csqrt: real implementation of complex square root z=sqrt(x) In: xr and xi: real and imaginary parts of x Out: zr and zi: real and imaginary parts of z=sqrt(x) No return value. */ void csqrt(double& zr, double& zi, double xr, double xi) { if (xi==0) if (xr>=0) zr=sqrt(xr), zi=0; else zi=sqrt(-xr), zr=0; else { double xm=sqrt(xr*xr+xi*xi); double ri=sqrt((xm-xr)/2); zr=xi/2/ri; zi=ri; } }//csqrt /* function Daubechies: calculates the Daubechies filter of a given order p In: filter order p Out: h[2p]: the 2p FIR coefficients No reutrn value. The calculated filters are minimum phase, which means the energy concentrates at the beginning. This is usually used for reconstruction. On the contrary, for wavelet analysis the filter is mirrored. */ void Daubechies(int p, double* h) { //initialize h(z) double r01=pow(2, -p-p+1.5); h[0]=1; for (int i=1; i<=p; i++) { h[i]=h[i-1]*(p+1-i)/i; } //construct polynomial p double *P=new double[p], *rp=new double[p], *ip=new double[p]; P[p-1]=1; double r02=1; for (int i=p-1; i>0; i--) { double rate=(i+1-1.0)/(p-2.0+i+1); P[i-1]=P[i]*rate; r02/=rate; } Roots(p-1, P, rp, ip); for (int i=0; i<p-1; i++) { //current length of h is p+1+i, h[0:p+i] if (i<p-2 && rp[i]==rp[i+1] && ip[i]==-ip[i+1]) { double ar=rp[i], ai=ip[i]; double bkr=-2*ar+1, bki=-2*ai, ckr=4*(ar*ar-ai*ai-ar), cki=4*(2*ar*ai-ai), dlr, dli; csqrt(dlr, dli, ckr, cki); double akr=bkr+dlr, aki=bki+dli; if (akr*akr+aki*aki>1) akr=bkr-dlr, aki=bki-dli; double ak1=-2*akr, ak2=akr*akr+aki*aki; h[p+2+i]=ak2*h[p+i]; h[p+1+i]=ak2*h[p-1+i]+ak1*h[p+i]; for (int j=p+i; j>1; j--) h[j]=h[j]+ak1*h[j-1]+ak2*h[j-2]; h[1]=h[1]+ak1*h[0]; r02/=ak2; i++; } else //real root of P { double ak, bk=-(2*rp[i]-1), delk=4*rp[i]*(rp[i]-1); if (bk>0) ak=bk-sqrt(delk); else ak=bk+sqrt(delk); r02/=ak; h[p+1+i]=-ak*h[p+i]; for (int j=p+i; j>0; j--) h[j]=h[j]-ak*h[j-1]; } } delete[] P; delete[] rp; delete[] ip; r01=r01*sqrt(r02); for (int i=0; i<p*2; i++) h[i]*=r01; }//Daubechies /* Periodic wavelet decomposition and reconstruction routines The wavelet transform of an N-point sequence is arranged in "interleaved" format as another N-point sequance. Level 1 details are found at N/2 points 1, 3, 5, ..., N-1; level 2 details are found at N/4 points 2, 6, ..., N-2; level 3 details are found at N/8 points 4, 12, ..., N-4; etc. */ /* function dwtpqmf: in this implementation h and g are the same as reconstruction qmf filters. In fact the actual filters used are their mirrors and filter origin are aligned to the ends of the real filters, which turn out to be the starts of h and g. The inverse transform is idwtp(), the same as inversing dwtp(). In: in[Count]: waveform data h[M], g[M]: quadratic mirror filter pair N: maximal time resolution Count=kN, N=2^lN being the reciprocal of the most detailed frequency scale, i.e. N=1 for no transforming at all, N=2 for dividing into approx. and detail, N=4 for dividing into approx+detail(approx+detial), etc. Count*2/N=2k gives the smallest length to be convolved with h and g. Out: out[N], the wavelet transform, arranged in interleaved format. Returns maximal atom length (should equal N). */ int dwtpqmf(double* in, int Count, int N, double* h, double* g, int M, double* out) { double* tmp=new double[Count]; double *tmpa=tmp, *tmpla=in; int C=Count, L=0, n=1; A: { //C: signal length at current layer //L: layer index, 0 being most detailed //n: atom length on current layer, equals 2^L. //C*n=(C<<L)=Count double* tmpd=&tmpa[C/2]; for (int i=0; i<C; i+=2) { int i2=i/2; tmpa[i2]=tmpla[i]*h[0]; tmpd[i2]=tmpla[i]*g[0]; for (int j=1; j<M; j++) { if (i+j<C) { tmpa[i2]+=tmpla[i+j]*h[j]; tmpd[i2]+=tmpla[i+j]*g[j]; } else { tmpa[i2]+=tmpla[i+j-C]*h[j]; tmpd[i2]+=tmpla[i+j-C]*g[j]; } } } for (int i=0; i*2+1<C; i++) out[(2*i+1)<<L]=tmpd[i]; for (int i=0; i*2<C; i++) out[i<<(L+1)]=tmpa[i]; n*=2; if (n<N) { tmpla=tmpa; tmpa=tmpd; L++; C/=2; goto A; } } delete[] tmp; return n; }//dwtpqmf /* function dwtp: in this implementation h and g can be different from mirrored reconstruction filters, i.e. the biorthogonal transform. h[0] and g[0] are aligned at the ends of the filters, i.e. h[-M+1:0], g[-M+1:0]. In: in[Count]: waveform data h[-M+1:0], g[-M+1:0]: quadratic mirror filter pair N: maximal time resolution Out: out[N], the wavelet transform, arranged in interleaved format. Returns maximal atom length (should equal N). */ int dwtp(double* in, int Count, int N, double* h, double* g, int M, double* out) { double* tmp=new double[Count]; double *tmpa=tmp, *tmpla=in; int C=Count, L=0, n=1; A: { double* tmpd=&tmpa[C/2]; for (int i=0; i<C; i+=2) { int i2=i/2; tmpa[i2]=tmpla[i]*h[0]; tmpd[i2]=tmpla[i]*g[0]; for (int j=-1; j>-M; j--) { if (i-j<C) { tmpa[i2]+=tmpla[i-j]*h[j]; tmpd[i2]+=tmpla[i-j]*g[j]; } else { tmpa[i2]+=tmpla[i-j-C]*h[j]; tmpd[i2]+=tmpla[i-j-C]*g[j]; } } } for (int i=0; i*2+1<C; i++) out[(2*i+1)<<L]=tmpd[i]; for (int i=0; i*2<C; i++) out[i<<(L+1)]=tmpa[i]; n*=2; if (n<N) { tmpla=tmpa; tmpa=tmpd; L++; C/=2; goto A; } } delete[] tmp; return n; }//dwtp /* function dwtp: in this implementation h and g can be different size. h[0] and g[0] are aligned at the ends of the filters, i.e. h[-Mh+1:0], g[-Mg+1:0]. In: in[Count]: waveform data h[-Mh+1:0], g[-Mg+1:0]: quadratic mirror filter pair N: maximal time resolution Out: out[N], the wavelet transform, arranged in interleaved format. Returns maximal atom length (should equal N). */ int dwtp(double* in, int Count, int N, double* h, int Mh, double* g, int Mg, double* out) { double* tmp=new double[Count]; double *tmpa=tmp, *tmpla=in; int C=Count, L=0, n=1; A: { double* tmpd=&tmpa[C/2]; for (int i=0; i<C; i+=2) { int i2=i/2; tmpa[i2]=tmpla[i]*h[0]; tmpd[i2]=tmpla[i]*g[0]; for (int j=-1; j>-Mh; j--) { if (i-j<C) { tmpa[i2]+=tmpla[i-j]*h[j]; } else { tmpa[i2]+=tmpla[i-j-C]*h[j]; } } for (int j=-1; j>-Mg; j--) { if (i-j<C) { tmpd[i2]+=tmpla[i-j]*g[j]; } else { tmpd[i2]+=tmpla[i-j-C]*g[j]; } } } for (int i=0; i*2+1<C; i++) out[(2*i+1)<<L]=tmpd[i]; for (int i=0; i*2<C; i++) out[i<<(L+1)]=tmpa[i]; n*=2; if (n<N) { tmpla=tmpa; tmpa=tmpd; L++; C/=2; goto A; } } delete[] tmp; return n; }//dwtp /* function dwtp: in this implementation h and g can be arbitrarily located: h from $sh to $eh, g from $sg to $eg. In: in[Count]: waveform data h[sh:eh-1], g[sg:eg-1]: quadratic mirror filter pair N: maximal time resolution Out: out[N], the wavelet transform, arranged in interleaved format. Returns maximal atom length (should equal N). */ int dwtp(double* in, int Count, int N, double* h, int sh, int eh, double* g, int sg, int eg, double* out) { double* tmp=new double[Count]; double *tmpa=tmp, *tmpla=in; int C=Count, L=0, n=1; A: { double* tmpd=&tmpa[C/2]; for (int i=0; i<C; i+=2) { int i2=i/2; tmpa[i2]=0;//tmpla[i]*h[0]; tmpd[i2]=0;//tmpla[i]*g[0]; for (int j=sh; j<=eh; j++) { int ind=i-j; if (ind>=C) tmpa[i2]+=tmpla[ind-C]*h[j]; else if (ind<0) tmpa[i2]+=tmpla[ind+C]*h[j]; else tmpa[i2]+=tmpla[ind]*h[j]; } for (int j=sg; j<=eg; j++) { int ind=i-j; if (ind>=C) tmpd[i2]+=tmpla[i-j-C]*g[j]; else if (ind<0) tmpd[i2]+=tmpla[i-j+C]*g[j]; else tmpd[i2]+=tmpla[i-j]*g[j]; } } for (int i=0; i*2+1<C; i++) out[(2*i+1)<<L]=tmpd[i]; for (int i=0; i*2<C; i++) out[i<<(L+1)]=tmpa[i]; n*=2; if (n<N) { tmpla=tmpa; tmpa=tmpd; L++; C/=2; goto A; } } delete[] tmp; return n; }//dwtp /* function idwtp: periodic wavelet reconstruction by qmf In: in[Count]: wavelet transform in interleaved format h[M], g[M]: quadratic mirror filter pair N: maximal time resolution Out: out[N], waveform data (detail level 0). No return value. */ void idwtp(double* in, int Count, int N, double* h, double* g, int M, double* out) { double* tmp=new double[Count]; memcpy(out, in, sizeof(double)*Count); int n=N, C=Count/N, L=log2(N)-1; while (n>1) { memset(tmp, 0, sizeof(double)*C*2); //2k<<L being the approx, (2k+1)<<L being the detail for (int i=0; i<C; i++) { for (int j=0; j<M; j++) { if (i*2+j<C*2) { tmp[i*2+j]+=out[(2*i)<<L]*h[j]+out[(2*i+1)<<L]*g[j]; } else { tmp[i*2+j-C*2]+=out[(2*i)<<L]*h[j]+out[(2*i+1)<<L]*g[j]; } } } for (int i=0; i<C*2; i++) out[i<<L]=tmp[i]; n/=2; C*=2; L--; } delete[] tmp; }//idwtp /* function idwtp: in which h and g can have different length. In: in[Count]: wavelet transform in interleaved format h[Mh], g[Mg]: quadratic mirror filter pair N: maximal time resolution Out: out[N], waveform data (detail level 0). No return value. */ void idwtp(double* in, int Count, int N, double* h, int Mh, double* g, int Mg, double* out) { double* tmp=new double[Count]; memcpy(out, in, sizeof(double)*Count); int n=N, C=Count/N, L=log2(N)-1; while (n>1) { memset(tmp, 0, sizeof(double)*C*2); //2k<<L being the approx, (2k+1)<<L being the detail for (int i=0; i<C; i++) { for (int j=0; j<Mh; j++) { int ind=i*2+j+(Mg-Mh)/2; if (ind>=C*2) { tmp[ind-C*2]+=out[(2*i)<<L]*h[j]; } else if (ind<0) { tmp[ind+C*2]+=out[(2*i)<<L]*h[j]; } else { tmp[ind]+=out[(2*i)<<L]*h[j]; } } } for (int i=0; i<C; i++) { for (int j=0; j<Mg; j++) { int ind=i*2+j+(Mh-Mg)/2; if (ind>=C*2) { tmp[ind-C*2]+=out[(2*i+1)<<L]*g[j]; } else if (ind<0) { tmp[ind+C*2]+=out[(2*i+1)<<L]*g[j]; } else { tmp[ind]+=out[(2*i+1)<<L]*g[j]; } } } for (int i=0; i<C*2; i++) out[i<<L]=tmp[i]; n/=2; C*=2; L--; } delete[] tmp; }//idwtp /* function idwtp: in which h and g can be arbitrarily located: h from $sh to $eh, g from $sg to $eg In: in[Count]: wavelet transform in interleaved format h[sh:eh-1], g[sg:eg-1]: quadratic mirror filter pair N: maximal time resolution Out: out[N], waveform data (detail level 0). No return value. */ void idwtp(double* in, int Count, int N, double* h, int sh, int eh, double* g, int sg, int eg, double* out) { double* tmp=new double[Count]; memcpy(out, in, sizeof(double)*Count); int n=N, C=Count/N, L=log2(N)-1; while (n>1) { memset(tmp, 0, sizeof(double)*C*2); //2k<<L being the approx, (2k+1)<<L being the detail for (int i=0; i<C; i++) { for (int j=sh; j<=eh; j++) { int ind=i*2+j; if (ind>=C*2) tmp[ind-C*2]+=out[(2*i)<<L]*h[j]; else if (ind<0) tmp[ind+C*2]+=out[(2*i)<<L]*h[j]; else tmp[ind]+=out[(2*i)<<L]*h[j]; } } for (int i=0; i<C; i++) { for (int j=sg; j<=eg; j++) { int ind=i*2+j; if (ind>=C*2) tmp[ind-C*2]+=out[(2*i+1)<<L]*g[j]; else if (ind<0) tmp[ind+C*2]+=out[(2*i+1)<<L]*g[j]; else tmp[ind]+=out[(2*i+1)<<L]*g[j]; } } for (int i=0; i<C*2; i++) out[i<<L]=tmp[i]; n/=2; C*=2; L--; } delete[] tmp; }//idwtp //--------------------------------------------------------------------------- /* Spline biorthogonal wavelet routines. Further reading: "Calculation of biorthogonal spline wavelets.pdf" */ //function Cmb: combination number C(n, k) (n>=k>=0) int Cmb(int n, int k) { if (k>n/2) k=n-k; int c=1; for (int i=1; i<=k; i++) c=c*(n+1-i)/i; return c; } /* function splinewl: computes spline biorthogonal wavelet filters. This version of splinewl calcualtes the positive-time half of h and hm coefficients only. p1 and p2 must have the same parity. If p1 is even, p1 coefficients will be returned in h1; if p1 is odd, p1-1 coefficients will be returned in h1. Actual length of h is p1+1, of hm is p1+2p2-1. only a half of each is kept. p even: h[0:p1/2] <- [p1/2:p1], hm[0:p1/2+p2-1] <- [p1/2+p2-1:p1+2p2-2] p odd: h[0:(p1-1)/2] <- [(p1+1)/2:p1], hm[0:(p1-3)/2+p2] <- [(p1-1)/2+p2:p1+2p2-2] i.e. h[0:hp1] <- [p1-hp1:p1], hm[0:hp1+p2-1] <- [p1-hp1-1+p2:p1+2p2-2] In: p1, p2: specify vanishing moments of h and hm Out: h[] and hm[] as specified above. No return value. */ void splinewl(int p1, int p2, double* h, double* hm) { int hp1=p1/2, hp2=p2/2; int q=(p1+p2)/2; h[hp1]=sqrt(2.0)*pow(2, -p1); // h1[hp1]=1; for (int i=1, j=hp1-1; i<=hp1; i++, j--) { h[j]=h[j+1]*(p1+1-i)/i; } double *_hh1=new double[p2+1], *_hh2=new double[2*q]; double *hh1=&_hh1[p2-hp2], *hh2=&_hh2[q]; hh1[hp2]=sqrt(2.0)*pow(2, -p2); for (int i=1, j=hp2-1; i<=hp2; i++, j--) { hh1[j]=hh1[j+1]*(p2+1-i)/i; } if (p2%2) //p2 is odd { for (int i=0; i<=hp2; i++) hh1[-i-1]=hh1[i]; } else //p2 even { for (int i=1; i<=hp2; i++) hh1[-i]=hh1[i]; } memset(_hh2, 0, sizeof(double)*2*q); for (int n=1-q; n<=q-1; n++) { int k=abs(n); int CC1=Cmb(q-1+k, k), CC2=Cmb(2*k, k-n); //CC=1.0*C(q-1+k, k)*C(2*k, k-n) for (; k<=q-1; k++) { hh2[n]=hh2[n]+1.0*CC1*CC2*pow(0.25, k); CC1=CC1*(q+k)/(k+1); CC2=CC2*(2*k+1)*(2*k+2)/((k+1-n)*(k+1+n)); } hh2[n]*=pow(-1, n); } //hh1[hp2-p2:hp2], hh2[1-q:q-1] //h2=conv(hh1, hh2), but the positive half only memset(hm, 0, sizeof(double)*(hp1+p2)); for (int i=hp2-p2; i<=hp2; i++) for (int j=1-q; j<=q-1; j++) { if (i+j>=0 && i+j<hp1+p2) hm[i+j]+=hh1[i]*hh2[j]; } delete[] _hh1; delete[] _hh2; }//splinewl /* function splinewl: calculates the analysis and reconstruction filter pairs of spline biorthogonal wavelet (h, g) and (hm, gm). h has the size p1+1, hm has the size p1+2p2-1. If p1+1 is odd, then all four filters are symmetric; if not, then h and hm are symmetric, while g and gm are anti-symmetric. The concatenation of filters h with hm (or g with gm) introduces a time shift of p1+p2-1, which is the return value multiplied by -1. If normmode==1, the results are normalized so that ||h||^2=||g||^2=1; if normmode==2, the results are normalized so that ||hm||^2=||gm||^2=1, if normmode==3, the results are normalized so that ||h||^2==||g||^2=||hm||^2=||gm||^2. If a *points* buffer is specified, the function returns the starting and ending positions (inclusive) of h, hm, g, and gm, in the order of (hs, he, hms, hme, gs, ge, gms, gme), as ps[0]~ps[7]. In: p1 and p2, specify vanishing moments of h and hm, respectively. normmode: mode for normalization Out: h[p1+1], g[p1+1], hm[p1+2p2-1], gm[p1+2p2-1], points[8] (optional) Returns -p1-p2+1. */ int splinewl(int p1, int p2, double* h, double* hm, double* g, double* gm, int normmode, int* points) { int lf=p1+1, lb=p1+2*p2-1; int hlf=lf/2, hlb=lb/2; double *h1=&h[hlf], *h2=&hm[hlb]; int hp1=p1/2, hp2=p2/2; int q=(p1+p2)/2; h1[hp1]=sqrt(2.0)*pow(2, -p1); // h1[hp1]=2*pow(2, -p1); for (int i=1, j=hp1-1; i<=hp1; i++, j--) h1[j]=h1[j+1]*(p1+1-i)/i; double *_hh1=new double[p2+1+2*q]; double *_hh2=&_hh1[p2+1]; double *hh1=&_hh1[p2-hp2], *hh2=&_hh2[q]; hh1[hp2]=sqrt(2.0)*pow(2, -p2); // hh1[hp2]=pow(2, -p2); for (int i=1, j=hp2-1; i<=hp2; i++, j--) hh1[j]=hh1[j+1]*(p2+1-i)/i; if (p2%2) for (int i=0; i<=hp2; i++) hh1[-i-1]=hh1[i]; else for (int i=1; i<=hp2; i++) hh1[-i]=hh1[i]; memset(_hh2, 0, sizeof(double)*2*q); for (int n=1-q; n<=q-1; n++) { int k=abs(n); int CC1=Cmb(q-1+k, k), CC2=Cmb(2*k, k-n); //CC=1.0*C(q-1+k, k)*C(2*k, k-n) for (int k=abs(n); k<=q-1; k++) { hh2[n]=hh2[n]+1.0*CC1*CC2*pow(0.25, k); CC1=CC1*(q+k)/(k+1); CC2=CC2*(2*k+1)*(2*k+2)/((k+1-n)*(k+1+n)); } hh2[n]*=pow(-1, n); } //hh1[hp2-p2:hp2], hh2[1-q:q-1] //h2=conv(hh1, hh2), but the positive half only memset(h2, 0, sizeof(double)*(hp1+p2)); for (int i=hp2-p2; i<=hp2; i++) for (int j=1-q; j<=q-1; j++) if (i+j>=0 && i+j<hp1+p2) h2[i+j]+=hh1[i]*hh2[j]; delete[] _hh1; int hs, he, hms, hme, gs, ge, gms, gme; if (lf%2) { hs=-hlf, he=hlf, hms=-hlb, hme=hlb; gs=-hlb+1, ge=hlb+1, gms=-hlf-1, gme=hlf-1; } else { hs=-hlf, he=hlf-1, hms=-hlb+1, hme=hlb; gs=-hlb, ge=hlb-1, gms=-hlf+1, gme=hlf; } if (lf%2) { for (int i=1; i<=hlf; i++) h1[-i]=h1[i]; for (int i=1; i<=hlb; i++) h2[-i]=h2[i]; double* _g=&g[hlb-1], *_gm=&gm[hlf+1]; for (int i=gs; i<=ge; i++) _g[i]=(i%2)?h2[1-i]:-h2[1-i]; for (int i=gms; i<=gme; i++) _gm[i]=(i%2)?h1[-1-i]:-h1[-1-i]; } else { for (int i=0; i<hlf; i++) h1[-i-1]=h1[i]; for (int i=0; i<hlb; i++) h2[-i-1]=h2[i]; h2=&h2[-1]; double *_g=&g[hlb], *_gm=&gm[hlf-1]; for (int i=gs; i<=ge; i++) _g[i]=(i%2)?-h2[-i]:h2[-i]; for (int i=gms; i<=gme; i++) _gm[i]=(i%2)?-h1[-i]:h1[-i]; } if (normmode) { double sumh=0; for (int i=0; i<=he-hs; i++) sumh+=h[i]*h[i]; double sumhm=0; for (int i=0; i<=hme-hms; i++) sumhm+=hm[i]*hm[i]; if (normmode==1) { double rr=sqrt(sumh); for (int i=0; i<=hme-hms; i++) hm[i]*=rr; rr=1.0/rr; for (int i=0; i<=he-hs; i++) h[i]*=rr; rr=sqrt(sumhm); for (int i=0; i<=gme-gms; i++) gm[i]*=rr; rr=1.0/rr; for (int i=0; i<=ge-gs; i++) g[i]*=rr; } else if (normmode==2) { double rr=sqrt(sumh); for (int i=0; i<=ge-gs; i++) g[i]*=rr; rr=1.0/rr; for (int i=0; i<=gme-gms; i++) gm[i]*=rr; rr=sqrt(sumhm); for (int i=0; i<=he-hs; i++) h[i]*=rr; rr=1.0/rr; for (int i=0; i<=hme-hms; i++) hm[i]*=rr; } else if (normmode==3) { double rr=pow(sumh/sumhm, 0.25); for (int i=0; i<=hme-hms; i++) hm[i]*=rr; for (int i=0; i<=ge-gs; i++) g[i]*=rr; rr=1.0/rr; for (int i=0; i<=he-hs; i++) h[i]*=rr; for (int i=0; i<=gme-gms; i++) gm[i]*=rr; } } if (points) { points[0]=hs, points[1]=he, points[2]=hms, points[3]=hme; points[4]=gs, points[5]=ge, points[6]=gms, points[7]=gme; } return -p1-p2+1; }//splinewl //--------------------------------------------------------------------------- /* function wavpacqmf: calculate pseudo local cosine transforms using wavelet packet In: data[Count], Count=fr*WID, waveform data WID: largest scale, equals 2^ORDER wid: smallest scale, euqals 2^order h[M], g[M]: quadratic mirror filter pair, fr>2*M Out: spec[0][fr][WID], spec[1][2*fr][WID/2], ..., spec[ORDER-order-1][FR][wid] No return value. */ void wavpacqmf(double*** spec, double* data, int Count, int WID, int wid, int M, double* h, double* g) { int fr=Count/WID, ORDER=log2(WID), order=log2(wid); double* _data1=new double[Count*2]; double *data1=_data1, *data2=&_data1[Count]; //the qmf always filters data1 and puts the results to data2 memcpy(data1, data, sizeof(double)*Count); int l=0, C=fr*WID, FR=1; double *ldata, *ldataa, *ldatad; while (l<ORDER) { //qmf for (int f=0; f<FR; f++) { ldata=&data1[f*C]; if (f%2==0) ldataa=&data2[f*C], ldatad=&data2[f*C+C/2]; else ldatad=&data2[f*C], ldataa=&data2[f*C+C/2]; memset(&data2[f*C], 0, sizeof(double)*C); for (int i=0; i<C; i+=2) { int i2=i/2; ldataa[i2]=ldata[i]*h[0]; ldatad[i2]=ldata[i]*g[0]; for (int j=1; j<M; j++) { if (i+j<C) { ldataa[i2]+=ldata[i+j]*h[j]; ldatad[i2]+=ldata[i+j]*g[j]; } else { ldataa[i2]+=ldata[i+j-C]*h[j]; ldatad[i2]+=ldata[i+j-C]*g[j]; } } } } double *tmp=data2; data2=data1; data1=tmp; l++; C=(C>>1); FR=(FR<<1); if (l>=order) { for (int f=0; f<FR; f++) for(int i=0; i<C; i++) spec[ORDER-l][i][f]=data1[f*C+i]; } } delete[] _data1; }//wavpacqmf /* function iwavpacqmf: inverse transform of wavpacqmf In: spec[Fr][Wid], Fr>M*2 h[M], g[M], quadratic mirror filter pair Out: data[Fr*Wid] No return value. */ void iwavpacqmf(double* data, double** spec, int Fr, int Wid, int M, double* h, double* g) { int Count=Fr*Wid, Order=log2(Wid); double* _data1=new double[Count]; double *data1, *data2, *ldata, *ldataa, *ldatad; if (Order%2) data1=_data1, data2=data; else data1=data, data2=_data1; //data pass to buffer for (int i=0, t=0; i<Wid; i++) for (int j=0; j<Fr; j++) data1[t++]=spec[j][i]; int l=Order; int C=Fr; int K=Wid/2; while (l>0) { memset(data2, 0, sizeof(double)*Count); for (int k=0; k<K; k++) { if (k%2==0) ldataa=&data1[2*k*C], ldatad=&data1[(2*k+1)*C]; else ldatad=&data1[2*k*C], ldataa=&data1[(2*k+1)*C]; ldata=&data2[2*k*C]; //qmf for (int i=0; i<C; i++) { for (int j=0; j<M; j++) { if (i*2+j<C*2) { ldata[i*2+j]+=ldataa[i]*h[j]+ldatad[i]*g[j]; } else { ldata[i*2+j-C*2]+=ldataa[i]*h[j]+ldatad[i]*g[j]; } } } } double *tmp=data2; data2=data1; data1=tmp; l--; C=(C<<1); K=(K>>1); } delete[] _data1; }//iwavpacqmf /* function wavpac: calculate pseudo local cosine transforms using wavelet packet, In: data[Count], Count=fr*WID, waveform data WID: largest scale, equals 2^ORDER wid: smallest scale, euqals 2^order h[hs:he-1], g[gs:ge-1]: filter pair Out: spec[0][fr][WID], spec[1][2*fr][WID/2], ..., spec[ORDER-order-1][FR][wid] No return value. */ void wavpac(double*** spec, double* data, int Count, int WID, int wid, double* h, int hs, int he, double* g, int gs, int ge) { int fr=Count/WID, ORDER=log2(WID), order=log2(wid); double* _data1=new double[Count*2]; double *data1=_data1, *data2=&_data1[Count]; //the qmf always filters data1 and puts the results to data2 memcpy(data1, data, sizeof(double)*Count); int l=0, C=fr*WID, FR=1; double *ldata, *ldataa, *ldatad; while (l<ORDER) { //qmf for (int f=0; f<FR; f++) { ldata=&data1[f*C]; if (f%2==0) ldataa=&data2[f*C], ldatad=&data2[f*C+C/2]; else ldatad=&data2[f*C], ldataa=&data2[f*C+C/2]; memset(&data2[f*C], 0, sizeof(double)*C); for (int i=0; i<C; i+=2) { int i2=i/2; ldataa[i2]=0;//ldata[i]*h[0]; ldatad[i2]=0;//ldata[i]*g[0]; for (int j=hs; j<=he; j++) { int ind=i-j; if (ind>=C) { ldataa[i2]+=ldata[ind-C]*h[j]; } else if (ind<0) { ldataa[i2]+=ldata[ind+C]*h[j]; } else { ldataa[i2]+=ldata[ind]*h[j]; } } for (int j=gs; j<=ge; j++) { int ind=i-j; if (ind>=C) { ldatad[i2]+=ldata[ind-C]*g[j]; } else if (ind<0) { ldatad[i2]+=ldata[ind+C]*g[j]; } else { ldatad[i2]+=ldata[ind]*g[j]; } } } } double *tmp=data2; data2=data1; data1=tmp; l++; C=(C>>1); FR=(FR<<1); if (l>=order) { for (int f=0; f<FR; f++) for(int i=0; i<C; i++) spec[ORDER-l][i][f]=data1[f*C+i]; } } delete[] _data1; }//wavpac /* function iwavpac: inverse transform of wavpac In: spec[Fr][Wid] h[hs:he-1], g[gs:ge-1], reconstruction filter pair Out: data[Fr*Wid] No return value. */ void iwavpac(double* data, double** spec, int Fr, int Wid, double* h, int hs, int he, double* g, int gs, int ge) { int Count=Fr*Wid, Order=log2(Wid); double* _data1=new double[Count]; double *data1, *data2, *ldata, *ldataa, *ldatad; if (Order%2) data1=_data1, data2=data; else data1=data, data2=_data1; //data pass to buffer for (int i=0, t=0; i<Wid; i++) for (int j=0; j<Fr; j++) data1[t++]=spec[j][i]; int l=Order; int C=Fr; int K=Wid/2; while (l>0) { memset(data2, 0, sizeof(double)*Count); for (int k=0; k<K; k++) { if (k%2==0) ldataa=&data1[2*k*C], ldatad=&data1[(2*k+1)*C]; else ldatad=&data1[2*k*C], ldataa=&data1[(2*k+1)*C]; ldata=&data2[2*k*C]; //qmf for (int i=0; i<C; i++) { for (int j=hs; j<=he; j++) { int ind=i*2+j; if (ind>=C*2) { ldata[ind-C*2]+=ldataa[i]*h[j]; } else if (ind<0) { ldata[ind+C*2]+=ldataa[i]*h[j]; } else { ldata[ind]+=ldataa[i]*h[j]; } } for (int j=gs; j<=ge; j++) { int ind=i*2+j; if (ind>=C*2) { ldata[ind-C*2]+=ldatad[i]*g[j]; } else if (ind<0) { ldata[ind+C*2]+=ldatad[i]*g[j]; } else { ldata[ind]+=ldatad[i]*g[j]; } } } } double *tmp=data2; data2=data1; data1=tmp; l--; C=(C<<1); K=(K>>1); } delete[] _data1; }//iwavpac