1

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

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;

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

  • 我可以按顺序单独执行每个块,并得到声音输出。
  • 我可以执行第一个块直到'分界线'注释,然后是以下块,我会得到声音输出。
  • 如果我一起执行所有代码,我不会得到声音输出。

我猜在声明 aSynthDef然后使用 实例化它之间必须有一些延迟Synth(),而服务器确实设置了一些东西。任何人都可以解释一下吗?

4

3 回答 3

2

我通常使用 Server.sync() 方法来解决这个问题。它暂停执行封闭线程(例如例程),直到所有异步服务器命令都已完成。这包括发送 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;
});
于 2014-10-09T19:19:19.303 回答
1

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

我没有足够的经验sclang立即告诉您应该如何更改代码(我通常通过 OSC 使用 scsynth,仅使用 sclang 来编写 SynthDefs),但是您应该能够completionMsg使用SynthDef.add.

于 2013-08-17T15:35:45.860 回答
1

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

(
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;
)
于 2013-09-03T07:58:54.123 回答