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

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

Issue 15907012: Implement SpeechRecognizerImplAndroid (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 6 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
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "content/browser/speech/speech_recognizer_impl_android.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/bind.h"
12 #include "base/utf_string_conversions.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/speech_recognition_event_listener.h"
15 #include "content/public/common/speech_recognition_grammar.h"
16 #include "content/public/common/speech_recognition_result.h"
17 #include "jni/SpeechRecognition_jni.h"
18
19 using base::android::AppendJavaStringArrayToStringVector;
20 using base::android::AttachCurrentThread;
21 using base::android::GetApplicationContext;
22 using base::android::JavaFloatArrayToFloatVector;
23
24 namespace content {
25
26 void SpeechRecognizerImplAndroid::Init(JNIEnv* env) {
27 RegisterNativesImpl(env);
28 }
29
30 SpeechRecognizerImplAndroid::SpeechRecognizerImplAndroid(
31 SpeechRecognitionEventListener* listener,
32 const SpeechRecognitionSessionConfig& config,
33 int session_id)
34 : SpeechRecognizer(listener, session_id),
35 config_(config) {
36 }
37
38 SpeechRecognizerImplAndroid::~SpeechRecognizerImplAndroid() { }
39
40 void SpeechRecognizerImplAndroid::StartRecognition() {
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
42 listener_->OnRecognitionStart(session_id_);
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 I'd like to have feedback by some other reviewer o
43 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
44 base::Bind(&content::SpeechRecognizerImplAndroid::StartRecognitionJNI,
45 this, config_.continuous, config_.interim_results));
46 }
47 void SpeechRecognizerImplAndroid::StartRecognitionJNI(bool continuous,
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Nit: \n
janx 2013/06/05 13:51:00 I was collating coupled functions together, but si
48 bool partial_results) {
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Why not keeping the interim_results name? I unders
janx 2013/06/05 13:51:00 Let's go with "interim" then.
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
50 j_recognition_.Reset(Java_SpeechRecognition_createSpeechRecognition(
51 AttachCurrentThread(),
52 GetApplicationContext(),
53 reinterpret_cast<jlong>(this)));
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 I am definitely not a JNI expert, so I'd like some
janx 2013/06/05 13:51:00 Fixed both occurences (this CL and http://crrev.co
54 Java_SpeechRecognition_StartRecognition(AttachCurrentThread(),
55 j_recognition_.obj(), continuous, partial_results);
56 }
57
58 void SpeechRecognizerImplAndroid::AbortRecognition() {
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
60 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
61 base::Bind(&content::SpeechRecognizerImplAndroid::CancelRecognitionJNI,
62 this));
63 OnRecognitionError(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_ABORTED));
64 listener_->OnRecognitionEnd(session_id_);
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Keep in mind that OnRecognitionEnd is the final ev
65 }
66 void SpeechRecognizerImplAndroid::CancelRecognitionJNI() {
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Similarly to my previous comment (on partial_resul
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Nit: \n (here and similarly below)
janx 2013/06/05 13:51:00 Done.
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
68 Java_SpeechRecognition_CancelRecognition(AttachCurrentThread(),
69 j_recognition_.obj());
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 At this point we must be sure that the JNI object
70 }
71
72 void SpeechRecognizerImplAndroid::StopAudioCapture() {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
74 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
75 base::Bind(&content::SpeechRecognizerImplAndroid::StopRecognitionJNI,
76 this));
77 listener_->OnRecognitionEnd(session_id_);
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Again: OnRecognitionEnd will cause the manager to
78 }
79 void SpeechRecognizerImplAndroid::StopRecognitionJNI() {
80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
81 Java_SpeechRecognition_StopRecognition(AttachCurrentThread(),
82 j_recognition_.obj());
83 }
84
85 bool SpeechRecognizerImplAndroid::IsActive() const {
86 return false; // FIXME
janx 2013/05/31 17:22:24 Recognition seems to work when IsActive() and IsCa
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Hmm, actually I think you should implement this. I
janx 2013/06/05 13:51:00 Thanks for your input, I'll go ahead and reimpleme
87 }
88
89 bool SpeechRecognizerImplAndroid::IsCapturingAudio() const {
90 return false; // FIXME
janx 2013/05/31 17:22:24 ditto
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Ditto :) Btw, you should be able to implement the
janx 2013/06/05 13:51:00 Done.
91 }
92
93 void SpeechRecognizerImplAndroid::OnAudioStartJNI(JNIEnv* env, jobject obj) {
94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
95 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
96 base::Bind(&SpeechRecognizerImplAndroid::OnAudioStart, this));
97 }
98 void SpeechRecognizerImplAndroid::OnAudioStart() {
99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
100 listener_->OnAudioStart(session_id_);
101 }
102
103 void SpeechRecognizerImplAndroid::OnSoundStartJNI(JNIEnv* env, jobject obj) {
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
105 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
106 base::Bind(&SpeechRecognizerImplAndroid::OnSoundStart, this));
107 }
108 void SpeechRecognizerImplAndroid::OnSoundStart() {
109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
110 listener_->OnSoundStart(session_id_);
111 }
112
113 void SpeechRecognizerImplAndroid::OnSoundEndJNI(JNIEnv* env, jobject obj) {
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
115 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
116 base::Bind(&SpeechRecognizerImplAndroid::OnSoundEnd, this));
117 }
118 void SpeechRecognizerImplAndroid::OnSoundEnd() {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
120 listener_->OnSoundEnd(session_id_);
121 // Since Android's speech API doesn't have an AudioEnd event, we emulate it.
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 It's ok emulating the event but not here. The same
janx 2013/06/05 13:51:00 Ok, I'll emulate the AudioEnd event in the Java fi
122 listener_->OnAudioEnd(session_id_);
123 }
124
125 void SpeechRecognizerImplAndroid::OnRecognitionResultsJNI(JNIEnv* env,
126 jobject obj, jobjectArray strings, jfloatArray floats,
127 jboolean partial) {
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
129 std::vector<string16> options;
130 AppendJavaStringArrayToStringVector(env, strings, &options);
131 std::vector<float> scores;
132 JavaFloatArrayToFloatVector(env, floats, &scores);
133 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
134 base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionResults,
135 this, options, scores, partial));
136 }
137 void SpeechRecognizerImplAndroid::OnRecognitionResults(
138 std::vector<string16> options, std::vector<float> scores,
139 bool partial) {
140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
141 SpeechRecognitionResults results;
142 results.push_back(SpeechRecognitionResult());
143 SpeechRecognitionResult& result = results.back();
144 for (unsigned int i = 0; i < options.size(); i++) {
145 result.hypotheses.push_back(
146 SpeechRecognitionHypothesis(options[i],
147 static_cast<double>(scores[i])));
148 }
149 result.is_provisional = partial;
150 listener_->OnRecognitionResults(session_id_, results);
151 }
152
153 void SpeechRecognizerImplAndroid::OnRecognitionErrorJNI(JNIEnv* env,
154 jobject obj, jint error) {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
156 SpeechRecognitionErrorCode code = SPEECH_RECOGNITION_ERROR_NONE;
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Is it actually possible to get another error code
janx 2013/06/05 13:51:00 SPEECH_RECOGNITION_ERROR_NONE is a hack and should
157
158 // Translate Android speech recognition errors to Web Speech API errors.
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 Can we move this translation in the .java file ? I
159 switch(error) {
160 case 3: // ERROR_AUDIO
161 code = SPEECH_RECOGNITION_ERROR_AUDIO;
162 break;
163 case 5: // ERROR_CLIENT
164 code = SPEECH_RECOGNITION_ERROR_ABORTED;
165 break;
166 case 8: // ERROR_RECOGNIZER_BUSY
167 case 9: // ERROR_INSUFFICIENT_PERMISSIONS
168 code = SPEECH_RECOGNITION_ERROR_NOT_ALLOWED;
169 break;
170 case 1: // ERROR_NETWORK_TIMEOUT
171 case 2: // ERROR_NETWORK
172 case 4: // ERROR_SERVER
173 code = SPEECH_RECOGNITION_ERROR_NETWORK;
174 break;
175 case 7: // ERROR_NO_MATCH
176 code = SPEECH_RECOGNITION_ERROR_NO_MATCH;
177 break;
178 case 6: // ERROR_SPEECH_TIMEOUT
179 code = SPEECH_RECOGNITION_ERROR_NO_SPEECH;
180 break;
181 }
182
183 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
184 base::Bind(&SpeechRecognizerImplAndroid::OnRecognitionError, this,
185 SpeechRecognitionError(code)));
186 }
187 void SpeechRecognizerImplAndroid::OnRecognitionError(
188 SpeechRecognitionError error) {
189 if (error.code != SPEECH_RECOGNITION_ERROR_NONE)
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 See previous comment, this shouldn't be required.
janx 2013/06/05 13:51:00 Removed.
190 listener_->OnRecognitionError(session_id_, error);
191 }
192
193 void SpeechRecognizerImplAndroid::OnAudioLevelsChangeJNI(JNIEnv* env,
194 jobject obj, jfloat rms) {
195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
196 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
197 base::Bind(&SpeechRecognizerImplAndroid::OnAudioLevelsChange, this, rms));
198 }
199 void SpeechRecognizerImplAndroid::OnAudioLevelsChange(float rms) {
200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
201 // FIXME set audio_level_ and noise_level from rms
janx 2013/05/31 17:22:24 The audio and noise levels are calculated from the
Primiano Tucci (use gerrit) 2013/06/03 16:24:11 I thinks that you can safely remove completely thi
janx 2013/06/05 13:51:00 Agreed, let's completely remove OnAudioLevelsChang
202 //listener_->OnAudioLevelsChange(session_id_,
203 // clip_detected ? 1.0f : audio_level_,
204 // noise_level);
205 }
206
207 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698