package edu.cmu.sphinx.linguist.allphone;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import edu.cmu.sphinx.linguist.Linguist;
import edu.cmu.sphinx.linguist.SearchGraph;
import edu.cmu.sphinx.linguist.acoustic.AcousticModel;
import edu.cmu.sphinx.linguist.acoustic.HMM;
import edu.cmu.sphinx.linguist.acoustic.LeftRightContext;
import edu.cmu.sphinx.linguist.acoustic.Unit;
import edu.cmu.sphinx.linguist.acoustic.UnitManager;
import edu.cmu.sphinx.linguist.acoustic.tiedstate.SenoneHMM;
import edu.cmu.sphinx.linguist.acoustic.tiedstate.SenoneSequence;
import edu.cmu.sphinx.util.LogMath;
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.S4Component;
import edu.cmu.sphinx.util.props.S4Double;
public class AllphoneLinguist implements Linguist {
/** The property that defines the acoustic model to use when building the search graph */
@S4Component(type = AcousticModel.class)
public final static String PROP_ACOUSTIC_MODEL = "acousticModel";
/**
* The property that controls phone insertion probability.
* Default value for context independent phoneme decoding is 0.05,
* while for context dependent - 0.01.
*/
@S4Double(defaultValue = 0.05)
public final static String PROP_PIP = "phoneInsertionProbability";
/**
* The property that controls whether to use context dependent phones.
* Changing it for true, don't forget to tune phone insertion probability.
*/
@S4Boolean(defaultValue = false)
public final static String PROP_CD = "useContextDependentPhones";
private AcousticModel acousticModel;
private ArrayList<HMM> ciHMMs;
private ArrayList<HMM> fillerHMMs;
private ArrayList<HMM> leftContextSilHMMs;
private HashMap<SenoneSequence, ArrayList<Unit>> senonesToUnits;
private HashMap<Unit, HashMap<Unit, ArrayList<HMM>>> cdHMMs;
private float pip;
private boolean useCD;
public AllphoneLinguist() {
}
public void newProperties(PropertySheet ps) throws PropertyException {
acousticModel = (AcousticModel) ps.getComponent(PROP_ACOUSTIC_MODEL);
pip = LogMath.getLogMath().linearToLog(ps.getFloat(PROP_PIP));
useCD = ps.getBoolean(PROP_CD);
if (useCD)
createContextDependentSuccessors();
else
createContextIndependentSuccessors();
}
public SearchGraph getSearchGraph() {
return new AllphoneSearchGraph(this);
}
public void startRecognition() {
}
public void stopRecognition() {
}
public void allocate() throws IOException {
}
public void deallocate() throws IOException {
}
public AcousticModel getAcousticModel() {
return acousticModel;
}
public float getPhoneInsertionProb() {
return pip;
}
public boolean useContextDependentPhones() {
return useCD;
}
public ArrayList<HMM> getCISuccessors() {
return ciHMMs;
}
public ArrayList<HMM> getCDSuccessors(Unit lc, Unit base) {
if (lc.isFiller())
return leftContextSilHMMs;
if (base == UnitManager.SILENCE)
return fillerHMMs;
return cdHMMs.get(lc).get(base);
}
public ArrayList<Unit> getUnits(SenoneSequence senoneSeq) {
return senonesToUnits.get(senoneSeq);
}
private void createContextIndependentSuccessors() {
Iterator<HMM> hmmIter = acousticModel.getHMMIterator();
ciHMMs = new ArrayList<HMM>();
senonesToUnits = new HashMap<SenoneSequence, ArrayList<Unit>>();
while (hmmIter.hasNext()) {
HMM hmm = hmmIter.next();
if (!hmm.getUnit().isContextDependent()) {
ArrayList<Unit> sameSenonesUnits;
SenoneSequence senoneSeq = ((SenoneHMM)hmm).getSenoneSequence();
if ((sameSenonesUnits = senonesToUnits.get(senoneSeq)) == null) {
sameSenonesUnits = new ArrayList<Unit>();
senonesToUnits.put(senoneSeq, sameSenonesUnits);
}
sameSenonesUnits.add(hmm.getUnit());
ciHMMs.add(hmm);
}
}
}
private void createContextDependentSuccessors() {
cdHMMs = new HashMap<Unit, HashMap<Unit, ArrayList<HMM>>>();
senonesToUnits = new HashMap<SenoneSequence, ArrayList<Unit>>();
fillerHMMs = new ArrayList<HMM>();
leftContextSilHMMs = new ArrayList<HMM>();
Iterator<HMM> hmmIter = acousticModel.getHMMIterator();
while (hmmIter.hasNext()) {
HMM hmm = hmmIter.next();
ArrayList<Unit> sameSenonesUnits;
SenoneSequence senoneSeq = ((SenoneHMM)hmm).getSenoneSequence();
if ((sameSenonesUnits = senonesToUnits.get(senoneSeq)) == null) {
sameSenonesUnits = new ArrayList<Unit>();
senonesToUnits.put(senoneSeq, sameSenonesUnits);
}
sameSenonesUnits.add(hmm.getUnit());
if (hmm.getUnit().isFiller()) {
fillerHMMs.add(hmm);
continue;
}
if (hmm.getUnit().isContextDependent()) {
LeftRightContext context = (LeftRightContext)hmm.getUnit().getContext();
Unit lc = context.getLeftContext()[0];
if (lc == UnitManager.SILENCE) {
leftContextSilHMMs.add(hmm);
continue;
}
Unit base = hmm.getUnit().getBaseUnit();
HashMap<Unit, ArrayList<HMM>> lcSuccessors;
if ((lcSuccessors = cdHMMs.get(lc)) == null) {
lcSuccessors = new HashMap<Unit, ArrayList<HMM>>();
cdHMMs.put(lc, lcSuccessors);
}
ArrayList<HMM> lcBaseSuccessors;
if ((lcBaseSuccessors = lcSuccessors.get(base)) == null) {
lcBaseSuccessors = new ArrayList<HMM>();
lcSuccessors.put(base, lcBaseSuccessors);
}
lcBaseSuccessors.add(hmm);
}
}
leftContextSilHMMs.addAll(fillerHMMs);
}
}