我构建了以下简单的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()
实例化它之间必须有一些延迟,而服务器确实设置了设置内容。任何人都可以放弃任何光明吗?
答案 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;
)