Thinking of it this way is a misconception and these kind of wrong ways of conceptualizing what is going on makes it much harder to write code that does what you want. Also, using randomness in a situation where you are not 100% sure what is going on makes trouble shooting much harder, so a good idea is to first write deterministic code till you understand exactly what is going on.
We can generalize the behaviour of a looping buffer. Below I am assuming we want to loop the whole buffer but the principles are the same if you wanted to loop only a portion of the buffer:
When the playhead reaches the end of the buffer, ie. the upper limit
1a. Wrap around to the beginning of the buffer, play forward
1b. Change direction and play backward (think of this as 'folding);
1c. Playhead is stuck on last frame = no sound until rate becomes negative
When the playhead is going backwards and reaches 0, ie. the lower limit
2a. Wrap around to the end of the buffer, play backward
2b. Change direction and play forward (again, this is 'folding);
2c. Playhead is stuck on first frame = no sound until rate becomes positive
PlayBuf with no looping: 1c and 2c
PlayBuf with looping:1a and 2c
My code example from above: 1a, 2b
BufRd with Phasor or Sweep: 1a, 2a.
(
s.newBufferAllocators;
s.waitForBoot{
var bufDur = 1; // values in seconds
b = Buffer.alloc(s, s.sampleRate * bufDur);
p = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
s.sync;
p.copyData(b, 0, 0.4 * s.sampleRate, s.sampleRate * bufDur) // carve out a 1 second buffer
}
)
b.numFrames // == 1 * s.sampleRate
b.play
( // 'Wrap' Looping
f = {
var loopDur = 1;
var phasor = Phasor.ar(0, 1, 0, loopDur * s.sampleRate);
BufRd.ar(1, b, phasor)
}.play
)
If you want a ‘folding’ looper, ie. a mechanism to change direction when you hit either the upper or lower limit, this is quite simple using BufRd (and as I said a couple of time, using PlayBuf is not the most obvious choice for the behaviour(s) your are after).
( // 'Fold' Looping' - behaviour 1b and 2b
f = {
var loopDur = 1;
var phasor = Phasor.ar(0, 1, 0, inf).fold(0, loopDur * s.sampleRate).poll;
BufRd.ar(1, b, phasor)
}.play
)