summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources/app_list/audio_manager.js
blob: 9862ac431247eb1987f4b28c763fd982bd4b3ffb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview The manager of audio streams.
 */

cr.define('speech', function() {
  'use strict';

  /**
   * The enum of the status of hotword audio recognition.
   *
   * @enum {number}
   */
  var AudioState = {
    STOPPED: 0,
    LISTENING: 1
  };

  /**
   * @constructor
   * @extends {cr.EventTarget}
   */
  function AudioManager() {
    this.audioContext_ = new window.webkitAudioContext();
    this.audioProc_ = null;
    this.state = AudioState.STOPPED;
  };

  AudioManager.prototype.__proto__ = cr.EventTarget.prototype;

  /**
   * Called when the audio data arrives.
   *
   * @param {Event} audioEvent The audio event.
   * @private
   */
  AudioManager.prototype.onAudioProcess_ = function(audioEvent) {
    var data = audioEvent.inputBuffer.getChannelData(0);
    var intData = new Int16Array(data.length);
    for (var i = 0; i < data.length; ++i)
      intData[i] = Math.round(data[i] * 32767);
    var event = new Event('audio');
    event.data = intData;
    this.dispatchEvent(event);
  };

  /**
   * Called when the audio stream is ready.
   *
   * @param {MediaStream} stream The media stream which is now available.
   * @private
   */
  AudioManager.prototype.onAudioReady_ = function(stream) {
    var audioIn = this.audioContext_.createMediaStreamSource(stream);
    this.audioProc_ = this.audioContext_.createScriptProcessor(
        4096 /* buffer size */, 1 /* channels */, 1 /* channels */);
    this.audioProc_.onaudioprocess = this.onAudioProcess_.bind(this);

    audioIn.connect(this.audioProc_);
    this.audioProc_.connect(this.audioContext_.destination);
    this.state = AudioState.LISTENING;
  };

  /**
   * 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() {
    if (this.state == AudioState.LISTENING)
      return;

    if (this.audioProc_) {
      this.audioProc_.connect(this.audioContext_.destination);
      this.state = AudioState.LISTENING;
      return;
    }

    navigator.webkitGetUserMedia(
        {audio: true},
        this.onAudioReady_.bind(this),
        function(msg) { console.error('Failed to getUserMedia: ' + msg); });
  };

  /**
   * Stops the audio processing.
   */
  AudioManager.prototype.stop = function() {
    if (this.state != AudioState.LISTENING)
      return;
    this.audioProc_.disconnect();
    this.state = AudioState.STOPPED;
  };

  return {
    AudioManager: AudioManager,
    AudioState: AudioState
  };
});