javascript - 使用 WebAudioApi 在 Javascript 中对音频 PCM 数据进行上采样

标签 javascript pcm web-audio-api resampling

对于一个项目,我正在通过 WebSockets 从 Java 服务器检索实时音频流。在服务器上,我正在以 8 位有符号字节值的形式处理 16Bit/8000hz/mono 的样本(两个字节组成一个样本)。然而,在浏览器上,支持的最低采样率为 22050 Hz。所以我的想法是“简单地”将现有的 8000 赫兹上采样到 32000 赫兹,这是受支持的,并且在我看来这是一个简单的计算。

到目前为止,我已经尝试过 linear upsamplingcosine interpolation ,但两者都不起作用。除了听起来确实失真之外,第一个还添加了一些咔嗒声。我可能在使用 Chrome 中的 WebAudioAPI 时也遇到问题,但至少声音正在播放,并且几乎无法识别它应有的样子。所以我猜没有编解码器或字节序问题。

这是收到带有声音数据的二进制数据包时执行的完整代码。为了简单起见,我一直在创建新的缓冲区和缓冲区源(是的,对性能没有好处)。 data 是一个ArrayBuffer。首先,我将样本转换为 Float ,然后我进行上采样。

//endianess-aware buffer view
var bufferView=new DataView(data),
//the audio buffer to set for output
buffer=_audioContext.createBuffer(1,640,32000),
//reference to underlying buffer array
buf=buffer.getChannelData(0),
floatBuffer8000=new Float32Array(160);


//16Bit => Float
for(var i=0,j=null;i<160;i++){
    j=bufferView.getInt16(i*2,false);
    floatBuffer8000[i]=(j>0)?j/32767:j/-32767;
}   

//convert 8000 => 32000
var point1,point2,point3,point4,mu=0.2,mu2=(1-Math.cos(mu*Math.PI))/2;
for(var i=0,j=0;i<160;i++){
    //index for dst buffer
    j=i*4;

    //the points to interpolate between
    point1=floatBuffer8000[i];
    point2=(i<159)?floatBuffer8000[i+1]:point1;
    point3=(i<158)?floatBuffer8000[i+2]:point1;
    point4=(i<157)?floatBuffer8000[i+3]:point1;


    //interpolate
    point2=(point1*(1-mu2)+point2*mu2);
    point3=(point2*(1-mu2)+point3*mu2);
    point4=(point3*(1-mu2)+point4*mu2);

    //put data into buffer
    buf[j]=point1;
    buf[j+1]=point2;
    buf[j+2]=point3;
    buf[j+3]=point4;
}

//playback
var node=_audioContext.createBufferSource(0);
node.buffer=buffer;
node.connect(_audioContext.destination);
node.noteOn(_audioContext.currentTime);

最佳答案

终于找到解决办法了。从16Bit到Float的转换是错误的,只需这样

floatBuffer8000[i]=j/32767.0;

此外,向 API 提供大量小样本效果不佳,因此您需要缓冲一些样本并一起​​播放它们。

关于javascript - 使用 WebAudioApi 在 Javascript 中对音频 PCM 数据进行上采样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13878661/

相关文章:

mp3 - JLayer Mono Mp3 到 PCM 解码

javascript - 如何在jquery函数内的函数内传递变量?

javascript - 在javascript中将数组转换为具有键和值的对象

audio - 重新采样为12位PCM声音?

debugging - 如何播放从编解码器转储的原始 PCM 文件?

javascript - 在 JavaScript 中将变量分配给 ScriptProcessorNode

javascript - 我如何使用从 audioContext 创建的分析器来检测是否可以听到播放的声音?

javascript - WebSocket 的 Webaudio 播放出现中断

javascript - 我们如何在 webgl 的两个 Canvas 中显示相同的对象?

javascript - HTML5 表单必需属性。如何检查所需的消息是否已显示?