webrtc/samples/js/demos/html/local-audio-volume.html
hta@webrtc.org 26c40ba166 Removed audio element from volume measuring demo.
This removes the possibility of feedback loops, which can happen if you
run this demo on an Android device.

BUG=
R=dutton@google.com

Review URL: https://webrtc-codereview.appspot.com/5589004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5258 4adac7df-926f-26a2-2b94-8c16560cd09d
2013-12-11 11:12:39 +00:00

173 lines
5.4 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Local Audio Rendering Demo</title>
<script type="text/javascript" src="../../base/adapter.js"></script>
<script>
var buttonStart;
var buttonStop;
var localStream;
var reporter;
var audioContext;
// 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.
$ = function(id) {
return document.getElementById(id);
};
function start() {
var constraints = {audio:true, video:false};
getUserMedia(constraints, gotStream, gotStreamFailed);
buttonStart.disabled = true;
buttonStop.disabled = false;
}
function stop() {
buttonStart.enabled = true;
buttonStop.enabled = false;
localStream.stop();
clearInterval(reporter);
soundMeter.stop();
}
function gotStream(stream) {
var videoTracks = stream.getVideoTracks();
var audioTracks = stream.getAudioTracks();
if (audioTracks.length == 1 && videoTracks.length == 0) {
console.log('gotStream({audio:true, video:false})');
console.log('Using audio device: ' + audioTracks[0].label);
stream.onended = function() {
console.log('stream.onended');
buttonStart.disabled = false;
buttonStop.disabled = true;
};
localStream = stream;
var soundMeter = new SoundMeter(audioContext);
soundMeter.connectToSource(stream);
// Set up reporting of the volume every 0.2 seconds.
var meter = $('volume');
var decaying_meter = $('decaying_volume');
var meter_canvas = $('graphic_volume').getContext('2d');
var meter_slow = $('graphic_slow').getContext('2d');
var meter_clip = $('graphic_clip').getContext('2d');
reporter = setInterval(function() {
meter.textContent = soundMeter.volume.toFixed(2);
decaying_meter.textContent = soundMeter.slow_volume.toFixed(2);
paintMeter(meter_canvas, soundMeter.volume);
paintMeter(meter_slow, soundMeter.slow_volume);
paintMeter(meter_clip, soundMeter.clip);
}, 200);
} else {
alert('The media stream contains an invalid number of tracks:'
+ audioTracks.length + ' audio ' + videoTracks.length + ' video');
stream.stop();
}
}
function gotStreamFailed(error) {
buttonStart.disabled = false;
buttonStop.disabled = true;
alert('Failed to get access to local media. Error code: ' + error.code);
}
function onload() {
try {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
audioContext = new AudioContext();
} catch(e) {
alert('Web Audio API not found');
}
buttonStart = $('start');
buttonStop = $('stop');
buttonStart.enabled = true;
buttonStop.disabled = true;
}
function paintMeter(context, number) {
context.clearRect(0, 0, 400, 20);
context.fillStyle = 'red';
context.fillRect(0, 0, number * 400, 20);
}
</script>
<style>
button {
font: 14px sans-serif;
padding: 8px;
}
canvas {
border:1px solid #000000;
}
</style>
</head>
<body onload="onload()">
<h2>Measuring the volume of an audio stream using WebAudio</h2>
<p>Demonstrates measuring the volume of a local media stream
using WebAudio.<br>
Press Start, select a microphone, listen to your own voice in loopback,
and see the numbers change as you speak.</p>
The "instant" volume changes approximately every 50 ms; the "slow"
volume approximates the average volume over about a second.
<br>
Note that you will NOT hear your own voice; use the
<a href="local-audio-rendering.html">local audio rendering demo</a>
for that.
<p>
<button id="start" onclick="start()">Start</button>
<button id="stop" onclick="stop()">Stop</button><br><br>
Volume (instant): <span id="volume">Not set</span><br>
Volume (slow): <span id="decaying_volume">Not set</span><br>
<canvas id="graphic_volume" width="400" height="20"></canvas> Volume<br>
<canvas id="graphic_slow" width="400" height="20"></canvas> Slow<br>
<canvas id="graphic_clip" width="400" height="20"></canvas> Clipping
</body>
</html>