package be.tarsos.dsp.wavelet.lift;
/**
* <p>
* HaarWavelet (flat LineWavelet) wavelet.
* </p>
*
* <p>
* As with all Lifting scheme wavelet transform functions, the first stage of a
* transform step is the split stage. The split step moves the even element to
* the first half of an N element region and the odd elements to the second half
* of the N element region.
* </p>
*
* <p>
* The Lifting Scheme version of the HaarWavelet transform uses a wavelet
* function (predict stage) that "predicts" that an odd element will have the
* same value as it preceeding even element. Stated another way, the odd element
* is "predicted" to be on a flat (zero slope LineWavelet) shared with the even
* point. The difference between this "prediction" and the actual odd value
* replaces the odd element.
* </p>
*
* <p>
* The wavelet scaling function (a.k.a. smoothing function) used in the update
* stage calculates the average between an even and an odd element.
* </p>
*
* <p>
* The merge stage at the end of the inverse transform interleaves odd and even
* elements from the two halves of the array (e.g., ordering them
* even<sub>0</sub>, odd<sub>0</sub>, even<sub>1</sub>, odd<sub>1</sub>, ...)
* </p>
*
* <h4>
* Copyright and Use</h4>
*
* <p>
* You may use this source code without limitation and without fee as long as
* you include:
* </p>
* <blockquote> This software was written and is copyrighted by Ian Kaplan, Bear
* Products International, www.bearcave.com, 2001. </blockquote>
* <p>
* This software is provided "as is", without any warrenty or claim as to its
* usefulness. Anyone who uses this source code uses it at their own risk. Nor
* is any support provided by Ian Kaplan and Bear Products International.
* <p>
* Please send any bug fixes or suggested source changes to:
*
* <pre>
* iank@bearcave.com
* </pre>
*
* @author Ian Kaplan
*/
public class HaarWavelet extends LiftingSchemeBaseWavelet {
/**
* HaarWavelet predict step
*/
protected void predict(float[] vec, int N, int direction) {
int half = N >> 1;
for (int i = 0; i < half; i++) {
float predictVal = vec[i];
int j = i + half;
if (direction == forward) {
vec[j] = vec[j] - predictVal;
} else if (direction == inverse) {
vec[j] = vec[j] + predictVal;
} else {
System.out.println("HaarWavelet::predict: bad direction value");
}
}
}
public void forwardTransOne(float[] vec) {
final int N = vec.length;
split(vec, N);
predict(vec, N, forward);
update(vec, N, forward);
} // forwardTrans
/**
* <p>
* Update step of the HaarWavelet wavelet transform.
* </p>
* <p>
* The wavelet transform calculates a set of detail or difference
* coefficients in the predict step. These are stored in the upper half of
* the array. The update step calculates an average from the even-odd
* element pairs. The averages will replace the even elements in the lower
* half of the array.
* </p>
* <p>
* The HaarWavelet wavelet calculation used in the Lifting Scheme is
* </p>
*
* <pre>
* d<sub>j+1, i</sub> = odd<sub>j+1, i</sub> = odd<sub>j, i</sub> - even<sub>j, i</sub>
* a<sub>j+1, i</sub> = even<sub>j, i</sub> = (even<sub>j, i</sub> + odd<sub>j, i</sub>)/2
* </pre>
* <p>
* Note that the Lifting Scheme uses an in-place algorithm. The odd elements
* have been replaced by the detail coefficients in the predict step. With a
* little algebra we can substitute the coefficient calculation into the
* average calculation, which gives us
* </p>
*
* <pre>
* a<sub>j+1, i</sub> = even<sub>j, i</sub> = even<sub>j, i</sub> + (odd<sub>j, i</sub>/2)
* </pre>
*/
protected void update(float[] vec, int N, int direction) {
int half = N >> 1;
for (int i = 0; i < half; i++) {
int j = i + half;
float updateVal = vec[j] / 2.0f;
if (direction == forward) {
vec[i] = vec[i] + updateVal;
} else if (direction == inverse) {
vec[i] = vec[i] - updateVal;
} else {
System.out.println("update: bad direction value");
}
}
}
} // HaarWavelet