The Volume issue - a suggestion to remove it from scope

One of the irritating things in the stats and media discussion has been 
the question of "audio volume".

There are many apps that need it, yet defining the term has proved 
surprisingly slippery - what is it we measure, what's the baseline, do 
we need psychometric shaping of the signal before measuring it, what 
time scale does it need to be integrated over, and so on and so forth.

At the moment, there is a stat in the Chrome implementation called 
"audioVolume" that has no particular definition, and has proved 
troublesome in multiple ways (for instance, it's not available without 
linking the track to an active PeerConnection).

The suggestion has been made to expose a property on a MediaStreamTrack 
instead - but that runs into all the previously mentioned issues.

But there is another way: Use WebAudio. Get the samples. Let the 
application decide.

I created a demo, which works both in Firefox and Chrome, here:

https://webrtc.googlecode.com/svn/trunk/samples/js/demos/html/local-audio-volume.html

The essential part of the code is reproduced below, it's not long.
I believe that:

- This shows that volume can be measured in an application, from a 
MediaStreamTrack, without any modification to any part of the Media 
Capture and Streams spec.

- This shows that the application can control the definition of "volume" 
to be exactly what it wants it to be; again, without making any change 
to any part of the Media Capture And Streams spec.

- This shows that the cost is a Javascript invocation every 50 ms, where 
the heaviest operation is a square root. People can test for themselves 
if this matters for the devices they are concerned about.

Therefore, on the principle that we should not solve a problem twice, I 
propose that we declare the problem of "measuring the volume of an audio 
track" to be out of scope for the working group.

Does this make sense for people?

             Harald


   // Meter class that generates a number correlated to audio volume.
   // The meter class itself displays nothing, but it makes the
   // instantaneous and time-decaying volumes available for inspection.
   // It also reports on the fraction of samples that were at or near
   // the top of the measurement range.
   function SoundMeter(context) {
     this.context = context
     this.volume = 0.0;
     this.slow_volume = 0.0;
     this.clip = 0.0;
     this.script = context.createScriptProcessor(2048, 1, 1);
     that = this;
     this.script.onaudioprocess = function(event) {
       var input = event.inputBuffer.getChannelData(0);
       var i;
       var sum = 0.0;
       var clipcount = 0;
       for (i = 0; i < input.length; ++i) {
         sum += input[i] * input[i];
         if (Math.abs(input[i]) > 0.99) {
           clipcount += 1
         }
       }
       that.volume = Math.sqrt(sum / input.length);
       that.slow_volume = 0.95 * that.slow_volume + 0.05 * that.volume;
       that.clip = clipcount / input.length;
     }
   }

   SoundMeter.prototype.connectToSource = function(stream) {
     console.log('SoundMeter connecting');
     this.mic = this.context.createMediaStreamSource(stream);
     this.mic.connect(this.script);
     // Necessary to make sample run, but should not be.
     this.script.connect(this.context.destination);
   }

   SoundMeter.prototype.stop = function() {
     this.mic.disconnect();
     this.script.disconnect();
   }

   // End of SoundMeter class.

Received on Wednesday, 11 December 2013 09:25:44 UTC