You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LocalStatsCollector.js 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /**
  2. * Provides statistics for the local stream.
  3. */
  4. /**
  5. * Size of the webaudio analizer buffer.
  6. * @type {number}
  7. */
  8. var WEBAUDIO_ANALIZER_FFT_SIZE = 2048;
  9. /**
  10. * Value of the webaudio analizer smoothing time parameter.
  11. * @type {number}
  12. */
  13. var WEBAUDIO_ANALIZER_SMOOTING_TIME = 0.8;
  14. /**
  15. * Converts time domain data array to audio level.
  16. * @param array the time domain data array.
  17. * @returns {number} the audio level
  18. */
  19. function timeDomainDataToAudioLevel(samples) {
  20. var maxVolume = 0;
  21. var length = samples.length;
  22. for (var i = 0; i < length; i++) {
  23. if (maxVolume < samples[i])
  24. maxVolume = samples[i];
  25. }
  26. return parseFloat(((maxVolume - 127) / 128).toFixed(3));
  27. };
  28. /**
  29. * Animates audio level change
  30. * @param newLevel the new audio level
  31. * @param lastLevel the last audio level
  32. * @returns {Number} the audio level to be set
  33. */
  34. function animateLevel(newLevel, lastLevel)
  35. {
  36. var value = 0;
  37. var diff = lastLevel - newLevel;
  38. if(diff > 0.2)
  39. {
  40. value = lastLevel - 0.2;
  41. }
  42. else if(diff < -0.4)
  43. {
  44. value = lastLevel + 0.4;
  45. }
  46. else
  47. {
  48. value = newLevel;
  49. }
  50. return parseFloat(value.toFixed(3));
  51. }
  52. /**
  53. * <tt>LocalStatsCollector</tt> calculates statistics for the local stream.
  54. *
  55. * @param stream the local stream
  56. * @param interval stats refresh interval given in ms.
  57. * @param {function(LocalStatsCollector)} updateCallback the callback called on stats
  58. * update.
  59. * @constructor
  60. */
  61. function LocalStatsCollector(stream, interval, statisticsService, eventEmitter) {
  62. window.AudioContext = window.AudioContext || window.webkitAudioContext;
  63. this.stream = stream;
  64. this.intervalId = null;
  65. this.intervalMilis = interval;
  66. this.eventEmitter = eventEmitter;
  67. this.audioLevel = 0;
  68. this.statisticsService = statisticsService;
  69. }
  70. /**
  71. * Starts the collecting the statistics.
  72. */
  73. LocalStatsCollector.prototype.start = function () {
  74. if (config.disableAudioLevels || !window.AudioContext)
  75. return;
  76. var context = new AudioContext();
  77. var analyser = context.createAnalyser();
  78. analyser.smoothingTimeConstant = WEBAUDIO_ANALIZER_SMOOTING_TIME;
  79. analyser.fftSize = WEBAUDIO_ANALIZER_FFT_SIZE;
  80. var source = context.createMediaStreamSource(this.stream);
  81. source.connect(analyser);
  82. var self = this;
  83. this.intervalId = setInterval(
  84. function () {
  85. var array = new Uint8Array(analyser.frequencyBinCount);
  86. analyser.getByteTimeDomainData(array);
  87. var audioLevel = timeDomainDataToAudioLevel(array);
  88. if(audioLevel != self.audioLevel) {
  89. self.audioLevel = animateLevel(audioLevel, self.audioLevel);
  90. self.eventEmitter.emit(
  91. "statistics.audioLevel",
  92. self.statisticsService.LOCAL_JID,
  93. self.audioLevel);
  94. }
  95. },
  96. this.intervalMilis
  97. );
  98. };
  99. /**
  100. * Stops collecting the statistics.
  101. */
  102. LocalStatsCollector.prototype.stop = function () {
  103. if (this.intervalId) {
  104. clearInterval(this.intervalId);
  105. this.intervalId = null;
  106. }
  107. };
  108. module.exports = LocalStatsCollector;