Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TTS output always going to A2DP

My Android tutorial states that I can explicitly tell the TTS engine which stream to use:

For music playback:

params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_MUSIC));

And for phone calls:

params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_VOICE_CALL));

My understanding is that audio routing to a Bluetooth headset works such that STREAM_MUSIC goes to A2DP (aka "media audio" in Android Bluetooth settings) and STREAM_VOICE_CALL goes to HSP (aka "phone audio" in Android Bluetooth settings).

But regardless whether I use STREAM_MUSIC or STREAM_VOICE_CALL in my little application, the audio always goes for some reason to A2DP.

What am I am doing wrong? Is there a way to route TTS output to headset's HSP profile?

like image 301
an00b Avatar asked Aug 05 '11 22:08

an00b


3 Answers

I got this working for the most part, on most devices. Here is the part that starts the TTS on the voice call stream using Bluetooth SCO instead of A2DP.

if (mTtsReady) {
    myHash = new HashMap<String, String>();

    myHash.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "A2DP_Vol");

    OLD_AUDIO_MODE = am2.getMode();
    if(SMSstream == 1){
        if (am2.isBluetoothScoAvailableOffCall()) {
            am2.startBluetoothSco();
        }
        if(!am2.isSpeakerphoneOn()){
            speakerPhoneWasOn = false;
            am2.setSpeakerphoneOn(true);
        }
        myHash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
                String.valueOf(AudioManager.STREAM_VOICE_CALL));
        am2.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL,
                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);

    }
    else{
        am2.requestAudioFocus(null, AudioManager.STREAM_MUSIC,
        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
        myHash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
                String.valueOf(AudioManager.STREAM_MUSIC));
    }

    new CountDownTimer(SMS_DELAY, SMS_DELAY/2) {

        @Override
        public void onFinish() {
            try {
                mTts.speak(str, TextToSpeech.QUEUE_ADD,
                        myHash);
            } catch (Exception e) {
                Toast.makeText(application,
                        R.string.TTSNotReady,
                        Toast.LENGTH_LONG).show();
                e.printStackTrace();
            }

        }

        @Override
        public void onTick(long arg0) {

        }

    }.start();
}

Now I just have a problem getting the stream to revert back when done. It all works fine to read TTS. It will pause any music, play the TTS, and then resume music fine. However, when I exit the app later the stream for media now plays through the phone earpiece until I reboot. I posted that question here: Audio stream stays on earpiece after using AudioManager

You can see my whole project here: http://code.google.com/p/a2dpvolume/

like image 71
jroal Avatar answered Oct 26 '22 22:10

jroal


If your headset is compatible with the a2dp profile, then using AudioManager.STREAM_MUSIC and hence playing audio through the stream should get the job done.

I would also add, that if you are currently in a call, and you play audio through the voice stream, then any headset (a2dp or otherwise) can hear the audio. Unfortunately, you need to be in a call. Unfortunately I have found that setting the mode to MODE_IN_CALL does nothing.

To sum it up: If all that you are trying to do is play music (when not in a call), then use the AudioManager.STREAM_MUSIC and if the headset is A2DP compatible, then it will hear the music.

Also, take a look at AudioManager.isBluetoothA2dpOn(), to make sure that the system thinks that your headeset is plugged in.

like image 25
CornflakesDK Avatar answered Oct 26 '22 23:10

CornflakesDK


Yes it is possible to play the TTS (text-to-speech) output through a non A2DP headset like jroal says by using SCO.

Use AudioManager startBluetoothSco to enable SCO. Then listen for AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED broadcast with the EXTRA_SCO_AUDIO_STATE set to SCO_AUDIO_STATE_CONNECTED.

If you now do TextToSpeech to the STREAM_VOICE_CALL stream, it will end up in the headset (even the cheap non A2DP devices).

like image 1
takilara Avatar answered Oct 26 '22 23:10

takilara