8

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?

Charles
  • 50,943
  • 13
  • 104
  • 142
an00b
  • 11,338
  • 13
  • 64
  • 101

3 Answers3

5

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/

Community
  • 1
  • 1
jroal
  • 547
  • 6
  • 16
  • This is incredible. Belated thanks for posting this. Accepting, although I haven't tested this code in my app yet. – an00b Dec 06 '11 at 02:29
1

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.

CornflakesDK
  • 649
  • 7
  • 15
  • Thanks but I may have not explained what I want to do very well: I want to play the TTS (text-to-speech) output through a **non** A2DP headset. That is, I would like to be able to use the less expensive headsets for text-to-speech. After all, it's only voice, not hi-fi music... Is that possible? +1 for the attempt. – an00b Aug 12 '11 at 17:05
  • Well I actually don't think it's possible, cause you'd have to alter the way the system works, could be something bout (You scratch my back...) between the companies... But I'm not sure – CornflakesDK Aug 15 '11 at 07:31
1

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).

takilara
  • 108
  • 6