Android Dev
Android Dev

Reputation: 5

Text To Speech breaks

I am using this code for speaking

   Sample 1:

    speech.speak("Hello ABCD WELCOME ABCD", TextToSpeech.QUEUE_FLUSH,
                                        null);

There is no problem with this code if it is in sequence as shown in sample 1. If I will break this in two strings as shown in sample2, it is breaking the speaking as it says only hell or hello then says Welcome abcd.

    Sample 2:

    speech.speak("Hello ABCD", TextToSpeech.QUEUE_FLUSH,
                                        null);
    speech.speak("Welcome ABCD", TextToSpeech.QUEUE_FLUSH,
                                        null);

I want if speech.isSpeaking(), then it should wait for completing HELLO ABCD and after completion it should speak WELCOME ABCD.

Alternative way to use strings in hashmap or arraylist. There is any other solution?

Upvotes: 0

Views: 1716

Answers (2)

AL.
AL.

Reputation: 37808

I haven't tried TextToSpeech before, but seeing as the code you did is run after one another, the second speech.speak() value would overrun the first one as the queue code you set is TextToSpeech.QUEUE_FLUSH. As per it's documentation:

Queue mode where all entries in the playback queue (media to be played and text to be synthesized) are dropped and replaced by the new entry.

So, what I think would be suitable for you to use is TextToSpeech.QUEUE_ADD:

Queue mode where the new entry is added at the end of the playback queue.

Upvotes: 0

Markus Kauppinen
Markus Kauppinen

Reputation: 3235

There are several options. Some have their own caveats.

First of all, instead of TextToSpeech.QUEUE_FLUSH you can use TextToSpeech.QUEUE_ADD.

speech.speak("Hello ABCD", TextToSpeech.QUEUE_ADD, null);

speech.speak("Welcome ABCD", TextToSpeech.QUEUE_ADD, null);

This will add any new text to the queue but will completely speak out what was already there before starting to speak any new text. This is fine if you don't add new text to the queue too often. Otherwise the queue may get too full and the TTS engine doesn't talk fast enough to keep up.

You could use speech.isSpeaking() but how to use it in a smart way? Waiting in a loop wouldn't be very good programming:

speech.speak("Hello ABCD", TextToSpeech.QUEUE_FLUSH, null);

while (speech.isSpeaking()) {
    // Freezes the application. 
}

speech.speak("Welcome ABCD", TextToSpeech.QUEUE_FLUSH, null);

That would be somewhat okay in a background thread but probably it's better to just forget the idea completely.

It's also possible to use an UtteranceProgressListener to be informed whenever an "utterance" is completed -- basically when the text given in the speak() method call has been spoken out. This could be a smart way to start speaking new text only after the previous text has been completely spoken out.

The listener can be added for example as an anonymous inner class:

speech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {
            // Speaking started. 

        }

        @Override
        public void onDone(String utteranceId) {
            // Speaking stopped.

        }

        @Override
        public void onError(String utteranceId) {
            // There was an error.
        }
    });

The listener isn't very useful unless an utteranceId is given with the speak() method call. Otherwise you wouldn't know exactly which text was spoken out and what should be spoken out next. Of course you could track that with some member variable of your own, but there's a already built in mechanism for you:

speech.speak("Hello ABCD", TextToSpeech.QUEUE_ADD, "hello");

Now this speak() operation is identified as "hello". We can use this to speak "Welcome ABCD" only after "Hello ABCD" is spoken out:

speech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {
            // Speaking started. 

        }

        @Override
        public void onDone(String utteranceId) {
            // Speaking stopped.

            if (utteranceId.equals("hello")) {
                speech.speak("Welcome ABCD", TextToSpeech.QUEUE_ADD, "welcome");        
            }

        }

        @Override
        public void onError(String utteranceId) {
            // There was an error.
        }
    });

The listener should of course be set before speaking anything out.

That's the basic idea and whether you should use an UtteranceProgressListener or not depends on what kind of an application you are developing. It does get a bit complicated if there's a lot of "utterances" to speak out and monitor. You could study this approach if you notice problems with the TTS queue filling up.

Of course this can be made in a smarter way if your texts are for example in an ArrayList and you use the text's index as the utterance id and in the listener pick the next text to be spoken out based on the index.

Upvotes: 2

Related Questions