Masking triggers and adjust overlap legato style

hey, im masking the triggers from Impulse with binary values from a Demand Ugen and would like to adjust the overlap in relation to the pattern in a “legato style”.
In this example the pattern is [3, 3, 2], so for example for 3 the overlap should be 3 times the overlap beeing set.

(
var hanningWindow = { |phase|
	(1 - (phase * 2pi).cos) / 2 * (phase < 1);
};

{
	var sig, tFreq, trig, grainRate, grainWindow, phase;
	
	tFreq = \tFreq.kr(8);
	grainRate = tFreq / \overlap.kr(0.5);
	
	trig = Impulse.ar(tFreq);
	trig = trig * Demand.ar(trig, 0, Dseq([1, 0, 0, 1, 0, 0, 1, 0], inf));
	
	phase = Sweep.ar(trig, grainRate);
	grainWindow = hanningWindow.(phase);

	sig = SinOsc.ar(440);

	sig = sig * grainWindow;
	
	sig!2 * 0.5;
	
}.play;
)

any ideas on this? thanks :slight_smile:

you could maybe use a set of envelopes (size max voices), which decay after the overlap. Then, use a LocalIn for which voice/envelope to trigger. The correcspomding LocalOut sends the sum of the envelopes to the input, determining the index.

hey, thanks im not really sure how to go about your suggestion.

But i have implented it like this (without sharing the initial matrix creating function and the conversion function to binary and legato values, to keep it short).

(
~seqOfRows = [3, 0];

~binaryDurations = [
	[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
	[ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
	[ 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 ],
	[ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 ],
	[ 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0 ],
	[ 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0 ],
	[ 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1 ],
	[ 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1 ],
	[ 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1 ],
	[ 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 ],
	[ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
	[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
];

~legatoValues = [
	[ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 ],
	[ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 ],
	[ 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3 ],
	[ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ],
	[ 3, 3, 3, 3, 3, 3, 2, 2, 1, 3, 3, 3 ],
	[ 3, 3, 3, 1, 2, 2, 2, 2, 1, 3, 3, 3 ],
	[ 3, 3, 3, 1, 2, 2, 2, 2, 1, 2, 2, 1 ],
	[ 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 2, 1 ],
	[ 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1 ],
	[ 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1 ],
	[ 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
	[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
];
)

(
var timingInformation = { |numChannels, trig, grainFreq, grainRate|
	var arrayOfTrigsAndPhases = numChannels.collect{ |i|
		var localTrig = PulseDivider.ar(trig, numChannels, i);
		var hasTriggered = PulseCount.ar(localTrig) > 0;
		var localPhase = Sweep.ar(localTrig, grainFreq * hasTriggered);
		var localPhaseMul = Sweep.ar(localTrig, grainRate * hasTriggered);
		[localTrig, localPhase, localPhaseMul];
	};
	var trigsAndPhasesArray = arrayOfTrigsAndPhases.flop;
	(
		\trigger : trigsAndPhasesArray[0],
		\pulsaretPhase: trigsAndPhasesArray[1],
		\windowPhase: trigsAndPhasesArray[2]
	);
};

var matrixSeq = { |trig, reset, arrayOfDurations, arrayOfLegatos, valuesPerRow, seqOfRows, rowSeqSize|
	var noteInSeq = Demand.ar(trig, reset, Dseq([Dseries(0, 1, valuesPerRow)], inf));
	var rowTrig = HPZ1.ar(noteInSeq) < 0;
	var row = Demand.ar(rowTrig + Impulse.ar(0), reset,
		Dseq([Dser(seqOfRows, rowSeqSize)], inf)
	);
	var seqOffset = row.floor * valuesPerRow;
	var mask = Demand.ar(trig, reset, Dswitch1(arrayOfDurations, seqOffset + noteInSeq));
	var legato = Demand.ar(trig, reset, Dswitch1(arrayOfLegatos, seqOffset + noteInSeq));
	(trig: mask, legato: legato);
};

var hanningWindow = { |phase|
	(1 - (phase * 2pi).cos) / 2 * (phase < 1);
};

{
	var numChannels = 4;

	var sig, tFreq, trig, grainRate, grainFreq, grainWindow, phase, mask, legato, timings;

	tFreq = \tFreq.kr(440);
	grainFreq = \freq.kr(880);
	trig = Impulse.ar(tFreq);

	mask = matrixSeq.(
		trig: trig,
		reset: \reset.tr(0),
		arrayOfDurations: ~binaryDurations.flat,
		arrayOfLegatos: ~legatoValues.flat,
		valuesPerRow: ~binaryDurations.size,
		seqOfRows: ~seqOfRows,
		rowSeqSize: ~seqOfRows.size,
	);

	grainRate = (grainFreq / (\overlap.kr(2) * mask.legato));

	timings = timingInformation.(numChannels, trig * mask.trig, grainFreq, grainRate);

	grainWindow = hanningWindow.(timings.windowPhase);

	sig = sin(timings.pulsaretPhase * 2pi);

	sig = sig * grainWindow;

}.plot(0.2);
)

Its a bit messy because you have to pass parallel collections of items (binary durations and their related legato values) but it works for now.
I still have to implement the on / off of the trigger mask with Select for both, binary durations and legato. When then using the matrixSeq / trigger mask as an external Synth with busses and .asMap it gets even more tricky to pass both (i have also to figure out that). First one OffsetOut for the trigger and the remapping of two values mask.legato and mask.trig.