Enables LocalStatsCollector for the local audio levels instead of rtp stats. Fixes issue with local audio level calculations.

This commit is contained in:
hristoterezov 2014-07-27 15:24:27 +03:00
parent 913cdb9c7a
commit 83b4ee96d3
3 changed files with 67 additions and 47 deletions

49
app.js
View File

@ -445,33 +445,23 @@ function muteVideo(pc, unmute) {
} }
/** /**
* Callback called by {@link StatsCollector} in intervals supplied to it's * Callback for audio levels changed.
* constructor. * @param jid JID of the user
* @param statsCollector {@link StatsCollector} source of the event. * @param audioLevel the audio level value
*/ */
function statsUpdated(statsCollector) function audioLevelUpdated(jid, audioLevel)
{ {
Object.keys(statsCollector.jid2stats).forEach(function (jid) var resourceJid;
if(jid === LocalStatsCollector.LOCAL_JID)
{ {
var peerStats = statsCollector.jid2stats[jid]; resourceJid = AudioLevels.LOCAL_LEVEL;
Object.keys(peerStats.ssrc2AudioLevel).forEach(function (ssrc) }
{ else
AudioLevels.updateAudioLevel( Strophe.getResourceFromJid(jid), {
peerStats.ssrc2AudioLevel[ssrc]); resourceJid = Strophe.getResourceFromJid(jid);
}); }
});
}
/** AudioLevels.updateAudioLevel(resourceJid, audioLevel);
* Callback called by {@link LocalStatsCollector} in intervals supplied to it's
* constructor.
* @param statsCollector {@link LocalStatsCollector} source of the event.
*/
function localStatsUpdated(statsCollector)
{
AudioLevels.updateAudioLevel(
AudioLevels.LOCAL_LEVEL,
statsCollector.audioLevel);
} }
/** /**
@ -483,10 +473,7 @@ function startRtpStatsCollector()
if (config.enableRtpStats) if (config.enableRtpStats)
{ {
statsCollector = new StatsCollector( statsCollector = new StatsCollector(
getConferenceHandler().peerconnection, 200, statsUpdated); getConferenceHandler().peerconnection, 200, audioLevelUpdated);
stopLocalRtpStatsCollector();
statsCollector.start(); statsCollector.start();
} }
} }
@ -511,7 +498,7 @@ function startLocalRtpStatsCollector(stream)
{ {
if(config.enableRtpStats) if(config.enableRtpStats)
{ {
localStatsCollector = new LocalStatsCollector(stream, 200, localStatsUpdated); localStatsCollector = new LocalStatsCollector(stream, 100, audioLevelUpdated);
localStatsCollector.start(); localStatsCollector.start();
} }
} }
@ -1123,11 +1110,7 @@ function disposeConference(onUnload) {
handler.peerconnection.close(); handler.peerconnection.close();
} }
stopRTPStatsCollector(); stopRTPStatsCollector();
if(!onUnload) { if(onUnload) {
startLocalRtpStatsCollector(connection.jingle.localAudio);
}
else
{
stopLocalRtpStatsCollector(); stopLocalRtpStatsCollector();
} }
focus = null; focus = null;

View File

@ -6,13 +6,13 @@ var LocalStatsCollector = (function() {
* Size of the webaudio analizer buffer. * Size of the webaudio analizer buffer.
* @type {number} * @type {number}
*/ */
var WEBAUDIO_ANALIZER_FFT_SIZE = 512; var WEBAUDIO_ANALIZER_FFT_SIZE = 2048;
/** /**
* Value of the webaudio analizer smoothing time parameter. * Value of the webaudio analizer smoothing time parameter.
* @type {number} * @type {number}
*/ */
var WEBAUDIO_ANALIZER_SMOOTING_TIME = 0.1; var WEBAUDIO_ANALIZER_SMOOTING_TIME = 0.8;
/** /**
* <tt>LocalStatsCollector</tt> calculates statistics for the local stream. * <tt>LocalStatsCollector</tt> calculates statistics for the local stream.
@ -54,12 +54,16 @@ var LocalStatsCollector = (function() {
this.intervalId = setInterval( this.intervalId = setInterval(
function () { function () {
var array = new Uint8Array(analyser.frequencyBinCount); var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array); analyser.getByteTimeDomainData(array);
self.audioLevel = FrequencyDataToAudioLevel(array); var audioLevel = TimeDomainDataToAudioLevel(array);
self.updateCallback(self); if(audioLevel != self.audioLevel) {
self.audioLevel = animateLevel(audioLevel, self.audioLevel);
self.updateCallback(LocalStatsCollectorProto.LOCAL_JID, self.audioLevel);
}
}, },
this.intervalMilis this.intervalMilis
); );
}; };
/** /**
@ -73,22 +77,55 @@ var LocalStatsCollector = (function() {
}; };
/** /**
* Converts frequency data array to audio level. * Converts time domain data array to audio level.
* @param array the frequency data array. * @param array the time domain data array.
* @returns {number} the audio level * @returns {number} the audio level
*/ */
var FrequencyDataToAudioLevel = function (array) { var TimeDomainDataToAudioLevel = function (samples) {
var maxVolume = 0; var maxVolume = 0;
var length = array.length; var length = samples.length;
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
if (maxVolume < array[i]) if (maxVolume < samples[i])
maxVolume = array[i]; maxVolume = samples[i];
} }
return maxVolume / 255; return parseFloat(((maxVolume - 127) / 128).toFixed(3));
}; };
/**
* Animates audio level change
* @param newLevel the new audio level
* @param lastLevel the last audio level
* @returns {Number} the audio level to be set
*/
function animateLevel(newLevel, lastLevel)
{
var value = 0;
var diff = lastLevel - newLevel;
if(diff > 0.2)
{
value = lastLevel - 0.2;
}
else if(diff < -0.4)
{
value = lastLevel + 0.4;
}
else
{
value = newLevel;
}
return parseFloat(value.toFixed(3));
}
/**
* Indicates that this audio level is for local jid.
* @type {string}
*/
LocalStatsCollectorProto.LOCAL_JID = 'local';
return LocalStatsCollectorProto; return LocalStatsCollectorProto;
})(); })();

View File

@ -213,6 +213,8 @@ StatsCollector.prototype.processReport = function ()
// but it seems to vary between 0 and around 32k. // but it seems to vary between 0 and around 32k.
audioLevel = audioLevel / 32767; audioLevel = audioLevel / 32767;
jidStats.setSsrcAudioLevel(ssrc, audioLevel); jidStats.setSsrcAudioLevel(ssrc, audioLevel);
if(jid != connection.emuc.myroomjid)
this.updateCallback(jid, audioLevel);
} }
var key = 'packetsReceived'; var key = 'packetsReceived';
@ -281,7 +283,5 @@ StatsCollector.prototype.processReport = function ()
// bar indicator // bar indicator
//console.info("Loss SMA3: " + outputAvg + " Q: " + quality); //console.info("Loss SMA3: " + outputAvg + " Q: " + quality);
} }
self.updateCallback(self);
}; };