2011-06-19 17 views
5

Tengo un problema con el método isSpeaking(). Al pasar QUEUE_FLUSH al método speak(), isSpeaking() funciona bien. Sin embargo, cuando hago cola en varios enunciados (pasando QUEUE_ADD), el método isSpeaking() comienza a devolver false inmediatamente después de haber puesto en cola más de un enunciado.Problema con isSpeaking() al usar Text-to-Speech en Android

Entonces me encontré con the source code of the TtsService class y vimos este código:

public boolean isSpeaking() { 
    return (mSelf.mIsSpeaking && (mSpeechQueue.size() < 1)); 
} 

¿Alguien tiene alguna idea, ¿por qué este método implementado de tal manera?

Respuesta

8

Me encontré con este, también.

Ha sido exactamente un año desde que esta pregunta y no hay respuesta está en el horizonte ...

Así que solo puedo suponer que quien escribió esta pieza de código pretende que signifique

"solo si habla último enunciado".

¿Tiene esto sentido?

El único problema es que, independientemente del modo ya sea en QUEUE_ADD o QUEUE_FLUSH, observaciones empíricas sugieren que existen condiciones de carrera de tiempo graves implicados:

  1. isSpeaking() siempre devolverá falsa si se llama en onUtteranceCompleted().
  2. isSpeaking() siempre devolverá cierto si se llama inmediatamente después de la primera tts.speak() después de una onUtteranceCompleted().
  3. isSpeaking() siempre devolverá falsa si se llama inmediatamente después de una tts.speak() que tiene al menos uno más tts.speak() s separan entre el último onUtteranceCompleted() y ella misma.

En cierto modo, se comporta exactamente lo contrario de la "intención":

"sólo si habla el primera enunciado" (después de una onUtteranceCompleted())

Por qué se comporta como este me supera, pero al menos es lo que muestra LogCat.

También tenga en cuenta la siguiente adición a la official documentation:.

"Tenga en cuenta que un elemento de voz se considera completa una vez que esté datos de audio ha sido enviada al mezclador de audio, o escriba en un archivo que podría haber un retardo finito entre este punto y cuando el hardware de audio completa reproducción. "

En OTH Es decir, este método es totalmente inútil.

3

Hay una intención de transmisión cuando la cola está completa: ACTION_TTS_QUEUE_PROCESSING_COMPLETED.

Aquí hay una clase de ejemplo para registrar un BroadCastReceiver y utilizar esto para determinar el estado isSpeaking.

Init de llamadas y apagado de los lugares relevantes en su actividad y utilizar el Habla y funciones isSpeaking proporcionada en esta clase:

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.speech.tts.TextToSpeech; 
import android.speech.tts.TextToSpeech.OnInitListener; 

public class SpeechWrapper { 

private static TextToSpeech mTts = null;   
private static boolean isSpeaking = false; 
private static BroadcastReceiver receiver = new BroadcastReceiver(){ 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     if (intent.getAction().equals(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED) && mTts != null) 
     { 
      isSpeaking = false; 
     } 
    } 
}; 

private static void Speak(String sMessage, int intQueueType, int delay) { 
    if (mTts == null || sMessage == null) return; 
    sMessage = sMessage.trim(); 
    isSpeaking = true; 
    if (delay > 0) { 
     mTts.playSilence(delay, intQueueType, null); 
     intQueueType = TextToSpeech.QUEUE_ADD; 
    } 
    mTts.speak(sMessage, intQueueType, null); 
} 

public static void Init(Context context) { 
    mTts = new TextToSpeech(context, (OnInitListener) context); 
    IntentFilter filter = new IntentFilter(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED); 
    context.registerReceiver(receiver, filter); 
} 

public static void Shutdown() { 
    if (mTts != null) { 
     mTts.stop(); 
     mTts.shutdown(); 
    } 
} 

public static boolean isSpeaking() { 
    return isSpeaking; 
} 

} 
Cuestiones relacionadas