/* * * 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.instrumentation; import edu.cmu.sphinx.frontend.*; import edu.cmu.sphinx.frontend.endpoint.SpeechEndSignal; import edu.cmu.sphinx.frontend.endpoint.SpeechStartSignal; import edu.cmu.sphinx.recognizer.Recognizer; import edu.cmu.sphinx.recognizer.Recognizer.State; import edu.cmu.sphinx.recognizer.StateListener; import edu.cmu.sphinx.result.Result; import edu.cmu.sphinx.decoder.ResultListener; import edu.cmu.sphinx.util.TimerPool; import edu.cmu.sphinx.util.props.*; import java.text.DecimalFormat; /** Monitors a recognizer for speed */ public class SpeedTracker extends ConfigurableAdapter implements ResultListener, Resetable, StateListener, SignalListener, Monitor { /** The property that defines which recognizer to monitor */ @S4Component(type = Recognizer.class) public final static String PROP_RECOGNIZER = "recognizer"; /** The property that defines which frontend to monitor */ @S4Component(type = FrontEnd.class) public final static String PROP_FRONTEND = "frontend"; /** The property that defines whether summary accuracy information is displayed */ @S4Boolean(defaultValue = true) public final static String PROP_SHOW_SUMMARY = "showSummary"; /** The property that defines whether detailed accuracy information is displayed */ @S4Boolean(defaultValue = true) public final static String PROP_SHOW_DETAILS = "showDetails"; /** The property that defines whether detailed response information is displayed */ @S4Boolean(defaultValue = false) public final static String PROP_SHOW_RESPONSE_TIME = "showResponseTime"; /** The property that defines whether detailed timer information is displayed */ @S4Boolean(defaultValue = false) public final static String PROP_SHOW_TIMERS = "showTimers"; private static final DecimalFormat timeFormat = new DecimalFormat("0.00"); // ------------------------------ // Configuration data // ------------------------------ private String name; private Recognizer recognizer; private FrontEnd frontEnd; private boolean showSummary; private boolean showDetails; private boolean showTimers; private long startTime; private long audioStartTime; private float audioTime; private float processingTime; private float totalAudioTime; private float totalProcessingTime; private boolean showResponseTime; private int numUtteranceStart; private long maxResponseTime = Long.MIN_VALUE; private long minResponseTime = Long.MAX_VALUE; private long totalResponseTime; public SpeedTracker(Recognizer recognizer, FrontEnd frontEnd, boolean showSummary, boolean showDetails, boolean showResponseTime, boolean showTimers) { initLogger(); initRecognizer(recognizer); initFrontEnd(frontEnd); this.showSummary = showSummary; this.showDetails = showDetails; this.showResponseTime = showResponseTime; this.showTimers = showTimers; } public SpeedTracker() { } /* * (non-Javadoc) * * @see edu.cmu.sphinx.util.props.Configurable#newProperties(edu.cmu.sphinx.util.props.PropertySheet) */ public void newProperties(PropertySheet ps) throws PropertyException { super.newProperties(ps); initRecognizer((Recognizer) ps.getComponent(PROP_RECOGNIZER)); initFrontEnd((FrontEnd) ps.getComponent(PROP_FRONTEND)); showSummary = ps.getBoolean(PROP_SHOW_SUMMARY); showDetails = ps.getBoolean(PROP_SHOW_DETAILS); showResponseTime = ps.getBoolean(PROP_SHOW_RESPONSE_TIME); showTimers = ps.getBoolean(PROP_SHOW_TIMERS); } private void initFrontEnd(FrontEnd newFrontEnd) { if (frontEnd == null) { frontEnd = newFrontEnd; frontEnd.addSignalListener(this); } else if (frontEnd != newFrontEnd) { frontEnd.removeSignalListener(this); frontEnd = newFrontEnd; frontEnd.addSignalListener(this); } } private void initRecognizer(Recognizer newRecognizer) { if (recognizer == null) { recognizer = newRecognizer; recognizer.addResultListener(this); recognizer.addStateListener(this); } else if (recognizer != newRecognizer) { recognizer.removeResultListener(this); recognizer.removeStateListener(this); recognizer = newRecognizer; recognizer.addResultListener(this); recognizer.addStateListener(this); } } /* * (non-Javadoc) * * @see edu.cmu.sphinx.util.props.Configurable#getName() */ public String getName() { return name; } /* * (non-Javadoc) * * @see edu.cmu.sphinx.decoder.ResultListener#newResult(edu.cmu.sphinx.result.Result) */ public void newResult(Result result) { if (result.isFinal()) { processingTime = (getTime() - startTime) / 1000.0f; totalAudioTime += audioTime; totalProcessingTime += processingTime; if (showDetails) { showAudioUsage(); } } } /** Shows the audio usage data */ protected void showAudioUsage() { logger.info(" This Time Audio: " + timeFormat.format(audioTime) + "s" + " Proc: " + timeFormat.format(processingTime) + "s" + " Speed: " + timeFormat.format(getSpeed()) + " X real time"); showAudioSummary(); } /** Shows the audio summary data */ protected void showAudioSummary() { logger.info(" Total Time Audio: " + timeFormat.format(totalAudioTime) + "s" + " Proc: " + timeFormat.format(totalProcessingTime) + "s " + timeFormat.format(getCumulativeSpeed()) + " X real time"); if (showResponseTime) { float avgResponseTime = (float) totalResponseTime / (numUtteranceStart * 1000); logger.info (" Response Time: Avg: " + avgResponseTime + 's' + " Max: " + ((float) maxResponseTime / 1000) + "s Min: " + ((float) minResponseTime / 1000) + 's'); } } /** * Returns the speed of the last decoding as a fraction of real time. * * @return the speed of the last decoding */ public float getSpeed() { if (processingTime == 0 || audioTime == 0) { return 0; } else { return (processingTime / audioTime); } } /** Resets the speed statistics */ public void reset() { totalProcessingTime = 0; totalAudioTime = 0; numUtteranceStart = 0; } /** * Returns the cumulative speed of this decoder as a fraction of real time. * * @return the cumulative speed of this decoder */ public float getCumulativeSpeed() { if (totalProcessingTime == 0 || totalAudioTime == 0) { return 0; } else { return (totalProcessingTime / totalAudioTime); } } /* * (non-Javadoc) * * @see edu.cmu.sphinx.frontend.SignalListener#signalOccurred(edu.cmu.sphinx.frontend.Signal) */ public void signalOccurred(Signal signal) { if (signal instanceof SpeechStartSignal || signal instanceof DataStartSignal) { startTime = getTime(); audioStartTime = signal.getTime(); long responseTime = startTime - audioStartTime; totalResponseTime += responseTime; if (responseTime > maxResponseTime) { maxResponseTime = responseTime; } if (responseTime < minResponseTime) { minResponseTime = responseTime; } numUtteranceStart++; } else if (signal instanceof SpeechEndSignal) { audioTime = (signal.getTime() - audioStartTime) / 1000f; } else if (signal instanceof DataEndSignal) { audioTime = ((DataEndSignal) signal).getDuration() / 1000f; } } /** * Returns the current time in milliseconds * * @return the time in milliseconds. */ private long getTime() { return System.currentTimeMillis(); } public void statusChanged(Recognizer.State status) { if (status == State.ALLOCATED) { if (showTimers) { TimerPool.dumpAll(logger); } } if (status == State.DEALLOCATING) { if (showTimers) { TimerPool.dumpAll(logger); } } if (status == State.DEALLOCATED) { if (showSummary) { showAudioSummary(); } } } }