为什么我如何执行此代码?

时间:2013-08-08 19:37:47

标签: supercollider

我构建了以下简单的synth结构,它创建了一个合成器并通过效果单元路由其输出:

b = Bus.audio(numChannels: 2);

SynthDef(
    "mySynth",
    {
        |freq, amp, gate = 1|
        var vol = 0.5;
        var audio = Pulse.ar(freq, 0.5);
        var env = EnvGen.kr(Env.perc, doneAction:2);
        audio = Pan2.ar(audio, MouseX.kr(-1, 1));
        Out.ar(b, audio * env);
    }
).add;


SynthDef(
    "effects",
    {
        var audio = In.ar(b, 2);
        audio = LPF.ar(audio, MouseY.kr(200, 1000));
                    //TODO: Implement some crazy, revolutionary effects
            Out.ar(0, audio);
    }
).add;

// **** Dividing line for executing the code ****

e = Synth(\effects);

p = Pbind(*[
    instrument: \mySynth,
    scale: #[0, 2, 4, 5, 7, 9, 11],
    degree: Pseq([3,        3,      9,      9,      2,      9,      9,      3,      5,      7], inf),
    dur:        Pseq([0.2,  0.2,    0.2,    0.1,    0.1,    0.2,    0.2,    0.2,    0.1,    0.1], inf),
    amp:        Pseq([1,        0.6,    0.9,    0.3,    0.4,    0.9,    0.6,    0.85,   0.3,    0.4], inf),
]);

p.play;

当我以特定方式执行代码时,这只会产生声音输出:

  • 我可以按顺序逐个执行每个块,然后输出声音。
  • 我可以执行第一个块到“分界线”注释,然后执行以下块,我会听到声音输出。
  • 如果我一起执行所有代码,我就不会听到声音输出。

我猜测在声明SynthDef然后使用Synth()实例化它之间必须有一些延迟,而服务器确实设置了设置内容。任何人都可以放弃任何光明吗?

3 个答案:

答案 0 :(得分:2)

我通常使用Server.sync()方法解决这个问题。它暂停执行封闭线程(例如Routine),直到所有异步服务器命令都完成为止。这包括发送SynthDefs和分配缓冲区。您可以将Condition参数传递给Server.sync()以进行更明确的控制。

因此,例如,您可以一次执行此块:

s = Server.local;
s.boot;
s.doWhenBooted({
    Routine {
        SynthDef.new(\sine, {
            arg out=0, hz=220, dur=4.0;
            var snd, amp;
            snd = SinOsc.ar(hz);
            amp = EnvGen.ar(Env.linen(0.1, dur, 0.1), doneAction:2);
            Out.ar(out, (amp*snd).dup);
        }).send(s);
        s.sync; // waits here
        x = Synth.new(\sine);
    }.play;
});

答案 1 :(得分:1)

我确信你是对的,这与声明synthdef和准备就绪之间的延迟有关。

我对sclang的经验不足以立即告诉您应该如何更改代码(我通常通过OSC使用scsynth,只使用sclang编写SynthDefs),但是你应该可以做到completionMsg的可选SynthDef.add参数。

答案 2 :(得分:1)

这是因为你不能只是将SynthDefs“添加”到服务器并在同一个执行中创建所述synth的实例。如果你在执行时“播放”合成器,那么它们的实例就会被添加到服务器中,这样当你调用Synth执行时它就会被加载。工作代码包含在下面。

(
b = Bus.audio(numChannels: 2);

SynthDef(
    "mySynth",
    {
        |freq, amp, gate = 1|
        var vol = 0.5;
        var audio = Pulse.ar(freq, 0.5);
        var env = EnvGen.kr(Env.perc, doneAction:2);
        audio = Pan2.ar(audio, MouseX.kr(-1, 1));
        Out.ar(b, audio * env);
    }
).play;

SynthDef(
    "effects",
    {
        var audio = In.ar(b, 2);
        audio = LPF.ar(audio, MouseY.kr(200, 1000));
                    //TODO: Implement some crazy, revolutionary effects
            Out.ar(0, audio);
    }
).play;



// **** Dividing line for executing the code ****

e = Synth(\effects);

p = Pbind(*[
    instrument: \mySynth,
    scale: #[0, 2, 4, 5, 7, 9, 11],
    degree: Pseq([3,        3,      9,      9,      2,      9,      9,      3,      5,      7], inf),
    dur:        Pseq([0.2,  0.2,    0.2,    0.1,    0.1,    0.2,    0.2,    0.2,    0.1,    0.1], inf),
    amp:        Pseq([1,        0.6,    0.9,    0.3,    0.4,    0.9,    0.6,    0.85,   0.3,    0.4], inf),
]);

p.play;
)