Skip to content

Commit ad26442

Browse files
committed
Update volume sample to use audio worklet
fixes #1509
1 parent 4be13c9 commit ad26442

File tree

2 files changed

+52
-22
lines changed

2 files changed

+52
-22
lines changed

src/content/getusermedia/volume/js/soundmeter.js

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,22 @@ function SoundMeter(context) {
1818
this.instant = 0.0;
1919
this.slow = 0.0;
2020
this.clip = 0.0;
21-
this.script = context.createScriptProcessor(2048, 1, 1);
22-
const that = this;
23-
this.script.onaudioprocess = function(event) {
24-
const input = event.inputBuffer.getChannelData(0);
25-
let i;
26-
let sum = 0.0;
27-
let clipcount = 0;
28-
for (i = 0; i < input.length; ++i) {
29-
sum += input[i] * input[i];
30-
if (Math.abs(input[i]) > 0.99) {
31-
clipcount += 1;
32-
}
33-
}
34-
that.instant = Math.sqrt(sum / input.length);
35-
that.slow = 0.95 * that.slow + 0.05 * that.instant;
36-
that.clip = clipcount / input.length;
37-
};
21+
this.node = null;
3822
}
3923

40-
SoundMeter.prototype.connectToSource = function(stream, callback) {
24+
SoundMeter.prototype.connectToSource = async function(stream, callback) {
4125
console.log('SoundMeter connecting');
4226
try {
27+
await this.context.audioWorklet.addModule('js/volume-meter-processor.js');
4328
this.mic = this.context.createMediaStreamSource(stream);
44-
this.mic.connect(this.script);
45-
// necessary to make sample run, but should not be.
46-
this.script.connect(this.context.destination);
29+
this.node = new AudioWorkletNode(this.context, 'volume-meter-processor');
30+
this.node.port.onmessage = (event) => {
31+
const {instant, clip} = event.data;
32+
this.instant = instant;
33+
this.clip = clip;
34+
this.slow = 0.95 * this.slow + 0.05 * this.instant;
35+
};
36+
this.mic.connect(this.node);
4737
if (typeof callback !== 'undefined') {
4838
callback(null);
4939
}
@@ -58,5 +48,5 @@ SoundMeter.prototype.connectToSource = function(stream, callback) {
5848
SoundMeter.prototype.stop = function() {
5949
console.log('SoundMeter stopping');
6050
this.mic.disconnect();
61-
this.script.disconnect();
51+
this.node.disconnect();
6252
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2025 The WebRTC project authors. All Rights Reserved.
3+
*
4+
* Use of this source code is governed by a BSD-style license
5+
* that can be found in the LICENSE file in the root of the source
6+
* tree.
7+
*/
8+
9+
'use strict';
10+
11+
// This class is used to compute the volume of the input audio stream.
12+
class VolumeMeterProcessor extends AudioWorkletProcessor {
13+
constructor() {
14+
super();
15+
this._lastUpdate = Date.now();
16+
}
17+
process(inputs) {
18+
// This example only supports mono channel.
19+
const input = inputs[0][0];
20+
if (!input) {
21+
return true;
22+
}
23+
let sum = 0.0;
24+
let clipcount = 0;
25+
for (let i = 0; i < input.length; ++i) {
26+
sum += input[i] * input[i];
27+
if (Math.abs(input[i]) > 0.99) {
28+
clipcount += 1;
29+
}
30+
}
31+
const instant = Math.sqrt(sum / input.length);
32+
this.port.postMessage({
33+
instant: instant,
34+
clip: clipcount / input.length,
35+
});
36+
return true;
37+
}
38+
}
39+
40+
registerProcessor('volume-meter-processor', VolumeMeterProcessor);

0 commit comments

Comments
 (0)