2011-06-19 9 views
5

Mam problem z metodą isSpeaking(). Po przejściu QUEUE_FLUSH do metody speak(), isSpeaking() działa poprawnie. Jednak, gdy umieszczam w kolejce wiele wypowiedzi (przekazując QUEUE_ADD), metoda isSpeaking() rozpoczyna się od zwracania false natychmiast po kolejkowaniu kolejnych wypowiedzi.Problem z isSpeaking() podczas korzystania z funkcji zamiany tekstu na mowę w systemie Android

Wtedy natknąłem the source code of the TtsService class i zobaczyłem ten kod:

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

Czy ktoś ma jakiś pomysł, dlaczego ta metoda wdrożone w taki sposób?

Odpowiedz

8

Natknąłem się na ten też.

To było dokładnie rok odkąd zadał to pytanie i odpowiedź nie jest w horyzoncie ...

Więc mogę się tylko domyślać, że ten, kto napisał ten fragment kodu ma to oznaczać

"tylko wtedy, gdy mówi się ostatni wypowiedź".

Czy to ma sens?

Jedynym problemem jest to, że niezależnie od tego, czy w QUEUE_ADD lub QUEUE_FLUSH trybie obserwacje empiryczne wskazują, że istnieją poważne warunki wyścigowe rozrządu zaangażowane:

  1. isSpeaking() zawsze wróci fałszywy jeśli wezwany onUtteranceCompleted().
  2. isSpeaking() zawsze zwróci prawdziwą Jeśli wywołana natychmiast po pierwszytts.speak() po onUtteranceCompleted().
  3. isSpeaking() zawsze powróci fałszywy Jeśli wywołana natychmiast po tts.speak() że ma co najmniej jeden więcej tts.speak() s oddzielające między ostatnim onUtteranceCompleted() i sobie.

W pewnym sensie, to zachowuje się dokładnie naprzeciwko "przeznaczone":

"tylko wtedy, mówiąc pierwszy wypowiedź" (po onUtteranceCompleted())

Dlaczego zachowuje się tak, jak to jest poza mną, ale to przynajmniej to, co pokazuje LogCat.

Należy również zauważyć następujący dodatek do official documentation.

"Należy zauważyć, że element mowy jest uważana za kompletną raz to dane audio został wysłany do miksera audio, lub zapisać do pliku nie może być skończony lag pomiędzy tym punktem, a gdy sprzęt audio uzupełnia odtwarzania. "

W oth er słów, ta metoda jest całkowicie bezużyteczna.

3

Po zakończeniu kolejki istnieje zamiar transmisji: ACTION_TTS_QUEUE_PROCESSING_COMPLETED.

Oto przykładowa klasa rejestracji BroadCastReceiver i użycie jej do określenia stanu isSpeaking.

połączeń Init i wyłączania z odpowiednich miejscach w swojej działalności i użyć mówić i funkcje isSpeaking przewidzianej w tej klasie:

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; 
} 

} 
Powiązane problemy