/* * Copyright 1999-2004 Carnegie Mellon University. * Portions Copyright 2002 Sun Microsystems, Inc. * Portions Copyright 2002 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.linguist.acoustic.trivial; import edu.cmu.sphinx.frontend.Data; import edu.cmu.sphinx.frontend.FloatData; import edu.cmu.sphinx.linguist.acoustic.*; import edu.cmu.sphinx.linguist.acoustic.tiedstate.MixtureComponent; import edu.cmu.sphinx.util.props.PropertyException; import edu.cmu.sphinx.util.props.PropertySheet; import edu.cmu.sphinx.util.props.S4Integer; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; /** Represents the generic interface to the Acoustic Model for sphinx4 */ public class TrivialAcousticModel implements AcousticModel { /** Defines the left context size */ @S4Integer(defaultValue = 1) public final static String LEFT_CONTEXT_SIZE ="leftContextSize"; @S4Integer(defaultValue = 1) public final static String RIGHT_CONTEXT_SIZE = "leftContextSize"; private String name; private final Map<Unit, HMM> hmmMap = new HashMap<Unit, HMM>(); private int leftContextSize; private int rightContextSize; public TrivialAcousticModel(int leftContextSize, int rightContextSize) { init(leftContextSize,rightContextSize); } public TrivialAcousticModel() { } public void newProperties(PropertySheet ps) throws PropertyException { // get acoustic model configuration data from the sphinx // properties init(ps.getInt(LEFT_CONTEXT_SIZE),ps.getInt(RIGHT_CONTEXT_SIZE)); } private void init(int leftContextSize, int rightContextSize) { this.leftContextSize = leftContextSize; this.rightContextSize = rightContextSize; // create HMMs for all of the units String[] unitNames = { "AX_one", "AY_five", "AY_nine", "EH_seven", "EY_eight", "E_seven", "F_five", "F_four", "II_three", "II_zero", "I_six", "K_six", "N_nine", "N_nine_2", "N_one", "N_seven", "OO_two", "OW_four", "OW_oh", "OW_zero", "R_four", "R_three", "R_zero", "S_seven", "S_six", "S_six_2", "TH_three", "T_eight", "T_two", "V_five", "V_seven", "W_one", "Z_zero", "AX_one", "SIL" }; for (String unitName : unitNames) { createTrivialHMM(unitName); } } /** * Returns the name of this AcousticModel, or null if it has no name. * * @return the name of this AcousticModel, or null if it has no name */ public String getName() { return name; } /** * Returns the properties of this acoustic model. * * @return the properties of this acoustic model */ public Properties getProperties() { return new Properties(); } /** * Given a unit, returns the HMM that best matches the given unit. If exactMatch is false and an exact match is not * found, then different word positions are used. If any of the contexts are non-silence filler units. a silence * filler unit is tried instead. * * @param unit the unit of interest * @param position the position of the unit of interest * @param exactMatch if true, only an exact match is acceptable. * @return the HMM that best matches, or null if no match could be found. */ public HMM lookupNearestHMM(Unit unit, HMMPosition position, boolean exactMatch) { HMM hmm = null; if (!exactMatch || position == HMMPosition.UNDEFINED) { unit = unit.getBaseUnit(); hmm = hmmMap.get(unit); } return hmm; } /** * Returns an iterator that can be used to iterate through all the HMMs of the acoustic model * * @return an iterator that can be used to iterate through all HMMs in the model. The iterator returns objects of * type <code>HMM</code>. */ public Iterator<HMM> getHMMIterator() { return hmmMap.values().iterator(); } /** * Returns an iterator that can be used to iterate through all the CI units in the acoustic model * * @return an iterator that can be used to iterate through all CI units. The iterator returns objects of type * <code>Unit</code> */ public Iterator<Unit> getContextIndependentUnitIterator() { return hmmMap.keySet().iterator(); } /** * Returns the size of the left context for context dependent units * * @return the left context size */ public int getLeftContextSize() { return leftContextSize; } /** * Returns the size of the right context for context dependent units * * @return the left context size */ public int getRightContextSize() { return rightContextSize; } /** * Creates a trivial HMM * * @param unitName the name of the unit */ private void createTrivialHMM(String unitName) { // FIXME //Unit unit = Unit.getUnit(unitName); //HMM hmm = new TrivialHMM(unit, HMMPosition.UNDEFINED); //hmmMap.put(unit, hmm); } /* (non-Javadoc) * @see edu.cmu.sphinx.linguist.acoustic.AcousticModel#allocate() */ public void allocate() throws IOException { } /* (non-Javadoc) * @see edu.cmu.sphinx.linguist.acoustic.AcousticModel#deallocate() */ public void deallocate() { } } /** Trivial HMM */ class TrivialHMM implements HMM { private final static int NUM_STATES = 4; final Unit unit; final HMMPosition position; final HMMState[] hmmStates; private final Unit baseUnit; /** * Creates a trivial hmm * * @param unit the unit for the hmm * @param position the position of the hmm */ TrivialHMM(Unit unit, HMMPosition position) { this.unit = unit; this.position = position; hmmStates = new HMMState[NUM_STATES]; // baseUnit = Unit.getUnit(unit.getName()); baseUnit = unit.getBaseUnit(); for (int i = 0; i < hmmStates.length; i++) { boolean finalState = i == hmmStates.length - 1; hmmStates[i] = new TrivialHMMState(this, i, finalState); } } /** * Gets the unit associated with this HMM * * @return the unit associated with this HMM */ public Unit getUnit() { return unit; } /** * Gets the base unit associated with this HMM * * @return the unit associated with this HMM */ public Unit getBaseUnit() { return baseUnit; } /** * Retrieves the hmm state * * @param which the state of interest */ public HMMState getState(int which) { return hmmStates[which]; } /** * Returns the order of the HMM * * @return the order of the HMM */ public int getOrder() { return hmmStates.length; } /** * Retrieves the position of this HMM. * * @return the position for this HMM */ public HMMPosition getPosition() { return position; } /** * Gets the initial states (with probabilities) for this HMM * * @return the set of arcs that transition to the initial states for this HMM */ public HMMState getInitialState() { return hmmStates[0]; } } /** A trivial implementation of an HMMState */ class TrivialHMMState implements HMMState { private static final HMMStateArc[] EMPTY_ARC = new HMMStateArc[0]; private final HMM hmm; private final int which; private final boolean isFinal; TrivialHMMState(HMM hmm, int which, boolean isFinal) { this.hmm = hmm; this.which = which; this.isFinal = isFinal; } /** * Gets the HMM associated with this state * * @return the HMM */ public HMM getHMM() { return hmm; } /** * Gets the state * * @return the state */ public int getState() { return which; } /** * Gets the score for this HMM state * * @param feature the feature to be scored * @return the acoustic score for this state. */ public float getScore(Data feature) { return 0.0f; } public float[] calculateComponentScore(Data feature){ return new float[((FloatData) feature).getValues().length]; } /** * Determines if this HMMState is an emittting state * * @return true if the state is an emitting state */ public boolean isEmitting() { return !isFinal; } /** * Retrieves the state of successor states for this state * * @return the set of successor state arcs */ public HMMStateArc[] getSuccessors() { if (isFinal) { return EMPTY_ARC; } else { HMMStateArc[] arcs = new HMMStateArc[2]; arcs[0] = new HMMStateArc(this, 0f); arcs[1] = new HMMStateArc(hmm.getState(which + 1), 0f); return arcs; } } /** * Determines if this state is an exit state of the HMM * * @return true if the state is an exit state */ public boolean isExitState() { return isFinal; } /** * Returns the mixture components associated with this Gaussian * * @return the array of mixture components */ public MixtureComponent[] getMixtureComponents() { return null; } /** * Gets the ID for this senone * * @return the senone id */ public long getMixtureId() { return 0; } public float[] getLogMixtureWeights() { return null; } }