plectrum

Plectrum: instrument tuner for Android
Log | Files | Refs | README | LICENSE

LiftingSchemeBaseWavelet.java (6560B)


      1 package be.tarsos.dsp.wavelet.lift;
      2 
      3 /**
      4  * <p>
      5  * class LiftingSchemeBaseWavelet: base class for simple Lifting Scheme wavelets
      6  * using split, predict, update or update, predict, merge steps.
      7  * </p>
      8  * 
      9  * <p>
     10  * Simple lifting scheme wavelets consist of three steps, a split/merge step,
     11  * predict step and an update step:
     12  * </p>
     13  * <ul>
     14  * <li>
     15  * <p>
     16  * The split step divides the elements in an array so that the even elements are
     17  * in the first half and the odd elements are in the second half.
     18  * </p>
     19  * </li>
     20  * <li>
     21  * <p>
     22  * The merge step is the inverse of the split step. It takes two regions of an
     23  * array, an odd region and an even region and merges them into a new region
     24  * where an even element alternates with an odd element.
     25  * </p>
     26  * </li>
     27  * <li>
     28  * <p>
     29  * The predict step calculates the difference between an odd element and its
     30  * predicted value based on the even elements. The difference between the
     31  * predicted value and the actual value replaces the odd element.
     32  * </p>
     33  * </li>
     34  * <li>
     35  * <p>
     36  * The predict step operates on the odd elements. The update step operates on
     37  * the even element, replacing them with a difference between the predict value
     38  * and the actual odd element. The update step replaces each even element with
     39  * an average. The result of the update step becomes the input to the next
     40  * recursive step in the wavelet calculation.
     41  * </p>
     42  * </li>
     43  * 
     44  * </ul>
     45  * 
     46  * <p>
     47  * The split and merge methods are shared by all Lifting Scheme wavelet
     48  * algorithms. This base class provides the transform and inverse transform
     49  * methods (forwardTrans and inverseTrans). The predict and update methods are
     50  * abstract and are defined for a particular Lifting Scheme wavelet sub-class.
     51  * </p>
     52  * 
     53  * <p>
     54  * <b>References:</b>
     55  * </p>
     56  * 
     57  * <ul>
     58  * <li>
     59  * <a href="http://www.bearcave.com/misl/misl_tech/wavelets/lifting/index.html">
     60  * <i>The Wavelet Lifting Scheme</i></a> by Ian Kaplan, www.bearcave.com. This
     61  * is the parent web page for this Java source code.</li>
     62  * <li>
     63  * <i>Ripples in Mathematics: the Discrete Wavelet Transform</i> by Arne Jense
     64  * and Anders la Cour-Harbo, Springer, 2001</li>
     65  * <li>
     66  * <i>Building Your Own Wavelets at Home</i> in <a
     67  * href="http://www.multires.caltech.edu/teaching/courses/waveletcourse/">
     68  * Wavelets in Computer Graphics</a></li>
     69  * </ul>
     70  * 
     71  * <h4>
     72  * Copyright and Use</h4>
     73  * 
     74  * <p>
     75  * You may use this source code without limitation and without fee as long as
     76  * you include:
     77  * </p>
     78  * <blockquote> This software was written and is copyrighted by Ian Kaplan, Bear
     79  * Products International, www.bearcave.com, 2001. </blockquote>
     80  * <p>
     81  * This software is provided "as is", without any warrenty or claim as to its
     82  * usefulness. Anyone who uses this source code uses it at their own risk. Nor
     83  * is any support provided by Ian Kaplan and Bear Products International.
     84  * <p>
     85  * Please send any bug fixes or suggested source changes to:
     86  * 
     87  * <pre>
     88  *      iank@bearcave.com
     89  * </pre>
     90  * 
     91  * @author Ian Kaplan
     92  */
     93 public abstract class LiftingSchemeBaseWavelet {
     94 
     95 	/** "enumeration" for forward wavelet transform */
     96 	protected final int forward = 1;
     97 	/** "enumeration" for inverse wavelet transform */
     98 	protected final int inverse = 2;
     99 
    100 	/**
    101 	 * Split the <i>vec</i> into even and odd elements, where the even elements
    102 	 * are in the first half of the vector and the odd elements are in the
    103 	 * second half.
    104 	 */
    105 	protected void split(float[] vec, int N) {
    106 
    107 		int start = 1;
    108 		int end = N - 1;
    109 
    110 		while (start < end) {
    111 			for (int i = start; i < end; i = i + 2) {
    112 				float tmp = vec[i];
    113 				vec[i] = vec[i + 1];
    114 				vec[i + 1] = tmp;
    115 			}
    116 			start = start + 1;
    117 			end = end - 1;
    118 		}
    119 	}
    120 
    121 	/**
    122 	 * Merge the odd elements from the second half of the N element region in
    123 	 * the array with the even elements in the first half of the N element
    124 	 * region. The result will be the combination of the odd and even elements
    125 	 * in a region of length N.
    126 	 */
    127 	protected void merge(float[] vec, int N) {
    128 		int half = N >> 1;
    129 		int start = half - 1;
    130 		int end = half;
    131 
    132 		while (start > 0) {
    133 			for (int i = start; i < end; i = i + 2) {
    134 				float tmp = vec[i];
    135 				vec[i] = vec[i + 1];
    136 				vec[i + 1] = tmp;
    137 			}
    138 			start = start - 1;
    139 			end = end + 1;
    140 		}
    141 	}
    142 
    143 	/**
    144 	 * Predict step, to be defined by the subclass
    145 	 * 
    146 	 * @param vec
    147 	 *            input array
    148 	 * @param N
    149 	 *            size of region to act on (from 0..N-1)
    150 	 * @param direction
    151 	 *            forward or inverse transform
    152 	 */
    153 	protected abstract void predict(float[] vec, int N, int direction);
    154 
    155 	/**
    156 	 * Update step, to be defined by the subclass
    157 	 * 
    158 	 * @param vec
    159 	 *            input array
    160 	 * @param N
    161 	 *            size of region to act on (from 0..N-1)
    162 	 * @param direction
    163 	 *            forward or inverse transform
    164 	 */
    165 	protected abstract void update(float[] vec, int N, int direction);
    166 
    167 	/**
    168 	 * <p>
    169 	 * Simple wavelet Lifting Scheme forward transform
    170 	 * </p>
    171 	 * 
    172 	 * <p>
    173 	 * forwardTrans is passed an array of doubles. The array size must be a
    174 	 * power of two. Lifting Scheme wavelet transforms are calculated in-place
    175 	 * and the result is returned in the argument array.
    176 	 * </p>
    177 	 * 
    178 	 * <p>
    179 	 * The result of forwardTrans is a set of wavelet coefficients ordered by
    180 	 * increasing frequency and an approximate average of the input data set in
    181 	 * vec[0]. The coefficient bands follow this element in powers of two (e.g.,
    182 	 * 1, 2, 4, 8...).
    183 	 * </p>
    184 	 * 
    185 	 * @param vec
    186 	 *            the vector
    187 	 */
    188 	public void forwardTrans(float[] vec) {
    189 		final int N = vec.length;
    190 
    191 		for (int n = N; n > 1; n = n >> 1) {
    192 			split(vec, n);
    193 			predict(vec, n, forward);
    194 			update(vec, n, forward);
    195 		}
    196 	} // forwardTrans
    197 
    198 	/**
    199 	 * <p>
    200 	 * Default two step Lifting Scheme inverse wavelet transform
    201 	 * </p>
    202 	 * 
    203 	 * <p>
    204 	 * inverseTrans is passed the result of an ordered wavelet transform,
    205 	 * consisting of an average and a set of wavelet coefficients. The inverse
    206 	 * transform is calculated in-place and the result is returned in the
    207 	 * argument array.
    208 	 * </p>
    209 	 * 
    210 	 * @param vec
    211 	 *            the vector
    212 	 */
    213 	public void inverseTrans(float[] vec) {
    214 		final int N = vec.length;
    215 
    216 		for (int n = 2; n <= N; n = n << 1) {
    217 			update(vec, n, inverse);
    218 			predict(vec, n, inverse);
    219 			merge(vec, n);
    220 		}
    221 	} // inverseTrans
    222 
    223 } // LiftingSchemeBaseWavelet