Тон DTMF в RecognitionListener.onReadyForSpeech () принят за речь - PullRequest
9 голосов
/ 20 апреля 2011

Поиск Google Voice происходит со значительной задержкой с момента его вызова с помощью startActivityForResult () до отображения его диалогового окна, готового принять вашу речь.

Это требует от пользователя всегда смотреть наэкран, ожидая отображения диалогового окна, прежде чем говорить.

Итак, я думал о генерации звукового сигнала вместо диалогового окна путем реализации RecognitionListener и звучания тона DTMF в onReadyForSpeech (), как показано нижефрагмент:

  @Override
  public void onReadyForSpeech(Bundle params) {
    Log.d(LCTAG, "Called when the endpointer is ready for the user to start speaking.");
    mToneGenerator.startTone(ToneGenerator.TONE_DTMF_1);
    try {
      Thread.sleep(50);
    } catch (InterruptedException e) {
      Log.e(LCTAG, "InterruptedException while in Thread.sleep(50).");        
      e.printStackTrace();
    } // SystemClock.sleep(50);
    mToneGenerator.stopTone();
  }

Звук звучит прекрасно, но ... он также "слышен" микрофоном, поступая в службу распознавания голоса и всегда , генерируя ошибку распознавания ERROR_NO_MATCH .

Есть ли способ обойти это?

Ответы [ 3 ]

5 голосов
/ 20 апреля 2011

Вот случайная идея, и она вполне может не сработать.

Можете ли вы попробовать отключить микрофон (возможно, через AudioManager.setMicrophoneMute) во время воспроизведения тона?

1 голос
/ 07 октября 2011

Вот мой код, который работает для меня, помещенный в обратный вызов onReadyForSpeech () RecognitionListener.

private void playSpeechReadyTone(){
    audioManager.setMicrophoneMute(true);
    MediaPlayer mediaPlayer = MediaPlayer.create(JarvisService.this, R.raw.doublebeep);
    mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

        @Override
        public void onCompletion(MediaPlayer arg0) {
            audioManager.setMicrophoneMute(false);
        }
    });
    mediaPlayer.start();    
}
0 голосов
/ 19 июля 2013

Боюсь, что нет простого и понятного способа сделать это. Как назначил srf, вы не должны полагаться на AudioManager.setMicrophoneMute (логическое значение), поэтому, AFAIK, возможны следующие варианты:

  1. Воспроизвести аудиофайл перед вызовом SpeechRecognizer.startListening (намерение):

    final MediaPlayer mediaPlayer = MediaPlayer.create(JarvisService.this, R.raw.doublebeep);
    mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
    
         @Override
        public void onCompletion(MediaPlayer player) {
            player.release();
            // Safety start Speech Recognizer
            mSpeechRecognizer.startListening(getSpeechRecognizerIntent());
        }
    });
    mediaPlayer.start();
    

Однако, у этого решения есть проблема ... Если вы можете получить RecognitionListener.onError (int error) до вызова RecognitionListener.onReadyForSpeech, и в этом случае вы все равно будете воспроизводить звуковой сигнал каждый раз (это произойдет, например, если вы не подключены к Интернету и распознавание речи настроено для работы в Интернете)! Кроме того, вы должны управлять случаем отмены процесса распознавания речи во время воспроизведения звука (двойной сигнал).

  1. Воспроизведите звук в обратном вызове onReadyForSpeech (прочитайте оригинальный вопрос), но используйте RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS с соответствующим значением. В моем случае мой звуковой сигнал очень короткий (максимум 1 секунда), и я установил RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS на 4/5 секунд.

Также обратите внимание, что, как говорит Google Doc:

Обратите внимание, что определенные значения могут привести к нежелательным или неожиданным результатам - используйте их с осторожностью! Кроме того, в зависимости от реализации распознавателя, эти значения могут не действовать.

...