草庐IT

javascript - 网络音频合成 : how to handle changing the filter cutoff during the attack or release phase?

coder 2024-05-16 原文

我正在使用 WebAudio 构建 Roland Juno-106 合成器的仿真器。 The live WIP version is here .

如果在启动或释放期间更改了截止频率或包络调制量,同时滤波器同时被包络调制,我对如何处理更新滤波器犹豫不决。 That code is located around here .当前的实现不像模拟合成器那样响应,但我不太清楚如何计算它。

在真实的合成器上,滤波器会根据截止频率、包络调制量和包络中的当前阶段而立即改变,但上升或下降也会平滑地继续。

我将如何为这种行为建模?

最佳答案

辉煌的项目!

您不需要自己对这些求和 - Web Audio AudioParams 将它们的输入求和,因此如果您有潜在的音频速率调制源,如 LFO(连接到 GainNode 的 OscillatorNode),您只需将它连接()到音频参数。

这是这里的关键 - AudioParams 能够连接()到 - 并且对一个节点或 AudioParam 的多个输入连接求和。所以你通常想要一个

filter cutoff = (cutoff from envelope) + (cutoff from mod/LFO) + (cutoff from cutoff knob)

由于截止频率是一个频率,因此在对数刻度上不是线性频率,因此您希望以对数方式进行此加法(否则,在 440Hz 时将截止频率提升一个 Octave 的包络只会在 880Hz 时将其提升半个 Octave 等)——幸运的是,这很容易通过 BiquadFilter 上的“detune”参数实现。

失谐以音分(1200/倍频程)为单位,因此您必须使用增益节点来调整值(例如,如果您希望调制具有 +1/-1 倍频程范围,请确保振荡器输出介于 - 1200 和 +1200)。您可以在我的 Web 音频合成器 ( https://github.com/cwilso/midi-synth ) 中看到我是如何做到这一点的:特别是从第 500 行开始查看 synth.js:https://github.com/cwilso/midi-synth/blob/master/js/synth.js#L497-L519 .注意 modFilterGain.connect(this.filter1.detune);特别是。

您不想直接为调制设置任何值,因为实际值可能会以可能很快的速度变化 - 您想要使用参数调度器和来自 LFO 的输入求和。您可以根据需要根据时间设置旋钮值,但事实证明,设置 .value 与在同一 AudioParam 上设置预定值的交互效果不佳 - 因此您需要对 AudioParam 进行单独(求和)输入。这是棘手的一点,老实说,我的合成器今天做得不好(我应该将其更改为下面描述的方法)。

处理旋钮设置的正确方法是创建一个根据您的旋钮设置而变化的音频 channel - 也就是说,它是一个 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 以使用增益节点来缩放值(请记住,一个 Octave 音阶有 1200 音分,所以如果您想要您的旋钮代表一个六倍频程截止范围,.value 应该在零和 7200 之间)。然后将 DCOffsetGain 节点连接到过滤器的 .detune(它与来自 LFO 的连接相加而不是替换,并且还与 AudioParam 上的预定值相加(记住您需要以美分为单位缩放预定值, 也))。顺便说一下,这种方法也可以很容易地翻转包络极性(Juno 106 上的 VCF ENV 开关)——只需反转您在调度程序中设置的值。

希望这对您有所帮助。我现在有点时差,所以希望这是清醒的。 :)

关于javascript - 网络音频合成 : how to handle changing the filter cutoff during the attack or release phase?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30019666/

有关javascript - 网络音频合成 : how to handle changing the filter cutoff during the attack or release phase?的更多相关文章

随机推荐