Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript speex拆分音频数据-WebAudio-VOIP_Javascript_Audio_Voip_Web Audio Api_Speex - Fatal编程技术网

Javascript speex拆分音频数据-WebAudio-VOIP

Javascript speex拆分音频数据-WebAudio-VOIP,javascript,audio,voip,web-audio-api,speex,Javascript,Audio,Voip,Web Audio Api,Speex,我正在运行一个小应用程序,用javascript中的speex编解码器对音频阵列进行编码和解码: 用一个充满正弦波形的小阵列 for(var i=0;i<16384;i++) data.push(Math.sin(i/10)); for(var i=0;idecode>merge)听起来与以前不同 看看这个: 小提琴: 两个按钮应提供相同的音频输出 如何在两种方式下获得相同的输出?它们在speex.js中是用于分割音频数据的特殊模式吗?请注意,speex是一种特殊模式。因此,根据

我正在运行一个小应用程序,用javascript中的speex编解码器对音频阵列进行编码和解码:

用一个充满正弦波形的小阵列

for(var i=0;i<16384;i++)
    data.push(Math.sin(i/10));
for(var i=0;idecode>merge)听起来与以前不同

看看这个:

小提琴:

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

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

请注意,speex是一种特殊模式。因此,根据定义,它不能给出与编码缓冲区相同的结果。此外,它被设计为语音编解码器。因此,1-2 kHz范围将是最有效的,因为它需要特定形式的信号。在某些情况下另外,它可以与用于光栅图像的JPEG技术进行比较

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

buffer1.push(Math.sin(2*Math.PI*i*frequency/sampleRate));
我认为你应该用录音的声音做一个例子,并在这种情况下比较结果。这样更合适

总的来说,要想详细了解这个概念,你必须研究数字信号处理。我甚至不能提供一个合适的链接,因为它是一门完整的科学,而且数学上很密集。(我知道唯一适合阅读的书是在).如果这里有很强的数学背景的人能分享关于这个案例的适当文献,我将不胜感激


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

的状态恢复speex是一个有损编解码器,因此输出只是初始正弦波的近似值

您的正弦频率约为7 KHz,接近上编解码器的8 KHz频带,因此更可能被改变

编解码器的输出看起来像一个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); });
//在2个数组中生成一个连续的窦房结
var len=16384;
var buffer1=[];
var buffer2=[];
var缓冲区=[];

对于(var i=0;iYeah很好理解。也请注意解码单独的数据块。确实需要保持注释中所述的解码器状态,但我认为这个想法是将两个独立编码的信号缝合在一起。这个想法是实时传输语音数据,所以我必须将信号分成几个部分。感谢您的回答@kuroineko,我将尝试smo如果speex库中现在有内置的解决方案,那也没关系。内置的解决方案是让编解码器上下文保持活动状态,并为它提供连续的流。如果你用它来传输单个源点对点,那应该是可行的。@kuroineko speex上下文在哪里?我如何让它保持活动状态?在你的“原始”上按钮,你从<代码> VRG,不是<代码> DEVV ,经过编码解码后,两者都有相同的失真,但是在合并的音频中间有一个明显的中断。你还没有正确地排列所有的数组,但是我不相信修复这个词会停止中间的音频中断。谢谢你的回答。我在谷歌上搜索了很多,在发布这个问题之前也使用了原始库。我认为这是Javascript中唯一一个speex库。如果这个库不支持这一点,我必须在自己的基础上构建一个解决方案,这很难。我发布链接的那个库似乎有
init
接受
speex\u位
。但是我没有尝试过我自己的。Speex是一个开放的编解码器,我不敢相信有这么少的is库。至少有一个是完全支持的。
Coder
类,无论在使用库中被称为什么,都应该有类似于
Coder.init(Speex\u位)的东西
在解码下一个缓冲区之前调用,其中
speex_位
是speex数据的前一块。您用来录制麦克风的库根本没有公开他们使用的第三方speex编解码器的高级功能。我没能弄清楚他们使用的是哪一个,所以我想找到一个好的speex纯库会更简单如你所说,在没有recorder.js lib的情况下直接使用原始speex,这样我就可以在解码之前调用init。(看看新的decode/encode函数)但仍然不能很好地工作。你有什么想法吗?我和一个有VoIP经验的朋友谈过,他说当编解码器进程优先级不高时(浏览器中不是我们的情况),会在缓冲区末尾单击缓冲区的大小与编解码器正在处理的数据块不匹配。在他的例子中,缓冲区的大小为120ms。在这个js编解码器中很难看到数据块的大小。我尝试播放,但没有得到任何改进:(