Sync Buffer Playback

Hi all -

I asked a few questions about using BufRd a month or so ago here.

I learned a lot - but I’m still finding that I’m struggling to do certain things with SuperCollider and playback.

For instance, I’d like to have a looping Buffer that occasionally stays silent for the duration of a loop or longer.
I would’ve thought to get some kind of “sync” trigger from the playback Phasor and use it to control an envelope - but I’m not sure if this is possible since the output range of Phasor is predicated on BufFrames. I’ve been having trouble getting something to work, in any event.

Does anyone here have any suggestions?

Thank in advance.

Hm, this is a bit unclear. Do you mean that you want it to play an entire buffer, and then sometimes go silent? Or could it go silent in the middle? Should it always be silent for an entire buffer’s duration, or sometimes shorter than that?

I recently wrote a crossfade-looping synthdef like this, where the triggers control the play/silent behavior, and there is no Phasor at all. (“Looping” != Phasor – Phasor is just one way of looping – it’s one that will produce clicks unless the buffer is prepared for looping – so I think it’s often not the best way). The Impulse controls the starting moment of each cycle; silence would be just a matter of suppressing the trigger. You might need to use a Trig1 also to put a maximum limit on the gate duration.

(1..2).do { |numChan|
	SynthDef(("loop" ++ numChan).asSymbol, { |out, gate = 1, amp = 0.2, limit = 1, bufnum, pan = 0, loopStart = 0, loopEnd = -1, xfade = 2|
		var eg = EnvGen.kr(Env.asr(1, 1, 3), gate, doneAction: 2);
		var bufsr = BufSampleRate.kr(bufnum);
		var ratescale = BufRateScale.kr(bufnum);
		var start = loopStart * bufsr;
		var gateDur = loopEnd - loopStart - xfade;
		var trig = Impulse.kr(gateDur.reciprocal);

		// this line is a bit magic :wink:
		var gates = ToggleFF.kr(trig) * [1, -1] + [0, 1];

		var sig = PlayBuf.ar(numChan, bufnum, ratescale,
			trigger: gates, startPos: start, loop: 0
		);
		// equal power
		var egs = sin(EnvGen.kr(Env.asr(xfade, 1, xfade, \lin), gates) * 0.5pi);
		sig = (sig * egs).sum;
		if(numChan == 1) {
			sig = Pan2.ar(sig, pan);
		} {
			sig = Balance2.ar(sig[0], sig[1], pan);
		};
		sig = Limiter.ar(sig, limit);
		Out.ar(out, sig * (eg * amp));
	}).add;
};

hjh

1 Like

I was thinking that it would occasionally be silent for an entire buffer’s duration, so that it could remain “in sync” even when not sounding - but it would be nice to have some flexibility outside of that range. It seems like the example you provided has the framework for doing that and even more, though - so thank you!