SynthDef crashes when reading from buffer with Phasor-based looper

hey, you could check out this basic granulation attempt (make sure you got the latest update here for the necessary functions: A collection of functions for sub-sample accurate granulation and A collection of unit shapers).
The length of the buffer is normalized between 0 and 1.
You can change the looping segment with posLo and posHi.

Just for testing:

with \posLo, 0.50 and \posHi, 0.72:

(
SynthDef(\grains, { |sndBuf|

	var numChannels = 8;

	var reset, tFreqMD, tFreqMod, tFreq, events;
	var subSampleOffsets, triggers, accumulator;
	var overlapMod, overlap, maxOverlap;
	var windowSlopes, windowPhases, grainWindows;
	var posRate, posRateMod, pos;
	var rate, rateMod, grainPhases;
	var panMF, panMod, pan;
	var sigs, sig;

	reset = Trig1.ar(\reset.tr(0), SampleDur.ir);

	tFreqMD = \tFreqMD.kr(0, spec: ControlSpec(0, 2));
	tFreqMod = LFDNoise3.ar(\tFreqMF.kr(1, spec: ControlSpec(0.1, 5)));

	tFreq = \tFreq.kr(1, spec: ControlSpec(1, 1000, \exp));
	tFreq = tFreq * (2 ** (tFreqMod * tFreqMD));

	events = ~grainFunctions.eventsCircular[\events].(tFreq, reset);

	///////////////////////////////////////////////////////////////////////////////////

	// distribute triggers round-robin across the channels
	triggers = ~grainFunctions.multiChannel[\trigger].(numChannels, events[\trigger]);

	// calculate sub-sample offset per multichannel trigger
	subSampleOffsets = ~grainFunctions.helperFunctions[\subSampleOffset].(
		events[\phase],
		events[\slope],
		triggers
	);

	// create a multichannel accumulator with sub-sample accuracy
	accumulator = ~grainFunctions.multiChannel[\accumSubSample].(triggers, subSampleOffsets);

	///////////////////////////////////////////////////////////////////////////////////

	overlap = \overlap.kr(1, spec: ControlSpec(0.125, numChannels));
	overlapMod = ~grainFunctions.multiChannel[\dwhite].(triggers);
	overlap = overlap * (2 ** (overlapMod * \overlapMD.kr(0, spec: ControlSpec(0, 1))));

	maxOverlap = min(overlap, 2 ** tFreqMD.neg * numChannels);

	windowSlopes = Latch.ar(events[\slope] / max(0.001, maxOverlap), triggers);
	windowPhases = (windowSlopes * accumulator).clip(0, 1);

	///////////////////////////////////////////////////////////////////////////////////

	grainWindows = ~unitShapers.windowFunctions[\gaussian].(
		windowPhases,
		\windowSkew.kr(0.5, spec: ControlSpec(0, 1)),
		\windowIndex.kr(0, spec: ControlSpec(0, 5)),
	);

	///////////////////////////////////////////////////////////////////////////////////

	posRate = \posRate.kr(1, spec: ControlSpec(0.125, 4));
	posRateMod = SinOsc.ar(\posRateMF.kr(1, spec: ControlSpec(0.01, 1)));
	posRate = posRate + (posRate * posRateMod * \posRateMD.kr(0, spec: ControlSpec(0, 2)));

	pos = Phasor.ar(
		trig: DC.ar(0),
		rate: posRate * BufRateScale.kr(sndBuf) * SampleDur.ir / BufDur.kr(sndBuf),
		start: \posLo.kr(0, spec: ControlSpec(0, 1)),
		end: \posHi.kr(1, spec: ControlSpec(0, 1))
	);

	///////////////////////////////////////////////////////////////////////////////////

	rate = \rate.kr(1, spec: ControlSpec(0.125, 4));
	rateMod = SinOsc.ar(\rateMF.kr(1, spec: ControlSpec(0.01, 1)));
	rate = rate * (2 ** (rateMod * \rateMD.kr(0, spec: ControlSpec(0, 2))));

	///////////////////////////////////////////////////////////////////////////////////

	grainPhases = Latch.ar(rate, triggers) * accumulator;
	grainPhases = grainPhases + (Latch.ar(pos, triggers) * BufFrames.kr(sndBuf));

	sigs = BufRd.ar(
		numChannels: 1,
		bufnum: sndBuf,
		phase: grainPhases,
		loop: 1,
		interpolation: 4
	);

	sigs = sigs * grainWindows;

	///////////////////////////////////////////////////////////////////////////////////

	// panning
	panMF = \panMF.kr(0.3, spec: ControlSpec(0.01, 1));
	panMod = { |phase|
		SinOsc.ar(panMF, phase * pi)
	};

	pan = ~unitShapers.helperFunctions[\modScaleBipolar].(
		modulator: panMod.(0.5),
		value: \pan.kr(0.5, spec: ControlSpec(0, 1)),
		amount: \panMD.kr(0, spec: ControlSpec(0, 1)),
		direction: \full
	);

	sigs = PanAz.ar(2, sigs, pan.linlin(0, 1, -0.5, 0.5));
	sig = sigs.sum;

	///////////////////////////////////////////////////////////////////////////////////
	
	sig = sig * ~unitShapers.helperFunctions[\modScaleBipolar].(
		modulator: SinOsc.ar(\ampMF.kr(5, spec: ControlSpec(1, 10))),
		value: \amp.kr(-25, spec: ControlSpec(-35, -5)).dbamp,
		amount: \ampMD.kr(0, spec: ControlSpec(0, 1)),
		direction: \down
	);

	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;
)

~buffer = //... load your sample here ...

(
Synth(\grains, [

	\tFreq, 1000,
	\tFreqMF, 0.1,
	\tFreqMD, 0,
	
	\overlap, 8,
	\overlapMD, 0,

	\windowSkew, 0.5,
	\windowIndex, 0,

	\rate, 1,
	\rateMF, 0.1,
	\rateMD, 0,

	\posRate, 1.0,
	\posRateMF, 1,
	\posRateMD, 0,

	\posLo, 0.50,
	\posHi, 0.72,

	\sndBuf, ~buffer,
	
	\pan, 0.5,
	\panMF, 0.1,
	\panMD, 0,

	\amp, -10,
	\ampMF, 0.3,
	\ampMD, 0,
	
	\out, 0,

]);
)