Mercurial > hg > x
comparison 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 |
comparison
equal
deleted
inserted
replaced
0:9b9f21935f24 | 1:6422640a802f |
---|---|
1 //--------------------------------------------------------------------------- | |
2 | |
3 #include <math.h> | |
4 #include <mem.h> | |
5 #include "wavelet.h" | |
6 #include "matrix.h" | |
7 | |
8 //--------------------------------------------------------------------------- | |
9 /* | |
10 function csqrt: real implementation of complex square root z=sqrt(x) | |
11 | |
12 In: xr and xi: real and imaginary parts of x | |
13 Out: zr and zi: real and imaginary parts of z=sqrt(x) | |
14 | |
15 No return value. | |
16 */ | |
17 void csqrt(double& zr, double& zi, double xr, double xi) | |
18 { | |
19 if (xi==0) | |
20 if (xr>=0) zr=sqrt(xr), zi=0; | |
21 else zi=sqrt(-xr), zr=0; | |
22 else | |
23 { | |
24 double xm=sqrt(xr*xr+xi*xi); | |
25 double ri=sqrt((xm-xr)/2); | |
26 zr=xi/2/ri; | |
27 zi=ri; | |
28 } | |
29 }//csqrt | |
30 | |
31 /* | |
32 function Daubechies: calculates the Daubechies filter of a given order p | |
33 | |
34 In: filter order p | |
35 Out: h[2p]: the 2p FIR coefficients | |
36 | |
37 No reutrn value. The calculated filters are minimum phase, which means the energy concentrates at the | |
38 beginning. This is usually used for reconstruction. On the contrary, for wavelet analysis the filter | |
39 is mirrored. | |
40 */ | |
41 void Daubechies(int p, double* h) | |
42 { | |
43 //initialize h(z) | |
44 double r01=pow(2, -p-p+1.5); | |
45 | |
46 h[0]=1; | |
47 for (int i=1; i<=p; i++) | |
48 { | |
49 h[i]=h[i-1]*(p+1-i)/i; | |
50 } | |
51 | |
52 //construct polynomial p | |
53 double *P=new double[p], *rp=new double[p], *ip=new double[p]; | |
54 | |
55 P[p-1]=1; | |
56 double r02=1; | |
57 for (int i=p-1; i>0; i--) | |
58 { | |
59 double rate=(i+1-1.0)/(p-2.0+i+1); | |
60 P[i-1]=P[i]*rate; | |
61 r02/=rate; | |
62 } | |
63 Roots(p-1, P, rp, ip); | |
64 for (int i=0; i<p-1; i++) | |
65 { | |
66 //current length of h is p+1+i, h[0:p+i] | |
67 if (i<p-2 && rp[i]==rp[i+1] && ip[i]==-ip[i+1]) | |
68 { | |
69 double ar=rp[i], ai=ip[i]; | |
70 double bkr=-2*ar+1, bki=-2*ai, ckr=4*(ar*ar-ai*ai-ar), cki=4*(2*ar*ai-ai), dlr, dli; | |
71 csqrt(dlr, dli, ckr, cki); | |
72 double akr=bkr+dlr, aki=bki+dli; | |
73 if (akr*akr+aki*aki>1) akr=bkr-dlr, aki=bki-dli; | |
74 double ak1=-2*akr, ak2=akr*akr+aki*aki; | |
75 h[p+2+i]=ak2*h[p+i]; | |
76 h[p+1+i]=ak2*h[p-1+i]+ak1*h[p+i]; | |
77 for (int j=p+i; j>1; j--) h[j]=h[j]+ak1*h[j-1]+ak2*h[j-2]; | |
78 h[1]=h[1]+ak1*h[0]; | |
79 r02/=ak2; | |
80 i++; | |
81 } | |
82 else //real root of P | |
83 { | |
84 double ak, bk=-(2*rp[i]-1), delk=4*rp[i]*(rp[i]-1); | |
85 if (bk>0) ak=bk-sqrt(delk); | |
86 else ak=bk+sqrt(delk); | |
87 r02/=ak; | |
88 h[p+1+i]=-ak*h[p+i]; | |
89 for (int j=p+i; j>0; j--) h[j]=h[j]-ak*h[j-1]; | |
90 } | |
91 } | |
92 delete[] P; delete[] rp; delete[] ip; | |
93 r01=r01*sqrt(r02); | |
94 for (int i=0; i<p*2; i++) h[i]*=r01; | |
95 }//Daubechies | |
96 | |
97 /* | |
98 Periodic wavelet decomposition and reconstruction routines | |
99 | |
100 The wavelet transform of an N-point sequence is arranged in "interleaved" format | |
101 as another N-point sequance. Level 1 details are found at N/2 points 1, 3, 5, ..., | |
102 N-1; level 2 details are found at N/4 points 2, 6, ..., N-2; level 3 details are | |
103 found at N/8 points 4, 12, ..., N-4; etc. | |
104 */ | |
105 | |
106 /* | |
107 function dwtpqmf: in this implementation h and g are the same as reconstruction qmf filters. In fact | |
108 the actual filters used are their mirrors and filter origin are aligned to the ends of the real | |
109 filters, which turn out to be the starts of h and g. | |
110 | |
111 The inverse transform is idwtp(), the same as inversing dwtp(). | |
112 | |
113 In: in[Count]: waveform data | |
114 h[M], g[M]: quadratic mirror filter pair | |
115 N: maximal time resolution | |
116 Count=kN, N=2^lN being the reciprocal of the most detailed frequency scale, i.e. | |
117 N=1 for no transforming at all, N=2 for dividing into approx. and detail, | |
118 N=4 for dividing into approx+detail(approx+detial), etc. | |
119 Count*2/N=2k gives the smallest length to be convolved with h and g. | |
120 Out: out[N], the wavelet transform, arranged in interleaved format. | |
121 | |
122 Returns maximal atom length (should equal N). | |
123 */ | |
124 int dwtpqmf(double* in, int Count, int N, double* h, double* g, int M, double* out) | |
125 { | |
126 double* tmp=new double[Count]; | |
127 double *tmpa=tmp, *tmpla=in; | |
128 int C=Count, L=0, n=1; | |
129 | |
130 A: | |
131 { | |
132 //C: signal length at current layer | |
133 //L: layer index, 0 being most detailed | |
134 //n: atom length on current layer, equals 2^L. | |
135 //C*n=(C<<L)=Count | |
136 double* tmpd=&tmpa[C/2]; | |
137 for (int i=0; i<C; i+=2) | |
138 { | |
139 int i2=i/2; | |
140 tmpa[i2]=tmpla[i]*h[0]; | |
141 tmpd[i2]=tmpla[i]*g[0]; | |
142 for (int j=1; j<M; j++) | |
143 { | |
144 if (i+j<C) | |
145 { | |
146 tmpa[i2]+=tmpla[i+j]*h[j]; | |
147 tmpd[i2]+=tmpla[i+j]*g[j]; | |
148 } | |
149 else | |
150 { | |
151 tmpa[i2]+=tmpla[i+j-C]*h[j]; | |
152 tmpd[i2]+=tmpla[i+j-C]*g[j]; | |
153 } | |
154 } | |
155 } | |
156 for (int i=0; i*2+1<C; i++) out[(2*i+1)<<L]=tmpd[i]; | |
157 for (int i=0; i*2<C; i++) out[i<<(L+1)]=tmpa[i]; | |
158 n*=2; | |
159 if (n<N) | |
160 { | |
161 tmpla=tmpa; | |
162 tmpa=tmpd; | |
163 L++; | |
164 C/=2; | |
165 goto A; | |
166 } | |
167 } | |
168 delete[] tmp; | |
169 return n; | |
170 }//dwtpqmf | |
171 | |
172 /* | |
173 function dwtp: in this implementation h and g can be different from mirrored reconstruction filters, | |
174 i.e. the biorthogonal transform. h[0] and g[0] are aligned at the ends of the filters, i.e. h[-M+1:0], | |
175 g[-M+1:0]. | |
176 | |
177 In: in[Count]: waveform data | |
178 h[-M+1:0], g[-M+1:0]: quadratic mirror filter pair | |
179 N: maximal time resolution | |
180 Out: out[N], the wavelet transform, arranged in interleaved format. | |
181 | |
182 Returns maximal atom length (should equal N). | |
183 */ | |
184 int dwtp(double* in, int Count, int N, double* h, double* g, int M, double* out) | |
185 { | |
186 double* tmp=new double[Count]; | |
187 double *tmpa=tmp, *tmpla=in; | |
188 int C=Count, L=0, n=1; | |
189 | |
190 A: | |
191 { | |
192 double* tmpd=&tmpa[C/2]; | |
193 for (int i=0; i<C; i+=2) | |
194 { | |
195 int i2=i/2; | |
196 tmpa[i2]=tmpla[i]*h[0]; | |
197 tmpd[i2]=tmpla[i]*g[0]; | |
198 for (int j=-1; j>-M; j--) | |
199 { | |
200 if (i-j<C) | |
201 { | |
202 tmpa[i2]+=tmpla[i-j]*h[j]; | |
203 tmpd[i2]+=tmpla[i-j]*g[j]; | |
204 } | |
205 else | |
206 { | |
207 tmpa[i2]+=tmpla[i-j-C]*h[j]; | |
208 tmpd[i2]+=tmpla[i-j-C]*g[j]; | |
209 } | |
210 } | |
211 } | |
212 for (int i=0; i*2+1<C; i++) out[(2*i+1)<<L]=tmpd[i]; | |
213 for (int i=0; i*2<C; i++) out[i<<(L+1)]=tmpa[i]; | |
214 n*=2; | |
215 if (n<N) | |
216 { | |
217 tmpla=tmpa; | |
218 tmpa=tmpd; | |
219 L++; | |
220 C/=2; | |
221 goto A; | |
222 } | |
223 } | |
224 delete[] tmp; | |
225 return n; | |
226 }//dwtp | |
227 | |
228 /* | |
229 function dwtp: in this implementation h and g can be different size. h[0] and g[0] are aligned at the | |
230 ends of the filters, i.e. h[-Mh+1:0], g[-Mg+1:0]. | |
231 | |
232 In: in[Count]: waveform data | |
233 h[-Mh+1:0], g[-Mg+1:0]: quadratic mirror filter pair | |
234 N: maximal time resolution | |
235 Out: out[N], the wavelet transform, arranged in interleaved format. | |
236 | |
237 Returns maximal atom length (should equal N). | |
238 */ | |
239 int dwtp(double* in, int Count, int N, double* h, int Mh, double* g, int Mg, double* out) | |
240 { | |
241 double* tmp=new double[Count]; | |
242 double *tmpa=tmp, *tmpla=in; | |
243 int C=Count, L=0, n=1; | |
244 | |
245 A: | |
246 { | |
247 double* tmpd=&tmpa[C/2]; | |
248 for (int i=0; i<C; i+=2) | |
249 { | |
250 int i2=i/2; | |
251 tmpa[i2]=tmpla[i]*h[0]; | |
252 tmpd[i2]=tmpla[i]*g[0]; | |
253 for (int j=-1; j>-Mh; j--) | |
254 { | |
255 if (i-j<C) | |
256 { | |
257 tmpa[i2]+=tmpla[i-j]*h[j]; | |
258 } | |
259 else | |
260 { | |
261 tmpa[i2]+=tmpla[i-j-C]*h[j]; | |
262 } | |
263 } | |
264 for (int j=-1; j>-Mg; j--) | |
265 { | |
266 if (i-j<C) | |
267 { | |
268 tmpd[i2]+=tmpla[i-j]*g[j]; | |
269 } | |
270 else | |
271 { | |
272 tmpd[i2]+=tmpla[i-j-C]*g[j]; | |
273 } | |
274 } | |
275 } | |
276 for (int i=0; i*2+1<C; i++) out[(2*i+1)<<L]=tmpd[i]; | |
277 for (int i=0; i*2<C; i++) out[i<<(L+1)]=tmpa[i]; | |
278 n*=2; | |
279 if (n<N) | |
280 { | |
281 tmpla=tmpa; | |
282 tmpa=tmpd; | |
283 L++; | |
284 C/=2; | |
285 goto A; | |
286 } | |
287 } | |
288 delete[] tmp; | |
289 return n; | |
290 }//dwtp | |
291 | |
292 /* | |
293 function dwtp: in this implementation h and g can be arbitrarily located: h from $sh to $eh, g from | |
294 $sg to $eg. | |
295 | |
296 In: in[Count]: waveform data | |
297 h[sh:eh-1], g[sg:eg-1]: quadratic mirror filter pair | |
298 N: maximal time resolution | |
299 Out: out[N], the wavelet transform, arranged in interleaved format. | |
300 | |
301 Returns maximal atom length (should equal N). | |
302 */ | |
303 int dwtp(double* in, int Count, int N, double* h, int sh, int eh, double* g, int sg, int eg, double* out) | |
304 { | |
305 double* tmp=new double[Count]; | |
306 double *tmpa=tmp, *tmpla=in; | |
307 int C=Count, L=0, n=1; | |
308 | |
309 A: | |
310 { | |
311 double* tmpd=&tmpa[C/2]; | |
312 for (int i=0; i<C; i+=2) | |
313 { | |
314 int i2=i/2; | |
315 tmpa[i2]=0;//tmpla[i]*h[0]; | |
316 tmpd[i2]=0;//tmpla[i]*g[0]; | |
317 for (int j=sh; j<=eh; j++) | |
318 { | |
319 int ind=i-j; | |
320 if (ind>=C) tmpa[i2]+=tmpla[ind-C]*h[j]; | |
321 else if (ind<0) tmpa[i2]+=tmpla[ind+C]*h[j]; | |
322 else tmpa[i2]+=tmpla[ind]*h[j]; | |
323 } | |
324 for (int j=sg; j<=eg; j++) | |
325 { | |
326 int ind=i-j; | |
327 if (ind>=C) tmpd[i2]+=tmpla[i-j-C]*g[j]; | |
328 else if (ind<0) tmpd[i2]+=tmpla[i-j+C]*g[j]; | |
329 else tmpd[i2]+=tmpla[i-j]*g[j]; | |
330 } | |
331 } | |
332 for (int i=0; i*2+1<C; i++) out[(2*i+1)<<L]=tmpd[i]; | |
333 for (int i=0; i*2<C; i++) out[i<<(L+1)]=tmpa[i]; | |
334 n*=2; | |
335 if (n<N) | |
336 { | |
337 tmpla=tmpa; | |
338 tmpa=tmpd; | |
339 L++; | |
340 C/=2; | |
341 goto A; | |
342 } | |
343 } | |
344 delete[] tmp; | |
345 return n; | |
346 }//dwtp | |
347 | |
348 /* | |
349 function idwtp: periodic wavelet reconstruction by qmf | |
350 | |
351 In: in[Count]: wavelet transform in interleaved format | |
352 h[M], g[M]: quadratic mirror filter pair | |
353 N: maximal time resolution | |
354 Out: out[N], waveform data (detail level 0). | |
355 | |
356 No return value. | |
357 */ | |
358 void idwtp(double* in, int Count, int N, double* h, double* g, int M, double* out) | |
359 { | |
360 double* tmp=new double[Count]; | |
361 memcpy(out, in, sizeof(double)*Count); | |
362 int n=N, C=Count/N, L=log2(N)-1; | |
363 while (n>1) | |
364 { | |
365 memset(tmp, 0, sizeof(double)*C*2); | |
366 //2k<<L being the approx, (2k+1)<<L being the detail | |
367 for (int i=0; i<C; i++) | |
368 { | |
369 for (int j=0; j<M; j++) | |
370 { | |
371 if (i*2+j<C*2) | |
372 { | |
373 tmp[i*2+j]+=out[(2*i)<<L]*h[j]+out[(2*i+1)<<L]*g[j]; | |
374 } | |
375 else | |
376 { | |
377 tmp[i*2+j-C*2]+=out[(2*i)<<L]*h[j]+out[(2*i+1)<<L]*g[j]; | |
378 } | |
379 } | |
380 } | |
381 for (int i=0; i<C*2; i++) out[i<<L]=tmp[i]; | |
382 n/=2; | |
383 C*=2; | |
384 L--; | |
385 } | |
386 delete[] tmp; | |
387 }//idwtp | |
388 | |
389 /* | |
390 function idwtp: in which h and g can have different length. | |
391 | |
392 In: in[Count]: wavelet transform in interleaved format | |
393 h[Mh], g[Mg]: quadratic mirror filter pair | |
394 N: maximal time resolution | |
395 Out: out[N], waveform data (detail level 0). | |
396 | |
397 No return value. | |
398 */ | |
399 void idwtp(double* in, int Count, int N, double* h, int Mh, double* g, int Mg, double* out) | |
400 { | |
401 double* tmp=new double[Count]; | |
402 memcpy(out, in, sizeof(double)*Count); | |
403 int n=N, C=Count/N, L=log2(N)-1; | |
404 while (n>1) | |
405 { | |
406 memset(tmp, 0, sizeof(double)*C*2); | |
407 //2k<<L being the approx, (2k+1)<<L being the detail | |
408 for (int i=0; i<C; i++) | |
409 { | |
410 for (int j=0; j<Mh; j++) | |
411 { | |
412 int ind=i*2+j+(Mg-Mh)/2; | |
413 if (ind>=C*2) | |
414 { | |
415 tmp[ind-C*2]+=out[(2*i)<<L]*h[j]; | |
416 } | |
417 else if (ind<0) | |
418 { | |
419 tmp[ind+C*2]+=out[(2*i)<<L]*h[j]; | |
420 } | |
421 else | |
422 { | |
423 tmp[ind]+=out[(2*i)<<L]*h[j]; | |
424 } | |
425 } | |
426 } | |
427 for (int i=0; i<C; i++) | |
428 { | |
429 for (int j=0; j<Mg; j++) | |
430 { | |
431 int ind=i*2+j+(Mh-Mg)/2; | |
432 if (ind>=C*2) | |
433 { | |
434 tmp[ind-C*2]+=out[(2*i+1)<<L]*g[j]; | |
435 } | |
436 else if (ind<0) | |
437 { | |
438 tmp[ind+C*2]+=out[(2*i+1)<<L]*g[j]; | |
439 } | |
440 else | |
441 { | |
442 tmp[ind]+=out[(2*i+1)<<L]*g[j]; | |
443 } | |
444 } | |
445 } | |
446 for (int i=0; i<C*2; i++) out[i<<L]=tmp[i]; | |
447 n/=2; | |
448 C*=2; | |
449 L--; | |
450 } | |
451 delete[] tmp; | |
452 }//idwtp | |
453 | |
454 /* | |
455 function idwtp: in which h and g can be arbitrarily located: h from $sh to $eh, g from $sg to $eg | |
456 | |
457 In: in[Count]: wavelet transform in interleaved format | |
458 h[sh:eh-1], g[sg:eg-1]: quadratic mirror filter pair | |
459 N: maximal time resolution | |
460 Out: out[N], waveform data (detail level 0). | |
461 | |
462 No return value. | |
463 */ | |
464 void idwtp(double* in, int Count, int N, double* h, int sh, int eh, double* g, int sg, int eg, double* out) | |
465 { | |
466 double* tmp=new double[Count]; | |
467 memcpy(out, in, sizeof(double)*Count); | |
468 int n=N, C=Count/N, L=log2(N)-1; | |
469 while (n>1) | |
470 { | |
471 memset(tmp, 0, sizeof(double)*C*2); | |
472 //2k<<L being the approx, (2k+1)<<L being the detail | |
473 for (int i=0; i<C; i++) | |
474 { | |
475 for (int j=sh; j<=eh; j++) | |
476 { | |
477 int ind=i*2+j; | |
478 if (ind>=C*2) tmp[ind-C*2]+=out[(2*i)<<L]*h[j]; | |
479 else if (ind<0) tmp[ind+C*2]+=out[(2*i)<<L]*h[j]; | |
480 else tmp[ind]+=out[(2*i)<<L]*h[j]; | |
481 } | |
482 } | |
483 for (int i=0; i<C; i++) | |
484 { | |
485 for (int j=sg; j<=eg; j++) | |
486 { | |
487 int ind=i*2+j; | |
488 if (ind>=C*2) tmp[ind-C*2]+=out[(2*i+1)<<L]*g[j]; | |
489 else if (ind<0) tmp[ind+C*2]+=out[(2*i+1)<<L]*g[j]; | |
490 else tmp[ind]+=out[(2*i+1)<<L]*g[j]; | |
491 } | |
492 } | |
493 for (int i=0; i<C*2; i++) out[i<<L]=tmp[i]; | |
494 n/=2; | |
495 C*=2; | |
496 L--; | |
497 } | |
498 delete[] tmp; | |
499 }//idwtp | |
500 | |
501 //--------------------------------------------------------------------------- | |
502 | |
503 /* | |
504 Spline biorthogonal wavelet routines. | |
505 | |
506 Further reading: "Calculation of biorthogonal spline wavelets.pdf" | |
507 */ | |
508 | |
509 //function Cmb: combination number C(n, k) (n>=k>=0) | |
510 int Cmb(int n, int k) | |
511 { | |
512 if (k>n/2) k=n-k; | |
513 int c=1; | |
514 for (int i=1; i<=k; i++) c=c*(n+1-i)/i; | |
515 return c; | |
516 } | |
517 | |
518 /* | |
519 function splinewl: computes spline biorthogonal wavelet filters. This version of splinewl calcualtes | |
520 the positive-time half of h and hm coefficients only. | |
521 | |
522 p1 and p2 must have the same parity. If p1 is even, p1 coefficients will be returned in h1; if p1 is | |
523 odd, p1-1 coefficients will be returned in h1. | |
524 | |
525 Actual length of h is p1+1, of hm is p1+2p2-1. only a half of each is kept. | |
526 p even: h[0:p1/2] <- [p1/2:p1], hm[0:p1/2+p2-1] <- [p1/2+p2-1:p1+2p2-2] | |
527 p odd: h[0:(p1-1)/2] <- [(p1+1)/2:p1], hm[0:(p1-3)/2+p2] <- [(p1-1)/2+p2:p1+2p2-2] | |
528 i.e. h[0:hp1] <- [p1-hp1:p1], hm[0:hp1+p2-1] <- [p1-hp1-1+p2:p1+2p2-2] | |
529 | |
530 In: p1, p2: specify vanishing moments of h and hm | |
531 Out: h[] and hm[] as specified above. | |
532 | |
533 No return value. | |
534 */ | |
535 void splinewl(int p1, int p2, double* h, double* hm) | |
536 { | |
537 int hp1=p1/2, hp2=p2/2; | |
538 int q=(p1+p2)/2; | |
539 h[hp1]=sqrt(2.0)*pow(2, -p1); | |
540 // h1[hp1]=1; | |
541 for (int i=1, j=hp1-1; i<=hp1; i++, j--) | |
542 { | |
543 h[j]=h[j+1]*(p1+1-i)/i; | |
544 } | |
545 | |
546 double *_hh1=new double[p2+1], *_hh2=new double[2*q]; | |
547 double *hh1=&_hh1[p2-hp2], *hh2=&_hh2[q]; | |
548 | |
549 hh1[hp2]=sqrt(2.0)*pow(2, -p2); | |
550 for (int i=1, j=hp2-1; i<=hp2; i++, j--) | |
551 { | |
552 hh1[j]=hh1[j+1]*(p2+1-i)/i; | |
553 } | |
554 if (p2%2) //p2 is odd | |
555 { | |
556 for (int i=0; i<=hp2; i++) hh1[-i-1]=hh1[i]; | |
557 } | |
558 else //p2 even | |
559 { | |
560 for (int i=1; i<=hp2; i++) hh1[-i]=hh1[i]; | |
561 } | |
562 | |
563 memset(_hh2, 0, sizeof(double)*2*q); | |
564 for (int n=1-q; n<=q-1; n++) | |
565 { | |
566 int k=abs(n); | |
567 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) | |
568 for (; k<=q-1; k++) | |
569 { | |
570 hh2[n]=hh2[n]+1.0*CC1*CC2*pow(0.25, k); | |
571 CC1=CC1*(q+k)/(k+1); | |
572 CC2=CC2*(2*k+1)*(2*k+2)/((k+1-n)*(k+1+n)); | |
573 } | |
574 hh2[n]*=pow(-1, n); | |
575 } | |
576 | |
577 //hh1[hp2-p2:hp2], hh2[1-q:q-1] | |
578 //h2=conv(hh1, hh2), but the positive half only | |
579 memset(hm, 0, sizeof(double)*(hp1+p2)); | |
580 for (int i=hp2-p2; i<=hp2; i++) | |
581 for (int j=1-q; j<=q-1; j++) | |
582 { | |
583 if (i+j>=0 && i+j<hp1+p2) | |
584 hm[i+j]+=hh1[i]*hh2[j]; | |
585 } | |
586 | |
587 delete[] _hh1; | |
588 delete[] _hh2; | |
589 }//splinewl | |
590 | |
591 | |
592 /* | |
593 function splinewl: calculates the analysis and reconstruction filter pairs of spline biorthogonal | |
594 wavelet (h, g) and (hm, gm). h has the size p1+1, hm has the size p1+2p2-1. | |
595 | |
596 If p1+1 is odd, then all four filters are symmetric; if not, then h and hm are symmetric, while g and | |
597 gm are anti-symmetric. | |
598 | |
599 The concatenation of filters h with hm (or g with gm) introduces a time shift of p1+p2-1, which is the | |
600 return value multiplied by -1. | |
601 | |
602 If normmode==1, the results are normalized so that ||h||^2=||g||^2=1; | |
603 if normmode==2, the results are normalized so that ||hm||^2=||gm||^2=1, | |
604 if normmode==3, the results are normalized so that ||h||^2==||g||^2=||hm||^2=||gm||^2. | |
605 | |
606 If a *points* buffer is specified, the function returns the starting and ending | |
607 positions (inclusive) of h, hm, g, and gm, in the order of (hs, he, hms, hme, | |
608 gs, ge, gms, gme), as ps[0]~ps[7]. | |
609 | |
610 In: p1 and p2, specify vanishing moments of h and hm, respectively. | |
611 normmode: mode for normalization | |
612 Out: h[p1+1], g[p1+1], hm[p1+2p2-1], gm[p1+2p2-1], points[8] (optional) | |
613 | |
614 Returns -p1-p2+1. | |
615 */ | |
616 int splinewl(int p1, int p2, double* h, double* hm, double* g, double* gm, int normmode, int* points) | |
617 { | |
618 int lf=p1+1, lb=p1+2*p2-1; | |
619 int hlf=lf/2, hlb=lb/2; | |
620 | |
621 double *h1=&h[hlf], *h2=&hm[hlb]; | |
622 int hp1=p1/2, hp2=p2/2; | |
623 int q=(p1+p2)/2; | |
624 h1[hp1]=sqrt(2.0)*pow(2, -p1); | |
625 // h1[hp1]=2*pow(2, -p1); | |
626 for (int i=1, j=hp1-1; i<=hp1; i++, j--) h1[j]=h1[j+1]*(p1+1-i)/i; | |
627 | |
628 double *_hh1=new double[p2+1+2*q]; | |
629 double *_hh2=&_hh1[p2+1]; | |
630 double *hh1=&_hh1[p2-hp2], *hh2=&_hh2[q]; | |
631 hh1[hp2]=sqrt(2.0)*pow(2, -p2); | |
632 // hh1[hp2]=pow(2, -p2); | |
633 for (int i=1, j=hp2-1; i<=hp2; i++, j--) hh1[j]=hh1[j+1]*(p2+1-i)/i; | |
634 if (p2%2) for (int i=0; i<=hp2; i++) hh1[-i-1]=hh1[i]; | |
635 else for (int i=1; i<=hp2; i++) hh1[-i]=hh1[i]; | |
636 memset(_hh2, 0, sizeof(double)*2*q); | |
637 for (int n=1-q; n<=q-1; n++) | |
638 { | |
639 int k=abs(n); | |
640 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) | |
641 for (int k=abs(n); k<=q-1; k++) | |
642 { | |
643 hh2[n]=hh2[n]+1.0*CC1*CC2*pow(0.25, k); | |
644 CC1=CC1*(q+k)/(k+1); | |
645 CC2=CC2*(2*k+1)*(2*k+2)/((k+1-n)*(k+1+n)); | |
646 } | |
647 hh2[n]*=pow(-1, n); | |
648 } | |
649 //hh1[hp2-p2:hp2], hh2[1-q:q-1] | |
650 //h2=conv(hh1, hh2), but the positive half only | |
651 memset(h2, 0, sizeof(double)*(hp1+p2)); | |
652 for (int i=hp2-p2; i<=hp2; i++) for (int j=1-q; j<=q-1; j++) | |
653 if (i+j>=0 && i+j<hp1+p2) h2[i+j]+=hh1[i]*hh2[j]; | |
654 delete[] _hh1; | |
655 | |
656 int hs, he, hms, hme, gs, ge, gms, gme; | |
657 if (lf%2) | |
658 { | |
659 hs=-hlf, he=hlf, hms=-hlb, hme=hlb; | |
660 gs=-hlb+1, ge=hlb+1, gms=-hlf-1, gme=hlf-1; | |
661 } | |
662 else | |
663 { | |
664 hs=-hlf, he=hlf-1, hms=-hlb+1, hme=hlb; | |
665 gs=-hlb, ge=hlb-1, gms=-hlf+1, gme=hlf; | |
666 } | |
667 | |
668 if (lf%2) | |
669 { | |
670 for (int i=1; i<=hlf; i++) h1[-i]=h1[i]; | |
671 for (int i=1; i<=hlb; i++) h2[-i]=h2[i]; | |
672 double* _g=&g[hlb-1], *_gm=&gm[hlf+1]; | |
673 for (int i=gs; i<=ge; i++) _g[i]=(i%2)?h2[1-i]:-h2[1-i]; | |
674 for (int i=gms; i<=gme; i++) _gm[i]=(i%2)?h1[-1-i]:-h1[-1-i]; | |
675 } | |
676 else | |
677 { | |
678 for (int i=0; i<hlf; i++) h1[-i-1]=h1[i]; | |
679 for (int i=0; i<hlb; i++) h2[-i-1]=h2[i]; | |
680 h2=&h2[-1]; | |
681 double *_g=&g[hlb], *_gm=&gm[hlf-1]; | |
682 for (int i=gs; i<=ge; i++) _g[i]=(i%2)?-h2[-i]:h2[-i]; | |
683 for (int i=gms; i<=gme; i++) _gm[i]=(i%2)?-h1[-i]:h1[-i]; | |
684 } | |
685 | |
686 if (normmode) | |
687 { | |
688 double sumh=0; for (int i=0; i<=he-hs; i++) sumh+=h[i]*h[i]; | |
689 double sumhm=0; for (int i=0; i<=hme-hms; i++) sumhm+=hm[i]*hm[i]; | |
690 if (normmode==1) | |
691 { | |
692 double rr=sqrt(sumh); | |
693 for (int i=0; i<=hme-hms; i++) hm[i]*=rr; | |
694 rr=1.0/rr; | |
695 for (int i=0; i<=he-hs; i++) h[i]*=rr; | |
696 rr=sqrt(sumhm); | |
697 for (int i=0; i<=gme-gms; i++) gm[i]*=rr; | |
698 rr=1.0/rr; | |
699 for (int i=0; i<=ge-gs; i++) g[i]*=rr; | |
700 } | |
701 else if (normmode==2) | |
702 { | |
703 double rr=sqrt(sumh); | |
704 for (int i=0; i<=ge-gs; i++) g[i]*=rr; | |
705 rr=1.0/rr; | |
706 for (int i=0; i<=gme-gms; i++) gm[i]*=rr; | |
707 rr=sqrt(sumhm); | |
708 for (int i=0; i<=he-hs; i++) h[i]*=rr; | |
709 rr=1.0/rr; | |
710 for (int i=0; i<=hme-hms; i++) hm[i]*=rr; | |
711 } | |
712 else if (normmode==3) | |
713 { | |
714 double rr=pow(sumh/sumhm, 0.25); | |
715 for (int i=0; i<=hme-hms; i++) hm[i]*=rr; | |
716 for (int i=0; i<=ge-gs; i++) g[i]*=rr; | |
717 rr=1.0/rr; | |
718 for (int i=0; i<=he-hs; i++) h[i]*=rr; | |
719 for (int i=0; i<=gme-gms; i++) gm[i]*=rr; | |
720 } | |
721 } | |
722 | |
723 if (points) | |
724 { | |
725 points[0]=hs, points[1]=he, points[2]=hms, points[3]=hme; | |
726 points[4]=gs, points[5]=ge, points[6]=gms, points[7]=gme; | |
727 } | |
728 return -p1-p2+1; | |
729 }//splinewl | |
730 | |
731 //--------------------------------------------------------------------------- | |
732 /* | |
733 function wavpacqmf: calculate pseudo local cosine transforms using wavelet packet | |
734 | |
735 In: data[Count], Count=fr*WID, waveform data | |
736 WID: largest scale, equals 2^ORDER | |
737 wid: smallest scale, euqals 2^order | |
738 h[M], g[M]: quadratic mirror filter pair, fr>2*M | |
739 Out: spec[0][fr][WID], spec[1][2*fr][WID/2], ..., spec[ORDER-order-1][FR][wid] | |
740 | |
741 No return value. | |
742 */ | |
743 void wavpacqmf(double*** spec, double* data, int Count, int WID, int wid, int M, double* h, double* g) | |
744 { | |
745 int fr=Count/WID, ORDER=log2(WID), order=log2(wid); | |
746 double* _data1=new double[Count*2]; | |
747 double *data1=_data1, *data2=&_data1[Count]; | |
748 //the qmf always filters data1 and puts the results to data2 | |
749 memcpy(data1, data, sizeof(double)*Count); | |
750 int l=0, C=fr*WID, FR=1; | |
751 double *ldata, *ldataa, *ldatad; | |
752 while (l<ORDER) | |
753 { | |
754 //qmf | |
755 for (int f=0; f<FR; f++) | |
756 { | |
757 ldata=&data1[f*C]; | |
758 if (f%2==0) | |
759 ldataa=&data2[f*C], ldatad=&data2[f*C+C/2]; | |
760 else | |
761 ldatad=&data2[f*C], ldataa=&data2[f*C+C/2]; | |
762 | |
763 memset(&data2[f*C], 0, sizeof(double)*C); | |
764 for (int i=0; i<C; i+=2) | |
765 { | |
766 int i2=i/2; | |
767 ldataa[i2]=ldata[i]*h[0]; | |
768 ldatad[i2]=ldata[i]*g[0]; | |
769 for (int j=1; j<M; j++) | |
770 { | |
771 if (i+j<C) | |
772 { | |
773 ldataa[i2]+=ldata[i+j]*h[j]; | |
774 ldatad[i2]+=ldata[i+j]*g[j]; | |
775 } | |
776 else | |
777 { | |
778 ldataa[i2]+=ldata[i+j-C]*h[j]; | |
779 ldatad[i2]+=ldata[i+j-C]*g[j]; | |
780 } | |
781 } | |
782 } | |
783 } | |
784 double *tmp=data2; data2=data1; data1=tmp; | |
785 l++; | |
786 C=(C>>1); | |
787 FR=(FR<<1); | |
788 if (l>=order) | |
789 { | |
790 for (int f=0; f<FR; f++) | |
791 for(int i=0; i<C; i++) | |
792 spec[ORDER-l][i][f]=data1[f*C+i]; | |
793 } | |
794 } | |
795 | |
796 delete[] _data1; | |
797 }//wavpacqmf | |
798 | |
799 /* | |
800 function iwavpacqmf: inverse transform of wavpacqmf | |
801 | |
802 In: spec[Fr][Wid], Fr>M*2 | |
803 h[M], g[M], quadratic mirror filter pair | |
804 Out: data[Fr*Wid] | |
805 | |
806 No return value. | |
807 */ | |
808 void iwavpacqmf(double* data, double** spec, int Fr, int Wid, int M, double* h, double* g) | |
809 { | |
810 int Count=Fr*Wid, Order=log2(Wid); | |
811 double* _data1=new double[Count]; | |
812 double *data1, *data2, *ldata, *ldataa, *ldatad; | |
813 if (Order%2) data1=_data1, data2=data; | |
814 else data1=data, data2=_data1; | |
815 //data pass to buffer | |
816 for (int i=0, t=0; i<Wid; i++) | |
817 for (int j=0; j<Fr; j++) | |
818 data1[t++]=spec[j][i]; | |
819 | |
820 int l=Order; | |
821 int C=Fr; | |
822 int K=Wid/2; | |
823 while (l>0) | |
824 { | |
825 memset(data2, 0, sizeof(double)*Count); | |
826 for (int k=0; k<K; k++) | |
827 { | |
828 if (k%2==0) ldataa=&data1[2*k*C], ldatad=&data1[(2*k+1)*C]; | |
829 else ldatad=&data1[2*k*C], ldataa=&data1[(2*k+1)*C]; | |
830 ldata=&data2[2*k*C]; | |
831 //qmf | |
832 for (int i=0; i<C; i++) | |
833 { | |
834 for (int j=0; j<M; j++) | |
835 { | |
836 if (i*2+j<C*2) | |
837 { | |
838 ldata[i*2+j]+=ldataa[i]*h[j]+ldatad[i]*g[j]; | |
839 } | |
840 else | |
841 { | |
842 ldata[i*2+j-C*2]+=ldataa[i]*h[j]+ldatad[i]*g[j]; | |
843 } | |
844 } | |
845 } | |
846 } | |
847 | |
848 double *tmp=data2; data2=data1; data1=tmp; | |
849 l--; | |
850 C=(C<<1); | |
851 K=(K>>1); | |
852 } | |
853 delete[] _data1; | |
854 }//iwavpacqmf | |
855 | |
856 /* | |
857 function wavpac: calculate pseudo local cosine transforms using wavelet packet, | |
858 | |
859 In: data[Count], Count=fr*WID, waveform data | |
860 WID: largest scale, equals 2^ORDER | |
861 wid: smallest scale, euqals 2^order | |
862 h[hs:he-1], g[gs:ge-1]: filter pair | |
863 Out: spec[0][fr][WID], spec[1][2*fr][WID/2], ..., spec[ORDER-order-1][FR][wid] | |
864 | |
865 No return value. | |
866 */ | |
867 void wavpac(double*** spec, double* data, int Count, int WID, int wid, double* h, int hs, int he, double* g, int gs, int ge) | |
868 { | |
869 int fr=Count/WID, ORDER=log2(WID), order=log2(wid); | |
870 double* _data1=new double[Count*2]; | |
871 double *data1=_data1, *data2=&_data1[Count]; | |
872 //the qmf always filters data1 and puts the results to data2 | |
873 memcpy(data1, data, sizeof(double)*Count); | |
874 int l=0, C=fr*WID, FR=1; | |
875 double *ldata, *ldataa, *ldatad; | |
876 while (l<ORDER) | |
877 { | |
878 //qmf | |
879 for (int f=0; f<FR; f++) | |
880 { | |
881 ldata=&data1[f*C]; | |
882 if (f%2==0) | |
883 ldataa=&data2[f*C], ldatad=&data2[f*C+C/2]; | |
884 else | |
885 ldatad=&data2[f*C], ldataa=&data2[f*C+C/2]; | |
886 | |
887 memset(&data2[f*C], 0, sizeof(double)*C); | |
888 for (int i=0; i<C; i+=2) | |
889 { | |
890 int i2=i/2; | |
891 ldataa[i2]=0;//ldata[i]*h[0]; | |
892 ldatad[i2]=0;//ldata[i]*g[0]; | |
893 for (int j=hs; j<=he; j++) | |
894 { | |
895 int ind=i-j; | |
896 if (ind>=C) | |
897 { | |
898 ldataa[i2]+=ldata[ind-C]*h[j]; | |
899 } | |
900 else if (ind<0) | |
901 { | |
902 ldataa[i2]+=ldata[ind+C]*h[j]; | |
903 } | |
904 else | |
905 { | |
906 ldataa[i2]+=ldata[ind]*h[j]; | |
907 } | |
908 } | |
909 for (int j=gs; j<=ge; j++) | |
910 { | |
911 int ind=i-j; | |
912 if (ind>=C) | |
913 { | |
914 ldatad[i2]+=ldata[ind-C]*g[j]; | |
915 } | |
916 else if (ind<0) | |
917 { | |
918 ldatad[i2]+=ldata[ind+C]*g[j]; | |
919 } | |
920 else | |
921 { | |
922 ldatad[i2]+=ldata[ind]*g[j]; | |
923 } | |
924 } | |
925 } | |
926 } | |
927 double *tmp=data2; data2=data1; data1=tmp; | |
928 l++; | |
929 C=(C>>1); | |
930 FR=(FR<<1); | |
931 if (l>=order) | |
932 { | |
933 for (int f=0; f<FR; f++) | |
934 for(int i=0; i<C; i++) | |
935 spec[ORDER-l][i][f]=data1[f*C+i]; | |
936 } | |
937 } | |
938 | |
939 delete[] _data1; | |
940 }//wavpac | |
941 | |
942 /* | |
943 function iwavpac: inverse transform of wavpac | |
944 | |
945 In: spec[Fr][Wid] | |
946 h[hs:he-1], g[gs:ge-1], reconstruction filter pair | |
947 Out: data[Fr*Wid] | |
948 | |
949 No return value. | |
950 */ | |
951 void iwavpac(double* data, double** spec, int Fr, int Wid, double* h, int hs, int he, double* g, int gs, int ge) | |
952 { | |
953 int Count=Fr*Wid, Order=log2(Wid); | |
954 double* _data1=new double[Count]; | |
955 double *data1, *data2, *ldata, *ldataa, *ldatad; | |
956 if (Order%2) data1=_data1, data2=data; | |
957 else data1=data, data2=_data1; | |
958 //data pass to buffer | |
959 for (int i=0, t=0; i<Wid; i++) | |
960 for (int j=0; j<Fr; j++) | |
961 data1[t++]=spec[j][i]; | |
962 | |
963 int l=Order; | |
964 int C=Fr; | |
965 int K=Wid/2; | |
966 while (l>0) | |
967 { | |
968 memset(data2, 0, sizeof(double)*Count); | |
969 for (int k=0; k<K; k++) | |
970 { | |
971 if (k%2==0) ldataa=&data1[2*k*C], ldatad=&data1[(2*k+1)*C]; | |
972 else ldatad=&data1[2*k*C], ldataa=&data1[(2*k+1)*C]; | |
973 ldata=&data2[2*k*C]; | |
974 //qmf | |
975 for (int i=0; i<C; i++) | |
976 { | |
977 for (int j=hs; j<=he; j++) | |
978 { | |
979 int ind=i*2+j; | |
980 if (ind>=C*2) | |
981 { | |
982 ldata[ind-C*2]+=ldataa[i]*h[j]; | |
983 } | |
984 else if (ind<0) | |
985 { | |
986 ldata[ind+C*2]+=ldataa[i]*h[j]; | |
987 } | |
988 else | |
989 { | |
990 ldata[ind]+=ldataa[i]*h[j]; | |
991 } | |
992 } | |
993 for (int j=gs; j<=ge; j++) | |
994 { | |
995 int ind=i*2+j; | |
996 if (ind>=C*2) | |
997 { | |
998 ldata[ind-C*2]+=ldatad[i]*g[j]; | |
999 } | |
1000 else if (ind<0) | |
1001 { | |
1002 ldata[ind+C*2]+=ldatad[i]*g[j]; | |
1003 } | |
1004 else | |
1005 { | |
1006 ldata[ind]+=ldatad[i]*g[j]; | |
1007 } | |
1008 } | |
1009 } | |
1010 } | |
1011 | |
1012 double *tmp=data2; data2=data1; data1=tmp; | |
1013 l--; | |
1014 C=(C<<1); | |
1015 K=(K>>1); | |
1016 } | |
1017 delete[] _data1; | |
1018 }//iwavpac |