All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.dfki.lt.signalproc.window.Window Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2004-2006 DFKI GmbH.
 * All Rights Reserved.  Use is subject to license terms.
 * 
 * Permission is hereby granted, free of charge, to use and distribute
 * this software and its documentation without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of this work, and to
 * permit persons to whom this work is furnished to do so, subject to
 * the following conditions:
 * 
 * 1. The code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 * 2. Any modifications must be clearly marked as such.
 * 3. Original authors' names are not deleted.
 * 4. The authors' names are not used to endorse or promote products
 *    derived from this software without specific prior written
 *    permission.
 *
 * DFKI GMBH AND THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DFKI GMBH NOR THE
 * CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 * THIS SOFTWARE.
 */

package de.dfki.lt.signalproc.window;

import java.util.Arrays;

// TODO: Auto-generated Javadoc
/**
 * The Class Window.
 *
 * @author Marc Schröder Interface for windowing functions.
 */
public abstract class Window implements CopyingDataProcessor, InlineDataProcessor {
	
	/** The Constant RECT. */
	public static final int RECT = 0;
	
	/** The Constant HAMMING. */
	public static final int HAMMING = 1;
	
	/** The Constant BLACKMAN. */
	public static final int BLACKMAN = 2;
	
	/** The Constant HANN. */
	public static final int HANN = 3;
	
	/** The Constant GAUSS. */
	public static final int GAUSS = 4;
	
	/** The Constant BARTLETT. */
	public static final int BARTLETT = 5;

	/** The prescaling factor. */
	protected double prescalingFactor;
	
	/** The even length. */
	protected boolean evenLength;

	/**
	 * This array, whose length is the window length, holds the multiplication
	 * factors for each sample across the window. It must be initialised in the
	 * constructor, using the method #initialise().
	 */
	protected double[] window;

	/**
	 * Default constructor for subclasses that need to do something themselves
	 * before calling initialise().
	 */
	protected Window() {
		prescalingFactor = 1.;
	}

	/**
	 * Create a new window of length length. This will call #initialise() in the
	 * respective subclass in order to fill the window array with meaningful
	 * multiplication values.
	 * 
	 * @param length
	 *          the window length, in samples; this should be an odd number, so
	 *          that the window can be symmetric around the center point.
	 * @throw IllegalArgumentException if length is an even number.
	 */
	public Window(int length) {
		this(length, 1);
	}

	/**
	 * Create a new window of length length, and apply the given prescaling factor
	 * to each point. This will call #initialise() in the respective subclass in
	 * order to fill the window array with meaningful multiplication values.
	 * 
	 * @param length
	 *          the window length, in samples; this should be an odd number, so
	 *          that the window can be symmetric around the center point.
	 * @param prescalingFactor
	 *          a factor to apply to each window point.
	 * @throw IllegalArgumentException if length is an even number.
	 */
	public Window(int length, double prescalingFactor) {
		window = new double[length];
		this.evenLength = (length % 2 == 0);
		this.prescalingFactor = prescalingFactor;
		initialise();
	}

	/**
	 * Apply this window on the given source data array, at the given position.
	 * This method returns the resulting data in a new array of the same length as
	 * this window (@see getLength()). If src has less than getLength() data
	 * points left at pos, zeros are added at the end.
	 *
	 * @param src          the source data array to apply the windowing function to.
	 * @param pos          the position from which to apply the windowing function
	 * @return an array of the same length as this window, computed by applying
	 *         this window to the source data.
	 */
	public double[] apply(final double[] src, int pos) {
		double target[] = new double[window.length];
		apply(src, pos, target, 0);
		return target;
	}

	/**
	 * Apply the window function in-line, i.e. by modifying the original data.
	 *
	 * @param data the data
	 * @param pos          the position in the data array where to start applying the window
	 *          function.
	 * @param len          the amount of data after position pos to process. len must be less
	 *          than or equal to getLength(). If it is less than getLength(), a
	 *          truncated window will be applied.
	 */
	public void applyInline(double[] data, int pos, int len) {
		apply(data, pos, data, pos, len);
	}

	/**
	 * Apply this window on the given source data array, at the given position.
	 * This method returns the resulting data in the given target array, at the
	 * target position given by targetPos. If src has less than getLength() data
	 * points left at pos, zeros are added at the end.
	 *
	 * @param src          the source data array to apply the windowing function to.
	 * @param srcPos          the position in the source array from which to apply the windowing
	 *          function
	 * @param target          an array to receive the target data, computed by applying this
	 *          window to the source data. The target array must be long enough to
	 *          receive getLength() bytes after targetPos. if target == source and
	 *          targetPos == srcPos, then the window function is applied in-place.
	 * @param targetPos the target pos
	 */
	public void apply(final double[] src, int srcPos, double[] target, int targetPos) {
		apply(src, srcPos, target, targetPos, 0, window.length);
	}

	/**
	 * Apply this window on the given source data array, at the given position.
	 * This method returns the resulting data in the given target array, at the
	 * target position given by targetPos. If src has less than getLength() data
	 * points left at pos, zeros are added at the end.
	 *
	 * @param src          the source data array to apply the windowing function to.
	 * @param srcPos          the position in the source array from which to apply the windowing
	 *          function. If srcPos is negative, abs(srcPos) zeroes will be
	 *          pre-pended before the first data from src is taken into account;
	 *          if it is greater than src.length-getLength(), the result will be
	 *          filled up with trailing zeroes behind the last data.
	 * @param target          an array to receive the target data, computed by applying this
	 *          window to the source data. The target array must be long enough to
	 *          receive getLength() bytes after targetPos. if target == source and
	 *          targetPos == srcPos, then the window function is applied in-place.
	 * @param targetPos the target pos
	 * @param len          the number of samples of the window to apply; this must be less
	 *          than or equal getLength(). If it is less than getLength(), a
	 *          truncated window will be applied.
	 */
	public void apply(final double[] src, int srcPos, double[] target, int targetPos, int len) {
		apply(src, srcPos, target, targetPos, 0, len);
	}

	/**
	 * Apply a part of this window on the given source data array, at the given
	 * position. For example, by setting off to getLength()/2 and len to
	 * getLength()/2, only the right half of the window will be applied. This
	 * method returns the resulting data in the given target array, at the target
	 * position given by targetPos. If src has less than len data points left at
	 * srcPos, zeros are added at the end.
	 *
	 * @param src          the source data array to apply the windowing function to.
	 * @param srcPos          the position in the source array from which to apply the windowing
	 *          function. If srcPos is negative, abs(srcPos) zeroes will be
	 *          pre-pended before the first data from src is taken into account;
	 *          if it is greater than src.length-getLength(), the result will be
	 *          filled up with trailing zeroes behind the last data.
	 * @param target          an array to receive the target data, computed by applying this
	 *          window to the source data. The target array must be long enough to
	 *          receive getLength() bytes after targetPos. if target == source and
	 *          targetPos == srcPos, then the window function is applied in-place.
	 * @param targetPos the target pos
	 * @param off          the offset from the start of the window from where on the window
	 *          is to be applied.
	 * @param len          the number of samples of the window to apply; off+len must be less
	 *          than or equal getLength().
	 */
	public void apply(final double[] src, int srcPos, double[] target, int targetPos, int off, int len) {
		if (len < 0 || off < 0 || off + len > window.length)
			throw new IllegalArgumentException("Requested offset " + off + " or length " + len
					+ " does not fit into window length " + window.length);
		if (target.length < targetPos + len)
			throw new IllegalArgumentException("Target array cannot hold enough data");
		int start, end; // actual positions in src to apply the window to.
		// If these deviate from srcPos and srcPos+len, resp., zeroes need to be
		// pre-/appended.
		start = srcPos;
		if (start < 0) {
			start = 0;
			Arrays.fill(target, targetPos, targetPos + (start - srcPos), 0);
		}
		end = srcPos + len;
		if (end > src.length) {
			end = src.length;
			Arrays.fill(target, targetPos + end - srcPos, targetPos + len, 0);
		}
		for (int i = start; i < end; i++) {
			target[targetPos + i - srcPos] = src[i] * window[off + i - srcPos];
		}
	}

	/**
	 * The initialisation of the window array with multiplication factors
	 * corresponding to the specific windowing function. This needs to be
	 * implemented by each subclass.
	 */
	protected abstract void initialise();

	/**
	 * Return the length of this window, in samples.
	 *
	 * @return the length
	 */
	public int getLength() {
		if (window == null) {
			throw new NullPointerException("The window has not yet been initialised");
		}
		return window.length;
	}

	/**
	 * Get the value of the window function at index position i.
	 *
	 * @param i          the index position in the window for which to return the value
	 * @return the value of the window function, between 0 and 1.
	 */
	public double value(int i) {
		if (window == null) {
			throw new NullPointerException("The window has not yet been initialised");
		}
		if (i < 0 || i > window.length) {
			throw new IllegalArgumentException("Can only return values for index positions 0 to " + window.length);
		}
		return window[i];
	}

	/**
	 * Return this window's type, as defined by the constants in Window, or -1 if
	 * the window is not of a known type.
	 *
	 * @return the int
	 */
	public int type() {
		if (this instanceof RectWindow)
			return RECT;
		else if (this instanceof HammingWindow)
			return HAMMING;
		else if (this instanceof BlackmanWindow)
			return BLACKMAN;
		else if (this instanceof HannWindow)
			return HANN;
		else if (this instanceof GaussWindow)
			return GAUSS;
		else if (this instanceof BartlettWindow)
			return BARTLETT;
		else
			return -1;
	}

	/**
	 * Convenience method for requesting a window of the requested type.
	 *
	 * @param windowType          one of the constants defined in Window.
	 * @param length          window length (should be an odd number)
	 * @return a window of the requested type and length
	 */
	public static Window get(int windowType, int length) {
		return get(windowType, length, 1.);
	}

	/**
	 * Convenience method for requesting a window of the requested type.
	 *
	 * @param windowType          one of the constants defined in Window.
	 * @param length          window length (should be an odd number)
	 * @param prescale          a prescaling factor applied to all points in the window
	 * @return a window of the requested type and length
	 */
	public static Window get(int windowType, int length, double prescale) {
		switch (windowType) {
		case RECT:
			return new RectWindow(length, prescale);
		case HAMMING:
			return new HammingWindow(length, prescale);
		case BLACKMAN:
			return new BlackmanWindow(length, prescale);
		case HANN:
			return new HannWindow(length, prescale);
		case GAUSS:
			return new GaussWindow(length, prescale);
		case BARTLETT:
			return new BartlettWindow(length, prescale);
		default:
			throw new IllegalArgumentException("Unknown window type requested.");
		}
	}

	/**
	 * List all available window types.
	 *
	 * @return an integer corresponding to the constants defined in Window.
	 */
	public static int[] getAvailableTypes() {
		return new int[] { RECT, HAMMING, BLACKMAN, HANN, GAUSS, BARTLETT };
	}

	/**
	 * For a given type name (e.g., "Hann window", or "BARTLETT"), return the type
	 * code. Matching is done as case-insensitive prefix matching.
	 * 
	 * @param typeName
	 *          the type name.
	 * @return the type code corresponding to typeName, or -1 if none could be
	 *         determined.
	 */
	public static int getTypeByName(String typeName) {
		String tomatch = typeName.toUpperCase();
		if (tomatch.startsWith("HAMMING"))
			return HAMMING;
		else if (tomatch.startsWith("RECT"))
			return RECT;
		else if (tomatch.startsWith("BLACKMAN"))
			return BLACKMAN;
		else if (tomatch.startsWith("HANN"))
			return HANN;
		else if (tomatch.startsWith("GAUSS"))
			return GAUSS;
		else if (tomatch.startsWith("BARTLETT"))
			return BARTLETT;
		else
			return -1;
	}

	/**
	 * Get the type name of a window type.
	 *
	 * @param windowType          a valid window type
	 * @return a string representing the type name
	 */
	public static String getTypeName(int windowType) {
		Window w = get(windowType, 1);
		return w.toString();
	}

	// Normalize window coefficients to sum up to unity
	/**
	 * Normalize.
	 */
	public void normalize() {
		normalize(1.0f);
	}

	// Normalize window coefficients to sum up to val
	/**
	 * Normalize.
	 *
	 * @param val the val
	 */
	public void normalize(float val) {
		float total = 0.0f;
		int i;
		for (i = 0; i < window.length; i++)
			total += window[i];

		float scale = val / total;

		for (i = 0; i < window.length; i++)
			window[i] *= scale;
	}

	/**
	 * Gets the coeffs.
	 *
	 * @return the coeffs
	 */
	public double[] getCoeffs() {
		return window;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy