Reputation: 31
I need the TextToSpeech engine to speak my words one by one, and I am trying to catch the end of speaking of one word to start speaking the next one. But the OnUtteranceCompletedListener
cause some delay of the speech.
So my question is, how can I fix this or make a better implementation of the OnUtteranceCompletedListener
?
public class AndroidTextToSpeechActivity extends Activity implements TextToSpeech.OnInitListener {
int result = 0, CURRENT_WORD = 0;
HashMap<String, String> myHash;
String[] words;
Button btnSpeak;
TextToSpeech tts;
Handler hand = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = "Hi there how are you";
words = text.split(" ", 50);
myHash = new HashMap<String, String>();
tts = new TextToSpeech(this, this);
btnSpeak = (Button) findViewById(R.id.btnSpeak);
btnSpeak.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
hand.postDelayed(run, 300);
}
});
}
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
result = tts.setLanguage(Locale.getDefault());
tts.setPitch(1f);
tts.setSpeechRate(1f);
} else
Log.e("TTS", "Init failed");
}
Runnable run = new Runnable() {
public void run() {
text = words[CURRENT_WORD];
tts.speak(text, 1, myHash);
tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
@Override
public void onUtteranceCompleted(String utteranceId) {
CURRENT_WORD++;
hand.post(run1);
}
});
}
};
}
Upvotes: 3
Views: 1136
Reputation: 863
You can speed it up by not recreating the OnUtteranceCompleteListener in each run
OnUtteranceCompletedListener listener=new OnUtteranceCompletedListener(){
@Override
public void onUtteranceCompleted(String utteranceId) {
CURRENT_WORD++;
hand.post(run1);
}
}
tts.setOnUtteranceCompletedListener(listener);
Runnable run = new Runnable() {
public void run() {
text = words[CURRENT_WORD];
tts.speak(text, 1, myHash);
}
};
Furthamore, instead of using a Runnable to call the speek() method of the engine through a handler, you can use the onUtteranceCompleted method to call the speak() method
OnUtteranceCompletedListener listener=new OnUtteranceCompletedListener(){
@Override
public void onUtteranceCompleted(String utteranceId) {
CURRENT_WORD++;
if(CURRENT_WORD<max_words){
String text=words[CURRENT_WORD];
tts.speak(text,1,myHash);
}
}
}
tts.setOnUtteranceCompletedListener(listener);
Runnable run = new Runnable() {
public void run() {
text = words[CURRENT_WORD];
tts.speak(text, 1, myHash);
}
};
Upvotes: 2
Reputation: 18151
Your code will fail if Locale.getDefault()
language is not supported or need data files. Also, if onInit()
has not returned 300 ms after you pressed the btnSpeak
, speak()
will not function.
You should disable btnSpeak
in the xml layout file and enable it in onInit
. In the btnSpeak listener
loop through words
and call speak()
btnSpeak = (Button) findViewById(R.id.btnSpeak);
btnSpeak.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
for (int i = 0; i < words.length; i++) {
tts.speak(text, 1, myHash);
// call playSilence (long durationInMs, 1, myHash)
// if you want a slight delay between each word.
}
}
});
Upvotes: 0