Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@lgvr123
Created November 24, 2021 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lgvr123/ad5f501f7b8d6f9dacde6e1bc2777518 to your computer and use it in GitHub Desktop.
Save lgvr123/ad5f501f7b8d6f9dacde6e1bc2777518 to your computer and use it in GitHub Desktop.
~prolongeCore = {
// arguments du constructeur
// arg numChannels, params;
arg numChannels, params,
nbuf=0, bBufnum, cBufnum, blend=0.1;
var natural=params.atFail(\natural_release,0); // par défaut, le mode est "Gated Release";
// argument du synth
// var nbuf=\nbuf.ir(0), bBufnum = \bBufnum.ir, cBufnum=\cBufnum.ir; // v7 : to regular argument
var atk=\atk.ir(0.1),rel=\rel.kr(0.1);
// var blend=\blend.kr(0.1); // v7 : to regular argument
var bufStart=\bufStart.ir(-1), cueStart=\cueStart.ir(-1);
var gate=\gate.kr(1);
var bufidx1=0,bufnum1,ncue1=1,cueidx10=0, cueidx11=1, offset1, start1, end1;
var idx1, gate1, sig1, rel1;
var bufidx2=0,bufnum2,ncue2=1,cueidx20=0, cueidx21=1, offset2, start2, end2;
var idx2, gate2, sig2, rel2;
var trig1,trig2;
var sig, env;
var bfs, cus;
var trig0=Impulse.kr(0);
var isstart;
// debug
var poll=Impulse.kr(10);
var elapsed=Sweep.kr(trig0,1);
// loop 1
// .. buffer and cue points choice
rel2=LocalIn.kr(1,0);
trig1=rel2+Impulse.kr(0); // loop1's trigger is an initial trigger + the release of the loop2
isstart=SetResetFF.kr(rel2); // On est dans 1ère itération tant que on n'a pas le 1er "rel2"
// .. buffer and cue points choice
// Poll.kr(poll,elapsed,"*****");
// - Buffer to be used at start
if (bufStart.isNil) {bfs=-1} {bfs=bufStart};
bfs=bfs.clip(-1,nbuf-1);
bfs=Select.kr(isstart,[bfs,(-1)]); // à la 1ère itération, si bufStart<>-1, alors on ommence avec ce buffer, sinon on choisit au hazard.
bufidx1=Select.kr(bfs+1,[TIRand.kr(0,nbuf-1,trig1),bfs]);// randomly select the buffer index for the loop1
bufnum1=Index.kr(bBufnum,bufidx1); // bufnum the choosen buffer
// - Buffer to be used at start
ncue1=Index.kr(bBufnum,nbuf+bufidx1); // # cue points for that buffer
if (cueStart.isNil) {cus=-1} {cus=cueStart};
cus=cus.clip(-1,ncue1-2);
cus=Select.kr(isstart,[cus,(-1)]); // à la 1ère itération, si cueStart<>-1, alors on ommence à cette position, sinon on choisit au hazard.
cueidx10=Select.kr(cus+1,[TIRand.kr(0,ncue1-2,trig1), cus]);// randomly select a start cuepoint
cueidx11=TIRand.kr(cueidx10+1,ncue1-1,trig1); // randomly select a end cuepoint (after the start cuepoint)
offset1=Index.kr(bBufnum,2*nbuf+bufidx1); // offset for the buffer in the cuepoint array/buffer
start1=Index.kr(cBufnum,offset1+cueidx10); // real start cuepoint
end1=Index.kr(cBufnum,offset1+cueidx11); // real end cue point
Poll.kr(trig1,bufidx1,"* buf 1");
Poll.kr(trig1,start1,"- cue 1 start");
Poll.kr(trig1,end1,"- cue 1 end");
// En mode "Natural release", on s'arrête à la fin du sample quand le Gate est déclenché
if(natural==1) {
end1=(gate*end1)+((1-gate)*BufFrames.kr(bufnum1));
};
// ..sweep and read
idx1=Sweep.ar(trig1, BufSampleRate.kr(bufnum1))+start1;
sig1=BufRd.ar(numChannels, bufnum1, idx1, 0);// 1: mono, 2: stereo
// .. gate
rel1=Trig1.kr(idx1-end1,0); // release when end cue point is reached
gate1=SetResetFF.kr(trig1,rel1); // build a gate to be used in SelectX
// loop 2
trig2=rel1; // loop2's trigger is loop1's release
// .. buffer and cue points choice
bufidx2=TIRand.kr(0,nbuf-1,trig2);
bufnum2=Index.kr(bBufnum,bufidx2);
ncue2=Index.kr(bBufnum,nbuf+bufidx2);
cueidx20=TIRand.kr(0,ncue2-2,trig2);
cueidx21=TIRand.kr(cueidx20+1,ncue2-1,trig2);
offset2=Index.kr(bBufnum,2*nbuf+bufidx2);
start2=Index.kr(cBufnum,offset2+cueidx20);
end2=Index.kr(cBufnum,offset2+cueidx21);
Poll.kr(trig2,bufidx2,"* buf 2");
Poll.kr(trig2,start2,"- cue 2 start");
Poll.kr(trig2,end2,"- cue 2 end");
// En mode "Natural release", on s'arrête à la fin du sample quand le Gate est déclenché
if(natural==1) {
end2=(gate*end2)+((1-gate)*BufFrames.kr(bufnum2));
};
// ..sweep and read
idx2=Sweep.ar(trig2, BufSampleRate.kr(bufnum2)) + start2;
sig2=BufRd.ar(numChannels, bufnum2, idx2, 0);// 1: mono, 2: stereo
// .. gate
rel2=Trig1.kr(((1-gate1)*idx2)-end2,0); // release when end cue point is reached // ==> "(1-gate1)*idx2" : Limit analyse to the portion where loop2 is expected to play. Without this we face nonexpected starts
gate2=SetResetFF.kr(trig2,rel2);
// Poll.kr(trig1,end1, "--TRIG 1-- delay1");
// Poll.kr(rel1,end1, "--REL1 1-- delay1");
// Poll.kr(trig2,end2, "--TRIG 2-- delay2");
// Poll.kr(rel2,end2, "--REL 2-- delay2");
LocalOut.kr([rel2]);
// En mode "Natural release", on s'arrête à la fin du sample
if(natural==1) {
// Astuce: pour savoir si je dois utiliser rel1 pour finir le Synth,
// la logique voudrait qu'on écrive gate1*rel1 (et respectivemnt
// pour rel2 (1-gate1)*rel1.
// MAIS rel1 fait baculer gate1 à 0. Idem pour rel2 qui fait
// basculer gate1 à 1.
// DONC: il faut écrire (1-gate1)*rel1, aka gate2*rel1 et non gate1*rel1
FreeSelf.kr((1-gate)*( ((1-gate1)*rel1) + ((gate1)*rel2)));
};
sig=SelectX.ar(Lag.kr(1-gate1,blend),[sig1,sig2]);
// En mode "Gated release", on rajoute une envelope
if(natural==0) {
env=EnvGen.kr(Env.asr(atk,1,rel),gate,doneAction: 2);
sig=sig*env;
};
// return
sig;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment