Any tips on making a sample-instrument in SC?

Hello!

I’m trying to create a sample-instrument from recordings I made of notes on a church-organ. I held the notes for 10 seconds, but I want to have the possibility of looping a section in the middle of the organ-sample to make it sustain for as long as I want. I’ve been fiddling around with trying to crossfade between two loops to avoid the “pops” in the speakers when the sample loops back around, but haven’t been succesfull yet.

My attempt looks like this:

(
SynthDef.new(\susSampler2, {|amp=0.4,bn=1,gate=1,r=1|
	var masterEnv = EnvGen.kr(Env.asr(0.01,1.0,0.33),gate,doneAction:2);
	var time = BufFrames.kr(bn)-(1.5*44100);
	var sec = (time/44100)-1;
	var env1 = EnvGen.kr(Env([-1,-1,1],[1.0,0.5]));
	var attack = PlayBuf.ar(1, bn, r) * amp;
	var loop1 = LoopBuf.ar(1, bn, r, startPos:44100, startLoop:44100, endLoop:time) * amp;
	var loop2 = LoopBuf.ar(1, bn, r, startPos:((time)+44100)/2, startLoop:44100, endLoop:time) * amp;
	var tri = LFTri.kr(1/sec).range(-1,1);
	var x2 = XFade2.ar(loop2,loop1, tri);
	var x1 = XFade2.ar(attack, x2, env1) * masterEnv;
	Out.ar(0, x1!2);
}).add;
x = Synth(\susSampler2);
)

I first initiate a sample containing the attack of the organ note, and then I crossfade from this PlayBuf to another XFade object which crossfades between the two LoopBuf objects using a LFTri.kr.
So far I haven’t been able to make it so that the LFTri hits -1 exactely when the pop occurs in the other LoopBuf. I’m thinking there has to be an easier way to do this and I was wondering if anybody has a smart way of thinking about this? Cheers!

The best strategy to smoothly do looping with crossfading I have come across is this

1 Like

Nice! I tried fiddling around with it, and got it to work!
Also managed to edit my code so that it does the same trick:

(
SynthDef.new(\sust, {|amp=0.4,bn=1,gate=1,r=1|
	var masterEnv = EnvGen.kr(Env.asr(0.01,1.0,0.33),gate,doneAction:2);
	var time = (BufFrames.kr(bn)-(1.5*44100))*(1-(r-1));
	var sec = ((time/44100)-1)*(1-(r-1));
	var env1 = EnvGen.kr(Env([-1,-1,1],[1.0,0.5]));
	var attack = PlayBuf.ar(1, bn, r) * amp;
	var loop1 = LoopBuf.ar(1, bn, r, startPos:44100, startLoop:44100, endLoop:time) * amp;
	var loop2 = LoopBuf.ar(1, bn, r, startPos:((time)+44100)/2, startLoop:44100, endLoop:time) * amp;
	var tri = EnvGen.kr(Env([1,1,-1,-1,1],[sec*0.4,sec*0.1,sec*0.4,sec*0.1]), Impulse.kr(1/sec));
	var x2 = XFade2.ar(loop1,loop2, tri);
	var x1 = XFade2.ar(attack, x2, env1) * masterEnv;
	Out.ar(0, x1!2);
	tri.poll;
}).add;
)

I even think it might be more optimzed, peaking at about 0.6% CPU with 46 active UGENS and the other one peaking somewhere at 0.7% with 49 active UGENS.

I’m still open for more optimized ways of doing this though, so I’ll leave the post open for a while.