modified lib-jitsi-meet dev repo
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.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /**
  2. * Provides statistics for the local stream.
  3. */
  4. var RTCBrowserType = require('../RTC/RTCBrowserType');
  5. /**
  6. * Size of the webaudio analyzer buffer.
  7. * @type {number}
  8. */
  9. var WEBAUDIO_ANALYZER_FFT_SIZE = 2048;
  10. /**
  11. * Value of the webaudio analyzer smoothing time parameter.
  12. * @type {number}
  13. */
  14. var WEBAUDIO_ANALYZER_SMOOTING_TIME = 0.8;
  15. window.AudioContext = window.AudioContext || window.webkitAudioContext;
  16. var context = null;
  17. if(window.AudioContext) {
  18. context = new AudioContext();
  19. // XXX Not all browsers define a suspend method on AudioContext. As the
  20. // invocation is at the (ES6 module) global execution level, it breaks the
  21. // loading of the lib-jitsi-meet library in such browsers and, consequently,
  22. // the loading of the very Web app that uses the lib-jitsi-meet library. For
  23. // example, Google Chrome 40 on Android does not define the method but we
  24. // still want to be able to load the lib-jitsi-meet library there and
  25. // display a page which notifies the user that the Web app is not supported
  26. // there.
  27. context.suspend && context.suspend();
  28. }
  29. /**
  30. * Converts time domain data array to audio level.
  31. * @param samples the time domain data array.
  32. * @returns {number} the audio level
  33. */
  34. function timeDomainDataToAudioLevel(samples) {
  35. var maxVolume = 0;
  36. var length = samples.length;
  37. for (var i = 0; i < length; i++) {
  38. if (maxVolume < samples[i])
  39. {maxVolume = samples[i];}
  40. }
  41. return parseFloat(((maxVolume - 127) / 128).toFixed(3));
  42. }
  43. /**
  44. * Animates audio level change
  45. * @param newLevel the new audio level
  46. * @param lastLevel the last audio level
  47. * @returns {Number} the audio level to be set
  48. */
  49. function animateLevel(newLevel, lastLevel) {
  50. var value = 0;
  51. var diff = lastLevel - newLevel;
  52. if(diff > 0.2) {
  53. value = lastLevel - 0.2;
  54. }
  55. else if(diff < -0.4) {
  56. value = lastLevel + 0.4;
  57. }
  58. else {
  59. value = newLevel;
  60. }
  61. return parseFloat(value.toFixed(3));
  62. }
  63. /**
  64. * <tt>LocalStatsCollector</tt> calculates statistics for the local stream.
  65. *
  66. * @param stream the local stream
  67. * @param interval stats refresh interval given in ms.
  68. * @param callback function that receives the audio levels.
  69. * @constructor
  70. */
  71. function LocalStatsCollector(stream, interval, callback) {
  72. this.stream = stream;
  73. this.intervalId = null;
  74. this.intervalMilis = interval;
  75. this.audioLevel = 0;
  76. this.callback = callback;
  77. }
  78. /**
  79. * Starts the collecting the statistics.
  80. */
  81. LocalStatsCollector.prototype.start = function () {
  82. if (!context ||
  83. RTCBrowserType.isTemasysPluginUsed())
  84. {return;}
  85. context.resume();
  86. var analyser = context.createAnalyser();
  87. analyser.smoothingTimeConstant = WEBAUDIO_ANALYZER_SMOOTING_TIME;
  88. analyser.fftSize = WEBAUDIO_ANALYZER_FFT_SIZE;
  89. var source = context.createMediaStreamSource(this.stream);
  90. source.connect(analyser);
  91. var self = this;
  92. this.intervalId = setInterval(
  93. function () {
  94. var array = new Uint8Array(analyser.frequencyBinCount);
  95. analyser.getByteTimeDomainData(array);
  96. var audioLevel = timeDomainDataToAudioLevel(array);
  97. if (audioLevel != self.audioLevel) {
  98. self.audioLevel = animateLevel(audioLevel, self.audioLevel);
  99. self.callback(self.audioLevel);
  100. }
  101. },
  102. this.intervalMilis
  103. );
  104. };
  105. /**
  106. * Stops collecting the statistics.
  107. */
  108. LocalStatsCollector.prototype.stop = function () {
  109. if (this.intervalId) {
  110. clearInterval(this.intervalId);
  111. this.intervalId = null;
  112. }
  113. };
  114. module.exports = LocalStatsCollector;