hey, im creating a multichannel Playbuf here multiplied by a window function for granulation before i sum the signals and route the stereo signal to a fx bus. The fx itself is based on a feedback loop created by GrainBufJ and BufWr and i thought because this is granulation again that you could get rid of the GrainbufJ inside the fx and just use multichannel Playbuf / BufRd from the source multiplied by the window function and feed it into a multichannel BufWr before you sum the signals.
Can you help me on that?
(
var timingInformation = { |numChannels, trig, grainRate|
var arrayOfTrigsAndPhases = numChannels.collect{ |i|
var localTrig = PulseDivider.ar(trig, numChannels, i);
var hasTriggered = PulseCount.ar(localTrig) > 0;
var localPhase = Sweep.ar(localTrig, grainRate * hasTriggered);
[localTrig, localPhase];
};
var trigsAndPhasesArray = arrayOfTrigsAndPhases.flop;
(\trigger : trigsAndPhasesArray[0], \phase: trigsAndPhasesArray[1]);
};
var hanningWindow = { |phase|
(1 - (phase * 2pi).cos) / 2 * (phase < 1);
};
SynthDef(\grains, { |sndBuf|
var numChannels = 8;
var tFreq = \tFreq.kr(10);
var trig = Impulse.ar(tFreq);
var grainRate = tFreq / \overlap.kr(1);
var timings = timingInformation.(numChannels, trig, grainRate);
var grainWindows = hanningWindow.(timings.phase);
var pos = Phasor.ar(
trig: 0,
rate: \posRate.kr(1) * BufRateScale.kr(sndBuf) * SampleDur.ir / BufDur.kr(sndBuf),
start: \posLo.kr(0),
end: \posHi.kr(1)
);
var sig = PlayBuf.ar(
numChannels: 1,
bufnum: sndBuf,
rate: \playBackRate.kr(1),
trigger: timings.trigger,
startPos: pos * BufFrames.kr(sndBuf),
loop: 1
);
sig = sig * grainWindows;
sig = Pan2.ar(sig, \pan.kr(0));
sig = sig.sum;
sig = sig * \amp.kr(-25.dbamp);
sig = LeakDC.ar(sig);
OffsetOut.ar(\out.kr(0), sig);
}).add;
SynthDef(\granular_fx, {
var tFreqMod = SinOsc.ar(\tFreqMF.kr(1), Rand(0.0, 2pi)) * \tFreqMD.kr(0);
var rateMod = SinOsc.ar(\rateMF.kr(1), Rand(0.0, 2pi)).range(0, \rateMD.kr(0));
var offsetMod = SinOsc.ar(\offsetMF.kr(1), Rand(0.0, 2pi)).range(0, \offsetMD.kr(0));
var tFreq = \tFreq.kr(20) + tFreqMod;
var rate = \rate.kr(1) - rateMod;
var trig = Impulse.ar(tFreq);
var grainDur = max(\overlap.kr(1) / tFreq, \minGrainDur.kr(0.001));
var bufFrames = 2**16;
var sndBuf = { LocalBuf(bufFrames).clear } !2;
var writePos = Phasor.ar(DC.ar(0), end: bufFrames);
var readPos = (writePos - ControlDur.ir / bufFrames - \offset.kr(0) - offsetMod).wrap(0, 1);
var inSig = In.ar(\in.kr(0), 2);
var sig = GrainBufJ.ar(
numChannels: 1,
loop: 1,
trigger: trig,
dur: grainDur,
sndbuf: sndBuf,
rate: rate,
pos: readPos,
interp: 4,
pan: 0,
envbufnum: -1,
);
sig = HPF.ar(sig, \hpf.kr(40));
sig = LPF.ar(sig, \lpf.kr(15000));
// writing granulated + input back to grain buffer
sndBuf.do { |b, i|
BufWr.ar(sig[i] * \feedback.kr(0.3) + inSig[i], b, writePos)
};
sig = XFade2.ar(inSig, sig, \mix.kr(0).linlin(0, 1, -1, 1).lag(3));
sig = sig.tanh;
OffsetOut.ar(\out.kr(0), sig);
}).add;
)
// loadd soundfile into buffer
b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
// create bus for fx routing
~fxBus = Bus.audio(s, 2);
(
Routine({
s.bind {
Synth(\grains, [
\tFreq, 1000,
\overlap, 8,
\sndBuf, b,
\amp, -25.dbamp,
\out, ~fxBus,
], addAction: \addToHead);
};
s.sync;
// fx
s.bind {
Synth(\granular_fx, [
\in, ~fxBus,
\overlap, 2,
\tFreq, 26.60,
\tFreqMF, 25.10,
\tFreqMD, 0.0,
\rate, 2.0,
\rateMF, 19.80,
\rateMD, 1.0,
\offset, 0.042,
\offsetMF, 94,
\offsetMD, 0.11,
\lpf, 14000,
\hpf, 500,
\mix, 1,
\feedback, 0.35,
], addAction: \addToTail);
};
}).play;
)