超级对撞机:使用 Mix.fill 进行加法合成的变量和参数范围

Supercollider: scope of variables and arguments for additive synthesis using Mix.fill

我对如何在加法合成中实现参数感到很困惑。

我正在尝试实现一个系统,我可以在其中对以下参数进行排序:任意数量的分音、基频。我不确定任意数量的分音是否可行,但我认为对基频进行排序确实是完全可能的。

这是我正在处理的代码:

(
    z = {
        arg index, freq, nn;
        var finalFreq, ff, amp, nn;
        ff = index*freq;
        amp = 0.5/nn;
        finalFreq = freq + ff;
        finalFreq.postln;
        s = SinOsc.ar(finalFreq, 0, amp);
    };
)

(
SynthDef.new('additive',{
    arg freq, nn;
    var sig, env;
    env = Line.kr(1,0,0.2);
    sig = Mix.fill(nn, z) * env;
    Out.ar(0,sig);
}).add
)

(p = Pbind(
    \instrument, \additive,
    \dur, Pseq([0.1,0.2,0.3,0.4],inf),
    \freq, Pseq([100,440,880,55],inf),
    \nn, Pseq([1,5,10,100],inf)
).play;
)

失败 Index not an Integer。而且我什至不确定如何将参数发送到 z。

我设想利用变量范围的替代公式如下:

(
SynthDef.new('additive',{
    arg freq, nn;
    var sig, env;
    env = Line.kr(1,0,0.2);
    z = {
        arg index;
        var finalFreq, ff, amp, nn;
        ff = index*freq;
        amp = 0.5/nn;
        finalFreq = freq + ff;
        finalFreq.postln;
        s = SinOsc.ar(finalFreq, 0, amp);
    };

    sig = Mix.fill(nn, z) * env;
    Out.ar(0,sig);
}).add
)

它也不起作用,失败 Index not an Integer

你会如何解决这个问题?

Mix.fill 在创建 Synth 时创建一次数组,因此您不能使用 Synth 参数动态更改数组的大小。

您的底部示例还将 nn 声明为 z 函数内的变量,这意味着 amp = 0.5/nil

一个可能的解决方案是制作许多 SynthDef。假设您知道您想要的 SinOsc 的最小数量是 2,最大数量是 25。

(
(2..25).do({ arg nn;
    
    SynthDef.new('additive'++nn,{
        arg freq;
        var sig, env;
        env = Line.kr(1,0,0.2);
        z = {
            arg index;
            var finalFreq, ff, amp;
            ff = index*freq;
            amp = 0.5/nn;
            finalFreq = freq + ff;
            finalFreq.postln;
            s = SinOsc.ar(finalFreq, 0, amp);
        };
        
        sig = Mix.fill(nn, z) * env;
        Out.ar(0,sig);
    }).add
});
)

这将为您提供名为 additive2、additive3、additive4、...additive25 的 SynthDef。

当你想改变数组的大小时,你必须改变你正在播放的 SynthDef。这是一个 Pbind,它从你的附加 SynthDefs 之间随机选择:

Pbind(
    \instrument, Pfunc({ 'additive' ++ 2.rrand(25) })
).play

或者,使用上面示例中的 pbind:

(
n = [1,5,10,100];

n.do({ arg nn;
    
    SynthDef.new('additive'++nn,{
        arg freq;
        var sig, env;
        env = Line.kr(1,0,0.2);
        z = {
            arg index;
            var finalFreq, ff, amp;
            ff = index*freq;
            amp = 0.5/nn;
            finalFreq = freq + ff;
            finalFreq.postln;
            s = SinOsc.ar(finalFreq, 0, amp);
        };
        
        sig = Mix.fill(nn, z) * env;
        Out.ar(0,sig);
    }).add
});
)

Pbind(
    \instrument, Pfunc({ 'additive' ++ n.choose }),
    \dur, Pseq([0.1,0.2,0.3,0.4],inf),
    \freq, Pseq([100,440,880,55],inf)
).play