summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-04 20:33:47 +0000
committermukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-04 20:33:47 +0000
commit67599659c5bc4f29b4b3b79c6af13c9e54099ea8 (patch)
treed28606cf0ad7402d225ced907df3d97d29e133a8
parentc45250451180afaa0412eb71aaa7f5a41c087474 (diff)
downloadchromium_src-67599659c5bc4f29b4b3b79c6af13c9e54099ea8.zip
chromium_src-67599659c5bc4f29b4b3b79c6af13c9e54099ea8.tar.gz
chromium_src-67599659c5bc4f29b4b3b79c6af13c9e54099ea8.tar.bz2
Removes the dependency between AudioManager and PluginManager.
Now AudioManager can listen the audio without hotword recognition. The mean volume level would be useful to the speech UI. BUG=313904 R=xiyuan@chromium.org TEST=manually Review URL: https://codereview.chromium.org/92863004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238753 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/resources/app_list/audio_manager.js69
-rw-r--r--chrome/browser/resources/app_list/plugin_manager.js15
-rw-r--r--chrome/browser/resources/app_list/speech_manager.js78
-rw-r--r--chrome/browser/resources/app_list/start_page.html1
4 files changed, 89 insertions, 74 deletions
diff --git a/chrome/browser/resources/app_list/audio_manager.js b/chrome/browser/resources/app_list/audio_manager.js
index 4f2a301..9862ac4 100644
--- a/chrome/browser/resources/app_list/audio_manager.js
+++ b/chrome/browser/resources/app_list/audio_manager.js
@@ -3,7 +3,7 @@
// found in the LICENSE file.
/**
- * @fileoverview The manager of audio streams and interaction with the plugin.
+ * @fileoverview The manager of audio streams.
*/
cr.define('speech', function() {
@@ -15,38 +15,21 @@ cr.define('speech', function() {
* @enum {number}
*/
var AudioState = {
- UNINITIALIZED: 0,
- READY: 1,
- RECOGNIZING: 2
+ STOPPED: 0,
+ LISTENING: 1
};
/**
* @constructor
+ * @extends {cr.EventTarget}
*/
- function AudioManager(onReady, onRecognizing, onRecognized) {
- this.state = AudioState.UNINITIALIZED;
- if (!speech.isPluginAvailable())
- return;
- this.onReady_ = onReady;
- this.onRecognizing_ = onRecognizing;
- this.pluginManager_ = new speech.PluginManager(
- this.onPluginReady_.bind(this), onRecognized);
+ function AudioManager() {
this.audioContext_ = new window.webkitAudioContext();
this.audioProc_ = null;
- this.pluginManager_.scheduleInitialize(
- this.audioContext_.sampleRate,
- 'chrome://app-list/okgoogle_hotword.config');
+ this.state = AudioState.STOPPED;
};
- /**
- * Called when the plugin is ready.
- *
- * @private
- */
- AudioManager.prototype.onPluginReady_ = function() {
- this.state = AudioState.READY;
- this.onReady_();
- };
+ AudioManager.prototype.__proto__ = cr.EventTarget.prototype;
/**
* Called when the audio data arrives.
@@ -59,7 +42,9 @@ cr.define('speech', function() {
var intData = new Int16Array(data.length);
for (var i = 0; i < data.length; ++i)
intData[i] = Math.round(data[i] * 32767);
- this.pluginManager_.sendAudioData(intData.buffer);
+ var event = new Event('audio');
+ event.data = intData;
+ this.dispatchEvent(event);
};
/**
@@ -76,27 +61,27 @@ cr.define('speech', function() {
audioIn.connect(this.audioProc_);
this.audioProc_.connect(this.audioContext_.destination);
- this.state = AudioState.RECOGNIZING;
- this.onRecognizing_();
+ this.state = AudioState.LISTENING;
};
/**
- * Starts the audio recognition with the plugin.
+ * Returns the sampling rate of the current audio context.
+ * @return {number} The sampling rate.
+ */
+ AudioManager.prototype.getSampleRate = function() {
+ return this.audioContext_.sampleRate;
+ };
+
+ /**
+ * Starts the audio processing.
*/
AudioManager.prototype.start = function() {
- // Not yet initialized.
- if (this.state != AudioState.READY)
- return;
- if (this.pluginManager_.state < speech.PluginState.READY)
+ if (this.state == AudioState.LISTENING)
return;
- if (this.pluginManager_.state == speech.PluginState.READY)
- this.pluginManager_.startRecognizer();
-
if (this.audioProc_) {
this.audioProc_.connect(this.audioContext_.destination);
- this.state = AudioState.RECOGNIZING;
- this.onRecognizing_();
+ this.state = AudioState.LISTENING;
return;
}
@@ -107,17 +92,17 @@ cr.define('speech', function() {
};
/**
- * Stops the audio recognition.
+ * Stops the audio processing.
*/
AudioManager.prototype.stop = function() {
- if (this.state <= AudioState.READY)
+ if (this.state != AudioState.LISTENING)
return;
this.audioProc_.disconnect();
- this.pluginManager_.stopRecognizer();
- this.state = AudioState.READY;
+ this.state = AudioState.STOPPED;
};
return {
- AudioManager: AudioManager
+ AudioManager: AudioManager,
+ AudioState: AudioState
};
});
diff --git a/chrome/browser/resources/app_list/plugin_manager.js b/chrome/browser/resources/app_list/plugin_manager.js
index 0bce749..fb8a604 100644
--- a/chrome/browser/resources/app_list/plugin_manager.js
+++ b/chrome/browser/resources/app_list/plugin_manager.js
@@ -75,7 +75,7 @@ cr.define('speech', function() {
if (messageEvent.data == 'audio') {
if (this.state < PluginState.READY)
- this.onReady_();
+ this.onReady_(this);
this.state = PluginState.RECOGNIZING;
} else if (messageEvent.data == 'stopped') {
this.state = PluginState.READY;
@@ -133,23 +133,26 @@ cr.define('speech', function() {
* Asks the plugin to start recognizing the hotword.
*/
PluginManager.prototype.startRecognizer = function() {
- $('recognizer').postMessage(pluginCommands.START_RECOGNIZING);
+ if (this.state == PluginState.READY)
+ $('recognizer').postMessage(pluginCommands.START_RECOGNIZING);
};
/**
* Asks the plugin to stop recognizing the hotword.
*/
PluginManager.prototype.stopRecognizer = function() {
- $('recognizer').postMessage(pluginCommands.STOP_RECOGNIZING);
+ if (this.state == PluginState.RECOGNIZING)
+ $('recognizer').postMessage(pluginCommands.STOP_RECOGNIZING);
};
/**
* Sends the actual audio wave data.
*
- * @param {ArrayBuffer} data The audio data to be recognized.
+ * @param {cr.event.Event} event The event for the audio data.
*/
- PluginManager.prototype.sendAudioData = function(data) {
- $('recognizer').postMessage(data);
+ PluginManager.prototype.sendAudioData = function(event) {
+ if (this.state == PluginState.RECOGNIZING)
+ $('recognizer').postMessage(event.data.buffer);
};
return {
diff --git a/chrome/browser/resources/app_list/speech_manager.js b/chrome/browser/resources/app_list/speech_manager.js
index 08284be..c55eab7 100644
--- a/chrome/browser/resources/app_list/speech_manager.js
+++ b/chrome/browser/resources/app_list/speech_manager.js
@@ -19,7 +19,6 @@ cr.define('speech', function() {
* @enum {string}
*/
var SpeechState = {
- UNINITIALIZED: 'UNINITIALIZED',
READY: 'READY',
HOTWORD_RECOGNIZING: 'HOTWORD_RECOGNIZING',
RECOGNIZING: 'RECOGNIZING'
@@ -29,12 +28,18 @@ cr.define('speech', function() {
* @constructor
*/
function SpeechManager() {
- this.audioManager_ = new speech.AudioManager(
- this.onHotwordRecognizerReady_.bind(this),
- this.onHotwordRecognizing_.bind(this),
- this.onHotwordRecognized_.bind(this));
+ this.audioManager_ = new speech.AudioManager();
+ this.audioManager_.addEventListener('audio', this.onAudioLevel_.bind(this));
+ if (speech.isPluginAvailable()) {
+ var pluginManager = new speech.PluginManager(
+ this.onHotwordRecognizerReady_.bind(this),
+ this.onHotwordRecognized_.bind(this));
+ pluginManager.scheduleInitialize(
+ this.audioManager_.getSampleRate(),
+ 'chrome://app-list/okgoogle_hotword.config');
+ }
this.speechRecognitionManager_ = new speech.SpeechRecognitionManager(this);
- this.setState_(SpeechState.UNINITIALIZED);
+ this.setState_(SpeechState.READY);
}
/**
@@ -49,11 +54,32 @@ cr.define('speech', function() {
};
/**
+ * Called with the mean audio level when audio data arrives.
+ *
+ * @param {cr.event.Event} event The event object for the audio data.
+ * @private
+ */
+ SpeechManager.prototype.onAudioLevel_ = function(event) {
+ var data = event.data;
+ var level = 0;
+ for (var i = 0; i < data.length; ++i)
+ level += Math.abs(data[i]);
+ level /= data.length;
+ // TODO(mukai): use the result to make the audio feedback during the speech
+ // recognition.
+ };
+
+ /**
* Called when the hotword recognizer is ready.
*
+ * @param {PluginManager} pluginManager The hotword plugin manager which gets
+ * ready.
* @private
*/
- SpeechManager.prototype.onHotwordRecognizerReady_ = function() {
+ SpeechManager.prototype.onHotwordRecognizerReady_ = function(pluginManager) {
+ this.pluginManager_ = pluginManager;
+ this.audioManager_.addEventListener(
+ 'audio', pluginManager.sendAudioData.bind(pluginManager));
this.setState_(SpeechState.READY);
};
@@ -66,21 +92,12 @@ cr.define('speech', function() {
SpeechManager.prototype.onHotwordRecognized_ = function(confidence) {
if (this.state != SpeechState.HOTWORD_RECOGNIZING)
return;
- this.audioManager_.stop();
this.setState_(SpeechState.READY);
+ this.pluginManager_.stopRecognizer();
this.speechRecognitionManager_.start();
};
/**
- * Called when the hotword recognition has started.
- *
- * @private
- */
- SpeechManager.prototype.onHotwordRecognizing_ = function() {
- this.setState_(SpeechState.HOTWORD_RECOGNIZING);
- };
-
- /**
* Called when the speech recognition has happened.
*
* @param {string} result The speech recognition result.
@@ -108,7 +125,13 @@ cr.define('speech', function() {
*/
SpeechManager.prototype.onSpeechRecognitionEnded = function() {
// Restarts the hotword recognition.
- this.audioManager_.start();
+ if (this.pluginManager_) {
+ this.pluginManager_.startRecognizer();
+ this.audioManager_.start();
+ this.setState_(SpeechState.HOTWORD_RECOGNIZING);
+ } else {
+ this.audioManager_.stop();
+ }
chrome.send('setSpeechRecognitionState', [false]);
};
@@ -118,33 +141,32 @@ cr.define('speech', function() {
* @param {SpeechRecognitionError} e The error object.
*/
SpeechManager.prototype.onSpeechRecognitionError = function(e) {
- this.setState_(SpeechState.UNINITIALIZED);
+ this.setState_(SpeechState.READY);
};
/**
* Starts the speech recognition session.
*/
SpeechManager.prototype.start = function() {
- if (this.state == SpeechState.UNINITIALIZED) {
- console.warn('hotword recognizer is not yet initialized');
+ if (!this.pluginManager_)
return;
- }
if (this.state != SpeechState.READY) {
console.warn('Already in recognition state...');
return;
}
+ this.pluginManager_.startRecognizer();
this.audioManager_.start();
+ this.setState_(SpeechState.HOTWORD_RECOGNIZING);
};
/**
* Stops the speech recognition session.
*/
SpeechManager.prototype.stop = function() {
- if (this.state == SpeechState.UNINITIALIZED)
- return;
-
+ if (this.pluginManager_)
+ this.pluginManager_.stopRecognizer();
this.audioManager_.stop();
this.speechRecognitionManager_.stop();
this.setState_(SpeechState.READY);
@@ -155,9 +177,13 @@ cr.define('speech', function() {
*/
SpeechManager.prototype.toggleSpeechRecognition = function() {
if (this.state == SpeechState.RECOGNIZING) {
+ this.audioManager_.stop();
this.speechRecognitionManager_.stop();
} else {
- this.audioManager_.stop();
+ if (this.pluginManager_)
+ this.pluginManager_.stopRecognizer();
+ if (this.audioManager_.state == speech.AudioState.STOPPED)
+ this.audioManager_.start();
this.speechRecognitionManager_.start();
}
};
diff --git a/chrome/browser/resources/app_list/start_page.html b/chrome/browser/resources/app_list/start_page.html
index 47a9167..2ff0961 100644
--- a/chrome/browser/resources/app_list/start_page.html
+++ b/chrome/browser/resources/app_list/start_page.html
@@ -5,6 +5,7 @@
<link rel="stylesheet" href="chrome://app-list/start_page.css">
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/js/cr.js"></script>
+ <script src="chrome://resources/js/cr/event_target.js"></script>
<script src="chrome://resources/js/cr/ui.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="chrome://app-list/strings.js"></script>