如何在Web Audio API中为OscillatorNode设置相位偏移?

时间:2013-07-07 15:58:31

标签: javascript audio webkit web-audio

我正在尝试实现立体声阶段,如下所述:http://www.image-line.com/support/FLHelp/html/plugins/3x%20OSC.htm

“立体声相位(SP) - 允许您为发生器的左右声道设置不同的相位偏移。偏移导致振荡器从振荡器形状的不同点开始(例如,从最高点开始)正弦函数的值而不是零点。)立体相位偏移增加了所产生声音的丰富度和立体声全景。“

我正在尝试为OscillatorNode实现此目的。我唯一的想法是使用createPeriodicWave(https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#dfn-createPeriodicWave)但是,从规范中创建周期波的描述超出了我的理解,我没有通过谷歌找到任何例子。

任何解释createPeriodicWave描述的帮助都会有所帮助,就像有关如何实现这种效果的任何其他想法一样。

谢谢!

6 个答案:

答案 0 :(得分:4)

麦克莱伦和其他人,

这个答案帮助并随后使我进入了傅里叶的世界。在a page on the subject和一些维基百科的帮助下,我认为我得到了正方形和锯齿形图案,但三角形图案仍然无法实现。有谁知道吗?

它确实为你提供了相移的能力,如this article by Nick Thompson explains(尽管他以不同方式调用AudioContext方法,但原理是相同的)。

就方形和锯齿形图案而言:

var n = 4096;
var real = new Float32Array(n);
var imag = new Float32Array(n);
var ac = new AudioContext();
var osc = ac.createOscillator();

/* Pick a wave pattern */

/* Sine 
imag[1] = 1; */

/* Sawtooth 
for(x=1;x<n;x++)
    imag[x] = 2.0 / (Math.pow(-1, x) * Math.PI * x); */

/* Square */
for(x=1;x<n;x+=2)
    imag[x] = 4.0 / (Math.PI * x);

var wave = ac.createPeriodicWave(real, imag);

osc.setPeriodicWave(wave);  
osc.connect(ac.destination);
osc.start();
osc.stop(2); /* Have it stop after 2 seconds */

这将播放激活的图案,在这种情况下为方形图案。三角形公式会是什么样的?

答案 1 :(得分:2)

我认为使用OscillatorNode进行相位偏移是不可能的。

这样做的方法是使用context.createBuffer并生成正弦波缓冲区(或任何类型的波),并将其设置为BufferSourceNode的缓冲区,然后使用offset方法中的start()参数。但您需要以秒为单位计算样本偏移量。

var buffer = context.createBuffer(1,1024,44100);

var data = buffer.getChannelData(0);

for(var i=0; i < data.length; i++){
    //generate waveform
}

var osc = context.createBufferSourceNode();
osc.buffer = buffer;
osc.loop = true;

osc.connect(context.destination);
osc.start(time, offset in seconds);

答案 2 :(得分:1)

伪造它的一种简单方法是向左右声道添加单独的延迟节点,并为它们提供用户控制的延迟值。这将是我的方法,并且与相位设置具有或多或少相同的效果。

如果你想使用createPeriodicWave,不幸的是你可能必须要理解背后有些困难的数学。

基本上,您首先必须将波形表示为正弦波“部分”的总和。所有周期性波都有这种形式的一些表示。然后,一旦找到每个部分的相对大小,就必须通过将每个部分乘以一个复数来分别对左右声道进行相移。您可以在此处阅读有关将周期波表示为正弦波总和的更多详细信息:http://music.columbia.edu/cmc/musicandcomputers/chapter3/03_03.php

使用createPeriodicWave与使用BufferSourceNode相比具有明显优势:createPeriodicWave波形将自动避免aliasing。如果您在缓冲区中“手动”生成波形,则很难避免混叠。

答案 3 :(得分:0)

根据本文关于Wolfram的看法,可以像这样建立三角波:

/* Triangle */
for(x=1;x<n;x+=2) 
    imag[x] = 8.0 / Math.pow(Math.PI, 2) * Math.pow(-1, (x-1)/2) / Math.pow(x, 2) * Math.sin(Math.PI * x);

同样有用的方法是Wikipedia页面实际显示了傅里叶结构的工作原理。

答案 4 :(得分:0)

function getTriangleWave(imag, n) {
    for (var i = 1; i < n; i+=2) {
      imag[i] = (8*Math.sin(i*Math.PI/2))/(Math.pow((Math.PI*i), 2));
    }
    return imag;
}

答案 5 :(得分:0)

在Chrome 66中添加AudioWorklet的情况下,您可以像现在不推荐使用的ScriptProcessorNode一样编写声音处理程序。

我使用此工具创建了一个便利库,该便利库是一个普通的WebAudio API OscillatorNode,其相位(除其他外)也有所不同。您可以找到它here

const context = new AudioContext()
context.audioWorklet.addModule("worklet.js").then(() => {
  const osc = new BetterOscillator(context)
  osc.parameters.get("phase").value = Math.PI / 4
  osc.connect(context.destination)
  osc.start()
}