/// <summary> /// Calculate the Haar forward fast wavelet transform in 1-dimension. /// </summary> /// <param name="signal">Signal to compute (must be power two)</param> public static void Haar_forward_FWT_1d(ref double[] signal) { int m; int npts; npts = (int)DSPUtilities.NextPowerOfTwo((int)signal.Length); for (m = signal.Length - 1; m >= 0; m--) { Wavelet.Haar_forward_pass_1d(m + 1, ref signal); //Wavelet.Haar_ip_FFWT_1d(m + 1, ref signal); } /*int i = 0; * int w = signal.Length; * double[] vecp = new double[signal.Length]; * for (i = 0; i < signal.Length; i++) * vecp[i] = 0; * //while (w > 1) * // { * w /= 2; * for (i = 0; i < w; i++) * { * vecp[i] = (signal[2 * i] + signal[2 * i + 1]) / Math.Sqrt(2.0); * vecp[i + w] = (signal[2 * i] - signal[2 * i + 1]) / Math.Sqrt(2.0); * } * for (i = 0; i < (w * 2); i++) * signal[i] = vecp[i]; * // }*/ }
/// <summary> /// Calculate one iteration of the Haar inverse FWT in 2-dimensions. /// </summary> /// <param name="signal">Signal to compute (must be power two)</param> /* static void Haar_inverse_pass_2d(int n, ref double[][] signal) * { * int i, j; * int npts; * * npts = (int) Utilities.NextPowerOfTwo((int) n); * for (i = 0; i < npts; i++) * { * Wavelet.Haar_inverse_pass_1d(n, ref signal[i]); * } * double[] c = new double[npts]; * for (j = 0; j < npts; j++) * { * for (i = 0; i < npts; i++) * c[i] = signal[i][j]; * Wavelet.Haar_inverse_pass_1d(n, ref c); * for (i = 0; i < npts; i++) * signal[i][j] = c[i]; * } * }*/ /// <summary> /// Calculate the Haar inverse fast wavelet transform in 2-dimensions. /// </summary> /// <param name="signal">Signal to compute (must be power two)</param> public static void Haar_inverse_FWT_2d(int width, int height, ref double[] signal) { /*for (int m = 1; m <= signal.Length; m++) * { * Haar_inverse_pass_2d(m, ref signal); * }*/ double[] row = new double[DSPUtilities.NextPowerOfTwo((int)width)]; double[] column = new double[DSPUtilities.NextPowerOfTwo((int)height)]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { column[y] = signal[x + (y * width)]; } Wavelet.Haar_inverse_FWT_1d(ref column); for (int y = 0; y < height; y++) { signal[x + (y * width)] = column[y]; } } for (int y = 0; y < height; y++) { Array.Copy(signal, (int)(y * width), row, 0, (int)width); Wavelet.Haar_inverse_FWT_1d(ref row); Array.Copy(row, 0, signal, (int)(y * width), (int)width); } }
/// <summary> /// Calculate Haar in-place inverse fast wavelet transform in 1-dimension. /// </summary> /// <param name="n">Elements to compute</param> /// <param name="signal">Signal to compute (must be power two)</param> static void Haar_ip_IFWT_1d(int n, ref double[] signal) { double a0; double a1; int i; int j; int k; int l; int m; i = (int)DSPUtilities.NextPowerOfTwo((int)(n - 1)); j = 2 * i; m = 1; for (l = 1; l <= n; l++) { //System.Diagnostics.Debug.WriteLine("l = " + l); for (k = 0; k < m; k++) { a0 = signal[j * k] + signal[j * k + i]; a1 = signal[j * k] - signal[j * k + i]; signal[j * k] = a0; signal[j * k + i] = a1; } i /= 2; j /= 2; m *= 2; } }
// Haar Wavelet /// <summary> /// Calculate Haar in-place forward fast wavelet transform in 1-dimension. /// </summary> /// <param name="n">Elements to compute</param> /// <param name="signal">Signal to compute</param> static void Haar_ip_FFWT_1d(int n, ref double[] signal) { double a; double c; int i; int j; int k; int l; int m; i = 1; j = 2; m = (int)DSPUtilities.NextPowerOfTwo((int)n); for (l = n - 1; l >= 0; l--) { //System.Diagnostics.Debug.WriteLine("l = " + l); m /= 2; for (k = 0; k < m; k++) { a = (signal[j * k] + signal[j * k + i]) / 2.0; c = (signal[j * k] - signal[j * k + i]) / 2.0; signal[j * k] = a; signal[j * k + i] = c; } i *= 2; j *= 2; } }
/// <summary> /// Calculate one iteration of the Haar inverse FWT in 1-dimension. /// </summary> /// <param name="n">Elements to compute</param> /// <param name="signal">Signal to compute (must be power two)</param> static void Haar_inverse_pass_1d(int n, ref double[] signal) { int i; int npts = (int)DSPUtilities.NextPowerOfTwo((int)n); double[] r = new double[npts]; for (i = 0; i < npts / 2; i++) { r[2 * i] = signal[i] + signal[i + npts / 2]; r[2 * i + 1] = signal[i] - signal[i + npts / 2]; } for (i = 0; i < npts; i++) { signal[i] = r[i]; } }
/// <summary> /// Calculate one iteration of the Haar forward FWT in 1-dimension. /// </summary> /// <param name="n">Elements to compute</param> /// <param name="signal">Signal to compute (must be power two)</param> static void Haar_forward_pass_1d(int n, ref double[] signal) { int i; int npts; npts = (int)DSPUtilities.NextPowerOfTwo((int)n); double[] a = new double[npts / 2]; double[] c = new double[npts / 2]; for (i = 0; i < npts / 2; i++) { a[i] = (signal[2 * i] + signal[2 * i + 1]) / 2.0; c[i] = (signal[2 * i] - signal[2 * i + 1]) / 2.0; } for (i = 0; i < npts / 2; i++) { signal[i] = a[i]; signal[i + npts / 2] = c[i]; } }
/// <summary> /// Compute FFT /// </summary> /// <param name="NumSamples">NumSamples Number of samples (must be power two)</param> /// <param name="pRealIn">Real samples</param> /// <param name="pImagIn">Imaginary (optional, may be null)</param> /// <param name="pRealOut">Real coefficient output</param> /// <param name="pImagOut">Imaginary coefficient output</param> /// <param name="bInverseTransform">bInverseTransform when true, compute Inverse FFT</param> public static void Compute(int NumSamples, IEnumerable <double> pRealIn, Double[] pImagIn, Double[] pRealOut, Double[] pImagOut, Boolean bInverseTransform) { int NumBits; /* Number of bits needed to store indices */ int i, j, k, n; int BlockSize, BlockEnd; double angle_numerator = 2.0 * DSPUtilities.DDC_PI; double tr, ti; /* temp real, temp imaginary */ if (pRealIn == null || pRealOut == null || pImagOut == null) { // error throw new ArgumentNullException("Null argument"); } if (!DSPUtilities.IsPowerOfTwo((int)NumSamples)) { // error throw new ArgumentException("Number of samples must be power of 2"); } if (pRealIn.Count() < NumSamples || (pImagIn != null && pImagIn.Length < NumSamples) || pRealOut.Length < NumSamples || pImagOut.Length < NumSamples) { // error throw new ArgumentException("Invalid Array argument detected"); } if (bInverseTransform) { angle_numerator = -angle_numerator; } NumBits = NumberOfBitsNeeded(NumSamples); /* ** Do simultaneous data copy and bit-reversal ordering into outputs... */ for (i = 0; i < NumSamples; i++) { j = ReverseBits(i, NumBits); pRealOut[j] = pRealIn.ElementAt(i); pImagOut[j] = (double)((pImagIn == null) ? 0.0 : pImagIn[i]); } /* ** Do the FFT itself... */ BlockEnd = 1; for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1) { double delta_angle = angle_numerator / (double)BlockSize; double sm2 = Math.Sin(-2 * delta_angle); double sm1 = Math.Sin(-delta_angle); double cm2 = Math.Cos(-2 * delta_angle); double cm1 = Math.Cos(-delta_angle); double w = 2 * cm1; double ar0, ar1, ar2; double ai0, ai1, ai2; for (i = 0; i < NumSamples; i += BlockSize) { ar2 = cm2; ar1 = cm1; ai2 = sm2; ai1 = sm1; for (j = i, n = 0; n < BlockEnd; j++, n++) { ar0 = w * ar1 - ar2; ar2 = ar1; ar1 = ar0; ai0 = w * ai1 - ai2; ai2 = ai1; ai1 = ai0; k = j + BlockEnd; tr = ar0 * pRealOut[k] - ai0 * pImagOut[k]; ti = ar0 * pImagOut[k] + ai0 * pRealOut[k]; pRealOut[k] = (pRealOut[j] - tr); pImagOut[k] = (pImagOut[j] - ti); pRealOut[j] += (tr); pImagOut[j] += (ti); } } BlockEnd = BlockSize; } /* ** Need to normalize if inverse transform... */ if (bInverseTransform) { double denom = (double)(NumSamples); for (i = 0; i < NumSamples; i++) { pRealOut[i] /= denom; pImagOut[i] /= denom; } } }