Firstly, you need to enclose code you post in the backtick: ` not a quotation mark
- you can go back to edit your post using the pencil icon.
I added some comments to your code to explain the chain of events that cause you to not hear anything in this case:
(
~masterBus = Bus.audio(s, 1);
// A bus is allocated. There are a fixed number of buses on the server, so this is effectively instantaneous, as simple as picking the next free bus number.
SynthDef(\master, {
| vol = 0.25 |
Out.ar(0, In.ar(~masterBus)*vol); // ← In reads off the ~masterBus
}).add;
// A SynthDef called \master is defined, and sent to the server. It can take time for the server to load this def, so master is NOT AVAILABLE RIGHT AWAY.
SynthDef(\osc, {
arg out = 0, vol = 0.25; // ← NB! default output is arg
var snd = SinOsc.ar(440);
snd = snd * vol;
Out.ar(out, snd)}
).add;
// Same with \master, this is sent to the server but not loaded immediately.
x = Synth(\osc, [\out, ~masterBus], addAction: \addToHead);
// A new \osc synth is created on the server. If you did NOT have SynthDef(\osc) already defined on the server, this will fail since the server has not loaded it yet.
m = Synth(\master, [\vol, 0.1], addAction: \addToTail);
// A new \master synth is created on the server. You JUST created and sent a \master SynthDef in this same block - because it's not instantaneous, it will not have been loaded yet. So: this Synth will EITHER point to the LAST \master you defined, or nothing if you haven't yet defined one. Importantly, since you are creating a new Bus each time you execute this code, your old \master is pointing to the OLD bus from the last time you ran it: you're always one step behind.
)
Here are three things you can do to improve this code. You don’t need to do ALL of these things, but they represent good practices and will avoid all kinds of subtle problems.
(
fork {
// BUSES
~masterBus = ~masterBus ?? { Bus.audio(s, 1) };
// SYNTH DEFS
SynthDef(\master, {
|in, vol = 0.25|
Out.ar(0, In.ar(in) * vol);
}).add;
SynthDef(\osc, {
arg out = 0, vol = 0.25; // ← NB! default output is arg
var snd = SinOsc.ar(440);
snd = snd * vol;
Out.ar(out, snd);
}).add;
s.sync;
x = Synth(\osc, [\out, ~masterBus], addAction: \addToHead);
m = Synth(\master, [\in, ~masterBus, \vol, 0.1], addAction: \addToTail);
}
)
- Only allocate a Bus if you have not already (
??
only does the second half if ~masterBus
is nil).
- Enclose your code in
fork {}
and run s.sync
after you define your SynthDef
s. This ensures that the audio server is synchronized, meaning it’s loaded everything you’ve requested.
- Make the argument to
In
a synth control like your \out
control. This way, you aren’t baking your Bus
INTO the SynthDef itself, but rather setting it as an argument when you create the Synth.
Finally: since you only need to allocate a Bus and define your SynthDefs once, but you may want to start and stop the Synths many times, it’s actually very reasonable to separate these into two chunks of code.