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

Side by Side Diff: chrome/browser/ui/app_list/speech_recognizer.cc

Issue 676593003: Implement native speech recognition for the launcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactor and address review comments. Created 6 years, 1 month 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
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/app_list/speech_recognizer.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/strings/string16.h"
11 #include "chrome/browser/ui/app_list/speech_recognizer_delegate.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/speech_recognition_manager.h"
15 #include "content/public/browser/speech_recognition_session_config.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/common/speech_recognition_error.h"
18
19 namespace app_list {
20
21 // 5 second timeout to cancel if there's no speech heard.
Matt Giuca 2014/11/03 02:35:52 "// Length of timeout ..." (don't include the valu
Anand Mistry (off Chromium) 2014/11/03 06:51:55 Done.
22 static const int kNoSpeechTimeoutInSeconds = 5;
23
24 SpeechRecognizer::SpeechRecognizer(
25 SpeechRecognizerDelegate* delegate,
26 net::URLRequestContextGetter* url_request_context_getter,
27 const std::string& locale)
28 : delegate_(delegate),
29 url_request_context_getter_(url_request_context_getter),
30 locale_(locale),
31 speech_timeout_(false, false),
32 session_(-1),
33 weak_factory_(this) {
34 }
35
36 SpeechRecognizer::~SpeechRecognizer() {
37 }
38
39 void SpeechRecognizer::Start() {
40 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
41 // The speech recognizer checks to see if the request is allowed by looking
42 // up the renderer process. A renderer containing the app-list is hard-coded
43 // to be allowed.
44 content::WebContents* contents = delegate_->GetSpeechContents();
45 if (!contents)
46 return;
47
48 content::BrowserThread::PostTask(
49 content::BrowserThread::IO,
50 FROM_HERE,
51 base::Bind(&SpeechRecognizer::StartOnIOThread,
52 this,
53 contents->GetRenderProcessHost()->GetID(),
54 url_request_context_getter_));
55 }
56
57 void SpeechRecognizer::StartOnIOThread(
58 int render_process_id,
59 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
60 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
61 if (session_ != -1)
62 StopOnIOThread();
63
64 content::SpeechRecognitionSessionConfig config;
65 config.language = locale_;
66 config.is_legacy_api = false;
67 config.continuous = true;
68 config.interim_results = true;
69 config.max_hypotheses = 1;
70 config.filter_profanities = true;
71 config.url_request_context_getter = url_request_context_getter;
72 config.event_listener = weak_factory_.GetWeakPtr();
73 config.initial_context.render_process_id = render_process_id;
74
75 auto speech_instance = content::SpeechRecognitionManager::GetInstance();
76 session_ = speech_instance->CreateSession(config);
77 speech_instance->StartSession(session_);
78 }
79
80 void SpeechRecognizer::Stop() {
81 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
82 content::BrowserThread::PostTask(
83 content::BrowserThread::IO,
84 FROM_HERE,
85 base::Bind(&SpeechRecognizer::StopOnIOThread, this));
86 }
87
88 void SpeechRecognizer::StopOnIOThread() {
89 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
90 if (session_ == -1)
91 return;
92
93 // Prevent recursion.
94 int session = session_;
95 session_ = -1;
96 StopSpeechTimeout();
97 content::SpeechRecognitionManager::GetInstance()->StopAudioCaptureForSession(
98 session);
99 }
100
101 void SpeechRecognizer::NotifyRecognitionStateChanged(
102 SpeechRecognitionState new_state) {
103 content::BrowserThread::PostTask(
104 content::BrowserThread::UI,
105 FROM_HERE,
106 base::Bind(&SpeechRecognizerDelegate::OnSpeechRecognitionStateChanged,
107 base::Unretained(delegate_),
108 new_state));
109 }
110
111 void SpeechRecognizer::StartSpeechTimeout() {
112 content::BrowserThread::PostTask(
113 content::BrowserThread::UI,
114 FROM_HERE,
115 base::Bind(&base::Timer::Start,
116 base::Unretained(&speech_timeout_),
117 FROM_HERE,
118 base::TimeDelta::FromSeconds(kNoSpeechTimeoutInSeconds),
119 base::Bind(&SpeechRecognizer::SpeechTimeout, this)));
120 }
121
122 void SpeechRecognizer::StopSpeechTimeout() {
123 content::BrowserThread::PostTask(
124 content::BrowserThread::UI,
125 FROM_HERE,
126 base::Bind(&base::Timer::Stop,
127 base::Unretained(&speech_timeout_)));
128 }
129
130 void SpeechRecognizer::SpeechTimeout() {
131 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
132 Stop();
133 }
134
135 void SpeechRecognizer::OnRecognitionStart(int session_id) {
136 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_RECOGNIZING);
137 }
138
139 void SpeechRecognizer::OnRecognitionEnd(int session_id) {
140 StopOnIOThread();
141 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_READY);
142 }
143
144 void SpeechRecognizer::OnRecognitionResults(
145 int session_id, const content::SpeechRecognitionResults& results) {
146 base::string16 result_str;
147 size_t final_count = 0;
148 for (const auto& result : results) {
149 if (!result.is_provisional)
150 final_count++;
151 result_str += result.hypotheses[0].utterance;
152 }
153 StopSpeechTimeout();
154 content::BrowserThread::PostTask(
155 content::BrowserThread::UI,
156 FROM_HERE,
157 base::Bind(&SpeechRecognizerDelegate::OnSpeechResult,
158 base::Unretained(delegate_),
159 result_str,
160 final_count == results.size()));
161
162 // Stop the moment we have a final result.
163 if (final_count == results.size())
164 StopOnIOThread();
165 }
166
167 void SpeechRecognizer::OnRecognitionError(
168 int session_id, const content::SpeechRecognitionError& error) {
169 StopOnIOThread();
170 if (error.code == content::SPEECH_RECOGNITION_ERROR_NETWORK) {
171 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_NETWORK_ERROR);
172 }
173 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_READY);
174 }
175
176 void SpeechRecognizer::OnSoundStart(int session_id) {
177 StartSpeechTimeout();
178 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_IN_SPEECH);
179 }
180
181 void SpeechRecognizer::OnSoundEnd(int session_id) {
182 StopOnIOThread();
183 NotifyRecognitionStateChanged(SPEECH_RECOGNITION_RECOGNIZING);
184 }
185
186 void SpeechRecognizer::OnAudioLevelsChange(
187 int session_id, float volume, float noise_volume) {
188 volume = std::max(0.0f, volume - noise_volume);
189 // Both |volume| and |noise_volume| are defined to be in the range [0.0, 1.0].
190 // See: content/public/browser/speech_recognition_event_listener.h
191 int16_t sound_level = static_cast<int16_t>(INT16_MAX * volume);
192 content::BrowserThread::PostTask(
193 content::BrowserThread::UI,
194 FROM_HERE,
195 base::Bind(&SpeechRecognizerDelegate::OnSpeechSoundLevelChanged,
196 base::Unretained(delegate_),
197 sound_level));
198 }
199
200 void SpeechRecognizer::OnEnvironmentEstimationComplete(int session_id) {
201 }
202
203 void SpeechRecognizer::OnAudioStart(int session_id) {
204 }
205
206 void SpeechRecognizer::OnAudioEnd(int session_id) {
207 }
208
209 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698