我正在尝试实现立体声阶段,如下所述: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描述的帮助都会有所帮助,就像有关如何实现这种效果的任何其他想法一样。
谢谢!
答案 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()
}