/* * Copyright 1999-2004 Carnegie Mellon University. * Portions Copyright 2002-2004 Sun Microsystems, Inc. * Portions Copyright 2002-2004 Mitsubishi Electric Research Laboratories. * All Rights Reserved. Use is subject to license terms. * * See the file "license.terms" for information on usage and * redistribution of this file, and for a DISCLAIMER OF ALL * WARRANTIES. * */ package edu.cmu.sphinx.frontend.filter; import edu.cmu.sphinx.frontend.*; import edu.cmu.sphinx.util.props.PropertyException; import edu.cmu.sphinx.util.props.PropertySheet; import edu.cmu.sphinx.util.props.S4Boolean; import edu.cmu.sphinx.util.props.S4Double; import static java.lang.Math.max; import static java.lang.Math.min; import java.util.Random; /** * Implements a dither for the incoming packet. A small amount of random noise is added * to the signal to avoid floating point errors and prevent the energy from * being zero. <p> Other {@link Data} objects are passed along unchanged through * this Dither processor. <p> See also {@link EnergyFilter}, an alternative to Dither. */ public class Dither extends BaseDataProcessor { /** The maximal value which could be added/subtracted to/from the signal*/ @S4Double(defaultValue = 2.0) public static final String PROP_MAX_DITHER = "maxDither"; private double ditherMax; /** The maximal value of dithered values. */ @S4Double(defaultValue = Double.MAX_VALUE) public static final String PROP_MAX_VAL = "upperValueBound"; private double maxValue; /** The minimal value of dithered values. */ @S4Double(defaultValue = -Double.MAX_VALUE) public static final String PROP_MIN_VAL = "lowerValueBound"; private double minValue; /** The property about using random seed or not */ @S4Boolean(defaultValue = false) public static final String PROP_USE_RANDSEED = "useRandSeed"; private boolean useRandSeed; Random r; public Dither( double ditherMax, boolean useRandSeed, double maxValue, double minValue) { initLogger(); this.ditherMax = ditherMax; this.useRandSeed = useRandSeed; this.maxValue = maxValue; this.minValue = minValue; initialize(); } public Dither( ) { } @Override public void newProperties(PropertySheet ps) throws PropertyException { super.newProperties(ps); ditherMax = ps.getDouble(PROP_MAX_DITHER); useRandSeed = ps.getBoolean(PROP_USE_RANDSEED); maxValue = ps.getDouble(PROP_MAX_VAL); minValue = ps.getDouble(PROP_MIN_VAL); } @Override public void initialize() { super.initialize(); if (useRandSeed) r = new Random(); else r = new Random(12345); } /** * Returns the next DoubleData object, which is a dithered version of the input * * @return the next available DoubleData object, or null if no Data is available * @throws edu.cmu.sphinx.frontend.DataProcessingException * if a data processing error occurred */ @Override public Data getData() throws DataProcessingException { Data input = getPredecessor().getData(); // get the spectrum if (input != null && ditherMax != 0) { if (input instanceof DoubleData || input instanceof FloatData) { input = process(input); } } return input; } /** * Process data, adding dither * * @param input a frame * @return processed frame * @throws IllegalArgumentException */ private DoubleData process(Data input) throws IllegalArgumentException { DoubleData output; assert input instanceof DoubleData; double[] inFeatures; DoubleData doubleData = (DoubleData) input; inFeatures = doubleData.getValues(); double[] outFeatures = new double[inFeatures.length]; for (int i = 0; i < inFeatures.length; ++i) { outFeatures[i] = r.nextFloat() * 2 * ditherMax - ditherMax + inFeatures[i]; outFeatures[i] = max(min(outFeatures[i], maxValue), minValue); } output = new DoubleData(outFeatures, doubleData.getSampleRate(), doubleData.getFirstSampleNumber()); return output; } }