Ahmed
Ahmed

Reputation: 15069

Android Text to Speech is broken while phone ringing

In my android application I am using the Text to Speech engine to have a piece of Text spoken. The speech code runs when phone is ringing. The speech is broken and I see following Warnings in the logcat. Please note that this problem is seen on SDK 15 (Ice cream sandwich) particularly only when the speech code is invoked when phone is ringing, otherwise even on ICE, speech code works perfectly when invoked any other time when phone is not ringing. the code works fine on SDK 8 and 10.

The warnings I get are:

com.svox.pico W/AudioTrack(549): obtainBuffer() track 0x177dd8 disabled, restarting
com.svox.pico W/AudioTrack(549): obtainBuffer() track 0x177dd8 disabled, restarting
com.svox.pico D/dalvikvm(549):   GC_CONCURRENT freed 441K, 8% free 6552K/7111K, paused 3ms+107ms
com.svox.pico W/AudioTrack(549): obtainBuffer() track 0x156058 disabled, restarting
com.svox.pico D/dalvikvm(162):   GC_CONCURRENT freed 532K, 11% free 8391K/9415K, paused 5ms+6ms

The relevant piece of code runs in a thread in a Service and the service is started in a broadcast receiver when it gets a phone call.

// The constructor of speaker class
public Speaker(final Context context, final Settings settings) 
{   
    this.settings = settings;
    params = new HashMap<String, String>();      
    params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_ALARM));
    params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "myapp");

    this.context = context;      

    synchronized (synch) 
    {   
        talker = new TextToSpeech(context, this);
    }

    Utils.log(TAG, "Created TextToSpeech..");
}

@Override
public void onInit(final int status) 
{
    synchronized (synch) 
    {   
        Utils.log(TAG, "TTS onInit..");

        if(talker == null)
        {
            throw new RuntimeException(Utils.collectPlatformInfo(context));
        }

        if(TextToSpeech.ERROR == talker.setOnUtteranceCompletedListener(new SpeechFinishedListener()))
        {
            Utils.log(TAG, "Error tts setUt");
            return ; 
        }

        int code = talker.setLanguage(Locale.getDefault());

        if(code == TextToSpeech.LANG_NOT_SUPPORTED || code ==TextToSpeech.LANG_MISSING_DATA)
        {
            Utils.log(TAG, String.format("Error settingLang on TTS code %d", code));            
        }

        if(TextToSpeech.ERROR == talker.setSpeechRate(settings.getSpeed()))
        {
            //this error is not a fatal, we can continue
            Utils.log(TAG, "Error tts setSPeechrate");                      
        }

        if(TextToSpeech.ERROR == talker.setPitch(settings.getPitch()))
        {   
            //this error is not a fatal, we can continue
            Utils.log(TAG, "Error tts setPitch");           
        }

        ready = true;
    }
}

    // The function used to provide text to be spoken..
public void speak(final String text) throws InterruptedException
{
    if(bEngineFailure)
        return;

    if(!ready)
    {
        Utils.log(TAG, "engine not initialized");
        bEngineFailure = true;
        return;
    }

    bSpeechComplete = false;

    talker.speak(text, TextToSpeech.QUEUE_ADD, params);

    while(!bSpeechComplete)
    {
           Thread.sleep(100);           
    }   

}

Upvotes: 3

Views: 1064

Answers (1)

tyczj
tyczj

Reputation: 74056

This is just a guess because there is not much to go on here but I have seen a similar situation if the phone volume is on ring (not vibrate) to where the ringtone would play when a call comes in and some sort of other audio is playing (ie: TTS/music/video) one of the audio streams gets all choppy/broken because it is trying to play both at the same time. If this is your desired effect to play both at the same time then one work around you could do is extend the PhoneStateListener and pause the audio every so often then play the TTS

example of extending the PhoneStateListener can be found here

Upvotes: 2

Related Questions