Reputation: 1685
Here is my synthdef:
(
// Create a global audio bus for mixing all synths together
~mainBus = Bus.audio(s, 2); // Stereo bus (2 channels)
SynthDef(\squareSynthWithResonantFilter, {
|outBus, freq = 440, filterStartFreq = 1000, filterEndFreq = 200, filterResonance = 0.1, amp = 0.2, sustain = 0.5, attack = 0.01, release = 0.5, gate = 1|
var squareWave, ampEnv, filterEnv, filteredSignal, ampEnvGen, filterEnvGen;
squareWave = Pulse.ar(freq, 0.5);
ampEnv = Env.adsr(attack, 0.1, sustain, release);
ampEnvGen = EnvGen.kr(ampEnv, gate, doneAction: 2);
filterEnv = Env.adsr(attack, 0.1, sustain, release);
filterEnvGen = EnvGen.kr(filterEnv, gate);
filteredSignal = RLPF.ar(squareWave, filterEnvGen.linexp(0, 1, filterStartFreq, filterEndFreq), filterResonance);
Out.ar(outBus, [filteredSignal, filteredSignal] * ampEnvGen * amp);
}).add;
)
I expected my code to play a chord and then release the notes after 2 seconds.
// Routine to play the composition with simultaneous press and release
(
{
var melody = [
[440, 2000, 300, 0.9], // freq, filterStartFreq, filterEndFreq, filterResonance
[523.25, 1500, 500, 0.6],
[392, 2500, 400, 0.8],
[349.23, 1000, 300, 0.5],
[659.25, 2200, 200, 0.9],
[447, 1800, 300, 0.4]
];
var synths = [];
// here array.do works as expected
melody.do { |note|
var synth = Synth(\squareSynthWithResonantFilter, [
\outBus, ~mainBus, // Send to global bus
\freq, note[0],
\filterStartFreq, note[1],
\filterEndFreq, note[2],
\filterResonance, note[3],
\amp, 0.3, // fixed amplitude
\sustain, 1.2,
\attack, 0.02,
\release, 1.0,
\gate, 1 // Start with gate open
]);
synths.add(synth); // Store the synths for later release
"Created synth with ID: %".format(synth.nodeID).postln; // Debugging
};
2.wait; // Hold all notes for 2 seconds
// Release all notes together
synths.do { |synth|
synth.set(\gate, 0); // This only works on one of the notes
"Setting gate to 0 for synth: %".format(synth.nodeID).postln;
};
}.fork;
)
I wonder if this issue has something to do with the bus or limiter? Probably not.
// Apply global limiter to the mixed signal on the bus and send to main audio output
(
{
var busSignal = In.ar(~mainBus, 2); // Read from the global bus
var limitedSignal = Limiter.ar(busSignal, 0.9); // Apply limiter to the combined signal
Out.ar(0, limitedSignal); // Output the limited signal to speakers (stereo out)
}.play;
)
The console output is this:
Created synth with ID: 1013
Created synth with ID: 1014
Created synth with ID: 1015
Created synth with ID: 1016
Created synth with ID: 1017
Created synth with ID: 1018
Setting gate to 0 for synth: 1013
indicating that only the first synth has its gate set to 0.
Upvotes: 1
Views: 44
Reputation: 364
the issue is not with the iteration, but with the population of the synths
array.
the line
var synths = [];
creates a new object of class Array
, as can be verified by inspecting synths.class
. Array
is a fixed-capacity collection, and its .add
method has some unusual behavior; from the helpfile:
Adds an item to an ArrayedCollection if there is space. This method may return a new ArrayedCollection. For this reason, you should always assign the result of add to a variable - never depend on add changing the receiver.
so your code can be made to work as expected by changing this line:
synths.add(synth); // this returns a new array with the new item added;
// but the result is discarded
to:
synths = synths.add(synth);
Alternatively, you could initialize synths
as a List
rather than an Array
, the former being extensible by design.
Upvotes: 2