speex拆分音频数据-WebAudio-VOIP

speex splitted audio data - WebAudio - VOIP

本文关键字:-WebAudio-VOIP 数据 音频 拆分 speex      更新时间:2023-09-26

我正在运行一个小应用程序,该应用程序使用javascript中的speex编解码器对音频阵列进行编码和解码:https://github.com/dbieber/audiorecorder

用正弦波形填充的小阵列

for(var i=0;i<16384;i++)
    data.push(Math.sin(i/10));

这是有效的。但我想建立一个VOIP应用程序,并有一个以上的阵列。所以,如果我把数组分成两部分encode>decode>merge,听起来就和以前不一样了。

看看这个:

小提琴:http://jsfiddle.net/exh63zqL/

两个按钮应提供相同的音频输出。

如何在两种方式中获得相同的输出?它们是speex.js中用于分割音频数据的特殊模式吗?

Speex是一个有损编解码器,因此输出只是初始正弦波的近似值。

你的正弦频率大约是7千赫,接近编解码器的8KHz带宽,因此更有可能被改变。

编解码器输出的东西看起来像一梳dirach脉冲,听起来就像你通过手机听到的初始正弦曲线,这肯定与最初的不同。

看看这个小提琴,你可以在那里听编解码器对原始正弦波的处理,无论它们是否一分为二。

//Generate a continus sinus in 2 arrays
var len = 16384;
var buffer1 = [];
var buffer2 = [];
var buffer = [];
for(var i=0;i<len;i++){
    buffer.push(Math.sin(i/10));
    if(i < len/2)
        buffer1.push(Math.sin(i/10));
    else
        buffer2.push(Math.sin(i/10));
}
//Encode and decode both arrays seperatly
var en = Codec.encode(buffer1);
var dec1 = Codec.decode(en);
var en = Codec.encode(buffer2);
var dec2 = Codec.decode(en);
//Merge the arrays to 1 output array
var merge = [];
for(var i in dec1)
    merge.push(dec1[i]);
for(var i in dec2)
    merge.push(dec2[i]);
//encode and decode the whole array
var en = Codec.encode(buffer);
var dec = Codec.decode(en);
//-----------------
//Down under is only for playing the 2 different arrays
//-------------------
var audioCtx = new window.AudioContext || new window.webkitAudioContext;
function play (sound)
{
    var audioBuffer = audioCtx.createBuffer(1, sound.length, 44100);
    var bufferData = audioBuffer.getChannelData(0);
    bufferData.set(sound);
    var source = audioCtx.createBufferSource();
    source.buffer = audioBuffer;
    source.connect(audioCtx.destination);
    source.start();
}
$("#o").click(function() { play(dec); });
$("#c1").click(function() { play(dec1); });
$("#c2").click(function() { play(dec2); });
$("#m").click(function() { play(merge); });

如果合并两个半信号解码器输出,您将听到由于从一个信号到另一个信号的突然转换而产生的额外咔嗒声,听起来基本上像继电器换向
为了避免这种情况,您必须平滑两个缓冲区合并点周围的值。

请注意,Speex是一种有损编解码器。所以,根据定义,它不能给出与编码缓冲区相同的结果。此外,它被设计成语音编解码器。因此,1-2kHz范围将是最有效的,因为它期望特定形式的信号。在某种程度上,它可以与光栅图像的JPEG技术进行比较。

我稍微修改了你的jsfiddle示例,这样你就可以使用不同的参数来播放并比较结果。仅仅提供一个频率未知的简单正弦曲线并不是检查编解码器的正确方法。然而,在该示例中,您可以看到不同频率对初始信号的不同影响。

buffer1.push(Math.sin(2*Math.PI*i*frequency/sampleRate));

我认为你应该用录音建立一个例子,并比较这种情况下的结果。这样会更合适。

一般来说,要想详细了解这个想法,你必须检查数字信号处理。我甚至无法提供一个适当的链接,因为这是一门完整的科学,而且数学密集。(我所知道的唯一适合阅读的书是俄语)。如果这里有数学背景的人能分享关于这个案例的适当文献,我将不胜感激。

编辑:正如Kuroi Neko所提到的,缓冲区的边界有问题。而且似乎不可能像本文中提到的那样保存解码器状态,因为使用中的库不支持它。如果你查看源代码,你会发现他们使用了第三方speex编解码器,并且不能完全访问其功能。我认为最好的方法是为speex找到一个不错的库,它支持类似于的状态恢复