2 * These functions calculate the values for quadrature mirror filter
5 * Copyright (C) 1991--94 Wickerhauser Consulting. All Rights Reserved.
6 * May be freely copied for noncommercial use. See
7 * ``Adapted Wavelet Analysis from Theory to Software'' ISBN 1-56881-041-5
8 * by Mladen Victor Wickerhauser [AK Peters, Ltd., Wellesley, Mass., 1994]
16 #include "qf.h" /* Data structs and function prototypes */
17 #include "oqfs.h" /* Orthogonal filter coefficients. */
19 /********************************************************************
22 * Function `mkpqf()' returns a pointer to a `pqf' data structure
23 * containing the coefficients, length and the pre-periodized filter
24 * named by the input parameters.
27 * mkpqf( coefs, alpha, omega, flags )
30 * (const real *)coefs These are the filter coefficients,
31 * assumed to be given in the array
32 * `coefs[0],...,coefs[omega-alpha]'
33 * are the only nonzero values.
35 * (int)alpha These are to be the first and last valid
36 * (int)omega indices of the pqf->f struct member.
38 * (int)flags This is reserved for later uses, such as
39 * indicating when to generate a full QF
40 * sequence from just one symmetric half.
43 * (pqf *)mkpqf The return value is a pointer to a newly
44 * allocated pqf struct containing `coefs[]',
45 * `alpha', `omega', and the preperiodized
46 * version of `coefs[]'.
48 * (1) Conventional indexing: `alpha <= 0 <= omega'.
52 const real
*coefs
, /* Original filter coefficients. */
53 int alpha
, /* Least valid index of `?->f[]'. */
54 int omega
, /* Greatest valid index of `?->f[]'. */
55 int flags
) /* Reserved for future use. */
60 assert(alpha
<= 0); /* Conventional indexing. */
61 assert(0 <= omega
); /* Conventional indexing. */
63 qm
= (pqf
*)calloc(1,sizeof(pqf
)); assert(qm
);
67 M
= IFH( omega
-alpha
);
68 qm
->fp
= (real
*)calloc( PQFL(M
), sizeof(real
)); assert(qm
->fp
);
69 qfcirc( qm
->fp
, qm
->f
, alpha
, omega
);
71 qm
->center
= coe( qm
->f
, alpha
, omega
);
72 qm
->deviation
= lphdev( qm
->f
, alpha
, omega
);
76 /********************************************************************
79 * Function `qf()' returns a pointer to a `pqf' data structure
80 * containing the coefficients, name, length and kind of the filter
81 * named by the input parameters.
84 * qf( name, range, kind )
87 * (const char *)name This is the name of the filter, specified as
88 * at least the first letter of "Beylkin",
89 * "Coifman", "Vaidyanathan", or "Daubechies",
90 * written as a string (enclosed in " marks).
91 * Case is ignored, only the first letter
92 * matters, and "Standard" is an alias for "D".
94 * (int)range This is the length of the requested filter. Allowed
95 * values depend on what `name' is.
97 * (int)kind If kind==LOW_PASS_QF, qf() returns the summing or
98 * low-pass filter `pqf' structure.
99 * If kind==HIGH_PASS_QF, qf() returns the differencing
100 * or high-pass filter `pqf' structure.
103 * (pqf *)qf If a `name'd filter of the requested `range' and
104 * `kind' is listed, then the return value is
105 * a pointer to a newly-allocated pqf struct
106 * specifying a conventionally-indexed filter
107 * to be used for convolution-decimation.
108 * Otherwise, the returned pointer is NULL.
112 qf( /* Coefficient struct or NULL pointer. */
113 const char *name
, /* String "B", "C", "D", or "V". */
114 int range
, /* Length of coefficient array. */
115 int kind
) /* LOW_PASS_QF or HIGH_PASS_QF. */
119 /* These macros call `mkpqf()' with the right arguments: */
120 #define MKMKPQF(n, sd) mkpqf( n##sd##oqf, n##sd##alpha, n##sd##omega, 0 )
121 #define SETSDPQF(n, k) ( k==LOW_PASS_QF ) ? MKMKPQF(n, s) : MKMKPQF(n, d)
123 qm
= 0; /* Return NULL pointer if unsuccessful. */
125 /* Choose an orthogonal filter based on the first letter of
126 * the filter name: `name' argument starts with B, C, D, V
134 * Here are the coefficients for Gregory BEYLKIN'S wave packets.
138 case 18: qm
= SETSDPQF( b18
, kind
); break;
139 default: break; /* Fall out: the length is unavailable. */
141 break; /* Beylkin type. */
147 * Here are the coefficients for COIFLETS with respectively
148 * 2, 4, 6, 8 and 10 moments vanishing for phi. Filter Q has
149 * range/3 moments vanishing. Filter P has range/3 moments
150 * vanishing with the appropriate shift.
154 case 6: qm
= SETSDPQF( c06
, kind
); break;
155 case 12: qm
= SETSDPQF( c12
, kind
); break;
156 case 18: qm
= SETSDPQF( c18
, kind
); break;
157 case 24: qm
= SETSDPQF( c24
, kind
); break;
158 case 30: qm
= SETSDPQF( c30
, kind
); break;
159 default: break; /* Fall out: the length is unavailable. */
161 break; /* Coifman type. */
164 case 'S': /* STANDARD filters, in old terminology. */
167 /* Daubechies filters.
169 * Initialize quadrature mirror filters P,Q of length 'range' with
170 * smooth limits and minimal phase, as in DAUBECHIES:
174 case 2: qm
= SETSDPQF( d02
, kind
); break;
175 case 4: qm
= SETSDPQF( d04
, kind
); break;
176 case 6: qm
= SETSDPQF( d06
, kind
); break;
177 case 8: qm
= SETSDPQF( d08
, kind
); break;
178 case 10: qm
= SETSDPQF( d10
, kind
); break;
179 case 12: qm
= SETSDPQF( d12
, kind
); break;
180 case 14: qm
= SETSDPQF( d14
, kind
); break;
181 case 16: qm
= SETSDPQF( d16
, kind
); break;
182 case 18: qm
= SETSDPQF( d18
, kind
); break;
183 case 20: qm
= SETSDPQF( d20
, kind
); break;
184 default: break; /* Fall out: the length is unavailable. */
186 break; /* Standard or Daubechies type. */
190 /* Vaidyanathan filters
192 * The following coefficients correspond to one of the filters
193 * constructed by Vaidyanathan (Filter #24B from his paper
194 * in IEEE Trans. ASSP Vol.36, pp 81-94 (1988). These coefficients
195 * give an exact reconstruction scheme, but they don't satisfy ANY
196 * moment condition (not even the normalization : the sum of the c_n
197 * is close to 1, but not equal to 1). The function one obtains after
198 * iterating the reconstruction procedure 9 times looks continuous,
199 * but is of course not differentiable. It would be interesting to
200 * see how such a filter performs. It has been optimized, for its
201 * filter length, for the standard requirements that speech people
206 case 24: qm
= SETSDPQF( v24
, kind
); break;
207 default: break; /* Fall out: the length is unavailable. */
209 break; /* Vaidyanathan type. */
211 default: break; /* Fall out: the filter is unavailable. */
216 /*******************************************************************
219 * Compute the center-of-energy for a sequence.
222 * center = ( Sum_k k*in[x]^2 ) / (Sum_k in[k]^2 )
225 * coe( in, alpha, omega )
228 * (const real *)in The sequence is `in[alpha],...,in[omega]'
230 * (int)alpha These are to be the first and last
231 * (int)omega valid indices of the array `in[]'.
234 * (real)coe This is in the interval `[alpha, omega]'.
237 * (1) Conventional indexing: `alpha <= 0 <= omega'.
240 coe( /* Center of energy. */
241 const real
*in
, /* Sequence of coefficients. */
242 int alpha
, /* First valid `in[]' index. */
243 int omega
) /* Last valid `in[]' index. */
248 assert(alpha
<= 0); /* Conventional indexing. */
249 assert(0 <= omega
); /* Conventional indexing. */
251 center
= 0; energy
= 0;
252 for( k
=alpha
; k
<=omega
; k
++)
254 center
+= k
*in
[k
]*in
[k
];
255 energy
+= in
[k
]*in
[k
];
257 if( energy
>0 ) center
/= energy
;
261 /*******************************************************************
264 * Compute the maximum deviation from linear phase of the
265 * convolution-decimation operator associated to a sequence.
267 * Sum_{x>0} (-1)^x Sum_k k*in[k-x]*in[k+x]
268 * deviation = 2 * ----------------------------------------
272 * lphdev( in, alpha, omega )
275 * (const real *)in The sequence is `in[alpha],...,in[omega]'
277 * (int)alpha These are to be the first and last valid
278 * (int)omega indices of the `pqf->f[]' struct member.
281 * (real)lphdev This is the absolute value of the maximum.
284 * (1) Conventional indexing: `alpha <= 0 <= omega'.
287 lphdev( /* Center of energy. */
288 const real
*in
, /* Sequence of coefficients. */
289 int alpha
, /* First valid `in[]' index. */
290 int omega
) /* Last valid `in[]' index. */
292 real energy
, fx
, deviation
;
295 assert(alpha
<= 0); /* Conventional indexing. */
296 assert(0 <= omega
); /* Conventional indexing. */
298 /* First compute the sum of the squares of the sequence elements: */
300 for( k
=alpha
; k
<omega
; k
++) energy
+= in
[k
]*in
[k
];
302 /* If the sum of the squares in nonzero, compute the deviation: */
307 for( x
=1; x
<= (omega
-alpha
)/2; x
++ )
310 for( k
=x
+alpha
; k
<=omega
-x
; k
++ )
312 fx
+= k
*in
[k
-x
]*in
[k
+x
];
317 deviation
= absval(deviation
);
318 deviation
/= energy
; /* Normalize. */
319 deviation
*= 2; /* Final factor from the formula. */
321 /* If `energy==0' then `deviation' is trivially 0 */
326 /***************************************************************
329 * Periodize an array into a shorter-length array.
331 * Calling sequence and basic algorithm:
333 * periodize(FQ, Q, F, ALPHA, OMEGA)
336 * Let J = (ALPHA-K)/Q
337 * While K+J*Q <= OMEGA
342 * (real *)fq Preallocated array of length `q'.
343 * (int)q This is the period of `fq[]'.
344 * (const real *)f This array holds the original function.
345 * (int)alpha These are to be the first and last valid
346 * (int)omega indices of the array `f[]'.
349 * (real *)fq The array `fq[]' is assigned as follows:
350 * fq[k] = f[k+j0*q]+...+f[k+j1*q],
351 * k = 0, 1, ..., q-1;
352 * j0 = ceil[(alpha-k)/q];
353 * j1 = floor[(omega-k)/q].
356 * (1) `omega-alpha >= q > 0',
357 * (2) `alpha <= 0 <= omega'
361 real
*fq
, /* Preallocated output array. */
362 int q
, /* Length of `fq[]'. */
363 const real
*f
, /* Input array. */
364 int alpha
, /* First valid `f[]' index. */
365 int omega
) /* Last valid `f[]' index. */
369 assert(q
>0); /* Nontrivial period. */
370 assert(q
<=omega
-alpha
); /* Periodization needed. */
371 assert(alpha
<= 0); /* Conventional indexing. */
372 assert(0 <= omega
); /* Conventional indexing. */
377 j
= (alpha
-k
)/q
; /* `j==ceil((alpha-k)/q)' */
378 while( (k
+j
*q
) <= omega
)
387 /***************************************************************
390 * This function computes the periodized filter coefficients
391 * associated to the input array of quadrature mirror filter
392 * coefficients, for lengths 2, 4, 6,... It then fills an array
393 * with these periodized coefficients, duplicating some of them
394 * to facilitate circular convolution. If the input array is
395 * f[alpha], f[alpha+1], ..., f[omega],
396 * and M is the largest integer satisfying `2M<=omega-alpha',
397 * then the output array is the concatenation of:
400 * ----- -------------------------------------------------- -----
401 * 0 f2[0],f2[1],f2[0],f2[1]; 3
402 * 4 f4[0],f4[1],f4[2],f4[3],f4[0],f4[1],f4[2],f4[3]; 11
403 * 12 f6[0],f6[1],f6[2],...,f6[5],f6[0],f6[1],...,f6[5]; 23
404 * 24 f8[0],f8[1],f8[2],...,f8[7],f8[0],f8[1],...,f8[7]; 39
406 * S(m-1) f{2m}[0],...,f{2m}[2m-1],f{2m}[0],...,f{2m}[2m-1]; S(m)-1
408 * S(M-1) f{2M}[0],...,f{2M}[2M-1],f{2M}[0],...,f{2M}[2M-1]; S(M)-1
410 * where S(m)= 4+8+16+...+ 4(m-1) = 2m(m-1) gives the
411 * starting index of the m-th segment.
413 * The "midpoint" or "origin" of the m-th periodic subarray is:
414 * PQFO(m) = S(m-1)+2m = 2m*m.
416 * The total length of concatenated periodic subarrays `1,...,M' is
417 * PQFL(M) = S(M-1)+4M = 2M*(M+1).
419 * Calling sequence and basic algorithm:
421 * qfcirc(FP, F, ALPHA, OMEGA)
422 * Let M = IFH(omega-alpha)
425 * Let FQ = FP + PQFO(N)
426 * periodize( FQ, Q, F, ALPHA, OMEGA )
428 * Let FQ[K-Q] = FQ[K]
431 * (real *)fp This must point to a preallocated array
432 * with at least `PQFL(M)' memory
433 * locations. This function call fills
434 * those locations, beginning with 0.
436 * (const real *)f This is an array of quadrature mirror
437 * filter coefficients.
439 * (int)alpha These are to be the first and last valid
440 * (int)omega indices of the array `f[]'.
443 * (real *)fp This array is filled with periodized,
444 * partially duplicated arrays with
445 * lengths 4, 8, ..., 4M.
448 * (1) Conventional indexing: `alpha <= 0 <= omega'.
452 real
*fp
, /* Preallocated output array */
453 const real
*f
, /* Filter coefficients */
454 int alpha
, /* First valid `f[]' index */
455 int omega
) /* Last valid `f[]' index */
460 assert(alpha
<= 0); /* Conventional indexing */
461 assert(0 <= omega
); /* Conventional indexing */
463 M
= IFH(omega
-alpha
); /* Max with `2*M <= omega-alpha' */
465 for( m
=1; m
<=M
; m
++ )
469 periodize( fq
, q
, f
, alpha
, omega
);