summaryrefslogtreecommitdiff
path: root/scripts/mic_testing/frontend/recorder.js
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mic_testing/frontend/recorder.js')
-rw-r--r--scripts/mic_testing/frontend/recorder.js366
1 files changed, 0 insertions, 366 deletions
diff --git a/scripts/mic_testing/frontend/recorder.js b/scripts/mic_testing/frontend/recorder.js
deleted file mode 100644
index 92f2766f..00000000
--- a/scripts/mic_testing/frontend/recorder.js
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-var Recorder = function(source){
- var bufferLen = 4096;
- var toneFreq = 1000, errorMargin = 0.05;
-
- var context = source.context;
- var sampleRate = context.sampleRate;
- var recBuffersL = [], recBuffersR = [], recLength = 0;
- this.node = (context.createScriptProcessor ||
- context.createJavaScriptNode).call(context, bufferLen, 2, 2);
- var detectAppend = false, autoStop = false, recordCallback;
- var recording = false;
- var freqString;
-
- this.node.onaudioprocess = function(e) {
- if (!recording) return;
-
- var length = e.inputBuffer.getChannelData(0).length;
- var tmpLeft = new Float32Array(length);
- var tmpRight = new Float32Array(length);
- tmpLeft.set(e.inputBuffer.getChannelData(0), 0);
- tmpRight.set(e.inputBuffer.getChannelData(1), 0);
-
- recBuffersL.push(tmpLeft);
- recBuffersR.push(tmpRight);
- recLength += length;
- var stop = false;
-
- if (autoStop && detectTone(getFreqList(tmpLeft)))
- stop = true;
-
- if (recordCallback) {
- var tmpLeft = recBuffersL[recBuffersL.length - 1].subarray(
- -FFT_SIZE-1, -1);
- var tmpRight = recBuffersR[recBuffersR.length - 1].subarray(
- -FFT_SIZE-1, -1);
- recordCallback(tmpLeft, tmpRight, sampleRate, stop);
- }
- }
-
- /**
- * Starts recording
- * @param {function} callback function to get current buffer
- * @param {boolean} detect append tone or not
- * @param {boolean} auto stop when detecting append tone
- */
- this.record = function(cb, detect, stop) {
- recordCallback = cb;
- detectAppend = detect;
- autoStop = stop;
- recording = true;
- }
-
- /**
- * Stops recording
- */
- this.stop = function() {
- recording = false;
- recBuffersL = mergeBuffers(recBuffersL, recLength);
- recBuffersR = mergeBuffers(recBuffersR, recLength);
- if (detectAppend) {
- var freqList = getFreqList(recBuffersL);
- var index = getToneIndices(freqList);
- removeAppendTone(index[0], index[1]);
- exportFreqList(freqList);
- }
- }
-
- /**
- * Gets frequencies list
- * @param {Float32Array} buffer
- * @return {array} frequencies list
- */
- getFreqList = function(buffer) {
- var prevPeak = 0;
- var valid = true;
- var freqList = [];
- for (i = 1; i < recLength; i++) {
- if (buffer[i] > 0.1 &&
- buffer[i] >= buffer[i - 1] && buffer[i] >= buffer[i + 1]) {
- if (valid) {
- var freq = sampleRate / (i - prevPeak);
- freqList.push([freq, prevPeak, i]);
- prevPeak = i;
- valid = false;
- }
- } else if (buffer[i] < -0.1) {
- valid = true;
- }
- }
- return freqList;
- }
-
- /**
- * Checks average frequency is in allowed error margin
- * @param {float} average frequency
- * @return {boolean} checked result pass or fail
- */
- checkFreq = function (average) {
- if (Math.abs(average - toneFreq) / toneFreq < errorMargin)
- return true;
- return false;
- }
-
- /**
- * Detects append tone while recording.
- * @param {array} frequencies list
- * @return {boolean} detected or not
- */
- detectTone = function(freqList) {
- var passCriterion = 50;
- // Initialize function static variables
- if (typeof detectTone.startDetected == 'undefined') {
- detectTone.startDetected = false;
- detectTone.canStop = false;
- detectTone.accumulateTone = 0;
- }
-
- var windowSize = 10, windowSum = 0, i;
- var detected = false;
- for (i = 0; i < freqList.length && i < windowSize; i++) {
- windowSum += freqList[i][0];
- }
- if (checkFreq(windowSum / Math.min(windowSize, freqList.length))) {
- detected = true;
- detectTone.accumulateTone++;
- }
- for (; i < freqList.length; i++) {
- windowSum = windowSum + freqList[i][0] - freqList[i - windowSize][0];
- if (checkFreq(windowSum / windowSize)) {
- detected = true;
- detectTone.accumulateTone++;
- }
- }
- if (detected) {
- if (detectTone.accumulateTone > passCriterion) {
- if (!detectTone.startDetected)
- detectTone.startDetected = true;
- else if (detectTone.canStop) {
- detectTone.startDetected = false;
- detectTone.canStop = false;
- detectTone.accumulateTone = 0;
- return true;
- }
- }
- } else {
- detectTone.accumulateTone = 0;
- if (detectTone.startDetected)
- detectTone.canStop = true;
- }
- return false;
- }
-
- /**
- * Gets start and end indices from a frquencies list except append tone
- * @param {array} frequencies list
- * @return {array} start and end indices
- */
- getToneIndices = function(freqList) {
- // find start and end indices
- var flag, j, k;
- var windowSize = 10, windowSum;
- var index = new Array(2);
- var scanRange = [[0, freqList.length, 1], [freqList.length - 1, -1, -1]];
-
- if (freqList.length == 0) return index;
-
- for (i = 0; i < 2; i++) {
- flag = false;
- windowSum = 0;
- for (j = scanRange[i][0], k = 0; k < windowSize && j != scanRange[i][1];
- j += scanRange[i][2], k++) {
- windowSum += freqList[j][0];
- }
- for (; j != scanRange[i][1]; j += scanRange[i][2]) {
- windowSum = windowSum + freqList[j][0] -
- freqList[j - scanRange[i][2] * windowSize][0];
- var avg = windowSum / windowSize;
- if (checkFreq(avg) && !flag) {
- flag = true;
- }
- if (!checkFreq(avg) && flag) {
- index[i] = freqList[j][1];
- break;
- }
- }
- }
- return index;
- }
-
- /**
- * Removes append tone from recorded buffer
- * @param {int} start index
- * @param {int} end index
- */
- removeAppendTone = function(start, end) {
- if (!isNaN(start) && !isNaN(end) && end > start) {
- recBuffersL = truncateBuffers(recBuffersL, recLength, start, end);
- recBuffersR = truncateBuffers(recBuffersR, recLength, start, end);
- recLength = end - start;
- }
- }
-
- /**
- * Exports frequency list for debugging purpose
- */
- exportFreqList = function(freqList) {
- freqString = sampleRate + '\n';
- for (var i = 0; i < freqList.length; i++) {
- freqString += freqList[i][0] + ' ' + freqList[i][1] + ' ' +
- freqList[i][2] + '\n';
- }
- }
-
- this.getFreq = function() {
- return freqString;
- }
-
- /**
- * Clears recorded buffer
- */
- this.clear = function() {
- recLength = 0;
- recBuffersL = [];
- recBuffersR = [];
- }
-
- /**
- * Gets recorded buffer
- */
- this.getBuffer = function() {
- var buffers = [];
- buffers.push(recBuffersL);
- buffers.push(recBuffersR);
- return buffers;
- }
-
- /**
- * Exports WAV format file
- * @return {blob} audio file blob
- */
- this.exportWAV = function(type) {
- type = type || 'audio/wav';
- var interleaved = interleave(recBuffersL, recBuffersR);
- var dataview = encodeWAV(interleaved);
- var audioBlob = new Blob([dataview], { type: type });
- return audioBlob;
- }
-
- /**
- * Truncates buffer from start index to end index
- * @param {Float32Array} audio buffer
- * @param {int} buffer length
- * @param {int} start index
- * @param {int} end index
- * @return {Float32Array} a truncated buffer
- */
- truncateBuffers = function(recBuffers, recLength, startIdx, endIdx) {
- var buffer = new Float32Array(endIdx - startIdx);
- for (var i = startIdx, j = 0; i < endIdx; i++, j++) {
- buffer[j] = recBuffers[i];
- }
- return buffer;
- }
-
- /**
- * Merges buffer into an array
- * @param {array} a list of Float32Array of audio buffer
- * @param {int} buffer length
- * @return {Float32Array} a merged buffer
- */
- mergeBuffers = function(recBuffers, recLength) {
- var result = new Float32Array(recLength);
- var offset = 0;
- for (var i = 0; i < recBuffers.length; i++){
- result.set(recBuffers[i], offset);
- offset += recBuffers[i].length;
- }
- return result;
- }
-
- /**
- * Interleaves left and right channel buffer
- * @param {Float32Array} left channel buffer
- * @param {Float32Array} right channel buffer
- * @return {Float32Array} an interleaved buffer
- */
- interleave = function(inputL, inputR) {
- var length = inputL.length + inputR.length;
- var result = new Float32Array(length);
-
- var index = 0,
- inputIndex = 0;
-
- while (index < length){
- result[index++] = inputL[inputIndex];
- result[index++] = inputR[inputIndex];
- inputIndex++;
- }
- return result;
- }
-
- floatTo16BitPCM = function(output, offset, input) {
- for (var i = 0; i < input.length; i++, offset+=2){
- var s = Math.max(-1, Math.min(1, input[i]));
- output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
- }
- }
-
- writeString = function(view, offset, string) {
- for (var i = 0; i < string.length; i++){
- view.setUint8(offset + i, string.charCodeAt(i));
- }
- }
-
- /**
- * Encodes audio buffer into WAV format raw data
- * @param {Float32Array} an interleaved buffer
- * @return {DataView} WAV format raw data
- */
- encodeWAV = function(samples) {
- var buffer = new ArrayBuffer(44 + samples.length * 2);
- var view = new DataView(buffer);
-
- /* RIFF identifier */
- writeString(view, 0, 'RIFF');
- /* file length */
- view.setUint32(4, 32 + samples.length * 2, true);
- /* RIFF type */
- writeString(view, 8, 'WAVE');
- /* format chunk identifier */
- writeString(view, 12, 'fmt ');
- /* format chunk length */
- view.setUint32(16, 16, true);
- /* sample format (raw) */
- view.setUint16(20, 1, true);
- /* channel count */
- view.setUint16(22, 2, true);
- /* sample rate */
- view.setUint32(24, sampleRate, true);
- /* byte rate (sample rate * block align) */
- view.setUint32(28, sampleRate * 4, true);
- /* block align (channel count * bytes per sample) */
- view.setUint16(32, 4, true);
- /* bits per sample */
- view.setUint16(34, 16, true);
- /* data chunk identifier */
- writeString(view, 36, 'data');
- /* data chunk length */
- view.setUint32(40, samples.length * 2, true);
-
- floatTo16BitPCM(view, 44, samples);
-
- return view;
- }
-
- source.connect(this.node);
- this.node.connect(context.destination);
-};
-
-window.Recorder = Recorder;