Ndef .quant - synchronize settings to a clock, but 'pops'

Hello,

Goal: to move to specific locations of a sound file contained in a buffer, in sync with the clock (quant).
It seems that .set can not be synchronized with the quant parameter. So I tried to work around this problem with Ndefs:

// Loading sound into a buffer:
b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
(// Definition of the tempo and the quantization:
t = TempoClock.default.tempo = 110/60;
Ndef(\sound).proxyspace.quant = 4.0;
)

Ndef(\sound).play;

//the initialization Ndefs for the settings:
(
Ndef(\rate, 1.0); Ndef(\start, 0); Ndef(\end, b.numFrames-1);

//Le Ndef qui jouera le son
Ndef(\sound, {
	var ptr = Phasor.ar(trig:0, rate:Ndef(\rate), start:Ndef(\start), end:Ndef(\end));
	BufRd.ar(2, b, phase:ptr, loop:1)
});
)

Then, I change the \ start and \ end parameters of the Phasor:

Ndef(\start, (40000)); Ndef(\end, 80000);
Ndef(\start, (10000)); Ndef(\end, 100000);
Ndef(\start, (30000)); Ndef(\end, 160000);
Ndef(\start, (60000)); Ndef(\end, 200000);
Ndef(\start, (20000)); Ndef(\end, 80000);

And here is the problem:
Sometimes, when I go from one setting to another (ctrl + enter on one of the lines above), there is a click, or a pop… or more. On the sound a11wlk01.wav, it is not necessarily very obvious but it happens. By cons, with some sounds, it happens very often.

My question: Is there a way to avoid that? (crossfade? how?)

I think the issue is, if the phasor is currently close to the end and you set \end to a lower value, then the phasor must jump backward into the new range. That is, if you start with start = s1 and end = e1, and you switch to a new s2 and e2, you shouldn’t get a click if s2 <= phasor < e2 at that moment. Otherwise, “pop.”

Crossfading within one synth means that you will need two phasors and two BufRds, and use a trigger and envelope to switch between them.

  • The trigger detects when the crossfade is needed.
  • A ToggleFF could act as a gate for one envelope; 1 - toggle is the gate for the other.

Maybe like this.

s.boot;

b = Buffer.read(s, Platform.resourceDir ++ "/sounds/a11wlk01.wav");

(
Ndef(\rate, 1.0);

// fading start or end values will make the synth logic
// really complicated, I suggest to avoid that
Ndef(\start, 0).fadeTime_(0);
Ndef(\end, b.numFrames-1).fadeTime_(0);

// Le Ndef qui jouera le son
Ndef(\sound, {
	var start = Ndef(\start).kr(1),
	end = Ndef(\end).kr(1),
	// in the synth, '+' is analogous to 'or'
	trig = (Changed.kr(start) + Changed.kr(end)) > 0,
	gate1 = ToggleFF.kr(trig),
	gates = [gate1, 1.0 - gate1],
	// phasor ranges should update on trigger but not otherwise
	starts = Latch.kr(start, gates),
	ends = Latch.kr(end, gates),
	phasors = Phasor.ar(
		trig: 0,
		rate: Ndef(\rate).kr(1),
		start: starts,
		end: ends
	),
	bufs = BufRd.ar(1, b, phase: phasors, loop: 1),
	egs = EnvGen.kr(Env.asr(0.01, 1, 0.01), gates);
	Mix(bufs * egs).dup
});
)

Ndef(\sound).play;

Ndef(\start, (40000)); Ndef(\end, 80000);
Ndef(\start, (10000)); Ndef(\end, 100000);
Ndef(\start, (30000)); Ndef(\end, 160000);
Ndef(\start, (60000)); Ndef(\end, 200000);
Ndef(\start, (20000)); Ndef(\end, 80000);

Ndef(\sound).stop;

hjh

1 Like

Thank you very much, your solution is effective. I do not have any more crunches or “pops”.

There are a lot of new things for me, but I’m going to study that bit by bit.
Thanks again!