Short answer, you can easily synchronize them, but the code you have doesn’t.
The reason this is happening is your outer function is trying to send four other different functions to the server and you’ll end up with an error. You can fix some syntax to get it to not throw an error, but the timing will be off since you have to make sure the UGen functions are synchronized with s.bind
.
{}.play is a convenience method to build a temporary SynthDef with the UGen graph function and play it, so this is interpreted as “make and play a SynthDef that makes and plays these four SynthDefs,” which you can’t do.
By default, the UGens in a function will be synchronized as long as they all play on the same function. So if you could evaluate what you have, the first {}.play would have two oscillators in sync, but they would not be in sync with the second {}.play oscillators because they wouldn’t start at the same time. Observe:
{ [SinOsc.ar(110), SinOsc.ar(110)] }.plot;
{ [SinOsc.ar(400), SinOsc.ar(110)] }.plot;
They all have an initial phase of 0. If you change the phase argument, they’ll be at that phase.
{ [SinOsc.ar(110, pi), SinOsc.ar(110)] }.plot;
{ [SinOsc.ar(400, pi), SinOsc.ar(110)] }.plot;
A few other things about your code. If you want to just use a function to make sure this works, it looks like this, but as you had it before it’s way too loud:
({
{ [SinOsc.ar(110, 0, 0.6), SinOsc.ar(110, 0, 0.6), SinOsc.ar(220, 0, 0.6), SinOsc.ar(220, 0, 0.6), SinOsc.ar(440, 0, 0.5), SinOsc.ar(440, 0, 0.5), SinOsc.ar(880, 0, 0.45), SinOsc.ar(880, 0, 0.45)].sum * 0.01
}.play)
Several ways to improve this:
- Make this a SynthDef and then play it. That way it’s already been built on the server.
(
SynthDef(\mySynth, {
arg out = 0;
var sig = [
SinOsc.ar(110, 0, 0.6),
SinOsc.ar(110, 0, 0.6),
SinOsc.ar(220, 0, 0.6),
SinOsc.ar(220, 0, 0.6),
SinOsc.ar(440, 0, 0.5),
SinOsc.ar(440, 0, 0.5),
SinOsc.ar(880, 0, 0.45),
SinOsc.ar(880, 0, 0.45)].sum * 0.01;
Out.ar(out, sig);
}).add;
)
Synth(\mySynth);
- You can (and it’s far more idiomatic to) use iteration instead of typing out the same thing multiple times. You also don’t need duplicates of the same UGen with the same arguments. I assume you’re doing this to get stereo playback, but there’s a better way with
.collect
. See Eli Fieldsteel’s tutorial on iteration for a more detailed explanation.
(
SynthDef(\mySynth, {
arg out = 0, freq = 110;
var sig = 4.collect{
arg i; //index value
var ratio = 2.pow(i);
SinOsc.ar(ratio * freq, 0);
};
sig = sig * [0.6, 0.6, 0.5, 0.45].normalizeSum; //so it's not so loud
sig = sig.sum.dup;
Out.ar(out, sig);
}).add;
)
Synth(\mySynth);
- You could use
Pan2
instead of .dup
or !2
to control the panning.
(
SynthDef(\mySynth, {
arg out = 0, freq = 110, pan = 0; //add pan argument set to stereo center
var sig = 4.collect{
arg i; //index value
var ratio = 2.pow(i);
SinOsc.ar(ratio * freq, 0);
};
sig = sig * [0.6, 0.6, 0.5, 0.45].normalizeSum;
sig = Pan2.ar(sig, pan);
Out.ar(out, sig);
}).add;
)
x = Synth(\mySynth);
x.set(\pan, -1);
x.set(\pan, 1);
x.free;