Я пытаюсь создать фильтр шумоподавления в WebRt c, используя мою C библиотеку, скомпилированную в wasm и вызываемую из Javascript.
Я могу записать звук pcm с помощью WebAudioApi и обработать фрейм с помощью wasm.
Моя библиотека принимает ввод только в int16.
Вот мой код: Я пробовал 2 метода
Метод 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);
}
}
Преимущества метода в том, что он сохраняет количество байтов, поэтому потери данных не будет.
Но когда я конвертирую его обратно в Float32Array, значения с плавающей запятой выходят за пределы предельного значения аудиобуфера [-1,1 ]. Таким образом, аудиоданные не передаются.
Метод 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);
}
}
Преимущества этого метода в том, что он преобразует обратно значения в диапазоне [-1,1].
Но качество звука (искажение) сильно страдает из-за потери байтов.
Есть ли способ сохранить байты и эффективно преобразовать float32 - int16 и обратно.
Anyhelp было бы здорово.