我正在尝试使用编译成 wasm 并从 Javascript 调用的 C 库在 WebRtc 中创建噪声消除过滤器。
我能够使用 WebAudioApi 捕获 pcm 音频并使用 wasm 处理帧。
我的库只接受 int16 中的输入。
这是我的代码:我尝试了 2 种方法
方法一:
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);
}
}
该方法的优点是它保留了字节数,因此不会有数据丢失
但是当我将它转换回 Float32Array 时,浮点值超出了音频缓冲区限制值 [-1,1]。所以没有音频数据被推送。
方法二:
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);
}
}
这种方法的优点是它转换回范围 [-1,1] 内的值。
但是由于字节丢失,音频质量(失真)受到很大影响。
无论如何都可以保留字节并有效地转换 float32 - int16 并返回。
Anyhelp 将是巨大的。