package net.bible.service.device.speak; import net.bible.service.common.CommonUtils; import android.util.Log; /** * The speed and progress of TTS Speech * * @author Martin Denham [mjdenham at gmail dot com] * @see gnu.lgpl.License for license details.<br> * The copyright to this program is held by it's author. */ public class SpeakTiming { private String lastUtteranceId; private int lastSpeakTextLength; private long lastSpeakStartTime; private float cpms = DEFAULT_CPMS; private static final float DEFAULT_CPMS = 0.016f; private static final String SPEAK_CPMS_KEY = "SpeakCPMS"; private static final int SHORT_TEXT_LIMIT_MSEC = 20000; private static final String TAG = "Speak"; public SpeakTiming() { loadCpms(); Log.d(TAG, "Average Speak CPMS:"+cpms); } public void started(String utteranceId, int speakTextLength) { Log.d(TAG, "Speak timer started"); lastUtteranceId = utteranceId; lastSpeakTextLength = speakTextLength; lastSpeakStartTime = System.currentTimeMillis(); } /** a block of text is finished being read so update char/msec if necessary */ public void finished(String utteranceId) { Log.d(TAG, "Speak timer stopped"); if (utteranceId.equals(lastUtteranceId)) { long timeTaken = milliSecsSinceStart(); // ignore short text strings as they can be way off in cps e.g. passage header (e.g. Job 39 v7) has lots of 1 char numbers that take a long time to say if (timeTaken>SHORT_TEXT_LIMIT_MSEC) { // calculate characters per millisecond float latestCpms = ((float)lastSpeakTextLength)/milliSecsSinceStart(); updateAverageCpms(latestCpms); Log.d(TAG, "CPmS:"+cpms+" CPS:"+cpms*1000.0); } lastUtteranceId = null; lastSpeakStartTime = 0; lastSpeakTextLength = 0; } } /** estimate how much of the last string sent to TTS has been spoken */ public float getFractionCompleted() { float fractionCompleted = 1; if (cpms >0 && lastSpeakTextLength>0) { fractionCompleted = (float)milliSecsSinceStart()/((float)lastSpeakTextLength/cpms); Log.d(TAG, "Fraction completed:"+fractionCompleted); } else { Log.e(TAG, "SpeakTiming- Cpms:"+cpms+" lastSpeakTextLength:"+lastSpeakTextLength); } return fractionCompleted; } /** estimate how much of the last string sent to TTS has been spoken */ public long getCharsInSecs(int secs) { return (long)(cpms*(1000.0*secs)); } /** estimate how long it will take to speak so many chars */ public long getSecsForChars(long chars) { return Math.round(((1.0*chars)/cpms)/1000.0); } private long milliSecsSinceStart(){ long duration = System.currentTimeMillis() - lastSpeakStartTime; Log.d(TAG, "Duration:"+duration); return duration; } private void updateAverageCpms(float lastCpms) { // take the average of historical figures and the new figure to attempt to lessen the affect of weird text but aadjust for different types of text cpms = (cpms+lastCpms)/2.0f; saveCpms(); } private void loadCpms() { cpms = CommonUtils.getSharedPreferences().getFloat(SPEAK_CPMS_KEY, DEFAULT_CPMS); } private void saveCpms() { CommonUtils.getSharedPreferences().edit().putFloat(SPEAK_CPMS_KEY, cpms).commit(); } }