我正在构建一个模拟罗兰朱诺-106合成器使用WebAudio。活的WIP版本在这里。
如果在攻击或释放过程中,当滤波器同时被包络调制时,截止频率或包络调制量发生了变化,我就无法处理如何更新滤波器。代码就在这里附近。当前的实现并不像模拟合成器那样响应,但我不太清楚如何计算它。
在一个真实的合成器上,滤波器会立即发生变化,这取决于频率截止、包络调制量和包络中的电流级,但上升或下降也是平稳的。
我该如何模拟这种行为?
发布于 2015-05-04 15:57:02
精彩的计划!
你不需要自己和这些-网络音频AudioParams和他们的输入,所以如果你有一个潜在的音频调制源,如LFO ( OscillatorNode连接到GainNode),你只需连接()它到AudioParam。
这里的关键是AudioParams能够连接()到一个节点或AudioParam的多个输入连接。所以你通常想要一个模型
filter cutoff = (cutoff from envelope) + (cutoff from mod/LFO) + (cutoff from cutoff knob)由于截止是一个频率,因此在对数尺度上不是线性的,所以您想要以对数方式进行这个加法(否则,一个在440 at时提高截止倍频程的信封只会将它提升到880 at的半倍频程,等等)--幸运的是,通过BiquadFilter上的“绕行”参数可以很容易地做到这一点。
分离是以美分为单位的(1200/倍频程),所以你必须使用增益节点来调整值(例如,如果你想要你的调制有一个+1/-1倍频程范围,确保振荡器输出在-1200到+1200之间)。您可以在我的Web合成器(https://github.com/cwilso/midi-synth)中看到我是如何做到这一点的:特别是,请查看synth.js,从第500行开始:https://github.com/cwilso/midi-synth/blob/master/js/synth.js#L497-L519。请注意modFilterGain.connect( the .filter1.detune);特别是。
您不希望直接为调制设置任何值,因为实际值将以潜在的快速速度变化--您希望使用参数调度程序和来自LFO的输入求和。您可以根据需要按时间设置旋钮值,但事实证明,设置.value与在同一个AudioParam上设置计划值交互很差,因此您需要在AudioParam中有一个单独的(之和)输入。这是一个棘手的问题,老实说,我的synth今天并没有很好地做到这一点(我应该将它改为下面描述的方法)。
处理旋钮设置的正确方法是创建一个根据旋钮设置而变化的音频通道--也就是说,它是一个AudioNode,您可以将它连接到filter.detune,尽管该AudioNode生成的示例值仅为正值,并且只有当旋钮被更改时才会更改值。要做到这一点,您需要一个DC偏移源--也就是说,生成一个常量示例值流的AudioNode。我能想到的最简单的方法是使用生成的缓冲区为1的AudioBufferSourceNode:
function createDCOffset() {
var buffer=audioContext.createBuffer(1,1,audioContext.sampleRate);
var data = buffer.getChannelData(0);
data[0]=1;
var bufferSource=audioContext.createBufferSource();
bufferSource.buffer=buffer;
bufferSource.loop=true;
bufferSource.start(0);
return bufferSource;
}然后,只需将该DCOffset连接到增益节点,并将“旋钮”连接到增益的.value,以使用增益节点来缩放值(记住,一个八度有1200美分,所以如果您希望您的旋钮表示六倍频程截止范围,.value应该在零到7200之间)。然后将() DCOffsetGain节点连接到过滤器的.detune (它与来自LFO的连接相加,而不是替换连接,并与AudioParam上的计划值相加(请记住,您也需要用美分缩放预定值)。这种方法,BTW,使得翻转信封极性也很容易( VCF ENV开关在Juno 106上)--只是倒转您在调度程序中设置的值。
希望这能有所帮助。我现在有点时差,希望这是清醒的。:)
https://stackoverflow.com/questions/30019666
复制相似问题