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
3 // found in the LICENSE file.
6 * @fileoverview The class to Manage both offline / online speech recognition.
9 <include src="plugin_manager.js"/>
10 <include src="audio_manager.js"/>
11 <include src="speech_recognition_manager.js"/>
13 cr.define('speech', function() {
17 * The state of speech recognition.
23 HOTWORD_RECOGNIZING: 'HOTWORD_RECOGNIZING',
24 RECOGNIZING: 'RECOGNIZING',
25 IN_SPEECH: 'IN_SPEECH',
30 * Checks the prefix for the hotword module based on the language. This is
31 * fragile if the file structure has changed.
33 function getHotwordPrefix() {
34 var prefix = navigator.language.toLowerCase();
35 if (prefix == 'en-gb')
37 var hyphen = prefix.indexOf('-');
39 prefix = prefix.substr(0, hyphen);
48 function SpeechManager() {
49 this.audioManager_ = new speech.AudioManager();
50 this.audioManager_.addEventListener('audio', this.onAudioLevel_.bind(this));
51 this.speechRecognitionManager_ = new speech.SpeechRecognitionManager(this);
57 * @param {SpeechState} newState The new state.
60 SpeechManager.prototype.setState_ = function(newState) {
61 if (this.state == newState)
64 this.state = newState;
65 chrome.send('setSpeechRecognitionState', [this.state]);
69 * Called with the mean audio level when audio data arrives.
71 * @param {cr.event.Event} event The event object for the audio data.
74 SpeechManager.prototype.onAudioLevel_ = function(event) {
75 var data = event.data;
77 for (var i = 0; i < data.length; ++i)
78 level += Math.abs(data[i]);
80 chrome.send('speechSoundLevel', [level]);
84 * Called when the hotword recognizer is ready.
86 * @param {PluginManager} pluginManager The hotword plugin manager which gets
90 SpeechManager.prototype.onHotwordRecognizerReady_ = function(pluginManager) {
91 this.pluginManager_ = pluginManager;
92 this.audioManager_.addEventListener(
93 'audio', pluginManager.sendAudioData.bind(pluginManager));
94 this.pluginManager_.startRecognizer();
95 this.audioManager_.start();
96 this.setState_(SpeechState.HOTWORD_RECOGNIZING);
100 * Called when an error happens for loading the hotword recognizer.
104 SpeechManager.prototype.onHotwordRecognizerLoadError_ = function() {
105 this.setHotwordEnabled(false);
106 this.setState_(SpeechState.READY);
110 * Called when the hotword is recognized.
114 SpeechManager.prototype.onHotwordRecognized_ = function() {
115 if (this.state != SpeechState.HOTWORD_RECOGNIZING)
117 this.pluginManager_.stopRecognizer();
118 this.speechRecognitionManager_.start();
122 * Called when the speech recognition has happened.
124 * @param {string} result The speech recognition result.
125 * @param {boolean} isFinal Whether the result is final or not.
127 SpeechManager.prototype.onSpeechRecognized = function(result, isFinal) {
128 chrome.send('speechResult', [result, isFinal]);
130 this.speechRecognitionManager_.stop();
134 * Called when the speech recognition has started.
136 SpeechManager.prototype.onSpeechRecognitionStarted = function() {
137 this.setState_(SpeechState.RECOGNIZING);
141 * Called when the speech recognition has ended.
143 SpeechManager.prototype.onSpeechRecognitionEnded = function() {
144 // Restarts the hotword recognition.
145 if (this.state != SpeechState.STOPPING && this.pluginManager_) {
146 this.pluginManager_.startRecognizer();
147 this.audioManager_.start();
148 this.setState_(SpeechState.HOTWORD_RECOGNIZING);
150 this.audioManager_.stop();
151 this.setState_(SpeechState.READY);
156 * Called when a speech has started.
158 SpeechManager.prototype.onSpeechStarted = function() {
159 if (this.state == SpeechState.RECOGNIZING)
160 this.setState_(SpeechState.IN_SPEECH);
164 * Called when a speech has ended.
166 SpeechManager.prototype.onSpeechEnded = function() {
167 if (this.state == SpeechState.IN_SPEECH)
168 this.setState_(SpeechState.RECOGNIZING);
172 * Called when an error happened during the speech recognition.
174 * @param {SpeechRecognitionError} e The error object.
176 SpeechManager.prototype.onSpeechRecognitionError = function(e) {
177 if (this.state != SpeechState.STOPPING)
178 this.setState_(SpeechState.READY);
182 * Changes the availability of the hotword plugin.
184 * @param {boolean} enabled Whether enabled or not.
186 SpeechManager.prototype.setHotwordEnabled = function(enabled) {
187 var recognizer = $('recognizer');
194 var prefix = getHotwordPrefix();
195 var pluginManager = new speech.PluginManager(
197 this.onHotwordRecognizerReady_.bind(this),
198 this.onHotwordRecognized_.bind(this),
199 this.onHotwordRecognizerLoadError_.bind(this));
200 var modelUrl = 'chrome://app-list/_platform_specific/' + this.naclArch +
201 '_' + prefix + '/hotword.data';
202 pluginManager.scheduleInitialize(this.audioManager_.sampleRate, modelUrl);
206 document.body.removeChild(recognizer);
207 this.pluginManager_ = null;
208 if (this.state == SpeechState.HOTWORD_RECOGNIZING) {
209 this.audioManager_.stop();
210 this.setState_(SpeechState.READY);
216 * Sets the NaCl architecture for the hotword module.
218 * @param {string} arch The architecture.
220 SpeechManager.prototype.setNaclArch = function(arch) {
221 this.naclArch = arch;
225 * Called when the app-list bubble is shown.
227 * @param {boolean} hotwordEnabled Whether the hotword is enabled or not.
229 SpeechManager.prototype.onShown = function(hotwordEnabled) {
230 this.setHotwordEnabled(hotwordEnabled);
232 // No one sets the state if the content is initialized on shown but hotword
233 // is not enabled. Sets the state in such case.
234 if (!this.state && !hotwordEnabled)
235 this.setState_(SpeechState.READY);
239 * Called when the app-list bubble is hidden.
241 SpeechManager.prototype.onHidden = function() {
242 this.setHotwordEnabled(false);
244 // SpeechRecognition is asynchronous.
245 this.audioManager_.stop();
246 if (this.state == SpeechState.RECOGNIZING ||
247 this.state == SpeechState.IN_SPEECH) {
248 this.setState_(SpeechState.STOPPING);
249 this.speechRecognitionManager_.stop();
251 this.setState_(SpeechState.READY);
256 * Toggles the current state of speech recognition.
258 SpeechManager.prototype.toggleSpeechRecognition = function() {
259 if (this.state == SpeechState.RECOGNIZING ||
260 this.state == SpeechState.IN_SPEECH) {
261 this.audioManager_.stop();
262 this.speechRecognitionManager_.stop();
264 if (this.pluginManager_)
265 this.pluginManager_.stopRecognizer();
266 if (this.audioManager_.state == speech.AudioState.STOPPED)
267 this.audioManager_.start();
268 this.speechRecognitionManager_.start();
273 SpeechManager: SpeechManager