Thank you for your kind answers!
I have more questions:
- The
s.bind { ... }
examples in your examples and in the server help document uses Out.ar
to write the signal to the audio bus. Wouldn’t it be better in terms of timing accuracy to write the output of the SynthDef
as OffsetOut.ar
instead of Out.ar
? OffsetOut.ar produces the correct sound in the following example:
(
fork {
SynthDef(\testOut, { |freq = 440, out = 0|
var sig, env;
sig = SinOsc.ar(freq) * 0.1;
env = Env.perc(0.01, 0.05, 0.2).ar(Done.freeSelf);
Out.ar(out, sig * env)
}
).add;
s.sync;
200.do { s.bind { Synth(\testOut) }; 0.01.wait } }
)
(
fork {
SynthDef(\testOffsetOut, { |freq = 440, out = 0|
var sig, env;
sig = SinOsc.ar(freq) * 0.1;
env = Env.perc(0.01, 0.05, 0.2).ar(Done.freeSelf);
OffsetOut.ar(out, sig * env)
}
).add;
s.sync;
200.do { s.bind { Synth(\testOffsetOut) }; 0.01.wait } }
)
-
s.bind { ... }
is shorter than s.makeBundle(0.2, { ... })
, but it is still extra typing. Can it be enclosed by a function to reduce the typing? The enclosed s.bind { ... }
by a function seems to work in the following example, but I am not sure what will happen if the language-side algorithms or SynthDef are more complex than the example:
(
fork { s.bind { Synth(\testOffsetOut, [freq: 440, out: 1]) };
0.1.wait;
s.bind { Synth(\testOffsetOut, [freq: 660, out: 1]) };
0.1.wait;
s.bind { Synth(\testOffsetOut, [freq: 880, out: 1]) }
}
)
(
fork {
var synth = { |freq| s.bind { Synth(\testOffsetOut, [freq: freq]) } };
synth.(440);
0.1.wait;
synth.(660);
0.1.wait;
synth.(880)
}
)
(
fork {
var synth = { |freq| s.bind { Synth(\testOffsetOut, [freq: freq]) } };
synth.(440);
s.bind { Synth(\testOffsetOut, [freq: 440, out: 1]) };
0.1.wait;
synth.(660);
s.bind { Synth(\testOffsetOut, [freq: 660, out: 1]) };
0.1.wait;
synth.(880);
s.bind { Synth(\testOffsetOut, [freq: 880, out: 1]) }
}
)
- Can
{ ... }.play
be also used when SynthDef(...).play
can be used? I think not, because { ... }.play
takes extra time to be sent to the server when the code block is evaluated. However, in the following examples, { ... }.play
seems to work well when the sound length and repeat interval are not extremely short:
( // seems to work
fork {
var synth = { |freq|
s.bind { { SinOsc.ar(freq) * 0.1 * Env.perc(0.01, 0.05, 0.2).ar(Done.freeSelf) }.play }
};
synth.(440);
0.1.wait;
synth.(660);
0.1.wait;
synth.(880);
0.1.wait;
}
)
( // does not work corretly:
fork {
var synth = { |freq|
s.bind { { SinOsc.ar(freq) * 0.1 * Env.perc(0.01, 0.05, 0.2).ar(Done.freeSelf) }.play }
};
200.do { s.bind { synth.(440); 0.01.wait } }
}
)
( // seems to work
fork {
var synth, funcSynth;
SynthDef(\testOffsetOut_, { |freq = 440, out = 0|
var sig, env;
sig = SinOsc.ar(freq) * 0.1;
env = Env.perc(0.01, 0.05, 0.2).ar(doneAction: Done.freeSelf);
OffsetOut.ar(out, sig * env)
}
).add;
s.sync;
funcSynth = { |freq|
s.bind { { SinOsc.ar(freq) * 0.1 * Env.perc(0.01, 0.05, 0.2).ar(Done.freeSelf) }.play }
};
synth = { |freq|
s.bind { Synth(\testOffsetOut_, [freq: freq, out: 1]) }
};
funcSynth.(440);
synth.(440);
0.1.wait;
funcSynth.(660);
synth.(660);
0.1.wait;
funcSynth.(880);
synth.(880);
}
)