jiti-meet/modules/statistics/LocalStatsCollector.js

126 lines
3.2 KiB
JavaScript
Raw Normal View History

2015-07-28 17:49:58 +00:00
/* global config */
2014-12-17 16:21:25 +00:00
/**
* Provides statistics for the local stream.
*/
var RTCBrowserType = require('../RTC/RTCBrowserType');
2014-12-17 16:21:25 +00:00
/**
2015-07-28 17:52:51 +00:00
* Size of the webaudio analyzer buffer.
2014-12-17 16:21:25 +00:00
* @type {number}
*/
2015-07-28 17:52:51 +00:00
var WEBAUDIO_ANALYZER_FFT_SIZE = 2048;
2014-12-17 16:21:25 +00:00
/**
2015-07-28 17:52:51 +00:00
* Value of the webaudio analyzer smoothing time parameter.
2014-12-17 16:21:25 +00:00
* @type {number}
*/
2015-07-28 17:52:51 +00:00
var WEBAUDIO_ANALYZER_SMOOTING_TIME = 0.8;
2014-12-17 16:21:25 +00:00
/**
* Converts time domain data array to audio level.
2015-07-28 17:52:51 +00:00
* @param samples the time domain data array.
2014-12-17 16:21:25 +00:00
* @returns {number} the audio level
*/
function timeDomainDataToAudioLevel(samples) {
var maxVolume = 0;
var length = samples.length;
for (var i = 0; i < length; i++) {
if (maxVolume < samples[i])
maxVolume = samples[i];
}
return parseFloat(((maxVolume - 127) / 128).toFixed(3));
2015-07-28 17:49:58 +00:00
}
2014-12-17 16:21:25 +00:00
/**
* Animates audio level change
* @param newLevel the new audio level
* @param lastLevel the last audio level
* @returns {Number} the audio level to be set
*/
2015-07-28 17:49:58 +00:00
function animateLevel(newLevel, lastLevel) {
2014-12-17 16:21:25 +00:00
var value = 0;
var diff = lastLevel - newLevel;
2015-07-28 17:49:58 +00:00
if(diff > 0.2) {
2014-12-17 16:21:25 +00:00
value = lastLevel - 0.2;
}
2015-07-28 17:49:58 +00:00
else if(diff < -0.4) {
2014-12-17 16:21:25 +00:00
value = lastLevel + 0.4;
}
2015-07-28 17:49:58 +00:00
else {
2014-12-17 16:21:25 +00:00
value = newLevel;
}
return parseFloat(value.toFixed(3));
}
/**
* <tt>LocalStatsCollector</tt> calculates statistics for the local stream.
*
* @param stream the local stream
* @param interval stats refresh interval given in ms.
* @constructor
*/
function LocalStatsCollector(stream, interval, statisticsService, eventEmitter) {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
this.stream = stream;
this.intervalId = null;
this.intervalMilis = interval;
this.eventEmitter = eventEmitter;
this.audioLevel = 0;
this.statisticsService = statisticsService;
}
/**
* Starts the collecting the statistics.
*/
LocalStatsCollector.prototype.start = function () {
2015-07-28 17:49:58 +00:00
if (config.disableAudioLevels || !window.AudioContext ||
RTCBrowserType.isTemasysPluginUsed())
2014-12-17 16:21:25 +00:00
return;
var context = new AudioContext();
var analyser = context.createAnalyser();
2015-07-28 17:52:51 +00:00
analyser.smoothingTimeConstant = WEBAUDIO_ANALYZER_SMOOTING_TIME;
analyser.fftSize = WEBAUDIO_ANALYZER_FFT_SIZE;
2014-12-17 16:21:25 +00:00
var source = context.createMediaStreamSource(this.stream);
source.connect(analyser);
var self = this;
this.intervalId = setInterval(
function () {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteTimeDomainData(array);
var audioLevel = timeDomainDataToAudioLevel(array);
2015-07-28 17:52:51 +00:00
if (audioLevel != self.audioLevel) {
2014-12-17 16:21:25 +00:00
self.audioLevel = animateLevel(audioLevel, self.audioLevel);
self.eventEmitter.emit(
"statistics.audioLevel",
self.statisticsService.LOCAL_JID,
self.audioLevel);
}
},
this.intervalMilis
);
};
/**
* Stops collecting the statistics.
*/
LocalStatsCollector.prototype.stop = function () {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
};
module.exports = LocalStatsCollector;