Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: content/browser/speech/speech_recognizer_impl.cc

Issue 9663066: Refactoring of chrome speech recognition architecture (CL1.3) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Final review fixes. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_impl.h" 5 #include "content/browser/speech/speech_recognizer_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/time.h" 8 #include "base/time.h"
9 #include "content/browser/browser_main_loop.h" 9 #include "content/browser/browser_main_loop.h"
10 #include "content/browser/speech/audio_buffer.h" 10 #include "content/browser/speech/audio_buffer.h"
11 #include "content/browser/speech/google_one_shot_remote_engine.h"
12 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/speech_recognition_event_listener.h" 13 #include "content/public/browser/speech_recognition_event_listener.h"
12 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/speech_recognizer.h"
13 #include "content/public/common/speech_recognition_result.h" 15 #include "content/public/common/speech_recognition_result.h"
14 #include "net/url_request/url_request_context_getter.h" 16 #include "net/url_request/url_request_context_getter.h"
15 17
16 using content::BrowserMainLoop; 18 using content::BrowserMainLoop;
17 using content::BrowserThread; 19 using content::BrowserThread;
20 using content::SpeechRecognitionError;
18 using content::SpeechRecognitionEventListener; 21 using content::SpeechRecognitionEventListener;
22 using content::SpeechRecognitionResult;
19 using content::SpeechRecognizer; 23 using content::SpeechRecognizer;
20 using media::AudioInputController; 24 using media::AudioInputController;
21 using std::string;
22 25
23 namespace { 26 namespace {
24 27
25 // The following constants are related to the volume level indicator shown in 28 // The following constants are related to the volume level indicator shown in
26 // the UI for recorded audio. 29 // the UI for recorded audio.
27 // Multiplier used when new volume is greater than previous level. 30 // Multiplier used when new volume is greater than previous level.
28 const float kUpSmoothingFactor = 1.0f; 31 const float kUpSmoothingFactor = 1.0f;
29 // Multiplier used when new volume is lesser than previous level. 32 // Multiplier used when new volume is lesser than previous level.
30 const float kDownSmoothingFactor = 0.7f; 33 const float kDownSmoothingFactor = 0.7f;
31 // RMS dB value of a maximum (unclipped) sine wave for int16 samples. 34 // RMS dB value of a maximum (unclipped) sine wave for int16 samples.
(...skipping 25 matching lines...) Expand all
57 60
58 SpeechRecognizer* SpeechRecognizer::Create( 61 SpeechRecognizer* SpeechRecognizer::Create(
59 SpeechRecognitionEventListener* listener, 62 SpeechRecognitionEventListener* listener,
60 int caller_id, 63 int caller_id,
61 const std::string& language, 64 const std::string& language,
62 const std::string& grammar, 65 const std::string& grammar,
63 net::URLRequestContextGetter* context_getter, 66 net::URLRequestContextGetter* context_getter,
64 bool filter_profanities, 67 bool filter_profanities,
65 const std::string& hardware_info, 68 const std::string& hardware_info,
66 const std::string& origin_url) { 69 const std::string& origin_url) {
67 return new speech::SpeechRecognizerImpl( 70 return new speech::SpeechRecognizerImpl(listener,
68 listener, caller_id, language, grammar, context_getter, 71 caller_id,
69 filter_profanities, hardware_info, origin_url); 72 language,
73 grammar,
74 context_getter,
75 filter_profanities,
76 hardware_info,
77 origin_url);
70 } 78 }
71 79
72 namespace speech { 80 namespace speech {
73 81
74 const int SpeechRecognizerImpl::kAudioSampleRate = 16000; 82 const int SpeechRecognizerImpl::kAudioSampleRate = 16000;
75 const int SpeechRecognizerImpl::kAudioPacketIntervalMs = 100;
76 const ChannelLayout SpeechRecognizerImpl::kChannelLayout = CHANNEL_LAYOUT_MONO; 83 const ChannelLayout SpeechRecognizerImpl::kChannelLayout = CHANNEL_LAYOUT_MONO;
77 const int SpeechRecognizerImpl::kNumBitsPerAudioSample = 16; 84 const int SpeechRecognizerImpl::kNumBitsPerAudioSample = 16;
78 const int SpeechRecognizerImpl::kNoSpeechTimeoutSec = 8; 85 const int SpeechRecognizerImpl::kNoSpeechTimeoutMs = 8000;
79 const int SpeechRecognizerImpl::kEndpointerEstimationTimeMs = 300; 86 const int SpeechRecognizerImpl::kEndpointerEstimationTimeMs = 300;
80 87
81 SpeechRecognizerImpl::SpeechRecognizerImpl( 88 SpeechRecognizerImpl::SpeechRecognizerImpl(
82 SpeechRecognitionEventListener* listener, 89 SpeechRecognitionEventListener* listener,
83 int caller_id, 90 int caller_id,
84 const std::string& language, 91 const std::string& language,
85 const std::string& grammar, 92 const std::string& grammar,
86 net::URLRequestContextGetter* context_getter, 93 net::URLRequestContextGetter* context_getter,
87 bool filter_profanities, 94 bool filter_profanities,
88 const std::string& hardware_info, 95 const std::string& hardware_info,
89 const std::string& origin_url) 96 const std::string& origin_url)
90 : listener_(listener), 97 : listener_(listener),
98 testing_audio_manager_(NULL),
99 endpointer_(kAudioSampleRate),
100 context_getter_(context_getter),
91 caller_id_(caller_id), 101 caller_id_(caller_id),
92 language_(language), 102 language_(language),
93 grammar_(grammar), 103 grammar_(grammar),
94 filter_profanities_(filter_profanities), 104 filter_profanities_(filter_profanities),
95 hardware_info_(hardware_info), 105 hardware_info_(hardware_info),
96 origin_url_(origin_url), 106 origin_url_(origin_url),
97 context_getter_(context_getter),
98 codec_(AudioEncoder::CODEC_FLAC),
99 encoder_(NULL),
100 endpointer_(kAudioSampleRate),
101 num_samples_recorded_(0), 107 num_samples_recorded_(0),
102 audio_level_(0.0f), 108 audio_level_(0.0f) {
103 audio_manager_(NULL) { 109 DCHECK(listener_ != NULL);
104 endpointer_.set_speech_input_complete_silence_length( 110 endpointer_.set_speech_input_complete_silence_length(
105 base::Time::kMicrosecondsPerSecond / 2); 111 base::Time::kMicrosecondsPerSecond / 2);
106 endpointer_.set_long_speech_input_complete_silence_length( 112 endpointer_.set_long_speech_input_complete_silence_length(
107 base::Time::kMicrosecondsPerSecond); 113 base::Time::kMicrosecondsPerSecond);
108 endpointer_.set_long_speech_length(3 * base::Time::kMicrosecondsPerSecond); 114 endpointer_.set_long_speech_length(3 * base::Time::kMicrosecondsPerSecond);
109 endpointer_.StartSession(); 115 endpointer_.StartSession();
110 } 116 }
111 117
112 SpeechRecognizerImpl::~SpeechRecognizerImpl() { 118 SpeechRecognizerImpl::~SpeechRecognizerImpl() {
113 // Recording should have stopped earlier due to the endpointer or 119 // Recording should have stopped earlier due to the endpointer or
114 // |StopRecording| being called. 120 // |StopRecording| being called.
115 DCHECK(!audio_controller_.get()); 121 DCHECK(!audio_controller_.get());
116 DCHECK(!request_.get() || !request_->HasPendingRequest()); 122 DCHECK(!recognition_engine_.get() ||
117 DCHECK(!encoder_.get()); 123 !recognition_engine_->IsRecognitionPending());
118 endpointer_.EndSession(); 124 endpointer_.EndSession();
119 } 125 }
120 126
121 bool SpeechRecognizerImpl::StartRecognition() { 127 void SpeechRecognizerImpl::StartRecognition() {
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
123 DCHECK(!audio_controller_.get()); 129 DCHECK(!audio_controller_.get());
124 DCHECK(!request_.get() || !request_->HasPendingRequest()); 130 DCHECK(!recognition_engine_.get() ||
125 DCHECK(!encoder_.get()); 131 !recognition_engine_->IsRecognitionPending());
126 132
127 // The endpointer needs to estimate the environment/background noise before 133 // The endpointer needs to estimate the environment/background noise before
128 // starting to treat the audio as user input. In |HandleOnData| we wait until 134 // starting to treat the audio as user input. In |HandleOnData| we wait until
129 // such time has passed before switching to user input mode. 135 // such time has passed before switching to user input mode.
130 endpointer_.SetEnvironmentEstimationMode(); 136 endpointer_.SetEnvironmentEstimationMode();
131 137
132 encoder_.reset(AudioEncoder::Create(codec_, kAudioSampleRate, 138 AudioManager* audio_manager = (testing_audio_manager_ != NULL) ?
133 kNumBitsPerAudioSample)); 139 testing_audio_manager_ :
134 int samples_per_packet = (kAudioSampleRate * kAudioPacketIntervalMs) / 1000; 140 BrowserMainLoop::GetAudioManager();
141 const int samples_per_packet = kAudioSampleRate *
142 GoogleOneShotRemoteEngine::kAudioPacketIntervalMs / 1000;
135 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, 143 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
136 kAudioSampleRate, kNumBitsPerAudioSample, 144 kAudioSampleRate, kNumBitsPerAudioSample,
137 samples_per_packet); 145 samples_per_packet);
138 audio_controller_ = AudioInputController::Create( 146 audio_controller_ = AudioInputController::Create(audio_manager, this, params);
139 audio_manager_ ? audio_manager_ : BrowserMainLoop::GetAudioManager(),
140 this, params);
141 DCHECK(audio_controller_.get()); 147 DCHECK(audio_controller_.get());
142 VLOG(1) << "SpeechRecognizer starting record."; 148 VLOG(1) << "SpeechRecognizer starting record.";
143 num_samples_recorded_ = 0; 149 num_samples_recorded_ = 0;
144 audio_controller_->Record(); 150 audio_controller_->Record();
145
146 return true;
147 } 151 }
148 152
149 void SpeechRecognizerImpl::AbortRecognition() { 153 void SpeechRecognizerImpl::AbortRecognition() {
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
151 DCHECK(audio_controller_.get() || request_.get()); 155 DCHECK(audio_controller_.get() || recognition_engine_.get());
152 156
153 // Stop recording if required. 157 // Stop recording if required.
154 if (audio_controller_.get()) { 158 if (audio_controller_.get()) {
155 CloseAudioControllerSynchronously(); 159 CloseAudioControllerSynchronously();
156 } 160 }
157 161
158 VLOG(1) << "SpeechRecognizer canceling recognition."; 162 VLOG(1) << "SpeechRecognizer canceling recognition.";
159 encoder_.reset(); 163 recognition_engine_.reset();
160 request_.reset();
161 } 164 }
162 165
163 void SpeechRecognizerImpl::StopAudioCapture() { 166 void SpeechRecognizerImpl::StopAudioCapture() {
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
165 168
166 // If audio recording has already stopped and we are in recognition phase, 169 // If audio recording has already stopped and we are in recognition phase,
167 // silently ignore any more calls to stop recording. 170 // silently ignore any more calls to stop recording.
168 if (!audio_controller_.get()) 171 if (!audio_controller_.get())
169 return; 172 return;
170 173
171 CloseAudioControllerSynchronously(); 174 CloseAudioControllerSynchronously();
172
173 listener_->OnSoundEnd(caller_id_); 175 listener_->OnSoundEnd(caller_id_);
174 listener_->OnAudioEnd(caller_id_); 176 listener_->OnAudioEnd(caller_id_);
175 177
176 // UploadAudioChunk requires a non-empty final buffer. So we encode a packet
177 // of silence in case encoder had no data already.
178 std::vector<short> samples((kAudioSampleRate * kAudioPacketIntervalMs) /
179 1000);
180 AudioChunk dummy_chunk(reinterpret_cast<uint8*>(&samples[0]),
181 samples.size() * sizeof(short),
182 encoder_->bits_per_sample() / 8);
183 encoder_->Encode(dummy_chunk);
184 encoder_->Flush();
185 scoped_ptr<AudioChunk> encoded_data(encoder_->GetEncodedDataAndClear());
186 DCHECK(!encoded_data->IsEmpty());
187 encoder_.reset();
188
189 // If we haven't got any audio yet end the recognition sequence here. 178 // If we haven't got any audio yet end the recognition sequence here.
190 if (request_ == NULL) { 179 if (recognition_engine_ == NULL) {
191 // Guard against the listener freeing us until we finish our job. 180 // Guard against the listener freeing us until we finish our job.
192 scoped_refptr<SpeechRecognizerImpl> me(this); 181 scoped_refptr<SpeechRecognizerImpl> me(this);
193 listener_->OnRecognitionEnd(caller_id_); 182 listener_->OnRecognitionEnd(caller_id_);
194 } else { 183 } else {
195 request_->UploadAudioChunk(*encoded_data, true /* is_last_chunk */); 184 recognition_engine_->AudioChunksEnded();
196 } 185 }
197 } 186 }
198 187
199 // Invoked in the audio thread. 188 // Invoked in the audio thread.
200 void SpeechRecognizerImpl::OnError(AudioInputController* controller, 189 void SpeechRecognizerImpl::OnError(AudioInputController* controller,
201 int error_code) { 190 int error_code) {
202 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 191 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
203 base::Bind(&SpeechRecognizerImpl::HandleOnError, 192 base::Bind(&SpeechRecognizerImpl::HandleOnError,
204 this, error_code)); 193 this, error_code));
205 } 194 }
(...skipping 24 matching lines...) Expand all
230 void SpeechRecognizerImpl::HandleOnData(AudioChunk* raw_audio) { 219 void SpeechRecognizerImpl::HandleOnData(AudioChunk* raw_audio) {
231 scoped_ptr<AudioChunk> free_raw_audio_on_return(raw_audio); 220 scoped_ptr<AudioChunk> free_raw_audio_on_return(raw_audio);
232 // Check if we are still recording and if not discard this buffer, as 221 // Check if we are still recording and if not discard this buffer, as
233 // recording might have been stopped after this buffer was posted to the queue 222 // recording might have been stopped after this buffer was posted to the queue
234 // by |OnData|. 223 // by |OnData|.
235 if (!audio_controller_.get()) 224 if (!audio_controller_.get())
236 return; 225 return;
237 226
238 bool speech_was_heard_before_packet = endpointer_.DidStartReceivingSpeech(); 227 bool speech_was_heard_before_packet = endpointer_.DidStartReceivingSpeech();
239 228
240 encoder_->Encode(*raw_audio);
241 float rms; 229 float rms;
242 endpointer_.ProcessAudio(*raw_audio, &rms); 230 endpointer_.ProcessAudio(*raw_audio, &rms);
243 bool did_clip = DetectClipping(*raw_audio); 231 bool did_clip = DetectClipping(*raw_audio);
244 num_samples_recorded_ += raw_audio->NumSamples(); 232 num_samples_recorded_ += raw_audio->NumSamples();
245 233
246 if (request_ == NULL) { 234 if (recognition_engine_ == NULL) {
247 // This was the first audio packet recorded, so start a request to the 235 // This was the first audio packet recorded, so start a request to the
248 // server to send the data and inform the listener. 236 // server to send the data and inform the listener.
249 listener_->OnAudioStart(caller_id_); 237 listener_->OnAudioStart(caller_id_);
250 request_.reset(new SpeechRecognitionRequest(context_getter_.get(), this)); 238 GoogleOneShotRemoteEngineConfig google_sr_config;
251 request_->Start(language_, grammar_, filter_profanities_, 239 google_sr_config.language = language_;
252 hardware_info_, origin_url_, encoder_->mime_type()); 240 google_sr_config.grammar = grammar_;
241 google_sr_config.audio_sample_rate = kAudioSampleRate;
242 google_sr_config.audio_num_bits_per_sample = kNumBitsPerAudioSample;
243 google_sr_config.filter_profanities = filter_profanities_;
244 google_sr_config.hardware_info = hardware_info_;
245 google_sr_config.origin_url = origin_url_;
246 GoogleOneShotRemoteEngine* google_sr_engine =
247 new GoogleOneShotRemoteEngine(context_getter_.get());
248 google_sr_engine->SetConfig(google_sr_config);
249 recognition_engine_.reset(google_sr_engine);
250 recognition_engine_->set_delegate(this);
251 recognition_engine_->StartRecognition();
253 } 252 }
254 253
255 scoped_ptr<AudioChunk> encoded_data(encoder_->GetEncodedDataAndClear()); 254 recognition_engine_->TakeAudioChunk(*raw_audio);
256 DCHECK(!encoded_data->IsEmpty());
257 request_->UploadAudioChunk(*encoded_data, false /* is_last_chunk */);
258 255
259 if (endpointer_.IsEstimatingEnvironment()) { 256 if (endpointer_.IsEstimatingEnvironment()) {
260 // Check if we have gathered enough audio for the endpointer to do 257 // Check if we have gathered enough audio for the endpointer to do
261 // environment estimation and should move on to detect speech/end of speech. 258 // environment estimation and should move on to detect speech/end of speech.
262 if (num_samples_recorded_ >= (kEndpointerEstimationTimeMs * 259 if (num_samples_recorded_ >= (kEndpointerEstimationTimeMs *
263 kAudioSampleRate) / 1000) { 260 kAudioSampleRate) / 1000) {
264 endpointer_.SetUserInputMode(); 261 endpointer_.SetUserInputMode();
265 listener_->OnEnvironmentEstimationComplete(caller_id_); 262 listener_->OnEnvironmentEstimationComplete(caller_id_);
266 } 263 }
267 return; // No more processing since we are still estimating environment. 264 return; // No more processing since we are still estimating environment.
268 } 265 }
269 266
270 // Check if we have waited too long without hearing any speech. 267 // Check if we have waited too long without hearing any speech.
271 bool speech_was_heard_after_packet = endpointer_.DidStartReceivingSpeech(); 268 bool speech_was_heard_after_packet = endpointer_.DidStartReceivingSpeech();
272 if (!speech_was_heard_after_packet && 269 if (!speech_was_heard_after_packet &&
273 num_samples_recorded_ >= kNoSpeechTimeoutSec * kAudioSampleRate) { 270 num_samples_recorded_ >= (kNoSpeechTimeoutMs / 1000) * kAudioSampleRate) {
274 InformErrorAndAbortRecognition( 271 InformErrorAndAbortRecognition(
275 content::SPEECH_RECOGNITION_ERROR_NO_SPEECH); 272 content::SPEECH_RECOGNITION_ERROR_NO_SPEECH);
276 return; 273 return;
277 } 274 }
278 275
279 if (!speech_was_heard_before_packet && speech_was_heard_after_packet) 276 if (!speech_was_heard_before_packet && speech_was_heard_after_packet)
280 listener_->OnSoundStart(caller_id_); 277 listener_->OnSoundStart(caller_id_);
281 278
282 // Calculate the input volume to display in the UI, smoothing towards the 279 // Calculate the input volume to display in the UI, smoothing towards the
283 // new level. 280 // new level.
(...skipping 11 matching lines...) Expand all
295 noise_level = std::min(std::max(0.0f, noise_level), 292 noise_level = std::min(std::max(0.0f, noise_level),
296 kAudioMeterRangeMaxUnclipped); 293 kAudioMeterRangeMaxUnclipped);
297 294
298 listener_->OnAudioLevelsChange(caller_id_, did_clip ? 1.0f : audio_level_, 295 listener_->OnAudioLevelsChange(caller_id_, did_clip ? 1.0f : audio_level_,
299 noise_level); 296 noise_level);
300 297
301 if (endpointer_.speech_input_complete()) 298 if (endpointer_.speech_input_complete())
302 StopAudioCapture(); 299 StopAudioCapture();
303 } 300 }
304 301
305 void SpeechRecognizerImpl::SetRecognitionResult( 302 void SpeechRecognizerImpl::OnSpeechRecognitionEngineResult(
306 const content::SpeechRecognitionResult& result) { 303 const content::SpeechRecognitionResult& result) {
307 if (result.error != content::SPEECH_RECOGNITION_ERROR_NONE) { 304 if (result.error != content::SPEECH_RECOGNITION_ERROR_NONE) {
308 InformErrorAndAbortRecognition(result.error); 305 InformErrorAndAbortRecognition(result.error);
309 return; 306 return;
310 } 307 }
311 308
312 // Guard against the listener freeing us until we finish our job. 309 // Guard against the listener freeing us until we finish our job.
313 scoped_refptr<SpeechRecognizerImpl> me(this); 310 scoped_refptr<SpeechRecognizerImpl> me(this);
314 listener_->OnRecognitionResult(caller_id_, result); 311 listener_->OnRecognitionResult(caller_id_, result);
315 listener_->OnRecognitionEnd(caller_id_); 312 listener_->OnRecognitionEnd(caller_id_);
316 } 313 }
317 314
315 void SpeechRecognizerImpl::OnSpeechRecognitionEngineError(
316 const content::SpeechRecognitionError& error) {
317 InformErrorAndAbortRecognition(error.code);
318 }
319
318 void SpeechRecognizerImpl::InformErrorAndAbortRecognition( 320 void SpeechRecognizerImpl::InformErrorAndAbortRecognition(
319 content::SpeechRecognitionErrorCode error) { 321 content::SpeechRecognitionErrorCode error) {
320 DCHECK_NE(error, content::SPEECH_RECOGNITION_ERROR_NONE); 322 DCHECK_NE(error, content::SPEECH_RECOGNITION_ERROR_NONE);
321 AbortRecognition(); 323 AbortRecognition();
322 324
323 // Guard against the listener freeing us until we finish our job. 325 // Guard against the listener freeing us until we finish our job.
324 scoped_refptr<SpeechRecognizerImpl> me(this); 326 scoped_refptr<SpeechRecognizerImpl> me(this);
325 listener_->OnRecognitionError(caller_id_, error); 327 listener_->OnRecognitionError(caller_id_, error);
326 } 328 }
327 329
328 void SpeechRecognizerImpl::CloseAudioControllerSynchronously() { 330 void SpeechRecognizerImpl::CloseAudioControllerSynchronously() {
329 VLOG(1) << "SpeechRecognizer stopping record."; 331 VLOG(1) << "SpeechRecognizer stopping record.";
330 332
331 // TODO(satish): investigate the possibility to utilize the closure 333 // TODO(satish): investigate the possibility to utilize the closure
332 // and switch to async. version of this method. Compare with how 334 // and switch to async. version of this method. Compare with how
333 // it's done in e.g. the AudioRendererHost. 335 // it's done in e.g. the AudioRendererHost.
334 base::WaitableEvent closed_event(true, false); 336 base::WaitableEvent closed_event(true, false);
335 audio_controller_->Close(base::Bind(&base::WaitableEvent::Signal, 337 audio_controller_->Close(base::Bind(&base::WaitableEvent::Signal,
336 base::Unretained(&closed_event))); 338 base::Unretained(&closed_event)));
337 closed_event.Wait(); 339 closed_event.Wait();
338 audio_controller_ = NULL; // Releases the ref ptr. 340 audio_controller_ = NULL; // Releases the ref ptr.
339 } 341 }
340 342
341 void SpeechRecognizerImpl::SetAudioManagerForTesting(
342 AudioManager* audio_manager) {
343 audio_manager_ = audio_manager;
344 }
345
346 bool SpeechRecognizerImpl::IsActive() const { 343 bool SpeechRecognizerImpl::IsActive() const {
347 return (request_.get() != NULL); 344 return (recognition_engine_.get() != NULL);
348 } 345 }
349 346
350 bool SpeechRecognizerImpl::IsCapturingAudio() const { 347 bool SpeechRecognizerImpl::IsCapturingAudio() const {
351 return (audio_controller_.get() != NULL); 348 return (audio_controller_.get() != NULL);
352 } 349 }
353 350
351 const SpeechRecognitionEngine&
352 SpeechRecognizerImpl::recognition_engine() const {
353 return *(recognition_engine_.get());
354 }
355
356 void SpeechRecognizerImpl::SetAudioManagerForTesting(
357 AudioManager* audio_manager) {
358 testing_audio_manager_ = audio_manager;
359 }
360
361
354 } // namespace speech 362 } // namespace speech
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698