Understanding Phasor in PV_BufRd

I’m trying to get my head around how to use Phasor (or Line) as the phase parameter of PV_BufRd. My goal is to find the “correct” rate for the playback so that I can use that as a reference for shifting into another playback speed using always-fun timestretch playback. The problem I’m running into is that Phasor seems to behave differently in PV_BufRd than it does in BufRd.

If I have this:

a = PathName.new("pathName");
r = 1024;
h = 0.25;
f = SoundFile.new(a.fullPath);
f.openRead;
b = Buffer.alloc(s, f.duration.calcPVRecSize(r, h));
c = Buffer.read(s, a.fullPath);

(
SynthDef("pvRec", { arg recBuf, sndBuf;
	var in, chain, bufnum;
	bufnum = LocalBuf.new(1024);
	Line.kr(1, 1, BufDur.kr(sndBuf), doneAction: 2);
	in = PlayBuf.ar(1, sndBuf, BufRateScale.kr(sndBuf), loop:0);
	chain = FFT(bufnum, in, 0.25, 1);
	chain = PV_RecordBuf(chain, recBuf, 0, 1, 0, 0.25, 1);
}).send
)
d = Synth("pvRec", ["recBuf", b, "sndBuf", c]);

(
SynthDef("pvPhasor", { arg out, recBuf, rate=1, t_trig;
	var chain, bufnum, pos;
	bufnum = LocalBuf.new(1024);
	pos = Phasor.ar(0, 0.0000025, 0, 1);
	SendReply.kr(t_trig, '/rep', BufRateScale.kr(bufnum)*0.001);
	chain = PV_BufRd(bufnum, recBuf, pos);
	Out.ar(out, IFFT(chain, 1).dup);
}).send
)

f = Synth("pvPhasor", ["out", 0, "recBuf", b]);

I have to set the rate of Phasor to 0.0000025 in order to play at what sounds like the correct rate. For reference, the file that I’m using for test playback is about 10 seconds long.

If I use Line.kr as the phase position instead, I also have to use something I wouldn’t expect to get it to play near what sounds like the correct rate:

phasePos = Line.kr(0, 1, BufDur.kr(recBuf)*0.25);

I’ve searched as much as I can, but I haven’t been able to find something that clears this up. Does anyone have an idea how to get the “correct” rate? There must be something obvious that I’m missing, but I just can’t work it out.

Both approaches play back at what sounds like a natural rate, but I’d prefer to be able use something that bears a relationship to the actual file, and not something I’ve determined by trial and error. The hop size I’m using is 0.25, so I’m guessing that’s a strong clue that might explain using Line.kr, but I can’t use that to explain Phasor.kr, which I’d prefer to use.

Any help or pointers would be appreciated.

I would get the correct rate by not getting the rate – that is, by using a known rate and boundary, and scaling this down into the required 0 to 1 range.

If c is the buffer with the original sound:

Phasor.ar(rate: BufRateScale.ir(c), start: 0, end: BufFrames.ir(c)) / BufFrames.ir(c)

// or if you'd rather use kr
	var phase = Phasor.kr(
		rate: BufRateScale.ir(c) * BlockSize.ir,
		start: 0, end: BufFrames.ir(c)
	) / BufFrames.ir(c);

This moves through the buffer’s timespan in terms of sample frames – so the rate is simply BufRateScale – then divides by the number of frames to normalize the time position.

Took me a while to see what’s up here. The relevant duration is that of the original sound. The recording buffer’s size is roughly proportional to the duration, but it isn’t the duration. BufDur.kr(c) instead, and then remove the * 0.25.

hjh

Thanks so much for that, that most certainly works, and is making some sense to me.

Can you explain the reason for using .ir vs .kr here for BufRateScale and BufFrames? I think I understand that there’s no reason to have it change if the buffer isn’t changing, but is there an added reason, like a potential for some variability? Or is it just best practice to use .ir when referencing buffers?

There’s no compelling reason to use ir instead of kr. I used it because my specific examples were hardcoding buffers rather than using a kr argument but there is nothing wrong with using kr in the same context.

hjh