Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make TextToSpeech to speak a text with max volume and restore original volume after speak end?

Tags:

android

I save the current volume both STREAM_RING and STREAM_MUSIC before sTts.get().speak(s, TextToSpeech.QUEUE_ADD, null), I hope the TextToSpeech can speak a text with max volume, but in fact I find the TextToSpeech speak the text with current volume, it seems that sTts.get().speak is asynchronous.

How can I make TextToSpeech to speak a text with max volume and restore original volume after speak end? Thanks!

public class SpeechTxt {
private static SoftReference<TextToSpeech> sTts;

public static void SpeakOut(final Context context, final String s) {
    final Context appContext = context.getApplicationContext();
    if (sTts == null) {
        sTts = new SoftReference<TextToSpeech>(new TextToSpeech(appContext,
                new TextToSpeech.OnInitListener() {
                    @Override
                    public void onInit(int status) {
                        if (status == TextToSpeech.SUCCESS) {
                            speak(appContext, s);
                        } else {                                
                        }
                    }
                }));
    } else {
        speak(appContext, s);
    }
}

private static void speak(Context context, String s) {
    if (sTts != null) {
        switch (sTts.get().setLanguage(Locale.getDefault())) {
        case TextToSpeech.LANG_COUNTRY_AVAILABLE:
        case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
        case TextToSpeech.LANG_AVAILABLE: {

            sTts.get().setPitch((float) 0.6);
            sTts.get().setSpeechRate((float) 0.8);

            int currentRing=PublicParFun.GetCurrentVol(context, AudioManager.STREAM_RING);
            int currentPlay=PublicParFun.GetCurrentVol(context, AudioManager.STREAM_MUSIC);

            PublicParFun.SetRingVol(context, 0);
            PublicParFun.SetPlayVol(context,1000000);

                    sTts.get().speak(s, TextToSpeech.QUEUE_ADD, null);

            PublicParFun.SetRingVol(context, currentRing);
            PublicParFun.SetPlayVol(context,currentPlay);

            break;
        }
        case TextToSpeech.LANG_MISSING_DATA: {

            break;
        }
        case TextToSpeech.LANG_NOT_SUPPORTED: // not much to do here
        }
    }
}


public static int GetCurrentVol(Context myContext,int streamType){
    AudioManager mAudioManager = (AudioManager)myContext.getSystemService(Context.AUDIO_SERVICE);
    int current = mAudioManager.getStreamVolume( streamType);   
    return current;
}   

public static void SetRingVol(Context myContext,int vol){       
    SetVol(myContext,AudioManager.STREAM_RING, vol);
}


public static void SetPlayVol(Context myContext,int vol){
    SetVol(myContext,AudioManager.STREAM_MUSIC, vol);
}

private static void SetVol(Context myContext,int streamType,int vol){
    AudioManager mAudioManager = (AudioManager)myContext.getSystemService(Context.AUDIO_SERVICE);
    int max = mAudioManager.getStreamMaxVolume(streamType);
    if (vol>max){
        vol=max;
    }
    mAudioManager.setStreamVolume(streamType,vol, 0);
}

}

Edit

  1. Is the following code right? I fixed my original code by your thinking.

  2. I can't understand why the code need to add HashMap, I think sTts.get().setOnUtteranceProgressListener and sTts.get().setOnUtteranceCompletedListener don't need HashMap, right?

    HashMap ttsParameters = new HashMap(); ttsParameters.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");

package bll;
public class SpeechTxt { private static SoftReference sTts;

public static void SpeakOut(final Context context, final String s) {
    final Context appContext = context.getApplicationContext();
    if (sTts == null) {
        sTts = new SoftReference<TextToSpeech>(new TextToSpeech(appContext,
                new TextToSpeech.OnInitListener() {
                    @Override
                    public void onInit(int status) {
                        if (status == TextToSpeech.SUCCESS) {
                            speak(appContext, s);
                        } else {                                
                        }
                    }
                }));
    } else {
        speak(appContext, s);
    }
}

 private static void speak(Context context, String s) {
        if (sTts != null) {
            switch (sTts.get().setLanguage(Locale.getDefault())) {
            case TextToSpeech.LANG_COUNTRY_AVAILABLE:
            case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
            case TextToSpeech.LANG_AVAILABLE: {

                sTts.get().setPitch((float) 0.6);
                sTts.get().setSpeechRate((float) 0.8);

                final int currentRing=PublicParFun.GetCurrentVol(context, AudioManager.STREAM_RING);
                final int currentPlay=PublicParFun.GetCurrentVol(context, AudioManager.STREAM_MUSIC);

                PublicParFun.SetRingVol(context, 0);
                PublicParFun.SetPlayVol(context,1000000);

                final Context myContext=context;

                HashMap<String, String> ttsParameters = new HashMap<String, String>();
                ttsParameters.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");

                if (android.os.Build.VERSION.SDK_INT >=15){
                    sTts.get().setOnUtteranceProgressListener(new UtteranceProgressListener()
                    {
                        @Override
                        public void onDone(String utteranceId)
                        {
                            PublicParFun.SetRingVol(myContext, currentRing);
                             PublicParFun.SetPlayVol(myContext,currentPlay);
                        }

                        @Override
                        public void onError(String utteranceId)
                        {
                            //also, set the volume back
                        }

                        @Override
                        public void onStart(String utteranceId)
                        {
                           // set the volume to max
                        }
                    });

                }else{                  
                  sTts.get().setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
                      @Override
                      public void onUtteranceCompleted(String utteranceId) {
                         PublicParFun.SetRingVol(myContext, currentRing);
                         PublicParFun.SetPlayVol(myContext,currentPlay);
                    }
                   });
                }
                sTts.get().speak(s, TextToSpeech.QUEUE_ADD, ttsParameters);
                break;
            }
            case TextToSpeech.LANG_MISSING_DATA: {
                break;
            }
            case TextToSpeech.LANG_NOT_SUPPORTED: // not much to do here
            }
        }
    }

}

Edit Again

I test many times, when sTts.get().speak(s, TextToSpeech.QUEUE_ADD, ttsParameters) speak a short string, the sTts.get().setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() is invoked correctly.

but if sTts.get().speak(s, TextToSpeech.QUEUE_ADD, ttsParameters) speak a long string (about 15 seconds), it seems that sTts.get().setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() is not be invoked. Why?

        sTts.get().setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {
              @Override
              public void onUtteranceCompleted(String utteranceId) {
                 PublicParFun.SetRingVol(myContext, currentRing);
                 PublicParFun.SetPlayVol(myContext,currentPlay);
            }
           });
like image 937
HelloCW Avatar asked May 30 '14 07:05

HelloCW


1 Answers

The problem could be, that You set the currentRingVolume directly safter You started the TTS. The code will not wait until the speech has ended. For setting the volume back to the current volume, do it after speech has finished with an UtteranceProgressListener (or onUtteranceCompletetListener < API 15. this depends on which API You are developing):

   //first set the HashMap to Your tts
   HashMap<String, String> ttsParameters = new HashMap<String, String>();
   ttsParameters.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"stringId");
   tts.speak("Say Hello",TextToSpeech.QUEUE_FLUSH, ttsParameters );

Set onUtteranceProgressListener:

   int result = tts.setOnUtteranceProgressListener(new UtteranceProgressListener()
        {
            @Override
            public void onDone(String utteranceId)
            {
                //here set the volume back
            }

            @Override
            public void onError(String utteranceId)
            {
                //also, set the volume back
            }

            @Override
            public void onStart(String utteranceId)
            {
               // set the volume to max
            }
        });

EDIT

and for API < 15:

   tts.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {

    @Override
    public void onUtteranceCompleted(String utteranceId) {

        //set volume back
    }
   });

To find out what version is installed:

   if (android.os.Build.VERSION.SDK_INT >=8){

     }
like image 193
Opiatefuchs Avatar answered Oct 12 '22 00:10

Opiatefuchs