Reputation: 1
:)
I've installed AppRTC (https://github.com/webrtc/apprtc) to a separate server to try out more flexible control of the WebRTC parameters.
The main task is to disable Automatic Gain Control (AGC).
The following steps have been performed:
{
video:
{
frameRate: 30,
width: 640,
height: 480
},
audio:
{
echoCancellation: true,
noiseSuppression: true,
autoGainControl: false
}
}
The GainNode filter has been added via audioContext.createGain() and has received a fixed value via gainNode.gain.value
To be able to test the AGC absence - a graphical audio meter has been added using audioContext.createScriptProcessor(...).onaudioprocess
The problem is that in fact the AGC is not disabled and Gain still remains dynamic.
During a long monotone loud sound the analyzer drops to a significantly lower value after 5-6 seconds.
And after 5-6 seconds of silence gets back to previous range.
All this has been tested on macOs Catalina 10.15.7, in the following browsers:
The question: is there a functioning possibility to turn off AGC and to follow that not only "by hearing" but also by the meter values?
The full code of the gain fixation method:
src/web_app/html/index_template.html
var loadingParams = {
errorMessages: [],
isLoopback: false,
warningMessages: [],
roomId: '101',
roomLink: 'https://www.xxxx.com/r/101',
// mediaConstraints: {"audio": true, "video": true},
mediaConstraints: {video: {frameRate: 30, width: 640, height: 480}, audio: {echoCancellation: true, noiseSuppression: true, autoGainControl: false}},
offerOptions: {},
peerConnectionConfig: {"bundlePolicy": "max-bundle", "iceServers": [{"urls": ["turn:www.xxxx.com:3478?transport=udp", "turn:www.xxxx.com:3478?transport=tcp"], "username": "demo", "credential": "demo"}, {"urls": ["stun:www.xxxx.com:3478"], "username": "demo", "credential": "demo"}], "rtcpMuxPolicy": "require"},
peerConnectionConstraints: {"optional": []},
iceServerRequestUrl: 'https://www.xxxx.com//v1alpha/iceconfig?key=',
iceServerTransports: '',
wssUrl: 'wss://www.xxxx.com:8089/ws',
wssPostUrl: 'https://www.xxxx.com:8089',
bypassJoinConfirmation: false,
versionInfo: {"time": "Wed Sep 23 12:49:00 2020 +0200", "gitHash": "78600dbe205774c115cf481a091387d928c99d6a", "branch": "master"},
};
src/web_app/js/appcontroller.js
AppController.prototype.gainStream = function (stream, gainValue) {
var max_level_L = 0;
var old_level_L = 0;
var cnvs = document.createElement('canvas');
cnvs.style.cssText = 'position:fixed;width:320px;height:30px;z-index:100;background:#000';
document.body.appendChild(cnvs);
var cnvs_cntxt = cnvs.getContext("2d");
var videoTracks = stream.getVideoTracks();
var context = new AudioContext();
var mediaStreamSource = context.createMediaStreamSource(stream);
var mediaStreamDestination = context.createMediaStreamDestination();
var gainNode = context.createGain();
var javascriptNode = context.createScriptProcessor(1024, 1, 1);
mediaStreamSource.connect(gainNode);
mediaStreamSource.connect(javascriptNode);
gainNode.connect(mediaStreamDestination);
javascriptNode.connect(mediaStreamDestination);
javascriptNode.onaudioprocess = function(event){
var inpt_L = event.inputBuffer.getChannelData(0);
var instant_L = 0.0;
var sum_L = 0.0;
for(var i = 0; i < inpt_L.length; ++i) {
sum_L += inpt_L[i] * inpt_L[i];
}
instant_L = Math.sqrt(sum_L / inpt_L.length);
max_level_L = Math.max(max_level_L, instant_L);
instant_L = Math.max( instant_L, old_level_L -0.008 );
old_level_L = instant_L;
cnvs_cntxt.clearRect(0, 0, cnvs.width, cnvs.height);
cnvs_cntxt.fillStyle = '#00ff00';
cnvs_cntxt.fillRect(10,10,(cnvs.width-20)*(instant_L/max_level_L),(cnvs.height-20)); // x,y,w,h
}
gainNode.gain.value = gainValue;
var controlledStream = mediaStreamDestination.stream;
for (const videoTrack of videoTracks) {
controlledStream.addTrack(videoTrack);
}
return controlledStream;
};
AppController.prototype.onLocalStreamAdded_ = function(stream) {
trace('User has granted access to local media.');
this.localStream_ = this.gainStream(stream, 100);
this.infoBox_.getLocalTrackIds(this.localStream_);
if (!this.roomSelection_) {
this.attachLocalStream_();
}
};
Thank you!
Best Regards, Andrei Costenco
Upvotes: 0
Views: 2170
Reputation: 9116
I think the problem you ran into is that echoCancellation
and noiseSuppression
do modify the signal as well. Since you mentioned that you are using a long monotone sound to test your code it could very well be that the noiseSuppression
algorithm tries to reduce that "noise".
Unfortunately there is no way to tell why the signal was modified. You have to trust the browser here that it actually has switched off the gain control and that all remaining modifications come from the other two algorithms.
If you don't want to fully trust the browser you could also experiment a bit by using other sounds to run your tests. It should not be "noisy" but it's difficult to say what get's detected by the browser as noise and what doesn't.
Upvotes: 2