OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 /** | 5 /** |
6 * @fileoverview The class to Manage both offline / online speech recognition. | 6 * @fileoverview The class to Manage both offline / online speech recognition. |
7 */ | 7 */ |
8 | 8 |
9 <include src="plugin_manager.js"/> | 9 <include src="plugin_manager.js"/> |
10 <include src="audio_manager.js"/> | 10 <include src="audio_manager.js"/> |
11 <include src="speech_recognition_manager.js"/> | 11 <include src="speech_recognition_manager.js"/> |
12 | 12 |
13 cr.define('speech', function() { | 13 cr.define('speech', function() { |
14 'use strict'; | 14 'use strict'; |
15 | 15 |
16 /** | 16 /** |
17 * The state of speech recognition. | 17 * The state of speech recognition. |
18 * | 18 * |
19 * @enum {string} | 19 * @enum {string} |
20 */ | 20 */ |
21 var SpeechState = { | 21 var SpeechState = { |
22 READY: 'READY', | 22 READY: 'READY', |
23 HOTWORD_RECOGNIZING: 'HOTWORD_RECOGNIZING', | 23 HOTWORD_RECOGNIZING: 'HOTWORD_RECOGNIZING', |
24 RECOGNIZING: 'RECOGNIZING', | 24 RECOGNIZING: 'RECOGNIZING', |
| 25 IN_SPEECH: 'IN_SPEECH', |
25 STOPPING: 'STOPPING' | 26 STOPPING: 'STOPPING' |
26 }; | 27 }; |
27 | 28 |
28 /** | 29 /** |
29 * @constructor | 30 * @constructor |
30 */ | 31 */ |
31 function SpeechManager() { | 32 function SpeechManager() { |
32 this.audioManager_ = new speech.AudioManager(); | 33 this.audioManager_ = new speech.AudioManager(); |
33 this.audioManager_.addEventListener('audio', this.onAudioLevel_.bind(this)); | 34 this.audioManager_.addEventListener('audio', this.onAudioLevel_.bind(this)); |
34 if (speech.isPluginAvailable()) { | 35 if (speech.isPluginAvailable()) { |
35 var pluginManager = new speech.PluginManager( | 36 var pluginManager = new speech.PluginManager( |
36 this.onHotwordRecognizerReady_.bind(this), | 37 this.onHotwordRecognizerReady_.bind(this), |
37 this.onHotwordRecognized_.bind(this)); | 38 this.onHotwordRecognized_.bind(this)); |
38 pluginManager.scheduleInitialize( | 39 pluginManager.scheduleInitialize( |
39 this.audioManager_.getSampleRate(), | 40 this.audioManager_.getSampleRate(), |
40 'chrome://app-list/okgoogle_hotword.config'); | 41 'chrome://app-list/okgoogle_hotword.config'); |
41 } | 42 } |
| 43 this.shown_ = false; |
42 this.speechRecognitionManager_ = new speech.SpeechRecognitionManager(this); | 44 this.speechRecognitionManager_ = new speech.SpeechRecognitionManager(this); |
43 this.setState_(SpeechState.READY); | 45 this.setState_(SpeechState.READY); |
44 } | 46 } |
45 | 47 |
46 /** | 48 /** |
47 * Updates the state. | 49 * Updates the state. |
48 * | 50 * |
49 * @param {SpeechState} newState The new state. | 51 * @param {SpeechState} newState The new state. |
50 * @private | 52 * @private |
51 */ | 53 */ |
52 SpeechManager.prototype.setState_ = function(newState) { | 54 SpeechManager.prototype.setState_ = function(newState) { |
53 this.state = newState; | 55 this.state = newState; |
| 56 chrome.send('setSpeechRecognitionState', [this.state]); |
54 }; | 57 }; |
55 | 58 |
56 /** | 59 /** |
57 * Called with the mean audio level when audio data arrives. | 60 * Called with the mean audio level when audio data arrives. |
58 * | 61 * |
59 * @param {cr.event.Event} event The event object for the audio data. | 62 * @param {cr.event.Event} event The event object for the audio data. |
60 * @private | 63 * @private |
61 */ | 64 */ |
62 SpeechManager.prototype.onAudioLevel_ = function(event) { | 65 SpeechManager.prototype.onAudioLevel_ = function(event) { |
63 var data = event.data; | 66 var data = event.data; |
64 var level = 0; | 67 var level = 0; |
65 for (var i = 0; i < data.length; ++i) | 68 for (var i = 0; i < data.length; ++i) |
66 level += Math.abs(data[i]); | 69 level += Math.abs(data[i]); |
67 level /= data.length; | 70 level /= data.length; |
68 chrome.send('speechSoundLevel', [level]); | 71 chrome.send('speechSoundLevel', [level]); |
69 }; | 72 }; |
70 | 73 |
71 /** | 74 /** |
72 * Called when the hotword recognizer is ready. | 75 * Called when the hotword recognizer is ready. |
73 * | 76 * |
74 * @param {PluginManager} pluginManager The hotword plugin manager which gets | 77 * @param {PluginManager} pluginManager The hotword plugin manager which gets |
75 * ready. | 78 * ready. |
76 * @private | 79 * @private |
77 */ | 80 */ |
78 SpeechManager.prototype.onHotwordRecognizerReady_ = function(pluginManager) { | 81 SpeechManager.prototype.onHotwordRecognizerReady_ = function(pluginManager) { |
79 this.pluginManager_ = pluginManager; | 82 this.pluginManager_ = pluginManager; |
80 this.audioManager_.addEventListener( | 83 this.audioManager_.addEventListener( |
81 'audio', pluginManager.sendAudioData.bind(pluginManager)); | 84 'audio', pluginManager.sendAudioData.bind(pluginManager)); |
82 this.setState_(SpeechState.READY); | 85 if (this.shown_) { |
| 86 this.pluginManager_.startRecognizer(); |
| 87 this.audioManager_.start(); |
| 88 this.setState_(SpeechState.HOTWORD_RECOGNIZING); |
| 89 } else { |
| 90 this.setState_(SpeechState.READY); |
| 91 } |
83 }; | 92 }; |
84 | 93 |
85 /** | 94 /** |
86 * Called when the hotword is recognized. | 95 * Called when the hotword is recognized. |
87 * | 96 * |
88 * @param {number} confidence The confidence store of the recognition. | 97 * @param {number} confidence The confidence store of the recognition. |
89 * @private | 98 * @private |
90 */ | 99 */ |
91 SpeechManager.prototype.onHotwordRecognized_ = function(confidence) { | 100 SpeechManager.prototype.onHotwordRecognized_ = function(confidence) { |
92 if (this.state != SpeechState.HOTWORD_RECOGNIZING) | 101 if (this.state != SpeechState.HOTWORD_RECOGNIZING) |
(...skipping 13 matching lines...) Expand all Loading... |
106 chrome.send('speechResult', [result, isFinal]); | 115 chrome.send('speechResult', [result, isFinal]); |
107 if (isFinal) | 116 if (isFinal) |
108 this.speechRecognitionManager_.stop(); | 117 this.speechRecognitionManager_.stop(); |
109 }; | 118 }; |
110 | 119 |
111 /** | 120 /** |
112 * Called when the speech recognition has started. | 121 * Called when the speech recognition has started. |
113 */ | 122 */ |
114 SpeechManager.prototype.onSpeechRecognitionStarted = function() { | 123 SpeechManager.prototype.onSpeechRecognitionStarted = function() { |
115 this.setState_(SpeechState.RECOGNIZING); | 124 this.setState_(SpeechState.RECOGNIZING); |
116 chrome.send('setSpeechRecognitionState', ['on']); | |
117 }; | 125 }; |
118 | 126 |
119 /** | 127 /** |
120 * Called when the speech recognition has ended. | 128 * Called when the speech recognition has ended. |
121 */ | 129 */ |
122 SpeechManager.prototype.onSpeechRecognitionEnded = function() { | 130 SpeechManager.prototype.onSpeechRecognitionEnded = function() { |
123 // Restarts the hotword recognition. | 131 // Restarts the hotword recognition. |
124 if (this.state != SpeechState.STOPPING && this.pluginManager_) { | 132 if (this.state != SpeechState.STOPPING && this.pluginManager_) { |
125 this.pluginManager_.startRecognizer(); | 133 this.pluginManager_.startRecognizer(); |
126 this.audioManager_.start(); | 134 this.audioManager_.start(); |
127 this.setState_(SpeechState.HOTWORD_RECOGNIZING); | 135 this.setState_(SpeechState.HOTWORD_RECOGNIZING); |
128 } else { | 136 } else { |
129 this.audioManager_.stop(); | 137 this.audioManager_.stop(); |
130 } | 138 } |
131 chrome.send('setSpeechRecognitionState', ['off']); | 139 chrome.send('setSpeechRecognitionState', ['off']); |
132 }; | 140 }; |
133 | 141 |
134 /** | 142 /** |
135 * Called when a speech has started. | 143 * Called when a speech has started. |
136 */ | 144 */ |
137 SpeechManager.prototype.onSpeechStarted = function() { | 145 SpeechManager.prototype.onSpeechStarted = function() { |
138 if (this.state == SpeechState.RECOGNIZING) | 146 if (this.state == SpeechState.RECOGNIZING) |
139 chrome.send('setSpeechRecognitionState', ['in-speech']); | 147 this.setState_(SpeechState.IN_SPEECH); |
140 }; | 148 }; |
141 | 149 |
142 /** | 150 /** |
143 * Called when a speech has ended. | 151 * Called when a speech has ended. |
144 */ | 152 */ |
145 SpeechManager.prototype.onSpeechEnded = function() { | 153 SpeechManager.prototype.onSpeechEnded = function() { |
146 if (this.state == SpeechState.RECOGNIZING) | 154 if (this.state == SpeechState.IN_SPEECH) |
147 chrome.send('setSpeechRecognitionState', ['on']); | 155 this.setState_(SpeechState.RECOGNIZING); |
148 }; | 156 }; |
149 | 157 |
150 /** | 158 /** |
151 * Called when an error happened during the speech recognition. | 159 * Called when an error happened during the speech recognition. |
152 * | 160 * |
153 * @param {SpeechRecognitionError} e The error object. | 161 * @param {SpeechRecognitionError} e The error object. |
154 */ | 162 */ |
155 SpeechManager.prototype.onSpeechRecognitionError = function(e) { | 163 SpeechManager.prototype.onSpeechRecognitionError = function(e) { |
156 if (this.state != SpeechState.STOPPING) | 164 if (this.state != SpeechState.STOPPING) |
157 this.setState_(SpeechState.READY); | 165 this.setState_(SpeechState.READY); |
158 }; | 166 }; |
159 | 167 |
160 /** | 168 /** |
161 * Starts the speech recognition session. | 169 * Called when the app-list bubble is shown. |
162 */ | 170 */ |
163 SpeechManager.prototype.start = function() { | 171 SpeechManager.prototype.onShown = function() { |
| 172 this.shown_ = true; |
164 if (!this.pluginManager_) | 173 if (!this.pluginManager_) |
165 return; | 174 return; |
166 | 175 |
167 if (this.state == SpeechState.HOTWORD_RECOGNIZING) { | 176 if (this.state == SpeechState.HOTWORD_RECOGNIZING) { |
168 console.warn('Already in recognition state...'); | 177 console.warn('Already in recognition state...'); |
169 return; | 178 return; |
170 } | 179 } |
171 | 180 |
172 this.pluginManager_.startRecognizer(); | 181 this.pluginManager_.startRecognizer(); |
173 this.audioManager_.start(); | 182 this.audioManager_.start(); |
174 this.setState_(SpeechState.HOTWORD_RECOGNIZING); | 183 this.setState_(SpeechState.HOTWORD_RECOGNIZING); |
175 }; | 184 }; |
176 | 185 |
177 /** | 186 /** |
178 * Stops the speech recognition session. | 187 * Called when the app-list bubble is hidden. |
179 */ | 188 */ |
180 SpeechManager.prototype.stop = function() { | 189 SpeechManager.prototype.onHidden = function() { |
| 190 this.shown_ = false; |
181 if (this.pluginManager_) | 191 if (this.pluginManager_) |
182 this.pluginManager_.stopRecognizer(); | 192 this.pluginManager_.stopRecognizer(); |
183 | 193 |
184 // SpeechRecognition is asynchronous. | 194 // SpeechRecognition is asynchronous. |
185 this.audioManager_.stop(); | 195 this.audioManager_.stop(); |
186 if (this.state == SpeechState.RECOGNIZING) { | 196 if (this.state == SpeechState.RECOGNIZING || |
| 197 this.state == SpeechState.IN_SPEECH) { |
187 this.setState_(SpeechState.STOPPING); | 198 this.setState_(SpeechState.STOPPING); |
188 this.speechRecognitionManager_.stop(); | 199 this.speechRecognitionManager_.stop(); |
189 } else { | 200 } else { |
190 this.setState_(SpeechState.READY); | 201 this.setState_(SpeechState.READY); |
191 } | 202 } |
192 }; | 203 }; |
193 | 204 |
194 /** | 205 /** |
195 * Toggles the current state of speech recognition. | 206 * Toggles the current state of speech recognition. |
196 */ | 207 */ |
197 SpeechManager.prototype.toggleSpeechRecognition = function() { | 208 SpeechManager.prototype.toggleSpeechRecognition = function() { |
198 if (this.state == SpeechState.RECOGNIZING) { | 209 if (this.state == SpeechState.RECOGNIZING || |
| 210 this.state == SpeechState.IN_SPEECH) { |
199 this.audioManager_.stop(); | 211 this.audioManager_.stop(); |
200 this.speechRecognitionManager_.stop(); | 212 this.speechRecognitionManager_.stop(); |
201 } else { | 213 } else { |
202 if (this.pluginManager_) | 214 if (this.pluginManager_) |
203 this.pluginManager_.stopRecognizer(); | 215 this.pluginManager_.stopRecognizer(); |
204 if (this.audioManager_.state == speech.AudioState.STOPPED) | 216 if (this.audioManager_.state == speech.AudioState.STOPPED) |
205 this.audioManager_.start(); | 217 this.audioManager_.start(); |
206 this.speechRecognitionManager_.start(); | 218 this.speechRecognitionManager_.start(); |
207 } | 219 } |
208 }; | 220 }; |
209 | 221 |
210 return { | 222 return { |
211 SpeechManager: SpeechManager | 223 SpeechManager: SpeechManager |
212 }; | 224 }; |
213 }); | 225 }); |
OLD | NEW |