OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 /** |
| 6 * @fileoverview The manager of offline hotword speech recognizer plugin. |
| 7 */ |
| 8 |
| 9 cr.define('speech', function() { |
| 10 'use strict'; |
| 11 |
| 12 /** |
| 13 * The type of the plugin state. |
| 14 ** @enum {number} |
| 15 */ |
| 16 var PluginState = { |
| 17 UNINITIALIZED: 0, |
| 18 LOADED: 1, |
| 19 SAMPLING_RATE_READY: 2, |
| 20 READY: 3, |
| 21 RECOGNIZING: 4 |
| 22 }; |
| 23 |
| 24 /** |
| 25 * The command names of the plugin. |
| 26 * @enum {string} |
| 27 */ |
| 28 var pluginCommands = { |
| 29 SET_SAMPLING_RATE: 'h', |
| 30 SET_CONFIG: 'm', |
| 31 START_RECOGNIZING: 'r', |
| 32 STOP_RECOGNIZING: 's' |
| 33 }; |
| 34 |
| 35 /** |
| 36 * The regexp pattern of the hotword recognition result. |
| 37 */ |
| 38 var recognitionPattern = /^HotwordFiredEvent: \[(.*)\] confidence: (.*)/; |
| 39 |
| 40 /** |
| 41 * Checks the availability of the plugin. |
| 42 * @return {boolean} True only if the plugin is available. |
| 43 */ |
| 44 function isPluginAvailable() { |
| 45 return !!($('recognizer') && $('recognizer').postMessage); |
| 46 } |
| 47 |
| 48 /** |
| 49 * @constructor |
| 50 */ |
| 51 function PluginManager(onReady, onRecognized) { |
| 52 this.state = PluginState.UNINITIALIZED; |
| 53 this.onReady_ = onReady; |
| 54 this.onRecognized_ = onRecognized; |
| 55 this.samplingRate_ = null; |
| 56 this.config_ = null; |
| 57 if (isPluginAvailable()) { |
| 58 $('recognizer').addEventListener('message', this.onMessage_.bind(this)); |
| 59 $('recognizer').addEventListener('load', this.onLoad_.bind(this)); |
| 60 } |
| 61 }; |
| 62 |
| 63 /** |
| 64 * The event handler of the plugin status. |
| 65 * |
| 66 * @param {Event} messageEvent the event object from the plugin. |
| 67 * @private |
| 68 */ |
| 69 PluginManager.prototype.onMessage_ = function(messageEvent) { |
| 70 if (this.state == PluginState.LOADED) { |
| 71 if (messageEvent.data == 'stopped') |
| 72 this.state = PluginState.SAMPLING_RATE_READY; |
| 73 return; |
| 74 } |
| 75 |
| 76 if (messageEvent.data == 'audio') { |
| 77 if (this.state < PluginState.READY) |
| 78 this.onReady_(); |
| 79 this.state = PluginState.RECOGNIZING; |
| 80 } else if (messageEvent.data == 'stopped') { |
| 81 this.state = PluginState.READY; |
| 82 } else { |
| 83 var matched = recognitionPattern.exec(messageEvent.data); |
| 84 if (matched && matched[1] == 'hotword_ok_google') |
| 85 this.onRecognized_(Number(matched[2])); |
| 86 } |
| 87 }; |
| 88 |
| 89 /** |
| 90 * The event handler when the plugin is loaded. |
| 91 * |
| 92 * @private |
| 93 */ |
| 94 PluginManager.prototype.onLoad_ = function() { |
| 95 if (this.state == PluginState.UNINITIALIZED) { |
| 96 this.state = PluginState.LOADED; |
| 97 if (this.samplingRate_ && this.config_) |
| 98 this.initialize_(this.samplingRate_, this.config_); |
| 99 } |
| 100 }; |
| 101 |
| 102 /** |
| 103 * Sends the initialization messages to the plugin. This method is private. |
| 104 * The initialization will happen from onLoad_ or scheduleInitialize. |
| 105 * |
| 106 * @param {number} samplingRate the sampling rate the plugin accepts. |
| 107 * @param {string} config the url of the config file. |
| 108 * @private |
| 109 */ |
| 110 PluginManager.prototype.initialize_ = function(samplingRate, config) { |
| 111 $('recognizer').postMessage( |
| 112 pluginCommands.SET_SAMPLING_RATE + samplingRate); |
| 113 $('recognizer').postMessage(pluginCommands.SET_CONFIG + config); |
| 114 }; |
| 115 |
| 116 /** |
| 117 * Initializes the plugin with the specified parameter, or schedules the |
| 118 * initialization if the plugin is not ready. |
| 119 * |
| 120 * @param {number} samplingRate the sampling rate the plugin accepts. |
| 121 * @param {string} config the url of the config file. |
| 122 */ |
| 123 PluginManager.prototype.scheduleInitialize = function(samplingRate, config) { |
| 124 if (this.state == PluginState.UNINITIALIZED) { |
| 125 this.samplingRate_ = samplingRate; |
| 126 this.config_ = config; |
| 127 } else { |
| 128 this.initialize_(samplingRate, config); |
| 129 } |
| 130 }; |
| 131 |
| 132 /** |
| 133 * Asks the plugin to start recognizing the hotword. |
| 134 */ |
| 135 PluginManager.prototype.startRecognizer = function() { |
| 136 $('recognizer').postMessage(pluginCommands.START_RECOGNIZING); |
| 137 }; |
| 138 |
| 139 /** |
| 140 * Asks the plugin to stop recognizing the hotword. |
| 141 */ |
| 142 PluginManager.prototype.stopRecognizer = function() { |
| 143 $('recognizer').postMessage(pluginCommands.STOP_RECOGNIZING); |
| 144 }; |
| 145 |
| 146 /** |
| 147 * Sends the actual audio wave data. |
| 148 * |
| 149 * @param {ArrayBuffer} data The audio data to be recognized. |
| 150 */ |
| 151 PluginManager.prototype.sendAudioData = function(data) { |
| 152 $('recognizer').postMessage(data); |
| 153 }; |
| 154 |
| 155 return { |
| 156 PluginManager: PluginManager, |
| 157 PluginState: PluginState, |
| 158 isPluginAvailable: isPluginAvailable |
| 159 }; |
| 160 }); |
OLD | NEW |