I am trying to create a noise cancellation filter in WebRtc using my C library compiled into wasm and called from Javascript.
I am able to capture the pcm audio using WebAudioApi and process the frame with wasm.
My library accepts input in int16 only.
Here is my code : I tried 2 Methods
Method 1 :
navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
var audiocontext;
var audiosource;
var audiopreprocessnode;
audiocontext = new (window.AudioContext || window.webkitAudioContext)();
audiosource = audiocontext.createMediaStreamSource(stream);
audioPreprocessNode = audioCtx.createScriptProcessor(2048,1,1);
audiosource.connect(audioPreprocessNode);
audioPreprocessNode.connect(audioCtx.destination);
audioPreprocessNode.onaudioprocess = function(e) {
var input = new Int16Array(e.inputbuffer.getChannelData(0));
console.log(input.length); // prints 4096
var denoised_array = Module["_denoise"](input);
var output = new Float32Array(denoised_array);
console.log(output.length); // prints 2048
e.outputBuffer.getChannelData(0).set(output);
}
}
Advantages of the method is It preserves the no of bytes , so no data loss will be there
But when i convert back it to Float32Array the float values goes beyond tha audiobuffer limit value [-1,1]. So no audio data being pushed.
Method 2:
function floatTo16Bit(inputArray){
var output = new Int16Array(2048);
for (var i = 0; i < inputArray.length; i++){
var s = Math.max(-1, Math.min(1, inputArray[i]));
output[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
}
return output;
}
function int16ToFloat32(inputArray) {
var output = new Float32Array(2048);
for (var i = 0; i < 2048; i++) {
var int = inputArray[i];
var float = (int >= 0x8000) ? -(0x10000 - int) / 0x8000 : int / 0x7FFF;
output[i] = float;
}
return output;
}
navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
var audiocontext;
var audiosource;
var audiopreprocessnode;
audiocontext = new (window.AudioContext || window.webkitAudioContext)();
audiosource = audiocontext.createMediaStreamSource(stream);
audioPreprocessNode = audioCtx.createScriptProcessor(2048,1,1);
audiosource.connect(audioPreprocessNode);
audioPreprocessNode.connect(audioCtx.destination);
audioPreprocessNode.onaudioprocess = function(e) {
var input = floatTo16Bit(e.inputbuffer.getChannelData(0));
console.log(input.length); // prints 2048
var denoised_array = Module["_denoise"](input);
var output = int16ToFloat32(denoised_array);
console.log(output.length); // prints 2048
e.outputBuffer.getChannelData(0).set(output);
}
}
Advantages of this method is it converts back values within the range[-1,1].
But audio quality(distortion) suffer a lot due to loss of bytes.
Is there anyway to preserver the bytes and convert float32 - int16 and back efficiently.
Anyhelp would be greatfull.