/* * * Copyright 1999-2004 Carnegie Mellon University. * Portions Copyright 2004 Sun Microsystems, Inc. * Portions Copyright 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.recognizer; import edu.cmu.sphinx.decoder.Decoder; import edu.cmu.sphinx.decoder.ResultProducer; import edu.cmu.sphinx.decoder.ResultListener; import edu.cmu.sphinx.instrumentation.Monitor; import edu.cmu.sphinx.instrumentation.Resetable; import edu.cmu.sphinx.result.Result; import edu.cmu.sphinx.util.props.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * The Sphinx-4 recognizer. This is the main entry point for Sphinx-4. Typical usage of a recognizer is like so: * <code> * public void recognizeDigits() { * URL digitsConfig = new URL("file:./digits.xml"); * ConfigurationManager cm = new ConfigurationManager(digitsConfig); * Recognizer sphinxDigitsRecognizer * = (Recognizer) cm.lookup("digitsRecognizer"); * boolean done = false; * Result result; * * sphinxDigitsRecognizer.allocate(); * * // echo spoken digits, quit when 'nine' is spoken * * while (!done) { * result = sphinxDigitsRecognizer.recognize(); * System.out.println("Result: " + result); * done = result.toString().equals("nine"); * } * sphinxDigitsRecognizer.deallocate(); * } * </code> * Note that some Recognizer methods may throw an IllegalStateException if the recognizer is not in the proper state */ public class Recognizer implements Configurable, ResultProducer { /** The property for the decoder to be used by this recognizer. */ @S4Component(type = Decoder.class) public final static String PROP_DECODER = "decoder"; /** The property for the set of monitors for this recognizer */ @S4ComponentList(type = Monitor.class) public final static String PROP_MONITORS = "monitors"; /** Defines the possible states of the recognizer. */ public static enum State { DEALLOCATED, ALLOCATING, ALLOCATED, READY, RECOGNIZING, DEALLOCATING, ERROR } private String name; private Decoder decoder; private State currentState = State.DEALLOCATED; private final List<StateListener> stateListeners = Collections.synchronizedList(new ArrayList<StateListener>()); private List<Monitor> monitors; public Recognizer(Decoder decoder, List<Monitor> monitors) { this.decoder = decoder; this.monitors = monitors; name = null; } public Recognizer() { } /* (non-Javadoc) * @see edu.cmu.sphinx.util.props.Configurable#newProperties(edu.cmu.sphinx.util.props.PropertySheet) */ public void newProperties(PropertySheet ps) throws PropertyException { decoder = (Decoder) ps.getComponent(PROP_DECODER); monitors = ps.getComponentList(PROP_MONITORS, Monitor.class); name = ps.getInstanceName(); } /** * Performs recognition for the given number of input frames, or until a 'final' result is generated. This method * should only be called when the recognizer is in the <code>allocated</code> state. * * @param referenceText what was actually spoken * @return a recognition result * @throws IllegalStateException if the recognizer is not in the <code>ALLOCATED</code> state */ public Result recognize(String referenceText) throws IllegalStateException { Result result = null; checkState(State.READY); try { setState(State.RECOGNIZING); result = decoder.decode(referenceText); } finally { setState(State.READY); } return result; } /** * Performs recognition for the given number of input frames, or until a 'final' result is generated. This method * should only be called when the recognizer is in the <code>allocated</code> state. * * @return a recognition result * @throws IllegalStateException if the recognizer is not in the <code>ALLOCATED</code> state */ public Result recognize() throws IllegalStateException { return recognize(null); } /** * Checks to ensure that the recognizer is in the given state. * * @param desiredState the state that the recognizer should be in * @throws IllegalStateException if the recognizer is not in the desired state. */ private void checkState(State desiredState) { if (currentState != desiredState) { throw new IllegalStateException("Expected state " + desiredState + " actual state " + currentState); } } /** * sets the current state * * @param newState the new state */ private void setState(State newState) { currentState = newState; synchronized (stateListeners) { for (StateListener sl : stateListeners) { sl.statusChanged(currentState); } } } /** * Allocate the resources needed for the recognizer. Note this method make take some time to complete. This method * should only be called when the recognizer is in the <code> deallocated </code> state. * * @throws IllegalStateException if the recognizer is not in the <code>DEALLOCATED</code> state */ public void allocate() throws IllegalStateException { checkState(State.DEALLOCATED); setState(State.ALLOCATING); decoder.allocate(); setState(State.ALLOCATED); setState(State.READY); } /** * Deallocates the recognizer. This method should only be called if the recognizer is in the <code> allocated * </code> state. * * @throws IllegalStateException if the recognizer is not in the <code>ALLOCATED</code> state */ public void deallocate() throws IllegalStateException { checkState(State.READY); setState(State.DEALLOCATING); decoder.deallocate(); setState(State.DEALLOCATED); } /** * Retrieves the recognizer state. This method can be called in any state. * * @return the recognizer state */ public State getState() { return currentState; } /** Resets the monitors monitoring this recognizer */ public void resetMonitors() { for (Monitor listener : monitors) { if (listener instanceof Resetable) ((Resetable)listener).reset(); } } /** * Adds a result listener to this recognizer. A result listener is called whenever a new result is generated by the * recognizer. This method can be called in any state. * * @param resultListener the listener to add */ public void addResultListener(ResultListener resultListener) { decoder.addResultListener(resultListener); } /** * Adds a status listener to this recognizer. The status listener is called whenever the status of the recognizer * changes. This method can be called in any state. * * @param stateListener the listener to add */ public void addStateListener(StateListener stateListener) { stateListeners.add(stateListener); } /** * Removes a previously added result listener. This method can be called in any state. * * @param resultListener the listener to remove */ public void removeResultListener(ResultListener resultListener) { decoder.removeResultListener(resultListener); } /** * Removes a previously added state listener. This method can be called in any state. * * @param stateListener the state listener to remove */ public void removeStateListener(StateListener stateListener) { stateListeners.remove(stateListener); } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "Recognizer: " + name + " State: " + currentState; } }