您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

LocalStatsCollector.js 3.2KB

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