/* * Copyright 1999-2002 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; import java.util.Arrays; /** Represents a unit of speech. Units may represent phones, words or any other suitable unit */ public class Unit { public final static Unit[] EMPTY_ARRAY = new Unit[0]; private final String name; private final boolean filler; private final boolean silence; private final int baseID; private final Unit baseUnit; private final Context context; private volatile String key; /** * Constructs a context independent unit. Constructors are package private, use the UnitManager to create and access * units. * * @param name the name of the unit * @param filler <code>true</code> if the unit is a filler unit * @param id the base id for the unit */ Unit(String name, boolean filler, int id) { this.name = name; this.filler = filler; this.silence = name.equals(UnitManager.SILENCE_NAME); this.baseID = id; this.baseUnit = this; this.context = Context.EMPTY_CONTEXT; } /** * Constructs a context dependent unit. Constructors are package private, use the UnitManager to create and access * units. * * @param baseUnit the base id for the unit * @param filler <code>true</code> if the unit is a filler unit * @param context the context for this unit */ Unit(Unit baseUnit, boolean filler, Context context) { this.name = baseUnit.getName(); this.filler = filler; this.silence = name.equals(UnitManager.SILENCE_NAME); this.baseID = baseUnit.getBaseID(); this.baseUnit = baseUnit; this.context = context; } /** * Gets the name for this unit * * @return the name for this unit */ public String getName() { return name; } /** * Determines if this unit is a filler unit * * @return <code>true</code> if the unit is a filler unit */ public boolean isFiller() { return filler; } /** * Determines if this unit is the silence unit * * @return true if the unit is the silence unit */ public boolean isSilence() { return silence; } /** * Gets the base ID for this unit * * @return the id */ public int getBaseID() { return baseID; } /** * Gets the base unit associated with this HMM * * @return the unit associated with this HMM */ public Unit getBaseUnit() { return baseUnit; } /** * Returns the context for this unit * * @return the context for this unit (or null if context independent) */ public Context getContext() { return context; } /** * Determines if this unit is context dependent * * @return true if the unit is context dependent */ public boolean isContextDependent() { return getContext() != Context.EMPTY_CONTEXT; } /** gets the key for this unit * @return the key */ private String getKey() { return toString(); } /** * Checks to see of an object is equal to this unit * * @param o the object to check * @return true if the objects are equal */ @Override public boolean equals(Object o) { if (this == o) { return true; } else if (o instanceof Unit) { Unit otherUnit = (Unit) o; return getKey().equals(otherUnit.getKey()); } else { return false; } } /** * calculates a hashCode for this unit. Since we defined an equals for Unit, we must define a hashCode as well * * @return the hashcode for this object */ @Override public int hashCode() { return getKey().hashCode(); } /** * Converts to a string * * @return string version */ @Override public String toString() { if (key == null) { if (context == Context.EMPTY_CONTEXT) { key = (filler ? "*" : "") + name; } else { key = (filler ? "*" : "") + name + '[' + context + ']'; } } return key; } /** * Checks to see if the given unit with associated contexts is a partial match for this unit. Zero, One or both * contexts can be null. A null context matches any context * * @param name the name of the unit * @param context the context to match against * @return true if this unit matches the name and non-null context */ public boolean isPartialMatch(String name, Context context) { return getName().equals(name) && context.isPartialMatch(this.context); } /** * Creates and returns an empty context with the given size. The context is padded with SIL filler * * @param size the size of the context * @return the context */ public static Unit[] getEmptyContext(int size) { Unit[] context = new Unit[size]; Arrays.fill(context, UnitManager.SILENCE); return context; } /** * Checks to see that there is 100% overlap in the given contexts * * @param a context to check for a match * @param b context to check for a match * @return <code>true</code> if the contexts match */ public static boolean isContextMatch(Unit[] a, Unit[] b) { if (a == null || b == null) { return a == b; } else if (a.length != b.length) { return false; } else { for (int i = 0; i < a.length; i++) { if (!a[i].getName().equals(b[i].getName())) { return false; } } return true; } } }