xue@11: /* xue@11: Harmonic sinusoidal modelling and tools xue@11: xue@11: C++ code package for harmonic sinusoidal modelling and relevant signal processing. xue@11: Centre for Digital Music, Queen Mary, University of London. xue@11: This file copyright 2011 Wen Xue. xue@11: xue@11: This program is free software; you can redistribute it and/or xue@11: modify it under the terms of the GNU General Public License as xue@11: published by the Free Software Foundation; either version 2 of the xue@11: License, or (at your option) any later version. xue@11: */ xue@1: //--------------------------------------------------------------------------- xue@1: xue@1: #include Chris@2: #include xue@1: #include "wavelet.h" xue@1: #include "matrix.h" xue@1: Chris@5: /** \file wavelet.h */ Chris@5: xue@1: //--------------------------------------------------------------------------- Chris@5: /** xue@1: function csqrt: real implementation of complex square root z=sqrt(x) xue@1: xue@1: In: xr and xi: real and imaginary parts of x xue@1: Out: zr and zi: real and imaginary parts of z=sqrt(x) xue@1: xue@1: No return value. xue@1: */ xue@1: void csqrt(double& zr, double& zi, double xr, double xi) xue@1: { xue@1: if (xi==0) xue@1: if (xr>=0) zr=sqrt(xr), zi=0; xue@1: else zi=sqrt(-xr), zr=0; xue@1: else xue@1: { xue@1: double xm=sqrt(xr*xr+xi*xi); xue@1: double ri=sqrt((xm-xr)/2); xue@1: zr=xi/2/ri; xue@1: zi=ri; xue@1: } xue@1: }//csqrt xue@1: Chris@5: /** xue@1: function Daubechies: calculates the Daubechies filter of a given order p xue@1: xue@1: In: filter order p xue@1: Out: h[2p]: the 2p FIR coefficients xue@1: xue@1: No reutrn value. The calculated filters are minimum phase, which means the energy concentrates at the xue@1: beginning. This is usually used for reconstruction. On the contrary, for wavelet analysis the filter xue@1: is mirrored. xue@1: */ xue@1: void Daubechies(int p, double* h) xue@1: { xue@1: //initialize h(z) xue@1: double r01=pow(2, -p-p+1.5); xue@1: xue@1: h[0]=1; xue@1: for (int i=1; i<=p; i++) xue@1: { xue@1: h[i]=h[i-1]*(p+1-i)/i; xue@1: } xue@1: xue@1: //construct polynomial p xue@1: double *P=new double[p], *rp=new double[p], *ip=new double[p]; xue@1: xue@1: P[p-1]=1; xue@1: double r02=1; xue@1: for (int i=p-1; i>0; i--) xue@1: { xue@1: double rate=(i+1-1.0)/(p-2.0+i+1); xue@1: P[i-1]=P[i]*rate; xue@1: r02/=rate; xue@1: } xue@1: Roots(p-1, P, rp, ip); xue@1: for (int i=0; i1) akr=bkr-dlr, aki=bki-dli; xue@1: double ak1=-2*akr, ak2=akr*akr+aki*aki; xue@1: h[p+2+i]=ak2*h[p+i]; xue@1: h[p+1+i]=ak2*h[p-1+i]+ak1*h[p+i]; xue@1: for (int j=p+i; j>1; j--) h[j]=h[j]+ak1*h[j-1]+ak2*h[j-2]; xue@1: h[1]=h[1]+ak1*h[0]; xue@1: r02/=ak2; xue@1: i++; xue@1: } xue@1: else //real root of P xue@1: { xue@1: double ak, bk=-(2*rp[i]-1), delk=4*rp[i]*(rp[i]-1); xue@1: if (bk>0) ak=bk-sqrt(delk); xue@1: else ak=bk+sqrt(delk); xue@1: r02/=ak; xue@1: h[p+1+i]=-ak*h[p+i]; xue@1: for (int j=p+i; j>0; j--) h[j]=h[j]-ak*h[j-1]; xue@1: } xue@1: } xue@1: delete[] P; delete[] rp; delete[] ip; xue@1: r01=r01*sqrt(r02); xue@1: for (int i=0; i-M; j--) xue@1: { xue@1: if (i-j-Mh; j--) xue@1: { xue@1: if (i-j-Mg; j--) xue@1: { xue@1: if (i-j=C) tmpa[i2]+=tmpla[ind-C]*h[j]; xue@1: else if (ind<0) tmpa[i2]+=tmpla[ind+C]*h[j]; xue@1: else tmpa[i2]+=tmpla[ind]*h[j]; xue@1: } xue@1: for (int j=sg; j<=eg; j++) xue@1: { xue@1: int ind=i-j; xue@1: if (ind>=C) tmpd[i2]+=tmpla[i-j-C]*g[j]; xue@1: else if (ind<0) tmpd[i2]+=tmpla[i-j+C]*g[j]; xue@1: else tmpd[i2]+=tmpla[i-j]*g[j]; xue@1: } xue@1: } xue@1: for (int i=0; i*2+11) xue@1: { xue@1: memset(tmp, 0, sizeof(double)*C*2); xue@1: //2k<1) xue@1: { xue@1: memset(tmp, 0, sizeof(double)*C*2); xue@1: //2k<=C*2) xue@1: { xue@1: tmp[ind-C*2]+=out[(2*i)<=C*2) xue@1: { xue@1: tmp[ind-C*2]+=out[(2*i+1)<1) xue@1: { xue@1: memset(tmp, 0, sizeof(double)*C*2); xue@1: //2k<=C*2) tmp[ind-C*2]+=out[(2*i)<=C*2) tmp[ind-C*2]+=out[(2*i+1)<=k>=0) xue@1: int Cmb(int n, int k) xue@1: { xue@1: if (k>n/2) k=n-k; xue@1: int c=1; xue@1: for (int i=1; i<=k; i++) c=c*(n+1-i)/i; xue@1: return c; xue@1: } xue@1: Chris@5: /** xue@1: function splinewl: computes spline biorthogonal wavelet filters. This version of splinewl calcualtes xue@1: the positive-time half of h and hm coefficients only. xue@1: xue@1: p1 and p2 must have the same parity. If p1 is even, p1 coefficients will be returned in h1; if p1 is xue@1: odd, p1-1 coefficients will be returned in h1. xue@1: xue@1: Actual length of h is p1+1, of hm is p1+2p2-1. only a half of each is kept. xue@1: p even: h[0:p1/2] <- [p1/2:p1], hm[0:p1/2+p2-1] <- [p1/2+p2-1:p1+2p2-2] xue@1: p odd: h[0:(p1-1)/2] <- [(p1+1)/2:p1], hm[0:(p1-3)/2+p2] <- [(p1-1)/2+p2:p1+2p2-2] xue@1: i.e. h[0:hp1] <- [p1-hp1:p1], hm[0:hp1+p2-1] <- [p1-hp1-1+p2:p1+2p2-2] xue@1: xue@1: In: p1, p2: specify vanishing moments of h and hm xue@1: Out: h[] and hm[] as specified above. xue@1: xue@1: No return value. xue@1: */ xue@1: void splinewl(int p1, int p2, double* h, double* hm) xue@1: { xue@1: int hp1=p1/2, hp2=p2/2; xue@1: int q=(p1+p2)/2; xue@1: h[hp1]=sqrt(2.0)*pow(2, -p1); xue@1: // h1[hp1]=1; xue@1: for (int i=1, j=hp1-1; i<=hp1; i++, j--) xue@1: { xue@1: h[j]=h[j+1]*(p1+1-i)/i; xue@1: } xue@1: xue@1: double *_hh1=new double[p2+1], *_hh2=new double[2*q]; xue@1: double *hh1=&_hh1[p2-hp2], *hh2=&_hh2[q]; xue@1: xue@1: hh1[hp2]=sqrt(2.0)*pow(2, -p2); xue@1: for (int i=1, j=hp2-1; i<=hp2; i++, j--) xue@1: { xue@1: hh1[j]=hh1[j+1]*(p2+1-i)/i; xue@1: } xue@1: if (p2%2) //p2 is odd xue@1: { xue@1: for (int i=0; i<=hp2; i++) hh1[-i-1]=hh1[i]; xue@1: } xue@1: else //p2 even xue@1: { xue@1: for (int i=1; i<=hp2; i++) hh1[-i]=hh1[i]; xue@1: } xue@1: xue@1: memset(_hh2, 0, sizeof(double)*2*q); xue@1: for (int n=1-q; n<=q-1; n++) xue@1: { xue@1: int k=abs(n); xue@1: 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) xue@1: for (; k<=q-1; k++) xue@1: { xue@1: hh2[n]=hh2[n]+1.0*CC1*CC2*pow(0.25, k); xue@1: CC1=CC1*(q+k)/(k+1); xue@1: CC2=CC2*(2*k+1)*(2*k+2)/((k+1-n)*(k+1+n)); xue@1: } xue@1: hh2[n]*=pow(-1, n); xue@1: } xue@1: xue@1: //hh1[hp2-p2:hp2], hh2[1-q:q-1] xue@1: //h2=conv(hh1, hh2), but the positive half only xue@1: memset(hm, 0, sizeof(double)*(hp1+p2)); xue@1: for (int i=hp2-p2; i<=hp2; i++) xue@1: for (int j=1-q; j<=q-1; j++) xue@1: { xue@1: if (i+j>=0 && i+j=0 && i+j2*M xue@1: Out: spec[0][fr][WID], spec[1][2*fr][WID/2], ..., spec[ORDER-order-1][FR][wid] xue@1: xue@1: No return value. xue@1: */ xue@1: void wavpacqmf(double*** spec, double* data, int Count, int WID, int wid, int M, double* h, double* g) xue@1: { xue@1: int fr=Count/WID, ORDER=log2(WID), order=log2(wid); xue@1: double* _data1=new double[Count*2]; xue@1: double *data1=_data1, *data2=&_data1[Count]; xue@1: //the qmf always filters data1 and puts the results to data2 xue@1: memcpy(data1, data, sizeof(double)*Count); xue@1: int l=0, C=fr*WID, FR=1; xue@1: double *ldata, *ldataa, *ldatad; xue@1: while (l>1); xue@1: FR=(FR<<1); xue@1: if (l>=order) xue@1: { xue@1: for (int f=0; fM*2 xue@1: h[M], g[M], quadratic mirror filter pair xue@1: Out: data[Fr*Wid] xue@1: xue@1: No return value. xue@1: */ xue@1: void iwavpacqmf(double* data, double** spec, int Fr, int Wid, int M, double* h, double* g) xue@1: { xue@1: int Count=Fr*Wid, Order=log2(Wid); xue@1: double* _data1=new double[Count]; xue@1: double *data1, *data2, *ldata, *ldataa, *ldatad; xue@1: if (Order%2) data1=_data1, data2=data; xue@1: else data1=data, data2=_data1; xue@1: //data pass to buffer xue@1: for (int i=0, t=0; i0) xue@1: { xue@1: memset(data2, 0, sizeof(double)*Count); xue@1: for (int k=0; k>1); xue@1: } xue@1: delete[] _data1; xue@1: }//iwavpacqmf xue@1: Chris@5: /** xue@1: function wavpac: calculate pseudo local cosine transforms using wavelet packet, xue@1: xue@1: In: data[Count], Count=fr*WID, waveform data xue@1: WID: largest scale, equals 2^ORDER xue@1: wid: smallest scale, euqals 2^order xue@1: h[hs:he-1], g[gs:ge-1]: filter pair xue@1: Out: spec[0][fr][WID], spec[1][2*fr][WID/2], ..., spec[ORDER-order-1][FR][wid] xue@1: xue@1: No return value. xue@1: */ xue@1: void wavpac(double*** spec, double* data, int Count, int WID, int wid, double* h, int hs, int he, double* g, int gs, int ge) xue@1: { xue@1: int fr=Count/WID, ORDER=log2(WID), order=log2(wid); xue@1: double* _data1=new double[Count*2]; xue@1: double *data1=_data1, *data2=&_data1[Count]; xue@1: //the qmf always filters data1 and puts the results to data2 xue@1: memcpy(data1, data, sizeof(double)*Count); xue@1: int l=0, C=fr*WID, FR=1; xue@1: double *ldata, *ldataa, *ldatad; xue@1: while (l=C) xue@1: { xue@1: ldataa[i2]+=ldata[ind-C]*h[j]; xue@1: } xue@1: else if (ind<0) xue@1: { xue@1: ldataa[i2]+=ldata[ind+C]*h[j]; xue@1: } xue@1: else xue@1: { xue@1: ldataa[i2]+=ldata[ind]*h[j]; xue@1: } xue@1: } xue@1: for (int j=gs; j<=ge; j++) xue@1: { xue@1: int ind=i-j; xue@1: if (ind>=C) xue@1: { xue@1: ldatad[i2]+=ldata[ind-C]*g[j]; xue@1: } xue@1: else if (ind<0) xue@1: { xue@1: ldatad[i2]+=ldata[ind+C]*g[j]; xue@1: } xue@1: else xue@1: { xue@1: ldatad[i2]+=ldata[ind]*g[j]; xue@1: } xue@1: } xue@1: } xue@1: } xue@1: double *tmp=data2; data2=data1; data1=tmp; xue@1: l++; xue@1: C=(C>>1); xue@1: FR=(FR<<1); xue@1: if (l>=order) xue@1: { xue@1: for (int f=0; f0) xue@1: { xue@1: memset(data2, 0, sizeof(double)*Count); xue@1: for (int k=0; k=C*2) xue@1: { xue@1: ldata[ind-C*2]+=ldataa[i]*h[j]; xue@1: } xue@1: else if (ind<0) xue@1: { xue@1: ldata[ind+C*2]+=ldataa[i]*h[j]; xue@1: } xue@1: else xue@1: { xue@1: ldata[ind]+=ldataa[i]*h[j]; xue@1: } xue@1: } xue@1: for (int j=gs; j<=ge; j++) xue@1: { xue@1: int ind=i*2+j; xue@1: if (ind>=C*2) xue@1: { xue@1: ldata[ind-C*2]+=ldatad[i]*g[j]; xue@1: } xue@1: else if (ind<0) xue@1: { xue@1: ldata[ind+C*2]+=ldatad[i]*g[j]; xue@1: } xue@1: else xue@1: { xue@1: ldata[ind]+=ldatad[i]*g[j]; xue@1: } xue@1: } xue@1: } xue@1: } xue@1: xue@1: double *tmp=data2; data2=data1; data1=tmp; xue@1: l--; xue@1: C=(C<<1); xue@1: K=(K>>1); xue@1: } xue@1: delete[] _data1; xue@1: }//iwavpac