1

Im making an android application that has text to speech and I want to be able to customize its speech rate. I already have a code for it but i dont know how to apply the speech rate to the whole application.

Here's the settings that I've created for the application. THANKS IN ADVANCE! :D

public float getSpeechRate(){
    int checkedRadioButton = this.radioRate.getCheckedRadioButtonId();
    if (checkedRadioButton == R.id.rate_slow){
         return 0.5f;
    } else if (checkedRadioButton == R.id.rate_normal){
         return 1.0f;
    } else if(checkedRadioButton == R.id.rate_fast){
        return 1.5f;
    }
    return 0;
}

public void setSpeechRate(){
    float speechRate = this.getSpeechRate();
    if(speechRate == 0.5f){
        speakOut("This is a slow speech rate");
    } else if(speechRate == 1.0f){
        speakOut("This is a normal speech rate");
    } else {
        speakOut("This is a fast speech rate");
    }

This is how I invoke the text to speech

toSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int status) {
            Log.e("TTS", "TextToSpeech.OnInit...");
        }
    });
rann02
  • 11
  • 4

1 Answers1

2

Do:

  • Create a "Settings" page for the user to select the rate.
  • Store the selected value in the SharedPreferences as suggested by @brandall
  • Then in any Activity you want to use TTS, do:

    TextToSpeech tts = TextToSpeechHelper.getTextToSpeech(CurrentActivity.this, customListener);

EDIT 2

TextToSpeechHelper

 public class TextToSpeechHelper {

    private TextToSpeechHelper() {
        // Prevent the class instantiation
    }

    public static TextToSpeech getTextToSpeech(Context context, @NonNull CustomInitListener listener) {

        final TextToSpeech tts = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                Log.e("TTS", "TextToSpeech.OnInit...");

                if (status == TextToSpeech.SUCCESS) {
                    float rate = getSpeechRate(context);   
                    tts.setSpeechRate(rate);
                    listener.onSuccess();
                } else {
                    listener.onError();
                }
            }
        });


        return tts;
    }

    private static float getSpeechRate(Context context) {
        // Get the value stored in the shared preferences
        // ...
        return storedValue;
    }

    /**
     * Add a custom listener to perform actions when the TextToSpeech is initialized
     */
    public interface CustomInitListener {
        void onSuccess();

        void onError();
    }
}
Eselfar
  • 3,759
  • 3
  • 23
  • 43
  • You can pass the listener to `getTextToSpeech` if the action performed is different for each Activity – Eselfar Jan 30 '18 at 13:28
  • This won't work, as the TTS object will not be initialised until `onInit` has returned. You cannot apply languages or other parameters such as the speech rate to the engine until that time. Also, if the method is static, it should be returning a static TTS instance. – brandall Jan 30 '18 at 15:08
  • @brandall You're right on the first part, but why should the instance be static? – Eselfar Jan 30 '18 at 15:23
  • If you are using a static helper class across your application, then the TTS instance should also be static - otherwise it will create and return a new instance each time. If it does this, then what is the point of exposing a static helper? Each call to `getTextToSpeech()` should return the single static globally managed TTS object. Only if it is null, should a new one be created. – brandall Jan 30 '18 at 15:31
  • Not necessarily, you can instantiate a new TTS each time you need one. Both implementations are valid. You just need to not forget to call `shutdown()` on the TTS you don't need anymore. I'm not a huge fan of Singletons (as this is what you apparently suggest) – Eselfar Jan 30 '18 at 15:33
  • I had assumed by your helper class and static access method, you were intending to create a singleton? Otherwise why? Anyway, that's another subject. The call to `onInit` is Asynchronous and therefore `return tts` won't immediately return a useable TTS instance. If you call `tts.speak` from the returned instance, it will fail, unless `onInit` has completed. – brandall Jan 30 '18 at 15:40
  • No I didn't. The Helper instantiate the object, set the default values and returns it. As it doesn't keep anything you can use a static class. Maybe I should have named it differently. But back to the initial issue, yes you're right. So one option is for the Activity to instantiate the listener (but the Helper is useless in that case) or to implement your own callback – Eselfar Jan 30 '18 at 15:59