Package org.vocvark.AudioFeatures

Source Code of org.vocvark.AudioFeatures.LPC

/**
*
*/
package org.vocvark.AudioFeatures;

import org.vocvark.DataTypes.FeatureDefinition;

/**
* Calculates linear predictive coeffecients of an signal. Also includes a
* warping factor lambda that is disabled by default. Based upon code published
* at www.musicdsp.org.
* <p/>
* 2005. <i>Music-dsp source code archive</i> [online]. [cited 17 May 2005].
* Available from the World Wide Web:
* (http://musicdsp.org/archive.php?classid=2#137)
*
* @author Daniel McEnnis
*/
public class LPC extends FeatureExtractorBaseImpl {

    double lambda = 0.0;

    int numDimensions = 10;

    /**
     * Basic constructor for LPC that sets definition, dependencies, and offsets
     * field.
     */
    public LPC() {
        String name = "LPC";
        String description = "Linear Prediction Coeffecients calculated using autocorrelation and Levinson-Durbin recursion.";
        String[] attributes = new String[]{"lambda for frequency warping",
                "number of coeffecients to calculate"};
        definition = new FeatureDefinition(name, description, true, 10,
                attributes);
        dependencies = null;
        offsets = null;
    }

    /**
     * Code taken from www.musicdsp.org.
     * <p/>
     * mail.mutagene.net.2005. <i>Music dsp source archive</i> [online] [cited
     * May 10, 2005] Available on world wide web
     * (http://musicdsp.org/archive.php?classid=2#137)
     *
     * @param samples              The samples to extract the feature from.
     * @param sampling_rate        The sampling rate that the samples are encoded with.
     * @param other_feature_values The values of other features that are needed to calculate this
     *                             value. The order and offsets of these features must be the
     *                             same as those returned by this class's getDependencies and
     *                             getDependencyOffsets methods respectively. The first indice
     *                             indicates the feature/window and the second indicates the
     *                             value.
     * @return The extracted feature value(s).
     * @throws Exception Throws an informative exception if the feature cannot be
     *                   calculated.
     * @see FeatureExtractorBaseImpl#extractFeature(double[],
     *      double, double[][])
     */
    public double[] extractFeature(double[] samples, double sampling_rate,
                                   double[][] other_feature_values) throws Exception {
        // find the order-P autocorrelation array, R, for the sequence x of
        // length L and warping of lambda
        // wAutocorrelate(&pfSrc[stIndex],siglen,R,P,0);

        double[] R = new double[numDimensions + 1];
        double K[] = new double[numDimensions];
        double A[] = new double[numDimensions];
        double[] dl = new double[samples.length];
        double[] Rt = new double[samples.length];
        double r1, r2, r1t;
        R[0] = 0;
        Rt[0] = 0;
        r1 = 0;
        r2 = 0;
        r1t = 0;
        for (int k = 0; k < samples.length; k++) {
            Rt[0] += samples[k] * samples[k];

            dl[k] = r1 - lambda * (samples[k] - r2);
            r1 = samples[k];
            r2 = dl[k];
        }
        for (int i = 1; i < R.length; i++) {
            Rt[i] = 0;
            r1 = 0;
            r2 = 0;
            for (int k = 0; k < samples.length; k++) {
                Rt[i] += dl[k] * samples[k];

                r1t = dl[k];
                dl[k] = r1 - lambda * (r1t - r2);
                r1 = r1t;
                r2 = dl[k];
            }
        }
        for (int i = 0; i < R.length; i++)
            R[i] = Rt[i];

        // LevinsonRecursion(unsigned int P, float *R, float *A, float *K)
        double Am1[] = new double[62];
        ;

        if (R[0] == 0.0) {
            for (int i = 1; i < numDimensions; i++) {
                K[i] = 0.0;
                A[i] = 0.0;
            }
        } else {
            double km, Em1, Em;
            int k, s, m;
            for (k = 0; k < numDimensions; k++) {
                A[0] = 0;
                Am1[0] = 0;
            }
            A[0] = 1;
            Am1[0] = 1;
            km = 0;
            Em1 = R[0];
            for (m = 1; m < numDimensions; m++) // m=2:N+1
            {
                double err = 0.0f; // err = 0;
                for (k = 1; k <= m - 1; k++)
                    // for k=2:m-1
                    err += Am1[k] * R[m - k]; // err = err + am1(k)*R(m-k+1);
                km = (R[m] - err) / Em1; // km=(R(m)-err)/Em1;
                K[m - 1] = -km;
                A[m] = km; // am(m)=km;
                for (k = 1; k <= m - 1; k++)
                    // for k=2:m-1
                    A[k] = Am1[k] - km * Am1[m - k]; // am(k)=am1(k)-km*am1(m-k+1);
                Em = (1 - km * km) * Em1; // Em=(1-km*km)*Em1;
                for (s = 0; s < numDimensions; s++)
                    // for s=1:N+1
                    Am1[s] = A[s]; // am1(s) = am(s)
                Em1 = Em; // Em1 = Em;
            }
        }
        return K;
    }

    /**
     * Provide a complete copy of this feature. Used to implement the prottype
     * pattern
     */
    public Object clone() {
        LPC ret = new LPC();
        ret.lambda = this.lambda;
        try {
            ret.setNumDimensions(numDimensions);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }

    /**
     * Function permitting an unintelligent outside function (ie. EditFeatures
     * frame) to get the default values used to populate the table's entries.
     * The correct index values are inferred from definition.attribute value.
     *
     * @param index which of AreaMoment's attributes should be edited.
     */
    public String getElement(int index) throws Exception {
        switch (index) {
            case 0:
                return Double.toString(lambda);
            case 1:
                return Integer.toString(numDimensions);
            default:
                throw new Exception("INTERNAL ERROR: invalid index " + index
                        + " passed to LPC:getElement()");
        }
    }

    /**
     * Function permitting an unintelligent outside function (ie. EditFeatures
     * frame) to set the default values used to popylate the table's entries.
     * Like getElement, the correct index values are inferred from the
     * definition.attributes value.
     *
     * @param index attribute to be set
     * @param value new value of the attribute
     */
    public void setElement(int index, String value) throws Exception {
        switch (index) {
            case 0:
                try {
                    setLambda(Double.parseDouble(value));
                } catch (NumberFormatException e) {
                    throw new Exception("Lambda value must be a double");
                }
                break;
            case 1:
                try {
                    setNumDimensions(Integer.parseInt(value));
                } catch (NumberFormatException e) {
                    throw new Exception("Number of Dimensions must be an integer");
                }
                break;
            default:
                throw new Exception(
                        "INTERNAL ERROR: invalid index passed to LPC:setElement");
        }
    }

    /**
     * Edits the number of LPC coeffecients to be calculated. This is a unique
     * feature in that the number of dimensions of the feature are changed by
     * this function, requiring a reference back to the parent to redraw the
     * table displaying this information.
     *
     * @param n number of coeffecients to be calculated.
     * @throws Exception thrown if less than 1 feature is to be calculated.
     */
    public void setNumDimensions(int n) throws Exception {
        if (n < 1) {
            throw new Exception("Must have at least 1 LPC coeffecient - " + n
                    + " provided");
        } else {
            numDimensions = n;
            String name = definition.name;
            String description = definition.description;
            String[] attributes = definition.attributes;
            definition = new FeatureDefinition(name, description, true, numDimensions, attributes);

        }
    }

    /**
     * Provides a mechanism for editing the 'frequency warping' factor in the
     * LPC code from musicdsp.
     *
     * @param l new lmbda value
     * @throws Exception throws if the lambda value is not a real number.
     */
    public void setLambda(double l) throws Exception {
        if (Double.isNaN(l) || Double.isInfinite(l)) {
            throw new Exception("lambda must be a real number");
        } else {
            lambda = l;
        }
    }

}
TOP

Related Classes of org.vocvark.AudioFeatures.LPC

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.