(

// a general use envelope for controlling processes

SynthDef(\controlenv, {arg gate = 1, outbus = 0, doneAction = 2;
	var env;
	env = Control.names([\env]).kr(Env.newClear(10).asArray);
	Out.kr(outbus, EnvGen.kr(env, gate, doneAction: doneAction))
	}).load(s);

// the Ambisonic decoder- runs at the tail of everything
	
SynthDef(\bfdecode, {arg gate = 1, inbus = 20, scale = 1;
	var inw, inx, iny, inz, out, env;
	env = Env([0.01, 1, 1, 0.01], [0.01, 1, 0.01], \exp, 2);
	#inw, inx, iny, inz = In.ar(inbus, 4);
	// as "stereo" for now
	out =  Limiter.ar(
//		BFDecode1.ar(inw, inx, iny, inz, [0.25, -0.25, -0.75, -1.25]*pi),
		B2Ster.ar(inw, inx, iny),
		0.9, 0.01);
	Out.ar(0, out);
	}).load(s);

// writes the performance out to disc.  Channels 1-4 are the instruments
// Channels 5-8 are the pedal clicks, Channels 9-12 are the BF signal
SynthDef(\diskout, {arg insstart, pedsstart, bfbus, diskbuf;
	var ins, bf, peds, bfins;
	ins = In.ar(insstart, 4);
	peds = In.ar(pedsstart, 4);
	bf = In.ar(bfbus, 4);
	bfins = BFEncode1.ar(ins[0], 0.3pi) +
		BFEncode1.ar(ins[1], 0.1pi) +
		BFEncode1.ar(ins[2], -0.1pi) +
		BFEncode1.ar(ins[3], -0.3pi);
	DiskOut.ar(diskbuf, ins ++ peds ++ bf);
	}).load(s);

// kill mic input, replace with this for prac
SynthDef(\diskin, {arg busout, diskbuf;
	var a, b, c, d, e, f, g, h;
	#a, b, c, d, e, f, g, h = DiskIn.ar(8, diskbuf);
	Out.ar(busout, [a, b, c, d, e, f, g, h]);
	Out.ar(0, [a + b, c + d]);
	}).load(s);
		
// each instrument needs one of these when the piece starts- records all input

SynthDef(\recbuf, {arg gate = 1, inbus = 8, buffer = 0;
	var env, in, out;
	env = EnvGen.kr(
		Env([0.0001, 1, 1, 0.0001], [0.01, 1, 0.01], \exp, 2),
		gate, doneAction: 2);
	in = In.ar(inbus, 1) * env; // reads the input, and places the input in
		// a recordbuf
	RecordBuf.ar(in, buffer);
}).load(s);

// the pedal triggers

SynthDef(\pedals, {arg inbusstart, level;
	var in;
	in = HPF.ar(In.ar(inbusstart, 4) * 110, 60);
	SendTrig.ar(
		Trig1.ar(in - level.dbamp, 1.2), [0, 1, 2, 3]);
	}).load(s);

// the overalpping warps of input (opening winds, etc...)	
SynthDef(\warpoverlap, {arg gate = 1, bufnum = 0, inbus = 8,  outbus = 16, 
		procenv = 0, amp = 1, prelevel = 1, pshiftmix = 1;
	var in, out, warp, warpenv, env, bufsize, xpos, ypos, pshifts;
	bufsize = BufDur.kr(bufnum);
	xpos = LFNoise1.kr(0.1, 2);
	ypos = LFNoise1.kr(0.1, 2);
	env = In.kr(procenv) * amp;
	// an envelpe to control the input into the RecordBuf
	warpenv =  EnvGen.kr(Env([0.001, 1, 1, 0.001, 0.001], 
					[0.01, bufsize - 0.02, 0.01, 0.01], \exp), doneAction: 0);
	in = In.ar(inbus,1);
	RecordBuf.ar(Limiter.ar(in * warpenv, -6.dbamp, 0.01), bufnum, preLevel: prelevel, 
		loop: 0);
	// pointer is random, but has an env on it to ensure it doesn't run into the
	// record head
	warp = Warp1.ar(1, bufnum, 
		LFNoise2.kr(0.2, 0.4, 0.5) * Line.kr(0, 1, 5), 1, 0.1,
		-1, 8, 0.1); 
	// harmonize the warp (p5 and p8 below)
	pshifts = PitchShift.ar(warp, 0.1, [ -7, -12 ].midiratio, 0, 0.02).sum
		* pshiftmix;
	out = BFEncode2.ar((warp + pshifts) * env, xpos, ypos);
	Out.ar(outbus, out);
}).load(s);

// same as the above, except with sound from the past (in a buffer). Into MonoGrainBF.

SynthDef(\warpgrains, {arg gate = 1, bufnum = 0, outbus = 16, 
		procenv = 0, amp = 1, pshiftmix = 1;
	var in, out, warp, warpenv, env, bufsize, xpos, ypos, pshifts;
	bufsize = BufDur.kr(bufnum);
	env = In.kr(procenv) * amp;
	warp = Warp1.ar(1, bufnum, 
		LFNoise1.kr(0.2, 0.4, 0.5) * Line.kr(0, 1, 5), 1, 0.1, -1,
		8, 0.1); 
	pshifts = PitchShift.ar(warp, 0.1, [ -7, -12 ].midiratio, 0, 0.02).sum
		* pshiftmix;
	out = MonoGrainBF.ar((warp + pshifts) * env ,14.reciprocal, 7, 0.01, 0, 2pi);
	Out.ar(outbus, out);
}).load(s);

// a general purpose PitchShift with routing

SynthDef(\pshift, {arg procenv = 1, inbus = 8, outbus1 = 0, outbus2 = 0, pshift = 0, 
		amp = 1, amp2 = 0.0;
	var env, pshifts, in;
	in = In.ar(inbus);
	env = In.kr(procenv);
	pshifts = PitchShift.ar(in, 0.11, pshift.midiratio, 0, 0.02);
	Out.ar(outbus1, (pshifts + in) * env * amp);
	Out.ar(outbus2, BFEncode2.ar((pshifts * env * amp2), IRand.new(-1, 1), 1));
	}).load(s);

// a single ATS partial as a filter

SynthDef(\atsnote, {arg inbus = 24, outbus = 30, atsbuffer = 0, procenv = 0, 
		atspartial = 0, filepoint = 0.5, amp = 1;
	var in, env, out, freq, paramp;
	in = In.ar(inbus) * In.kr(procenv);
	#paramp, freq = AtsParInfo.kr(atsbuffer, atspartial, filepoint);
	out = BPF.ar(in, freq, 0.1 / freq, paramp * 30.dbamp);
	Out.ar(outbus, out);
}).load(s);

// sums and outputs the ATS partials above

SynthDef(\atswindow, {arg procenv = 0, inbus = 30, notedur = 1, attackpct = 0.1, 
		attackamp = 1, decaypct = 0.3, decayamp = 0.8, susamp = 0.7, 
		releasepct = 0.3, xpos = 0, ypos = 1, outbus = 20, amp = 1; 
	var in, env, out;
	in = In.ar(inbus, 1);
	env = Env([0.0001, attackamp, decayamp, susamp, 0.0001], 
		[attackpct, decaypct, (1-attackpct-decaypct-releasepct), releasepct], \exp);
	// adds a PitchShift an octave below- fattens up the sound a bit
	in = PitchShift.ar(In.ar(inbus), 0.11, 0.5, 0, 0.02) * 
		EnvGen.kr(env, timeScale: notedur, levelScale: amp, doneAction: 2) * 
		In.kr(procenv);
	Out.ar(outbus, BFEncode2.ar(in, xpos, ypos));
}).load(s);	

// plays a sample into a noisy perc sound- good to overlap them

SynthDef(\perc, {arg procenv, outbus = 0, freqmul = 1, bufnum = 0, start = 0, 
		freqbase = 1880, mul = 1, attack = 1, sus = 2;
	var in, amp, out, noise, freqs, partials, cf, bw, ster, rq, env, loc;
	in = PlayBuf.ar(1, bufnum, startPos: start * SampleRate.ir); 
	env = EnvGen.kr(Env([0, 1, 1, 0], [attack, sus, attack], \sin), doneAction: 2) *
		In.kr(procenv);
	amp = Amplitude.ar(in, 0.01, 0.03);
	partials = [0.5, 1, 2.3, 4, 6.4, 6.55];
	freqs = Array.fill(2, {arg i; var freqmul; 
		freqmul = [0.3, 0.33]; partials * freqmul[i]}); // detune the two a bit
	cf = LFDNoise3.kr([0.5, 0.63], 500, 1750);
	bw = LFNoise1.kr([4, 1.8], 495, 505);
	noise = Resonz.ar(
		GrayNoise.ar(in) + PinkNoise.ar(0.01), 
			(LFNoise2.kr(0.05, 220, 440) * freqs * freqmul) ++ 
				[freqbase, freqbase + Rand.new(5, 15), freqbase * 2], 0.01);
	ster = [noise[0].sum, noise[1].sum];
	ster = PitchShift.ar(ster, 0.1, 0.25, 0, 0.02, 2, ster);
	rq = bw / cf;
	noise = BPF.ar(ster, cf, rq, rq.reciprocal) + LPF.ar((ster * 0.4), 300);
	loc = IRand.new(1, 4) * 0.5pi;
	out = BFEncode1.ar(noise * mul * env, loc) + 
		BFEncode1.ar(noise * mul * env, loc + pi);
	Out.ar(outbus, out);
	}).load(s);

// a windowed playback, random rate, plays in one of 4 corners

SynthDef(\playback, {arg procenv = 0, outbus = 0, buffer, starttime = 0, 
		dur = 1, amp = 1;
	var env, playback, out, posarray;
	posarray = [-1, 1];
	env = EnvGen.kr(
		Env.sine(dur, amp), doneAction: 2) * 
		In.kr(procenv);
	playback = PlayBuf.ar(1, buffer, Rand.new(1.0, 0.5), 
		startPos: starttime * BufSampleRate.kr(buffer));
	out = BFEncode2.ar(playback * env, Select.kr(IRand.new(0, 1), posarray),
		Select.kr(IRand.new(0, 1), posarray));
	Out.ar(outbus, out);
	}).load(s);
	
// the opening gestures noise / slap sound- reacts to string legno battuto

SynthDef(\begslap, {arg procenv = 0, gate = 1, inbus = 0, triglevel = -18, amp = 1,
		outbus = 0, intime = 1;
	var trig, feed, out, in, delay, delin, comb, noise, durenv, x, y, out1, out2,
		env;
	in = In.ar(inbus); // the input 
	trig = Trig1.ar(in - triglevel, 40); // this should only fire once!
	durenv = EnvGen.kr(Env([0.05, 0.05, 0.45], [0.01, 10], \lin, 1), 1 - trig);
	env =  EnvGen.kr(
		Env([0.0001, 1, 1, 0.0001], [0.1, intime, 10], \exp, 1), gate, doneAction:2) *
		In.kr(procenv);
	in = in * EnvGen.kr(Env([0, 0, 1, 1, 0], [0.01, 0.01, intime, 0.1], \sin, 1), 
		1 - trig);
	delay = CombC.ar(in.tanh * 0.2, 0.5, [durenv, 0.5 - durenv, 0.2], 10, 
		[1, 0.707, 0.25]).sum;
	noise = (BPF.ar(
		GrayNoise.ar(Decay.ar(delay, 1).tanh).dup,
		[80, 70], durenv) * 5).tanh * 0.5;
	comb = (FreeVerb1.ar(delay,1, 0.9) * 10).tanh * 0.1;
	out = HPF.ar(comb + noise, 20);
	out1 = BFEncode2.ar(out[0], LFNoise2.kr(1, 2), LFNoise2.kr(1, 2));
	out2 = BFEncode2.ar(out[1], LFNoise2.kr(1, 2), LFNoise2.kr(1, 2));
	Out.ar(outbus, out1 + out2 * env);

}).load(s);

// a warped / filtered and granulated gesture that takes input from scraping the 
// instruments.

SynthDef(\scrapes, {arg procenv, outbus, amp = 1, dur = 10, freq = 1000, loc = 0, 
		time = 0, rate = 1, rq = 0.1, buffer = 0;
	var warp, filts, ps, env, pointer, grains, start, end;
	env = EnvGen.kr(
			Env([0, 0.2, 1, 1, 0.2, 0], [0.45, 0.02, 0.06, 0.02, 0.45], 
				[\sin, \exp, \lin, \exp, \sin]),
			timeScale: dur, levelScale: amp.dbamp, doneAction: 2) *
		In.kr(procenv);
	start = time /  BufDur.kr(buffer);
	end = (time + (dur * rate)) / BufDur.kr(buffer);
	pointer = Line.kr(start, end, dur);
	warp = Warp1.ar(1, buffer, pointer, 1, 0.11, 8, -1, 0.1);
	filts = BPF.ar(warp, [70, freq * 0.5, freq], rq, 
		[0.04, 0.2, 0.25]).sum * rq.reciprocal;
	ps = PitchShift.ar(filts, 0.2, 0.5, 0, 0.01, mul: 2) + filts;
	grains = MonoGrainBF.ar(ps, 0.055, 20, 0.01, loc, 
		1.0 - env, mul: env);
	Out.ar(outbus, grains);
	}).load(s);

// a harmonizer with delays- takes a single input

SynthDef(\harm, {arg procenv, outbus, inbus = 0, amp = 1, dur = 1, freq1 = 1, 
		freq2 = 1;
	var in, out, env, pshift;
	env = EnvGen.kr(
		Env.sine(dur, 1), levelScale: amp, doneAction: 2) * In.kr(procenv); 
	in = In.ar(inbus);
	pshift = PitchShift.ar(in, 0.11, [freq1, freq2, 0.5], 0, 0.01, 
		[Rand.new(0.4, 0.7), Rand.new(0.3, 0.6)]);
	pshift = pshift + DelayC.ar(pshift, 0.12, [0.1, 0.107], 0.5).sum * env;
	Out.ar(outbus, BFEncode2.ar(pshift, IRand.new(-1, 1), IRand.new(-1, 1)));
	}).load(s);

//same as above, but takes everyones input

SynthDef(\harmall, {arg procenv, outbus, inbus = 0, amp = 1, dur = 1, freq1 = 1, 
		freq2 = 1;
	var in, out, env, pshift;
	env = EnvGen.kr(
		Env.sine(dur, 1), levelScale: amp, doneAction: 2) * In.kr(procenv); 
	in = PitchShift.ar(In.ar(inbus, 4), 0.95);
	pshift = PitchShift.ar(in, 0.11, [freq1, freq2], 0, 0.01, 
		[Rand.new(0.4, 0.7), Rand.new(0.3, 0.6)]);
	Out.ar(outbus, BFEncode2.ar(pshift * env, IRand.new(-1, 1), IRand.new(-1, 1)));
	}).load(s);

SynthDef(\warpharm, {arg procenv, outbus, starttime = 0, warpfac = 1, buffer, amp = 1, 
		dur = 1, freq1 = 1, freq2 = 1;
	var in, out, env, warp, pointer, startpoint;
	env = EnvGen.kr(
		Env.sine(dur, 1), levelScale: amp, doneAction: 2) * In.kr(procenv);
	pointer = Line.kr(starttime, starttime + (dur * warpfac), dur, 
		BufDur.kr(buffer).reciprocal);
	warp = Warp1.ar(1, buffer, pointer, [freq1, freq2], 0.15, -1, 6, 0.2, 
		[Rand.new(0.4, 0.7), Rand.new(0.3, 0.6)]);
	Out.ar(outbus, BFEncode2.ar(warp * env, IRand.new(-1, 1), IRand.new(-1, 1)));
	}).load(s);

// similar to above, but adds a warp to harmonize and give the gesture a tail

SynthDef(\warpharmall, {arg procenv, outbus, starttime = 0, warpfac = 1, bufstart, 
		amp = 1, dur = 1, freq1 = 1, freq2 = 1;
	var in, out, env, warp, pointer, startpoint;
	env = EnvGen.kr(
		Env.sine(dur, 1), levelScale: amp, doneAction: 2) * In.kr(procenv);
//	startpoint = ( starttime / BufDur.kr(bufstart) ) * 2;
//	pointer = LFSaw.kr(warpfac / BufDur.kr(bufstart), startpoint + 1, 0.5, 0.5 );
	pointer = Line.kr(starttime, starttime + (dur * warpfac), dur, 
		BufDur.kr(bufstart).reciprocal);
	warp = Warp1.ar(1, [bufstart, bufstart + 1, bufstart + 2, bufstart + 3], 
		pointer, [freq1, freq2], 0.11, -1, 6, 0.2, 
		[Rand.new(0.4, 0.7), Rand.new(0.3, 0.6)].dup(4)).sum;
	warp = warp + DelayC.ar(warp, 0.12, [0.1, 0.107], 0.5) * env;
	Out.ar(outbus, BFEncode2.ar(warp.sum, IRand.new(-1, 1), IRand.new(-1, 1)));
	}).load(s);
		
// fitlers for the last gesture... take warpharmall, and put through filters

SynthDef(\whfilts, {arg procenv, outbus, filtbus, gate = 1;
	var hpenv, lpenv, w, x, y, z, a, b, c, d, b2a, a2b;
	// input the bfsignal
	#w, x, y, z = In.ar(filtbus, 4);
	// convert to A format
	#a, b, c, d = B2A.ar(w, x, y, z);
	hpenv = EnvGen.kr(
		Env([10, 10, 13000, 8000], [1, 40, 40], 2, 1), gate);
	lpenv = EnvGen.kr(
		Env([22000, 22000, 13000, 16000], [1, 40, 40], -2, 1), gate);
	// add some randomness to the envelopes
	hpenv = (hpenv + LFNoise2.ar(0.3, hpenv * 0.2)).min(20000);
	lpenv = (lpenv + LFNoise2.ar(0.4, lpenv * 0.2, lpenv * -0.2)).max(10);
	#a, b, c, d = HPF.ar(LPF.ar([a, b, c, d], lpenv), hpenv);
	// convert back to B format
	#w, x, y, z = A2B.ar(a, b, c, d);
	Out.ar(outbus, [w, x, y, z])
	}).load(s);
	
// inbus will be used for a warped version- 1 freq

SynthDef(\specdelay, {arg procenv, outbus, dur, freq, deltime = 0.1, buffer, time, 
		rq = 0.3, stretchfactor = 1, amp = 1;
	var filts, delays, in, out, deltimes, filtfreqs, env, startpos, endpos, pointer,
		starttime, endtime;
	env = EnvGen.kr(Env.sine(dur, 1), doneAction: 2) * In.kr(procenv);
	// play buf will act as a delayed version of the live input
	starttime = time / BufDur.kr(buffer);
	endtime = (time + (dur / stretchfactor)) / BufDur.kr(buffer);
	pointer = Line.kr(starttime, endtime, dur);
	in = Warp1.ar(1, buffer, pointer, 1, 0.11, -1, 8, 0.2);
	filts = BPF.ar(in, freq, rq);
	delays = CombC.ar(filts, deltime, deltime, deltime * 10);
	out = HPF.ar( delays, 30 ) * env * amp;
	Out.ar(outbus, BFEncode1.ar(out, LFNoise2.kr(dur.reciprocal, pi)))
	}).load(s);	

SynthDef(\noisefilt, {arg procenv, inbus, outbus, dur, freq, rq = 0.3;
	var filts, in, out, env;
	in = WhiteNoise.ar(Amplitude.kr(In.ar(inbus), 0.01, 0.2));
	env = EnvGen.kr(Env.sine(dur, 1), doneAction: 2) * In.kr(procenv);
	filts = BPF.ar(in, freq, rq);
	out = HPF.ar( filts, 20 ) * env;
	Out.ar(outbus, BFEncode1.ar(out, LFNoise2.kr(dur.reciprocal, pi)))
	}).load(s);

// for faster note gestures (not for percussive sounds... too watery
// buffer is the starting buffer number of 24 buffers (can be recycled)
// about 6 second windows?

SynthDef(\specdelays, {arg procenv, buffer, outbus, inbus1, inbus2, warpbus, 
		rq = 0.3, freqscale = 1, dur, amp = 1;
	var filts, delays, in, out, deltimes, filtfreqs, env;
	// live and delayed warped .. all warps come from the same bus (2 live + warp)
	in = In.ar(inbus1) + In.ar(inbus2) + In.ar(warpbus);
	env = EnvGen.kr(Env.sine(dur, amp), doneAction: 2) * In.kr(procenv);
	deltimes = Array.fill(24, {Rand.new(0.1, 1.9)});
	filtfreqs = [ 50, 150, 250, 350, 450, 570, 700, 840, 1000, 1170, 1370, 1600, 1850,
		2150, 2500, 2900, 3400, 4000, 4800, 5800, 7000, 8500, 10500, 13500 ] * 
		freqscale;
	rq = [ 1, 0.33333333333333, 0.2, 0.14285714285714, 0.13333333333333, 		0.12280701754386, 0.11428571428571, 0.095238095238095, 0.1, 0.094017094017094, 
		0.094890510948905, 0.09375, 0.097297297297297, 0.093023255813953, 0.1, 
		0.13793103448276, 0.14705882352941, 0.15, 0.14583333333333, 0.17241379310345, 
		0.21428571428571, 0.23529411764706, 0.33333333333333, 0.25925925925926 ] * 
		rq;
	filts = BPF.ar(in, filtfreqs, rq);
	delays = Array.newClear(24);
	24.do{arg i; 
		delays[i] = BufCombC.ar(buffer + i, filts[i], deltimes[i], deltimes[i] * 10)};
	out = HPF.ar( delays.sum, 30 ) * env;
	Out.ar(outbus, BFEncode1.ar(out, LFNoise2.kr(dur.reciprocal, pi)))
	}).load(s);

SynthDef(\specdelaysall, {arg procenv, buffer, outbus, inbusstart, 
		warpbusstart, rq = 0.3, freqscale = 1, dur = 5, amp = 1;
	var filts, delays, in, out, deltimes, filtfreqs, env;
	// live and delayed warped - 4 live summed + warp
	in = In.ar(inbusstart, 4).sum + In.ar(warpbusstart);
	env = In.kr(procenv);
	deltimes = Array.fill(24, {Rand.new(0.1, 1.9)});
	filtfreqs = [ 50, 150, 250, 350, 450, 570, 700, 840, 1000, 1170, 1370, 1600, 1850,
		2150, 2500, 2900, 3400, 4000, 4800, 5800, 7000, 8500, 10500, 13500 ] * 
		freqscale;
	rq = [ 1, 0.33333333333333, 0.2, 0.14285714285714, 0.13333333333333, 		0.12280701754386, 0.11428571428571, 0.095238095238095, 0.1, 0.094017094017094, 
		0.094890510948905, 0.09375, 0.097297297297297, 0.093023255813953, 0.1, 
		0.13793103448276, 0.14705882352941, 0.15, 0.14583333333333, 0.17241379310345, 
		0.21428571428571, 0.23529411764706, 0.33333333333333, 0.25925925925926 ] * 
		rq;
	filts = BPF.ar(in, filtfreqs, rq);
	delays = Array.newClear(24);
	24.do{arg i; 
		delays[i] = BufCombC.ar(buffer + i, filts[i], deltimes[i], deltimes[i] * 10)};
	out = HPF.ar( delays.sum, 30 ) * env;
	Out.ar(outbus, BFEncode1.ar(out, LFNoise2.kr(dur.reciprocal, pi)))
	}).load(s);
	
// mono warp
SynthDef(\genwarp, {arg procenv, gate = 1, buffer, start = 0, warpfactor = 1, 
		outbus = 0;
	var env, warp, pointer, startpoint, endpoint, bufdur;
	env = EnvGen.kr(
		Env([0, 1, 0], [0.1, 0.1], \sin, 1), 
		gate, doneAction: 2) * In.kr(procenv);
	bufdur = BufDur.kr(buffer);
	pointer = EnvGen.kr(
		Env([start, bufdur], [bufdur - start]), timeScale: warpfactor, 
			levelScale: bufdur.reciprocal);
	warp = Warp1.ar(1, buffer, pointer, 1, 0.11, -1, 8, 0.1);
	Out.ar(outbus, warp * env);
	}).load(s);

// pshift the input down a semi-tone (account for this later) to prevent
// feedback into the filters. Also outputs the filepointer
	
SynthDef(\atsringin, {arg inbus, outbus, fptbus, amp = 1;
	var in, pshift, filepointer; 
	in = In.ar(inbus, 3) * amp; // readin from cel - bass bus
	pshift = PitchShift.ar(in, 0.11, -1.midiratio, 0, 0.01);
	filepointer = LFNoise2.kr(0.05, 0.4, 0.5);
	Out.ar(outbus, pshift);
	Out.kr(fptbus, filepointer);
	}).load(s);
	
// output a filepoiner on a control bus... map it to filepoint

SynthDef(\atsring, {arg inbus = 24, outbus = 30, atsbuffer = 0, rantime = 10,
		atspartial = 0, filepoint = 0.5, pchoffset = 4;
	var in, env, out, freq, freqmul, paramp;
	in = In.ar(inbus);
	freqmul = LFNoise2.kr(1, 3.midiratio - 1, 1);
	#paramp, freq = AtsParInfo.kr(atsbuffer, atspartial, filepoint);
	freq = freq * (freqmul * Line.kr(1, 0, rantime) + 1) * pchoffset.midiratio;
	out = Ringz.ar(in, freq, 1, paramp);
	Out.ar(outbus, out);
	}).load(s);

SynthDef(\atssum, {arg procenv, inbus = 0, outbus = 0, maxamp = 0.25, ampin = 0;
	var env, in, out, amp;
	env = In.kr(procenv);
	in = In.ar(inbus);
	amp = Amplitude.kr(In.ar(ampin), 0.01, 0.1);
	out = PitchShift.ar(in, 0.11, 0.25, 0, 0.01) + in;
	out = out.tanh * maxamp; // a cheap limiter w/ distortion
	Out.ar(outbus, BFEncode1.ar(out * env + amp, 0));
	}).load(s); 
	
SynthDef(\psgliss, {arg procenv, inbus, outbus, amp = 1, dur = 8;
	var env, in, out, pshift;
	env = EnvGen.kr(
		Env.sine(dur, amp), doneAction: 2) * In.kr(procenv);
	in = In.ar(inbus, 1);
	pshift = PitchShift.ar(in, 0.11, 
		[Line.kr(Rand(1.1, 1.2), 0.5, dur * 0.5), 
			Line.kr(Rand(0.6, 0.9), 1.334, dur * 0.5)],
		0, 0.02).sum;
	Out.ar(outbus, 
		BFEncode2.ar( pshift * env, (IRand(0, 1) * 2 - 1), (IRand(0, 1) * 2 - 1)));
	}).load(s);

SynthDef(\psfixed, {arg procenv, inbus, outbus, amp = 1, dur = 8, ps1 = 1, ps2 = 1;
	var env, in, out, pshift;
	env = EnvGen.kr(
		Env.sine(dur, amp), doneAction: 2) * In.kr(procenv);
	in = In.ar(inbus, 1);
	pshift = PitchShift.ar(in, 0.11, [ps1, ps2], 0, 0.02).sum;
	Out.ar(outbus, 
		BFEncode2.ar( pshift * env, (IRand(0, 1) * 2 - 1), (IRand(0, 1) * 2 - 1)));
	}).load(s);

SynthDef(\warpvoc, {arg outbus, buftime, dur = 1, rate = 1, buffer, scaler = 1;
	var prevsound, env, starttime, endtime, pointer;
	env = EnvGen.kr(
		Env.sine(dur, scaler), doneAction: 2);
	endtime = (buftime + (dur * rate));
	pointer = Line.kr(buftime, endtime, dur, BufDur.kr(buffer).reciprocal);
	prevsound = Warp1.ar(1, buffer, pointer, 1, 0.1, -1, 8, 0.2);
	Out.ar(outbus, prevsound * env);
	}).load(s);

SynthDef(\vocode, {arg procenv, inbus, psbus, outbus, amp = 1;
	var in, prevsound, env, loc, out;
	env = In.kr(procenv) * amp;
	in = In.ar(inbus); 
	prevsound = In.ar(psbus);
	loc = LFNoise2.kr(0.2, pi, pi);
	// q may need to be adjusted... play with this
	out = Vocoder.ar(prevsound, in, 20, 100, 10000, q:0.1, hpfscal:0.00) * env;
	out = Limiter.ar(out, 0.5, 0.01);
	out = Out.ar(outbus, 
		BFEncode1.ar(out, loc, 0, 1) + 
		BFEncode1.ar(out, loc + pi, 0, 1));
	}).load(s);
	
SynthDef(\route, {arg inbus, outbus, scale = 1;
	Out.ar(outbus, In.ar(inbus, 1) * scale);
	}).load(s);
	
)