floating-point - javascript中的音频Float32到Int16转换
问题描述
我正在尝试使用编译成 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 将是巨大的。
解决方案
不确定“保留字节”是什么意思,但从 float32 到 int16 的转换必然会丢失信息。但它不应该有太大的失真。毕竟,CD 只有 16 位。
为简单起见,我将通过将浮点数限制为 [-1, 1] 将浮点数转换为 int16,就像您所做的那样,然后乘以 32768 并取整数部分。这给出了一个有符号的 16 位整数。
反之,只需将 int16 值除以 32768。(再次假设您已签署 16 位数字。)
推荐阅读
- c# - DocuSign - 快速入门代码生成器是否适用于其他开发人员?
- postgresql - 带有 NULL 值的 PostgreSQL UPDATE 问题
- c - 将字符串作为参数传递给函数,然后使用该字符串值在 C 中打开文件
- c++ - 父类不向子类返回值
- pyqt - 如何将 windowsmediafoundation 设置为首选插件?
- javascript - JavaScript 斐波那契函数到 HTML 元素?
- sql-server - 创建最多 8 字节的唯一整数并且仍然具有并行插入
- reactjs - 如何修复我的减速器以返回对象的属性值?
- reactjs - React / Typescript:导入库中的“类型中缺少属性'children'”
- javascript - 为什么这个 HTML Canvas clearRect() 会这样?