1 
2 #include <math.h>
3 
4 /**
5   <p>
6   Daubechies D4 wavelet transform (D4 denotes four coefficients)
7   </p>
8   <p>
9   I have to confess up front that the comment here does not even come
10   close to describing wavelet algorithms and the Daubechies D4
11   algorithm in particular.  I don't think that it can be described in
12   anything less than a journal article or perhaps a book.  I even have
13   to apologize for the notation I use to describe the algorithm, which
14   is barely adequate.  But explaining the correct notation would take
15   a fair amount of space as well.  This comment really represents some
16   notes that I wrote up as I implemented the code.  If you are
17   unfamiliar with wavelets I suggest that you look at the bearcave.com
18   web pages and at the wavelet literature.  I have yet to see a really
19   good reference on wavelets for the software developer.  The best
20   book I can recommend is <i>Ripples in Mathematics</i> by Jensen and
21   Cour-Harbo.
22   </p>
23 
24   <p>
25   All wavelet algorithms have two components, a wavelet function and a
26   scaling function.  These are sometime also referred to as high pass
27   and low pass filters respectively.
28   </p>
29 
30   <p>
31   The wavelet function is passed two or more samples
32   and calculates a wavelet coefficient.  In the case of
33   the Haar wavelet this is
34   </p>
35 
36   <pre>
37   coef<sub>i</sub> = odd<sub>i</sub> - even<sub>i</sub>
38   or
39   coef<sub>i</sub> = 0.5 * (odd<sub>i</sub> - even<sub>i</sub>)
40   </pre>
41   <p>
42   depending on the version of the Haar algorithm used.
43   </p>
44   <p>
45   The scaling function produces a smoother version of the
46   original data.  In the case of the Haar wavelet algorithm
47   this is an average of two adjacent elements.
48   </p>
49   <p>
50   The Daubechies D4 wavelet algorithm also has a wavelet
51   and a scaling function.  The coefficients for the
52   scaling function are denoted as h<sub>i</sub> and the
53   wavelet coefficients are g<sub>i</sub>.
54   </p>
55   <p>
56   Mathematicians like to talk about wavelets in terms of
57   a wavelet algorithm applied to an infinite data set.
rd_tmpabuf_new(rd_tmpabuf_t * tab,size_t size,int assert_on_fail)58   In this case one step of the forward transform can be expressed
59   as the infinite matrix of wavelet coefficients
60   represented below multiplied by the infinite signal
61   vector.
62   </p>
63   <pre>
64      a<sub>i</sub> = ...h0,h1,h2,h3, 0, 0, 0, 0, 0, 0, 0, ...   s<sub>i</sub>
65      c<sub>i</sub> = ...g0,g1,g2,g3, 0, 0, 0, 0, 0, 0, 0, ...   s<sub>i+1</sub>
66    a<sub>i+1</sub> = ...0, 0, h0,h1,h2,h3, 0, 0, 0, 0, 0, ...   s<sub>i+2</sub>
67    c<sub>i+1</sub> = ...0, 0, g0,g1,g2,g3, 0, 0, 0, 0, 0, ...   s<sub>i+3</sub>
68    a<sub>i+2</sub> = ...0, 0, 0, 0, h0,h1,h2,h3, 0, 0, 0, ...   s<sub>i+4</sub>
69    c<sub>i+2</sub> = ...0, 0, 0, 0, g0,g1,g2,g3, 0, 0, 0, ...   s<sub>i+5</sub>
70    a<sub>i+3</sub> = ...0, 0, 0, 0, 0, 0, h0,h1,h2,h3, 0, ...   s<sub>i+6</sub>
71    c<sub>i+3</sub> = ...0, 0, 0, 0, 0, 0, g0,g1,g2,g3, 0, ...   s<sub>i+7</sub>
72   </pre>
73   <p>
74   The dot product (inner product) of the infinite vector and
75   a row of the matrix produces either a smoother version of the
76   signal (a<sub>i</sub>) or a wavelet coefficient (c<sub>i</sub>).
77   </p>
78   <p>
79   In an ordered wavelet transform, the smoothed (a<sub>i</sub>) are
80   stored in the first half of an <i>n</i> element array region.  The
81   wavelet coefficients (c<sub>i</sub>) are stored in the second half
82   the <i>n</i> element region.  The algorithm is recursive.  The
83   smoothed values become the input to the next step.
84   </p>
85   <p>
86   The transpose of the forward transform matrix above is used
87   to calculate an inverse transform step.  Here the dot product is
88   formed from the result of the forward transform and an inverse
89   transform matrix row.
90   </p>
91   <pre>
92       s<sub>i</sub> = ...h2,g2,h0,g0, 0, 0, 0, 0, 0, 0, 0, ...  a<sub>i</sub>
93     s<sub>i+1</sub> = ...h3,g3,h1,g1, 0, 0, 0, 0, 0, 0, 0, ...  c<sub>i</sub>
94     s<sub>i+2</sub> = ...0, 0, h2,g2,h0,g0, 0, 0, 0, 0, 0, ...  a<sub>i+1</sub>
95     s<sub>i+3</sub> = ...0, 0, h3,g3,h1,g1, 0, 0, 0, 0, 0, ...  c<sub>i+1</sub>
96     s<sub>i+4</sub> = ...0, 0, 0, 0, h2,g2,h0,g0, 0, 0, 0, ...  a<sub>i+2</sub>
97     s<sub>i+5</sub> = ...0, 0, 0, 0, h3,g3,h1,g1, 0, 0, 0, ...  c<sub>i+2</sub>
98     s<sub>i+6</sub> = ...0, 0, 0, 0, 0, 0, h2,g2,h0,g0, 0, ...  a<sub>i+3</sub>
99     s<sub>i+7</sub> = ...0, 0, 0, 0, 0, 0, h3,g3,h1,g1, 0, ...  c<sub>i+3</sub>
100   </pre>
101 
102   <p>
103   Using a standard dot product is grossly inefficient since most
104   of the operands are zero.  In practice the wavelet coefficient
105   values are moved along the signal vector and a four element
106   dot product is calculated.  Expressed in terms of arrays, for
107   the forward transform this would be:
108   </p>
109   <pre>
110   a<sub>i</sub> = s[i]*h0 + s[i+1]*h1 + s[i+2]*h2 + s[i+3]*h3
111   c<sub>i</sub> = s[i]*g0 + s[i+1]*g1 + s[i+2]*g2 + s[i+3]*g3
112   </pre>
113   <p>
114   This works fine if we have an infinite data set, since we don't
115   have to worry about shifting the coefficients "off the end" of
116   the signal.
117   </p>
118   <p>
119   I sometimes joke that I left my infinite data set in my other bear
120   suit.  The only problem with the algorithm described so far is that
121   we don't have an infinite signal.  The signal is finite.  In fact
122   not only must the signal be finite, but it must have a power of two
123   number of elements.
124   </p>
125   <p>
126   If i=N-1, the i+2 and i+3 elements will be beyond the end of
127   the array.  There are a number of methods for handling the
128   wavelet edge problem.  This version of the algorithm acts
129   like the data is periodic, where the data at the start of
130   the signal wraps around to the end.
131   </p>
132   <p>
133   This algorithm uses a temporary array.  A Lifting Scheme version of
134   the Daubechies D4 algorithm does not require a temporary.  The
135   matrix discussion above is based on material from <i>Ripples in
136   Mathematics</i>, by Jensen and Cour-Harbo.  Any error are mine.
137   </p>
138 
139   <p>
140   <b>Author</b>: Ian Kaplan<br>
141   <b>Use</b>: You may use this software for any purpose as long
142   as I cannot be held liable for the result.  Please credit me
143   with authorship if use use this source code.
144   <p>
145   This comment is formatted for the doxygen documentation generator
146   </p>
147  */
148 
149 //hacks by Nick
150 //doubles -> floats
151 //avoid new and delete within transform functions, put in one place
152 
153 class Daubechies {
154    private:
155    /** forward transform scaling coefficients */
156    float h0, h1, h2, h3;
157    /** forward transform wave coefficients */
158    float g0, g1, g2, g3;
159 
160    float Ih0, Ih1, Ih2, Ih3;
161    float Ig0, Ig1, Ig2, Ig3;
162    float* tmp;
163 
164 
165    /**
166      Forward Daubechies D4 transform
167     */
168    void transform( float* a, const int n )
169    {
170 
171 	  // printf("inside transform a %p tmp %p \n", a, tmp);
172 
173 
174 
175 	  // for(int i=0; i<64; ++i) printf("transform data i %d a %f tmp %f \n",i, a[i], tmp[i]);
176 
177 
178       if (n >= 4) {
179          int i, j;
180          const int half = n >> 1;
181 
182 	 //float* tmp = new float[n];
183 
184          for (i = 0, j = 0; j < n-3; j += 2, i++) {
185             tmp[i]      = a[j]*h0 + a[j+1]*h1 + a[j+2]*h2 + a[j+3]*h3;
186             tmp[i+half] = a[j]*g0 + a[j+1]*g1 + a[j+2]*g2 + a[j+3]*g3;
187 			//printf("transform data i %d j %d tmp[i] %f tmp[i+half] %f \n",i,j, tmp[i], tmp[i+half]);
188          }
189 
190          tmp[i]      = a[n-2]*h0 + a[n-1]*h1 + a[0]*h2 + a[1]*h3;
191          tmp[i+half] = a[n-2]*g0 + a[n-1]*g1 + a[0]*g2 + a[1]*g3;
192 
193          for (i = 0; i < n; i++) {
194             a[i] = tmp[i];
195          }
196 	// delete [] tmp;
197       }
198    }
199 
200    /**
201      Inverse Daubechies D4 transform
202     */
203    void invTransform( float* a, const int n )
204    {
205      if (n >= 4) {
206        int i, j;
207        const int half = n >> 1;
208        const int halfPls1 = half + 1;
209 
210       // float* tmp = new float[n];
211 
212        //      last smooth val  last coef.  first smooth  first coef
213        tmp[0] = a[half-1]*Ih0 + a[n-1]*Ih1 + a[0]*Ih2 + a[half]*Ih3;
214        tmp[1] = a[half-1]*Ig0 + a[n-1]*Ig1 + a[0]*Ig2 + a[half]*Ig3;
215        for (i = 0, j = 2; i < half-1; i++) {
216 	 //     smooth val     coef. val       smooth val    coef. val
217 	 tmp[j++] = a[i]*Ih0 + a[i+half]*Ih1 + a[i+1]*Ih2 + a[i+halfPls1]*Ih3;
218 	 tmp[j++] = a[i]*Ig0 + a[i+half]*Ig1 + a[i+1]*Ig2 + a[i+halfPls1]*Ig3;
219        }
220        for (i = 0; i < n; i++) {
221 	 a[i] = tmp[i];
222        }
223        //delete [] tmp;
224      }
225    }
226 
227 
228    public:
229 
230    Daubechies()
231    {
232       const float sqrt_3 = sqrt( 3 );
233       const float denom = 4 * sqrt( 2 );
234 
235       //
236       // forward transform scaling (smoothing) coefficients
237       //
238       h0 = (1 + sqrt_3)/denom;
239       h1 = (3 + sqrt_3)/denom;
240       h2 = (3 - sqrt_3)/denom;
241       h3 = (1 - sqrt_3)/denom;
242       //
243       // forward transform wavelet coefficients
244       //
245       g0 =  h3;
246       g1 = -h2;
247       g2 =  h1;
248       g3 = -h0;
249 
250       Ih0 = h2;
251       Ih1 = g2;  // h1
252       Ih2 = h0;
253       Ih3 = g0;  // h3
254 
255       Ig0 = h3;
256       Ig1 = g3;  // -h0
257       Ig2 = h1;
258       Ig3 = g1;  // -h2
259 
260 	  tmp = new float[4096]; //make sure big enough never to be an issue; size chosen here limits overall wavelet transform max N
261    }
262 
263    ~Daubechies() {
264 	    delete [] tmp;
265    }
266 
267    void daubTrans( float* ts, int N )
268    {
269       int n;
270       for (n = N; n >= 4; n >>= 1) {
271 
272 		  //printf("pre sub transform %d \n",n);
273 		  transform( ts, n );
274 		  //printf("post sub transform %d \n",n);
275       }
276    }
277 
278 
279    void invDaubTrans( float* coef, int N )
280    {
281       int n;
282       for (n = 4; n <= N; n <<= 1) {
283          invTransform( coef, n );
284       }
285    }
286 
287 }; // Daubechies
288