Javascript web音频API中的自定义波形

Javascript web音频API中的自定义波形,javascript,audio,signal-processing,web-audio-api,Javascript,Audio,Signal Processing,Web Audio Api,我正在阅读这篇很棒的文章: 我想使用Web Audio API的PeriodicWave对象来实现此演示: 但是,当我使用以下设置设置周期波时: var real = new Float32Array([0,0,1,0,1]); var imag = new Float32Array(real.length); var customWave = context.createPeriodicWave(real,imag); osc.setPeriodicWave(customWave);

我正在阅读这篇很棒的文章:

我想使用Web Audio API的PeriodicWave对象来实现此演示:

但是,当我使用以下设置设置周期波时:

 var real = new Float32Array([0,0,1,0,1]);
 var imag = new Float32Array(real.length);
 var customWave = context.createPeriodicWave(real,imag);
 osc.setPeriodicWave(customWave);
我输出的波形如下所示:

以下是完整代码: 要查看波形,请按几次播放声音

我相信这些应该是匹配的,所以我的问题如下:

  • 我是否遗漏了这个理论的一些基本内容,或者我只是错误地执行了它?PeriodicWave对象是否应该执行与本文中说明的相同的操作
  • 如果我采取了错误的方法,我将如何在Web Audio API中实现此图?通过将两个不同频率的正弦波连接到同一个增益节点,我能够在下面进行匹配-这与使用PeriodicWave对象有什么不同
  • 我是新的DSP和网络音频API-任何建议阅读将不胜感激
  • 其次,在我的示例中,在将正确的数据绘制到画布之前,我必须按下“播放声音”按钮几次-分析器似乎在振荡器后面,即使在我启动振荡器后调用Analyzer.getFloatTimeDomainData(),对这里发生的事有什么想法吗


  • 编辑:如注释中所述,我的图形是颠倒的(在画布上,0,0是左上角)

    演示和输出之间的唯一区别是两个音调之间的相位关系。演示是
    y=sin(x)+sin(2x)
    ,你的演示是
    y=sin(x)+sin(2x+pi/2)
    。我不清楚这个相移是从哪里来的,但我不认为你做了什么

    以下是wolfram alpha的一些图:


    请注意,第一个数组定义余弦项,第二个数组定义正弦项:

    real
    参数表示余弦项的数组 第二部分(A条款)。在音频术语中,第一个元素(索引0)是 周期波形的直流偏移。第二个元素(索引1) 表示基频。第三个元素表示 第一泛音,等等。第一个元素被忽略,并且 实现必须在内部将其设置为零

    imag
    参数表示正弦项的数组 (B)条款)。第一个元素(索引0)应设置为零(和 将被忽略),因为该项在傅里叶级数中不存在。 第二个元素(索引1)表示基频。这个 第三个元素代表第一泛音,依此类推

    您将看到,您得到了预期的波形,但“反转”(由于@Julian在其答案中指出了这一点,因此画得颠倒-固定如下):

    (我在这里内联了您的代码,并交换了阵列:)
    更新了修复了原始代码中的图纸问题

    //设置音频上下文
    window.AudioContext=window.AudioContext | | window.webkitadiocontext;
    var context=new window.AudioContext();
    //创建节点
    var-osc//创建事件侦听器,以便我们可以多次按下按钮
    var masterGain=context.createGain();
    var analyzer=context.createanalyzer();
    //路由
    主增益连接(分析仪);
    分析器.连接(上下文.目的地);
    var显示=假;
    //画布的绘制功能
    函数drawWave(分析仪,ctx){
    var buffer=new Float32Array(1024),
    w=ctx.canvas.width;
    ctx.strokeStyle=“#777”;
    ctx.setTransform(1,0,0,-1,0100.5);//翻转y轴并平移到中心
    ctx.lineWidth=2;
    (函数循环(){
    Analyzer.getFloatTimeDomainData(缓冲区);
    ctx.clearRect(0,-100,w,ctx.canvas.height);
    ctx.beginPath();
    ctx.moveTo(0,缓冲区[0]*90);
    对于(var x=2;x
    
    按钮{位置:固定;左侧:10px;顶部:10px}
    
    播放声音
    
    createPeriodicWave
    中,
    real
    数组是余弦部分(或a项),而
    imag
    数组(b项)是正弦部分

    见:

    我想你刚刚把两者颠倒过来了。文章中说:

    式中,Ai是第i个正弦的振幅,fi是 第i个正弦

    所以你的
    imag
    数组(正弦部分)应该是[0,0,1,0,1],你的实际数组应该是[0,0,0,0,0]

    像这样:

    var imag = new Float32Array([0,0,1,0,1]);
     var real = new Float32Array(real.length);
    
    在你的jsbin中尝试一下,你会发现它是有效的,唯一的一件事是它会被反转,因为你是用负数绘制的(意思是0坐标是顶部,而不是底部)。要获得文章中的内容,可以反向绘制,或者像这样使用imag数组:[0,0,-1,0,-1]


    如果您想使用不同的
    imag
    real
    配置玩一玩,并查看结果,您可以在这里看到:

    感谢您分享这张漂亮的wave渲染图!