every param which you update with synth.set here will be updated on the beginning of each measure:
(
var getSubDivs = { |trig, arrayOfSubDivs, numOfSubDivs, duration|
var hasTriggered = PulseCount.ar(trig) > 0;
var subDiv = Ddup(2, (Dseq(arrayOfSubDivs, numOfSubDivs).dpoll * duration));
Duty.ar(subDiv, trig, subDiv) * hasTriggered;
};
var rampOneShot = { |trig, duration, cycles|
var hasTriggered = PulseCount.ar(trig) > 0;
var phase = Sweep.ar(trig, 1 / duration).clip(0, cycles);
phase * hasTriggered;
};
var oneShotBurstsToTrig = { |phaseScaled|
var phaseStepped = phaseScaled.ceil;
var delta = HPZ1.ar(phaseStepped);
delta > 0;
};
var rampToSlope = { |phase|
var history = Delay1.ar(phase);
var delta = (phase - history);
delta.wrap(-0.5, 0.5);
};
var multiChannelTrigger = { |numChannels, trig|
var count = Demand.ar(trig, DC.ar(0), Dseries(0, 1, inf));
numChannels.collect{ |chan|
trig * BinaryOpUGen('==', (count + (numChannels - 1 - chan) + 1) % numChannels, 0);
};
};
var getSubSampleOffset = { |phase, trig|
var slope = rampToSlope.(phase);
var sampleCount = phase - (slope < 0) / slope;
Latch.ar(sampleCount, trig);
};
var accumulatorSubSample = { |trig, subSampleOffset|
var accum = Duty.ar(SampleDur.ir, trig, Dseries(0, 1));
accum + subSampleOffset;
};
var multiChannelAccumulator = { |triggers, subSampleOffsets|
triggers.collect{ |localTrig, i|
var hasTriggered = PulseCount.ar(localTrig) > 0;
var localAccum = accumulatorSubSample.(localTrig, subSampleOffsets[i]);
localAccum * hasTriggered;
};
};
var channelMask = { |triggers, numChannels, channelMask, centerMask|
var panChannels = Array.series(numChannels, -1 / numChannels, 2 / numChannels).wrap(-1.0, 1.0);
var panPositions = panChannels.collect { |pos| Dser([pos], channelMask) };
Demand.ar(triggers, 0, Dseq(panPositions ++ Dser([0], centerMask), inf));
};
SynthDef(\burst, {
var numChannels = 5;
var initTrigger, arrayOfSubDivs, numOfSubDivs;
var seqOfSubDivs, stepPhaseScaled, stepPhase, stepTrigger, stepSlope;
var triggers, subSampleOffsets, accumulator, overlap, maxOverlap, chanMask;
var windowSlopes, windowPhases, grainWindows;
var grainSlope, grainPhases, sigs, sig;
initTrigger = Trig1.ar(\trig.tr(0), SampleDur.ir);
arrayOfSubDivs = \arrayOfSubDivs.kr(Array.fill(16, 1));
numOfSubDivs = \numOfSubDivs.kr(12);
initTrigger.poll(initTrigger, \initTrig);
seqOfSubDivs = getSubDivs.(initTrigger, arrayOfSubDivs, numOfSubDivs, \sustain.kr(1));
stepPhaseScaled = rampOneShot.(initTrigger, seqOfSubDivs, numOfSubDivs);
stepTrigger = oneShotBurstsToTrig.(stepPhaseScaled);
stepPhase = stepPhaseScaled.wrap(0, 1);
stepSlope = rampToSlope.(stepPhase);
// distribute triggers round-robin across the channels
triggers = multiChannelTrigger.(numChannels, stepTrigger);
// calculate sub-sample offset per multichannel trigger
subSampleOffsets = getSubSampleOffset.(stepPhase, triggers);
// create a multichannel accumulator with sub-sample accuracy
accumulator = multiChannelAccumulator.(triggers, subSampleOffsets);
overlap = \overlap.kr(1);
maxOverlap = min(overlap, numChannels);
chanMask = channelMask.(triggers, numChannels - 1, \channelMask.kr(1), \centerMask.kr(1));
windowSlopes = Latch.ar(stepSlope, triggers) / max(0.001, maxOverlap);
windowPhases = (windowSlopes * accumulator).clip(0, 1);
grainWindows = IEnvGen.ar(Env([0, 1, 0], [0.01, 0.99], [4.0, -4.0]), windowPhases);
grainSlope = \freq.kr(440) * SampleDur.ir;
grainPhases = (grainSlope * accumulator).wrap(0, 1);
sigs = sin(grainPhases * 2pi);
sigs = sigs * grainWindows;
sigs = PanAz.ar(2, sigs, chanMask * \panMax.kr(0.8));
sig = sigs.sum;
sig = sig * \amp.kr(-15).dbamp;
sig = sig * Env.asr(0.001, 1, 0.001).ar(Done.freeSelf, \gate.kr(1));
sig = LeakDC.ar(sig);
sig = Limiter.ar(sig);
Out.ar(\out.kr(0), sig);
}).add;
)
(
//var arrayOfSubDivs = Array.fill(12, { 2 ** rrand(-1.0, 1.0) } ).normalizeSum;
//arrayOfSubDivs.debug(\arrayOfSubDivs);
var arrayOfSubDivs = [0.090043825988599, 0.10094508851196, 0.059173625247572, 0.078758510686157, 0.057549414766475, 0.085870514810413, 0.10684511179581, 0.082087147023147, 0.1207103511832, 0.047718306079275, 0.12704484171827, 0.043253262189117];
Routine({
s.bind {
~synth = Synth(\burst, [
\trig, 0,
\freq, 440,
\overlap, 1,
\amp, -15,
\out, 0,
]);
};
s.sync;
loop {
s.bind {
~synth.set(
\trig, 1,
\sustain, 3.2,
\arrayOfSubDivs, arrayOfSubDivs,
\numOfSubDivs, 12,
);
};
4.wait;
};
}).play;
)