Hi, guys!
I’m trying to make a client representation of GrainBuf, where position of the grain is controlled by rate-modulated Phasor
something like this:
phasor = Phasor.ar(
trig: 0.0,
rate: posRate + SinOsc.ar(posRateMF, [1.51471, 2.58218], mul: posRateMD),
start: 0.0,
end: bufFrames,
resetPos: 0.0
);
gran = GrainBuf.ar(
numChannels: 1,
trigger: t,
dur: tFreq.reciprocal * overlap,
sndbuf: bufnum,
rate: rate,
pos: phasor / bufFrames,
interp: 2,
pan: 0,
envbufnum: -1,
maxGrains: 512,
);
Now I can’t figure out if there is a way to recreate this rate-modulated phasor behaviour. The simple approach to modulate rate would be to multiply by modulating function the time deltas between grain onset and routine start and use it for position, but that’s a different behaviour. It would be like Phasor’s output is multiplied by mod.
The rate parameter though works as increment value (level += rate), so modulating it gives different result.
So far the only aproach that’s working for me is just to have a synth with Phasor writing to a bus, and read it with grain nodes. Maybe it’s a best way to do it, but maybe someone knows a better way )?
(
SynthDef(\pbmono, {arg buf;
var phasor, play, e;
var dur = \dur.kr(0.2);
var delay = \delay.kr(0.0);
phasor = Phasor.ar(
rate: BufRateScale.kr(buf) * \rate.kr(1),
// start: Gate.ar(In.ar(\bus.kr), DC.ar(1) - Delay1.ar(DC.ar(2))), // not getting any values
start: Gate.ar(In.ar(\bus.kr), DC.ar(1) - Delay2.ar(DC.ar(2))), // looks accurate
end: BufFrames.kr(buf)
);
play = BufRd.ar(1, buf, phasor, 0, 2);
e = EnvGen.ar(Env.new([0, \amp.kr(0.1), 0], [dur * 0.5, dur * 0.5], curve: \sin),
doneAction: 2);
play = play * e;
OffsetOut.ar(\out.kr(0), play);
}).add
)
~bus = {Bus.audio(s,1)}.dup;
b = Buffer.read(s, Platform.resourceDir ++ "/sounds/a11wlk01.wav");
(
~func = { arg tFreq, overlap, buffer, niter, stretch, rate;
{
var posRatePhase = [1.51471, 2.58218];
var dur;
{
var sig = Phasor.ar(
rate: stretch + SinOsc.ar(
0.5,
phase: posRatePhase,
mul: 0.05
) * BufRateScale.kr(buffer.bufnum),
end: buffer.numFrames
);
~bus.do { |it i| OffsetOut.ar(it, sig[i])};
}.play(addAction: \addToHead);
2.do({arg j;
Routine({
niter.do{ arg i;
dur = (1 / abs(tFreq));
s.sendBundle(0.2,
["/s_new",
'pbmono',
-1,
1, // add to tail
1,
\bus, ~bus[j].index,
\dur, dur * overlap,
\amp, 0.3,
\buf, buffer.bufnum,
\rate, rate,
\out, j,
]
);
dur.wait;
}
}).play})
}
};
Routine(~func.value(
tFreq: 20,
overlap: 2,
buffer: b,
niter: 10000,
stretch: 0.5,
rate: 1,
)).play;
)