| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/speech/speech_recognizer.h" | 5 #include "content/browser/speech/speech_recognizer.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/time.h" | 9 #include "base/time.h" |
| 10 #include "content/browser/browser_main_loop.h" | 10 #include "content/browser/browser_main_loop.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 | 66 |
| 67 } // namespace | 67 } // namespace |
| 68 | 68 |
| 69 namespace speech { | 69 namespace speech { |
| 70 | 70 |
| 71 const int SpeechRecognizer::kAudioSampleRate = 16000; | 71 const int SpeechRecognizer::kAudioSampleRate = 16000; |
| 72 const ChannelLayout SpeechRecognizer::kChannelLayout = CHANNEL_LAYOUT_MONO; | 72 const ChannelLayout SpeechRecognizer::kChannelLayout = CHANNEL_LAYOUT_MONO; |
| 73 const int SpeechRecognizer::kNumBitsPerAudioSample = 16; | 73 const int SpeechRecognizer::kNumBitsPerAudioSample = 16; |
| 74 const int SpeechRecognizer::kNoSpeechTimeoutMs = 8000; | 74 const int SpeechRecognizer::kNoSpeechTimeoutMs = 8000; |
| 75 const int SpeechRecognizer::kEndpointerEstimationTimeMs = 300; | 75 const int SpeechRecognizer::kEndpointerEstimationTimeMs = 300; |
| 76 media::AudioManager* SpeechRecognizer::audio_manager_for_tests_ = NULL; |
| 76 | 77 |
| 77 COMPILE_ASSERT(SpeechRecognizer::kNumBitsPerAudioSample % 8 == 0, | 78 COMPILE_ASSERT(SpeechRecognizer::kNumBitsPerAudioSample % 8 == 0, |
| 78 kNumBitsPerAudioSample_must_be_a_multiple_of_8); | 79 kNumBitsPerAudioSample_must_be_a_multiple_of_8); |
| 79 | 80 |
| 80 SpeechRecognizer::SpeechRecognizer( | 81 SpeechRecognizer::SpeechRecognizer( |
| 81 SpeechRecognitionEventListener* listener, | 82 SpeechRecognitionEventListener* listener, |
| 82 int session_id, | 83 int session_id, |
| 83 bool is_single_shot, | 84 bool is_single_shot, |
| 84 SpeechRecognitionEngine* engine) | 85 SpeechRecognitionEngine* engine) |
| 85 : listener_(listener), | 86 : listener_(listener), |
| 86 testing_audio_manager_(NULL), | |
| 87 recognition_engine_(engine), | 87 recognition_engine_(engine), |
| 88 endpointer_(kAudioSampleRate), | 88 endpointer_(kAudioSampleRate), |
| 89 session_id_(session_id), | 89 session_id_(session_id), |
| 90 is_dispatching_event_(false), | 90 is_dispatching_event_(false), |
| 91 is_single_shot_(is_single_shot), | 91 is_single_shot_(is_single_shot), |
| 92 state_(STATE_IDLE) { | 92 state_(STATE_IDLE) { |
| 93 DCHECK(listener_ != NULL); | 93 DCHECK(listener_ != NULL); |
| 94 DCHECK(recognition_engine_ != NULL); | 94 DCHECK(recognition_engine_ != NULL); |
| 95 if (is_single_shot) { | 95 if (is_single_shot) { |
| 96 // In single shot recognition, the session is automatically ended after: | 96 // In single shot recognition, the session is automatically ended after: |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 scoped_refptr<SpeechRecognizer> me(this); | 235 scoped_refptr<SpeechRecognizer> me(this); |
| 236 | 236 |
| 237 if (event_args.event == EVENT_AUDIO_DATA) { | 237 if (event_args.event == EVENT_AUDIO_DATA) { |
| 238 DCHECK(event_args.audio_data.get() != NULL); | 238 DCHECK(event_args.audio_data.get() != NULL); |
| 239 ProcessAudioPipeline(*event_args.audio_data); | 239 ProcessAudioPipeline(*event_args.audio_data); |
| 240 } | 240 } |
| 241 | 241 |
| 242 // The audio pipeline must be processed before the event dispatch, otherwise | 242 // The audio pipeline must be processed before the event dispatch, otherwise |
| 243 // it would take actions according to the future state instead of the current. | 243 // it would take actions according to the future state instead of the current. |
| 244 state_ = ExecuteTransitionAndGetNextState(event_args); | 244 state_ = ExecuteTransitionAndGetNextState(event_args); |
| 245 | |
| 246 is_dispatching_event_ = false; | 245 is_dispatching_event_ = false; |
| 247 } | 246 } |
| 248 | 247 |
| 249 SpeechRecognizer::FSMState | 248 SpeechRecognizer::FSMState |
| 250 SpeechRecognizer::ExecuteTransitionAndGetNextState( | 249 SpeechRecognizer::ExecuteTransitionAndGetNextState( |
| 251 const FSMEventArgs& event_args) { | 250 const FSMEventArgs& event_args) { |
| 252 const FSMEvent event = event_args.event; | 251 const FSMEvent event = event_args.event; |
| 253 switch (state_) { | 252 switch (state_) { |
| 254 case STATE_IDLE: | 253 case STATE_IDLE: |
| 255 switch (event) { | 254 switch (event) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 if (route_to_sr_engine) { | 385 if (route_to_sr_engine) { |
| 387 DCHECK(recognition_engine_.get() != NULL); | 386 DCHECK(recognition_engine_.get() != NULL); |
| 388 recognition_engine_->TakeAudioChunk(raw_audio); | 387 recognition_engine_->TakeAudioChunk(raw_audio); |
| 389 } | 388 } |
| 390 } | 389 } |
| 391 | 390 |
| 392 SpeechRecognizer::FSMState | 391 SpeechRecognizer::FSMState |
| 393 SpeechRecognizer::StartRecording(const FSMEventArgs&) { | 392 SpeechRecognizer::StartRecording(const FSMEventArgs&) { |
| 394 DCHECK(recognition_engine_.get() != NULL); | 393 DCHECK(recognition_engine_.get() != NULL); |
| 395 DCHECK(!IsCapturingAudio()); | 394 DCHECK(!IsCapturingAudio()); |
| 396 AudioManager* audio_manager = (testing_audio_manager_ != NULL) ? | 395 AudioManager* audio_manager = (audio_manager_for_tests_ != NULL) ? |
| 397 testing_audio_manager_ : | 396 audio_manager_for_tests_ : |
| 398 BrowserMainLoop::GetAudioManager(); | 397 BrowserMainLoop::GetAudioManager(); |
| 399 DCHECK(audio_manager != NULL); | 398 DCHECK(audio_manager != NULL); |
| 400 | 399 |
| 401 DVLOG(1) << "SpeechRecognizer starting audio capture."; | 400 DVLOG(1) << "SpeechRecognizer starting audio capture."; |
| 402 num_samples_recorded_ = 0; | 401 num_samples_recorded_ = 0; |
| 403 audio_level_ = 0; | 402 audio_level_ = 0; |
| 404 listener_->OnRecognitionStart(session_id_); | 403 listener_->OnRecognitionStart(session_id_); |
| 405 | 404 |
| 406 if (!audio_manager->HasAudioInputDevices()) { | 405 if (!audio_manager->HasAudioInputDevices()) { |
| 407 return Abort(SpeechRecognitionError( | 406 return Abort(SpeechRecognitionError( |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 SpeechRecognizer::DetectEndOfSpeech(const FSMEventArgs& event_args) { | 478 SpeechRecognizer::DetectEndOfSpeech(const FSMEventArgs& event_args) { |
| 480 if (endpointer_.speech_input_complete()) | 479 if (endpointer_.speech_input_complete()) |
| 481 return StopCaptureAndWaitForResult(event_args); | 480 return StopCaptureAndWaitForResult(event_args); |
| 482 return STATE_RECOGNIZING; | 481 return STATE_RECOGNIZING; |
| 483 } | 482 } |
| 484 | 483 |
| 485 SpeechRecognizer::FSMState | 484 SpeechRecognizer::FSMState |
| 486 SpeechRecognizer::StopCaptureAndWaitForResult(const FSMEventArgs&) { | 485 SpeechRecognizer::StopCaptureAndWaitForResult(const FSMEventArgs&) { |
| 487 DCHECK(state_ >= STATE_ESTIMATING_ENVIRONMENT && state_ <= STATE_RECOGNIZING); | 486 DCHECK(state_ >= STATE_ESTIMATING_ENVIRONMENT && state_ <= STATE_RECOGNIZING); |
| 488 | 487 |
| 488 recognition_engine_->AudioChunksEnded(); |
| 489 |
| 489 DVLOG(1) << "Concluding recognition"; | 490 DVLOG(1) << "Concluding recognition"; |
| 490 CloseAudioControllerAsynchronously(); | 491 CloseAudioControllerAsynchronously(); |
| 491 recognition_engine_->AudioChunksEnded(); | |
| 492 | 492 |
| 493 if (state_ > STATE_WAITING_FOR_SPEECH) | 493 if (state_ > STATE_WAITING_FOR_SPEECH) |
| 494 listener_->OnSoundEnd(session_id_); | 494 listener_->OnSoundEnd(session_id_); |
| 495 | 495 |
| 496 listener_->OnAudioEnd(session_id_); | 496 listener_->OnAudioEnd(session_id_); |
| 497 return STATE_WAITING_FINAL_RESULT; | 497 return STATE_WAITING_FINAL_RESULT; |
| 498 } | 498 } |
| 499 | 499 |
| 500 SpeechRecognizer::FSMState | 500 SpeechRecognizer::FSMState |
| 501 SpeechRecognizer::AbortSilently(const FSMEventArgs& event_args) { | 501 SpeechRecognizer::AbortSilently(const FSMEventArgs& event_args) { |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 | 642 |
| 643 float noise_level = (endpointer_.NoiseLevelDb() - kAudioMeterMinDb) / | 643 float noise_level = (endpointer_.NoiseLevelDb() - kAudioMeterMinDb) / |
| 644 (kAudioMeterDbRange / kAudioMeterRangeMaxUnclipped); | 644 (kAudioMeterDbRange / kAudioMeterRangeMaxUnclipped); |
| 645 noise_level = std::min(std::max(0.0f, noise_level), | 645 noise_level = std::min(std::max(0.0f, noise_level), |
| 646 kAudioMeterRangeMaxUnclipped); | 646 kAudioMeterRangeMaxUnclipped); |
| 647 | 647 |
| 648 listener_->OnAudioLevelsChange( | 648 listener_->OnAudioLevelsChange( |
| 649 session_id_, clip_detected ? 1.0f : audio_level_, noise_level); | 649 session_id_, clip_detected ? 1.0f : audio_level_, noise_level); |
| 650 } | 650 } |
| 651 | 651 |
| 652 void SpeechRecognizer::SetAudioManagerForTesting( | 652 void SpeechRecognizer::SetAudioManagerForTests( |
| 653 AudioManager* audio_manager) { | 653 AudioManager* audio_manager) { |
| 654 testing_audio_manager_ = audio_manager; | 654 audio_manager_for_tests_ = audio_manager; |
| 655 } | 655 } |
| 656 | 656 |
| 657 SpeechRecognizer::FSMEventArgs::FSMEventArgs(FSMEvent event_value) | 657 SpeechRecognizer::FSMEventArgs::FSMEventArgs(FSMEvent event_value) |
| 658 : event(event_value), | 658 : event(event_value), |
| 659 audio_error_code(0), | 659 audio_error_code(0), |
| 660 audio_data(NULL), | 660 audio_data(NULL), |
| 661 engine_error(content::SPEECH_RECOGNITION_ERROR_NONE) { | 661 engine_error(content::SPEECH_RECOGNITION_ERROR_NONE) { |
| 662 } | 662 } |
| 663 | 663 |
| 664 SpeechRecognizer::FSMEventArgs::~FSMEventArgs() { | 664 SpeechRecognizer::FSMEventArgs::~FSMEventArgs() { |
| 665 } | 665 } |
| 666 | 666 |
| 667 } // namespace speech | 667 } // namespace speech |
| OLD | NEW |