/* PLAN:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GROWTH: granular sythesis, noise generators
SYMBIOSIS: amp, freq, phase, pitch tracking, convolution
CYCLES: patterns
TIME: envelopes
SPACE: root shapes <> steklenik topology { OctoPanOut.ar() }
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


IDEAS:
sources:
- GrainFM.ar
- Convolution experiments: Convolution2, StereoConvolution2L (for reverbs?)
- more FFT experiments
- granular synthesis
- deterministic generation of buffers contents
- samples, loops, recordings

aim for:
- deep basses - clean, or distorted - filtered
- high sonics - filtered this or the other way
- glitches
- reverberations (JPverb, Greyhole)
- experiments in random spatialization

more work on:
- GUI for the touch screen

LIST of CHAOTIC UGens/algos:

Crackle

HenonN HenonL HenonC Henon2DN Henon2DL Henon2DC HenonTrig
GbmanN GbmanL Gbman2DN Gbman2DL Gbman2DC GbmanTrig
StandardN StandardL Standard2DN Standard2DL Standard2DC StandardTrig
LatoocarfianN LatoocarfianL LatoocarfianC Latoocarfian2DN Latoocarfian2DL Latoocarfian2DC LatoocarfianTrig
LorenzL Lorenz2DN Lorenz2DL Lorenz2DC LorenzTrig
Fhn2DN Fhn2DL Fhn2DC FhnTrig

MarkovSynth
Logistic

ArneodoCoulletTresser

CuspN, 
FBSineN,  
LinCongN,  
QuadN

Brusselator
DoubleWell

FincoSprott
Rossler

PATTERN:
Phenon
Platoo
Pquad
Plorenz
PlinkCong
Pstandard
Pgbman
Pfhn


--------------------------------
monitoring tools,yah!

s.meter
s.plotTree
s.scope
--------------------------------
*/

// Quarks.gui
);







////////////////////////////////////////////////////////////////////////////////

// chaos patterns
Phenon().asStream.nextN(20);
Platoo().asStream.nextN(20)
Pquad().asStream.nextN(20)
Plorenz
PlinkCong
Pstandard
Pgbman
Pfhn

Pstandard().asStream.nextN(20);



p=Ppatlace([Place([Pstandard.new])],inf);
x=p.asStream;
20.do({ x.next.postln });


TempoClock.default.clear;
t= TempoClock.new;
t.tempo_(2.0); // equivalent to t.tempo = 2.0;
t.tempo;
t.tempo_(72/60) // 72 beats per minute
t.tempo;










////////////////////////////////////////////////////////////////////////////
( // basic synth SynthDef
SynthDef(\blipo, { | out, freq = 440, amp = 0.1, nharms = 10, pan = 0, gate = 1, sustain, attack=0.1 |
    var audio = Blip.ar(freq * (SinOsc.kr(3).range(1,1.01)), nharms, amp);
    var env = Linen.kr(gate, attackTime: attack, releaseTime: sustain, doneAction: Done.freeSelf); 
    OffsetOut.ar(out, Pan2.ar(audio, pan, env) );
}).add;

// reverb effect SynthDef
SynthDef("reverbo", { arg outBus = 0, inBus, wet = 0.1;
	var input = In.ar(inBus,2);
	var rev = JPverb.ar(input * wet, t60:6, damp:0.5);
    Out.ar(outBus, input + (rev));
}).add;
)

// create a 'private' 2-chan audio bus
~revbus = Bus.audio(s,2);

(
// start reverb effect on the private bus
~fxRev = Synth("reverbo", [\inBus, ~revbus, \wet, 0.9]);

~dotsP = Pbind(
	\dur, Pflatten(1, Plorenz() * 1),
	\attack, 0.01,
	\octave, 3,
	\nharms, Prand((2..7),500) );

~linesP = Pbind(
	\dur, Pflatten(1, Plorenz() * 5),
	\attack, 3,
	\octave, Prand([2,3,4],inf),
	\nharms, Prand((1..4),80),
	\amp, 0.075 );

~highP = Pbind(
	\dur, Pflatten(1, Plorenz() * 5),
	\attack, 3,
	\octave, 5,
	\nharms, Prand((1..3),50),
	\amp, 0.008 );

Pbindf(
	Ptpar([ 0, ~dotsP, 60, ~linesP, 160, ~highP]),
	\instrument, \blipo,
	\degree, (Pflatten(1, Plorenz()) * 18).asInteger,
	\mtranspose, Prand([Pn(0,24),Pn(2,24),Pn(4,24)], inf),
	\detune, Prand([0,1,0.5,1.5], inf),
	\scale, Scale.minor(\just),
	\legato, Prand((4..7),inf) * 0.2,
	\pan, Prand((-10..10),inf) * 0.1,
	\out, ~revbus
).play;
)
////////////////////////////////////////////////////////////////////////
















(
Pbind(	\dur, 0.1 + Pgbman() * 0.5,  \legato, 0.2, 	\degree, Pgbman() ).play;
)


(-10..10).postln;


Pseq(#[1, 2, 3], 4).asStream.all; 


Pflatten(1, Pstandard()).asStream.nextN(10)

















(
// a function to position sound in space
~octoPanOut = {
	arg in, in_x, in_y, fact; 

	var s1_x=0, s1_y=0, s1_amp,
	s2_x=0, s2_y=360, s2_amp,
	s3_x=0, s3_y=720, s3_amp,
	s4_x=0, s4_y=1080, s4_amp,
	s5_x=650, s5_y=1260, s5_amp,
	s6_x=650, s6_y=900, s6_amp,
	s7_x=650, s7_y=540, s7_amp,
	s8_x=650, s8_y=180, s8_amp ;

	var factor = (1 / (5000000 * fact)); 
	var distance =   {|x1,y1,x2,y2| (x2-x1) hypot: (y2-y1) }; // hypothenuse
	var amp = 1 / (1 + (distance.cubed * factor));

	// x,y are expected in rage 0-1 
	in_x = in_x * 650;
	in_y = in_y  * 1260;
	
	s1_amp = amp.value(in_x,in_y,s1_x,s1_y);
	s2_amp = amp.value(in_x,in_y,s2_x,s2_y);
	s3_amp = amp.value(in_x,in_y,s3_x,s3_y);
	s4_amp = amp.value(in_x,in_y,s4_x,s4_y);
	s5_amp = amp.value(in_x,in_y,s5_x,s5_y);
	s6_amp = amp.value(in_x,in_y,s6_x,s6_y);
	s7_amp = amp.value(in_x,in_y,s7_x,s7_y);
	s8_amp = amp.value(in_x,in_y,s8_x,s8_y);

	[in * s1_amp, in * s2_amp, in * s3_amp, in * s4_amp, in * s5_amp, in * s6_amp, in * s7_amp, in * s8_amp]
	
};

)

(


~octoBus1 = Bus.audio(s,1);
~octoBus2 = Bus.audio(s,1);
~octoBus3 = Bus.audio(s,1);
~octoBus4 = Bus.audio(s,1);

SynthDef("octoPanner", {
	arg inBus, x=0, y=0, radius=1; 
	var snd = In.ar(inBus,1);

	y = SinOsc.kr(0.1,phase:1.5pi).range(0,1);
	x = SinOsc.kr(0.1,phase:1pi,mul:5).clip2.range(0,1);
	

	snd = ~octoPanOut.value(snd, x, y, radius);
	Out.ar(0, snd);
}).add;

SynthDef(\testOcto, {
	arg out;

	var son = WhiteNoise.ar(1) ;

	Out.ar(out,son);
	//Out.ar(1,son);
}).add;



)

























~octoPanner1 = Synth("octoPanner", [\inBus, ~octoBus1]);


~whiteNoise = Synth(\testOcto, [\out, ~octoBus1]);

~octoPanner1.set(\radius, 0.1); // can control through











////////////////////////////////////////////////////////////////////////////
( // MarkovChain synth

(
SynthDef("markov",
	{ arg recEnable = 1, waitTime = 1;
		var fedIn = LocalIn.ar(1) * 0.5;
		var mark = MarkovSynth.ar(fedIn + (Saw.ar(MouseY.kr(10, 5000)) * MouseX.kr(0, 0.5)), recEnable, waitTime, 5);
		LocalOut.ar(mark);
		Out.ar(0, mark.dup);
	}
).play;
)

x = Synth("markov")
x.free;

// Table size of 3, on a periodic signal. A probabilistic explosion...
x = { MarkovSynth.ar(SinOsc.ar([801,802]), 1, 2, [3,3]) * 0.2; }.play;

x = { MarkovSynth.ar(SinOsc.ar(800), 1, 2, 10) + MarkovSynth.ar(SinOsc.ar(400 * [0,1]), 1, 2, 3) * 0.5; }.play;
x = { MarkovSynth.ar(SinOsc.ar(1801).clip2(0.99), 1, 0, 3) }.play;



x = { Splay.ar(MarkovSynth.ar(SinOsc.ar([360,480,400,401]), 1, 2, [3,10,3,10])) * 0.5; }.play(outbus:0);

x = { MarkovSynth.ar(SinOsc.ar([401,402]), 1, 2, [3,3]); }.play;
x = { MarkovSynth.ar(Pulse.ar([800,800]), 1, 2, [3,3]); }.play;
x.free;

)


~marko = { Splay.ar(MarkovSynth.ar(SinOsc.ar([360,480,400,401]), 1, 2, [3,10,3,10])) * 0.05; }.play(outbus:0);
~marko.free

~marko2 = { MarkovSynth.ar(SinOsc.ar([801,802]), 1, 2, [3,3]) * 0.05; }.play(outbus:0);
~marko2.free;





/////////////////////////////////////////////////////////////////////////////
/// ringz & trigs




{ Ringz.ar(in:StandardTrig.ar(1,10), freq: rrand(400,500), decaytime:0.1) * 0.2}.play(outbus:0);

{ Ringz.ar(in:HenonTrig.ar(1,10), freq: 1000, decaytime:0.3) * 0.5}.play(outbus:1);

{ Ringz.ar(in:GbmanTrig.ar(1,10), freq: 1000, decaytime:0.3) * 0.5.dup}.play

{ Ringz.ar(in:HenonTrig.ar(1,10), freq: 900, decaytime:0.3) * 0.5.dup}.play(outbus:2)

{ Ringz.ar(in:LatoocarfianTrig.ar(1,10), freq: 1000, decaytime:0.3) * 0.5.dup}.play


{ Ringz.ar(in:LorenzTrig.ar(1,10), freq: 500, decaytime:0.4) * 0.5.dup}.play

{ Ringz.ar(in:FhnTrig.ar(1,20), freq: 3000, decaytime:0.1) * 0.9.dup}.play

























(
x = SynthDef(\noiseCrackle, { // play // 

/* A noise generator based on a chaotic function.
Class Methods
Crackle.ar(chaosParam: 1.5, mul: 1.0, add: 0.0)
Crackle.kr(chaosParam: 1.5, mul: 1.0, add: 0.0)

Arguments:

chaosParam - A parameter of the chaotic function with useful values
from just below 1.0 to just above 2.0. Towards 2.0 the sound crackles.

mul	- Output will be multiplied by this value.
add	- This value will be added to the output.     *********************/

// TODO:
// expand on more arguments?

	arg out = 0, amp = 0.9, gate = 1;
	var sig, par, lpf, hpf, env;

	par = LFNoise1.kr(0.09).range(1.9,2.02);
	
	sig = Crackle.ar(par);

	lpf = RLPF.ar(
		in: sig,
		freq: Lag3.kr(LFNoise0.kr(0.08).exprange(50,10000),10),
		rq:0.8);
	lpf = Pan2.ar(in:lpf, pos:LFNoise1.kr(0.07));

	hpf = RHPF.ar(
		in:   sig,
		freq: Lag3.kr(LFNoise0.kr(0.065).exprange(50,10000),10),
		rq:   0.8);
	hpf = DelayN.ar(in:hpf, delaytime:0.11);
	hpf = Pan2.ar(in:hpf, pos:LFNoise1.kr(0.06));

	sig = lpf + hpf;

	// a fade-in/out envelope
	env = EnvGen.kr( Env([0, 1, 0], [1, 1], \sin, 1),
        gate, levelScale: amp, doneAction: Done.freeSelf);
	
	sig = sig * env;
	
	Out.ar(out, sig);
}).play;
)
x = Synth(\noiseCrackle);
x.set(\gate,0); // fadeout, and freeSelf
x.free;

( // LatoocarfianC - randomly modulate all params
{
Fold.ar(LatoocarfianC.ar(
    LFNoise2.kr(10).range(100,200),
    LFNoise2.kr([5,2],1.5,1.5),
    LFNoise2.kr([4,2],1.5,1.5),
    LFNoise2.kr([2,1],0.5,1.5),
    LFNoise2.kr([2,3],0.5,1.5)
) * 9, -1, 1 )*0.4 }.play(s);
)

( // chaos generator modulates panning - LatoocarfianC 
{Pan2.ar(
	in: Dust.ar(20) * 0.9,
	//pos: SinOsc.ar(0.3)
	pos:
	LatoocarfianC.ar(
    20,
    LFNoise2.kr(2,1.5,1.5),
    LFNoise2.kr(2,1.5,1.5),
    LFNoise2.kr(2,0.5,1.5),
    LFNoise2.kr(2,0.5,1.5)
	) * 0.4
)}.play;
)

( // LatoocarfianC being thrown around
SynthDef(\latoo_synth, {

	arg out=0;

	// wandering latoocarfian into variable 'freq':
	var freq = LatoocarfianC.ar(
		30,
		// randomize parameters:
		LFNoise2.kr(0.1,1.5,1.5),
		LFNoise2.kr(0.4,1.5,1.5),
		LFNoise2.kr(0.3,0.5,1.5),
		LFNoise2.kr(0.2,0.5,1.5)
	).range(40,130);

	// wandering latoocarfian applied as frequency to squarewave:
	var sig = Pulse.ar([freq,freq*0.99]);

	// adding sinwave for more clean deep sound
	sig = sig + SinOsc.ar([freq*0.998,freq*0.995]);

	
	// pinch of simple fold distortion
	sig = sig.fold(-1,1);

	// low pass filter to give sense of closing and opening
	sig = LPF.ar(sig, LFNoise2.kr(1).exprange(50,15000));

	// add space. lots of space
	sig = sig * 0.4 + Greyhole.ar(sig * 0.4, delayTime:0.4, damp: 0.3, diff: 0.6, feedback:0.5,);
	
	Out.ar(out,sig*0.5);
}).play;
)


(
var a = 1.4, b = 0.3, x0 = 0, x1 = 1, size = 64;
plot(size.collect { var aux = 1 - (a * (x1 ** 2)) + (b * x0); x0 = x1; x1 = aux; aux });
)
(
var a = 1, b = 3, c = 0.5, d = 0.5, xi = 0.5, yi = 0.5, size = 64;
plot(size.collect { var x = xi;
xi = sin(b * yi) + (c * sin(b * xi));
yi = sin(a * x) + (d * sin(a * yi));
xi
});
)

{LFTri.ar(0.1,3).range(0,2)}.play


{SinOsc.ar(freq:TRand.kr(trig:HenonTrig.kr(minfreq:1, maxfreq:10)).range(40,2000)).dup}.play;


( // henonSquare being thrown around
~henonSquare = SynthDef(\henonSquare, {

	arg out=0, gate=1;

	var env = EnvGen.kr(Env([0, 1, 0], [1, 4], \sin, 1), gate);
	
	var trig = HenonTrig.kr();

	// wandering attractor into variable 'freq':
	var freq = HenonN.ar(
		TRand.kr(trig:trig).exprange(1,20),
		// parameters:
		//a: LFNoise2.kr(0.5).range(0.3,1.6),
		//b: LFNoise2.kr(0.5).range(0,0.6)
		//a: 1.4,
		a: LFTri.kr(0.01,3).range(1,1.5), // ramp up and down, slowly
		b: 0.3
	).exprange(40,1000);

	// wandering attractor applied as frequency to squarewave:
	var sig = Pulse.ar([freq,freq]);

	// adding sinwave for more clean deep/soft sound
	sig = sig + SinOsc.ar([freq,freq*0.995]);
	
	// fold distortion
	sig = sig.fold2(0.5) * 2;

	// low pass filter to give sense of closing and opening
	sig = LPF.ar(sig, LFNoise2.kr(0.2).exprange(100,20000));

	sig = sig * env;

	// add space. lots of space
	sig = (sig * 0.5) + Greyhole.ar(sig * 0.5, delayTime:0.6, damp: 0.8, diff: 0, feedback:0.6,);

	DetectSilence.ar(sig, doneAction: Done.freeSelf); 
	
	Out.ar(out,sig * 0.5);
}).play;
)

~henonSquare.set(\gate, 0);






( // FM GRAINS // multiplication 200x
( // synthdef /////////
SynthDef(\fm_grainer, {
	arg out = 0, modfreq = rrand(10,1000), carfreq = 100 ;
	var signal;

	signal = GrainFM.ar(
		numChannels:2,
		trigger:	Impulse.kr(LFTri.kr(0.1, -1)+1*10),
		dur: 		0.05,
		carfreq: 	carfreq,
		modfreq: 	modfreq,
		//		index: 		LFNoise1.kr.range(1, 90),
		index: 	SinOsc.kr(0.05)*0.2,//	LFNoise1.kr.range(1, 90),
		pan:		LFNoise1.kr.range(-1,1),
		envbufnum:	-1
	) * 0.2;

	signal = signal * EnvGen.kr(Env.linen(1,60,10,0.4,\lin),doneAction:Done.freeSelf);
	
	Out.ar(out, Splay.ar(signal));
}).add;
)

( // with routine synth*env can be 'run' multiple times in succession!!
var r;
r = Routine {
	200.do({
		x = Synth(\fm_grainer,
			[
				"modfreq", rrand(10,1000),
				"carfreq", rrand(40,100),
				\out, 4
			]);
		1.wait;
	});
	"done".postln;
}.play;
)
)

( // granulating a buffer - using MouseX/y for

//////////////////////////////////////////////////////////////////////////////////////////////
// granulating a buffer
// a lot of potential
// expand, improve, make SynthDef more flexible (more arguments) + write Synth recipes

var winenv;
b = Buffer.read(s,
	PathName(thisProcess.nowExecutingPath).pathOnly +/+ "../smp/403312__marco-luzi__forest-soil_norm-mono.wav" );

// a custom envelope
// winenv = Env([0, 1, 0], [0.5, 0.5], [8, -8]);
// z = Buffer.sendCollection(s, Env([0, 1, 0], [0.5, 0.5], [8, -8]).discretize, 1);

SynthDef(\Granny, { |out=0, gate = 1, amp = 0.5, sndbuf, envbuf|
    var pan, env, freqdev;
    // use mouse x to control panning
    pan = MouseX.kr(-1, 1);
    env = EnvGen.kr(
        Env([0, 1, 0], [1, 1], \sin, 1),
        gate,
        levelScale: amp,
        doneAction: Done.freeSelf);
    Out.ar(out,
        GrainBuf.ar(
			numChannels: 2,
			trigger: Impulse.kr(200),
			dur: MouseY.kr.range(0.001,1),
			sndbuf: sndbuf,
			rate: 0.8, // the playback rate of the sampled sound
            pos: MouseX.kr.range(0, 25) * LFNoise2.kr(20).range(0.999,1.001),
			interp: 4, // 2: liner, 4: cubic
			pan: pan,
			envbufnum: envbuf,
		maxGrains: 1024)
		* env)
}).add;
)
(// granular Synth instances & parameters
// use built-in env
x = Synth(\Granny, [\sndbuf, b, \envbuf, -1]) // fade-in
x = Synth(\granSoil, [\sndbuf, b, \envbuf, -1]) // fade-inx\
x.set(\rate, 0.4, \amp, 4);
x.set(\gate, 0, \fadeTime, 2); // use envelope to fade out
x.free // stop.
// switch to the custom env

// you can create custom env in a buffer on a server after SynthDef and after Synth instantiation!
z = Buffer.sendCollection(s, Env([0, 1, 0], [0.5, 0.5], [8, -8]).discretize, 1);
z.plot
b.plot
x.set(\envbuf, z)
x.set(\envbuf, -1);
)

(// WeaklyNonlinear2

~weakly = { Out.ar(0,Pan2.ar(
	in: 0.1 * WeaklyNonlinear2.ar(
		input: Pulse.ar(
			//input: Pulse.ar(
			freq: 50.626,
			//mul: MouseY.kr(0.0001,1,'exponential')
			mul: LFNoise2.kr(1).linexp(-1,1,0.0001,1)
		),
		//freq: MouseX.kr(100,400)
		freq: LFNoise2.kr(0.5).linlin(-1,1,100,400)
	),
	//pos: 0.0
	pos: LFNoise2.kr(0.5) * 0.8
)
)}.play
)
~weakly.free;



( // three Ringz trigs, frequencies...
{
	var son = [
		Ringz.ar(LorenzTrig.ar(1,11), 1060 * SinOsc.ar(7).range(0.99,1.01), 0.04).fold2(0.5),
		Ringz.ar(HenonTrig.ar(1,12), 360 * SinOsc.ar(7).range(0.99,1.01), 0.18).fold2(0.5)
	]
	+ Pan2.ar(Ringz.ar(GbmanTrig.ar(1,13), 60 * SinOsc.ar(7).range(0.95,1.05), 0.18).fold2(0.5),SinOsc.ar(0.5));
	son + Greyhole.ar(son * 0.4, delayTime:0.2, feedback:0.6)
}.play;
)





(// Trigger versions of chaos UGens....
//
{ Ringz.ar(StandardTrig.ar(10, 20), 2205, 0.02).fold2(0.5).dup }.play
{ Ringz.ar(GbmanTrig.ar(1,70), 2205, 0.02).fold2(0.5).dup }.play

{ Ringz.ar(GbmanTrig.ar(1,20), GbmanL.ar(5).range(500,5000), 0.02).fold2(0.5).dup }.play
{ Ringz.ar(GbmanTrig.ar(1,40), GbmanL.ar(50).range(500,5000), 0.02).fold2(0.5).dup }.play
{ Ringz.ar(GbmanTrig.ar(1,40), 500, 0.02).fold2(0.5).dup }.play

{ Ringz.ar(GbmanTrig.ar(1,11), 1060 * SinOsc.ar(7).range(0.99,1.01), 0.04).fold2(0.5)!2}.play


{ Ringz.ar(LorenzTrig.ar(0.1,30), 2205, 0.02).fold2(0.5).dup }.play

{ LorenzTrig.ar(11025, 44100) }.play(s);

)

{ Ringz.ar(in:GbmanTrig.ar(9), freq: 160, decaytime:0.15) * 0.01.dup}.play





{ Ringz.ar(in:GbmanTrig.ar(1,10), freq: 1000, decaytime:0.3) * 0.5.dup}.play

{ Ringz.ar(in:HenonTrig.ar(1,10), freq: 1000, decaytime:0.3) * 0.5.dup}.play

{ Ringz.ar(in:LatoocarfianTrig.ar(1,10), freq: 1000, decaytime:0.3) * 0.5.dup}.play

{ Ringz.ar(in:StandardTrig.ar(1,10), freq: rrand(40,100), decaytime:0.3) * 0.5.dup}.play

{ Ringz.ar(in:LorenzTrig.ar(1,10), freq: 1000, decaytime:0.1) * 0.5.dup}.play

{ Ringz.ar(in:FhnTrig.ar(1,20), freq: 3000, decaytime:0.1) * 0.9.dup}.play




( // LorenzTrig
SynthDef(\lorenzTrigKick, {
	arg out=0;
	
	var trig = LorenzTrig.ar(0.1,20);
	
	var son = (SinOsc.ar(freq:40)
		+ Ringz.ar(in: trig, freq:1600, decaytime:0.05, mul: 0.1)
	    + (WhiteNoise.ar() * 0.1)
	)
	* EnvGen.ar(
		envelope: Env.perc(releaseTime:0.05),
		gate: trig
	).fold2(0.3) * 3;

	son = RLPF.ar(in: son,
		freq: 2000, rq: 0.4);

	son = son ! 2; // duplicate to two buses;
	Out.ar(out, son);

}).play;
)



{ LFTri.ar(LFTri.kr(0.02, iphase:3).range(100,15000)).dup}.play


(// Fhn - FitzHughNagumo Neuron Firing Oscillator 
SynthDef(\fhn, {|out=0, pan=0, amp=0.2|
    var sig, trig1, trig2, b0, b1;
    trig1=FhnTrig.kr(5, 8, 0.3, 0.3, 1, 1);
    trig2=FhnTrig.kr(8, 13, 0.27, 0.27, 0.6, 0.8);
    b0=Fhn2DN.kr(3, 5, 0.29, 0.29, 0.5, 1.1, mul:0.23, add:0.25);
    b1=Fhn2DN.kr(2, 3, 0.25, 0.25, 0.2, 1.5, mul:0.48, add:0.5);
    sig=Fhn2DN.ar(210, 35650, TExpRand.kr(0.001, 0.3, trig1), TExpRand.kr(0.001, 0.3, trig2), b0, b1, mul:amp);
	sig=LeakDC.ar(sig);
    Out.ar(0,Pan2.ar(sig, pan))
}).add;
)

~fhn = Synth(\fhn);
~fhn.free
)





( // pure melody experiments
SynthDef("plucking", {arg out = 0, amp = 0.1, freq = 440, decay = 5, coef = 0.1;
	var env, snd;
	env = EnvGen.kr(Env.linen(0, decay, 0), doneAction: 2);
	snd = Pluck.ar(
		in: BrownNoise.ar(amp),
		trig: Impulse.kr(0),
		maxdelaytime: 0.1,
		delaytime: freq.reciprocal,
		decaytime: decay,
		coef: coef);
	snd = LeakDC.ar(snd).clip2;
	Out.ar(out, snd * env);
}).add;

b = Bus.audio(s,1);

SynthDef("reverbBus", { arg outBus = 0, inBus, wet = 0.1;
	var input, rev;
	input = In.ar(inBus,1);
	rev = JPverb.ar(input * wet, t60:4, damp:0.5);
	DetectSilence.ar(rev, doneAction: Done.freeSelf); 
    Out.ar(outBus, input + (rev));
}).add;

r = Synth("reverbBus", [\inBus, b, \wet, 0.4]);

t = TempoClock.default;

Pbind(
	\instrument, "plucking",
	\scale, Scale.major.tuning_(\just),
	\octave, 4,
	//\degree, Pseq([1,3,7,8], inf), // four main notes
	//\mtranspose, Pseq([Pseq([0],3),Pseq([-5],3)],inf), // switched mode every 3 notes (*2)
	// results in:
	// [1  3  7  8  1  3  7  8  1  3  7  8] 3 x 4
	// [1, 3, 7, 3,-4,-2, 7, 8, 1,-2, 2, 3] 4 x 3
	\degree, Pseq([1, 3, 7, 3,-4,-2, 7, 8, 1,-2, 2, 3], inf),
	\mtranspose,	Pseq([
		//Pseq([0],144),
		Pseq([0],48),Pseq([3],48),Pseq([4],48)], inf),
	\gtranspose, Pseq([Pseq([0],36),Pseq([4],36),Pseq([[-3]],36),Pseq([2],36)],inf),
	//	\ctranspose, Pser([Pseries(-4,1,4) +.x Pseq([0], 144)],2),

	\coef, Pseq(
		[ Pseq([
			Prand([0.2,0.3,0.4,0.5],1),
			Prand([0.6,0.5],5),
			Prand([0.2,0.3],1),
			Prand([0.6,0.5],5)
		], 1),
			Prand([0.7,0.6],12)
		],inf),
	
	\dur, Pseq([Prand([0.25,0.25,0.24,0.245,0.255,0.25], 140),0.26,0.3,0.4,0.7], inf)
	      * Pseq([Pseq([0.8],110), Pgeom(0.8,1.002,34)],inf), 
	\decay, Pseq([8, Prand([1,2,3,4], 4),3,2,1], inf),
	//\decay, 3,
	\out, b, \amp, 0.4,
).play;
)










s.scope









// set reverb 'wetness'
~reverb.set(\wet,1);

( // set tempo
var bpm = 50;
t = TempoClock.default;
t.tempo_(bpm/60) // beats per minute
)




////////////////////////////////////////////////////////////////////////////////////////////////////////
(SynthDef("plck", {|out,freq,cf|Out.ar(out,LeakDC.ar(Pluck.ar(PinkNoise.ar(1),Impulse.kr(0),0.1,freq.reciprocal,5,cf))*EnvGen.kr(Env.linen(0,5,0),doneAction:2))}).add;b=Bus.audio();play({var in=In.ar(b);Out.ar(0,in+JPverb.ar(in*0.5,t60:4))});Pbind(\instrument,\plck,\out,b,\scale,Scale.major,\octave,4,\degree,Pseq([1,3,7,8,Prand([7,10,11,13,14]),8,7,3],inf),\dur,Pseq([Pwrand([Pseq([0.2,0.2]),0.4,Pseq([0.1],4),Pseq([0.05],4)],[0.5,0.3,0.1,0.1])], 240),\cf,{1.0.rand}).play)// #sctoot #SuperCollider
///////////////////////////////////////////////



// Melodic Minor Chords
(
Pbind(
	\instrument, "plucking",
	\scale, Scale.melodicMinor.tuning_(\just),
	\octave, 5,
	\degree, Prand([
		[0, 1, 4, 6],
		[0, 2, 5, 7],
		[-4, 0, 4, 5]
	], inf),
	\amp, Pwhite(0.1, 0.2),
	\decay, Pwhite(3, 1),
	\coef, Pseq([0.2, 0.6, 0.4], inf),
	//\dur, Pwrand([1/4, 18, 2/16, 1/2], [0.5, 0.29, 0.2, 0.01], inf)
	\dur, Pseq((16..1).linexp(1,16,0.1,1), inf),
	//	\dur, Pgeom(1,0.9, 20),
).play(quant: Quant(0.0));




)






// SpruceBudworm /////////////////////////////////////////////////////////////////

(
SynthDef(\spruceB, {
	var signal, envelope, reverb;

	signal = SpruceBudworm.ar(
		reset: 0.0,
		rate: SinOsc.kr(0.1).linlin(-1, 1, 0.09, 0.1)
	);


	envelope = EnvGen.kr(
		Env.pairs([[0,1],[0.005,1],[0.2,0]],\lin),
		gate:LFPulse.kr(
			freq:LFNoise0.kr(1).linlin(-1,1,0.001,10) ),
		doneAction: Done.none
	);

	//signal = LeakDC.ar(signal);

	//signal = signal * envelope;
	//signal = Pan2.ar(signal, 1);
	
	reverb = NHHall.ar(signal,
		rt60: 1,
		stereo: 0.2,
		lowFreq: 200,
		lowRatio: 0.5,
		hiFreq: 4000,
		hiRatio: 0.5,
		earlyDiffusion: 0.5,
		lateDiffusion: 0.5,
		modRate: 0.2,
		modDepth: 0.3);

	
	
	Out.ar(0, Pan2.ar(signal*0.7));	
}).add;
)

x = Synth(\spruceB);

(
{Out.ar(0,
	LeakDC.ar(0.9 * SpruceBudworm.ar(
		reset: 0.0,
		
		//rate: MouseX.kr(0.09,0.1)
		rate: [
			SinOsc.kr(0.1).linlin(-1,1,0.09,0.1),
			SinOsc.kr(0.4).linlin(-1,1,0.09,0.1)]
		//rate: LFNoise0.kr(			freq: 8).linlin(-1,1,0.09,0.1)
	)
	)
	* EnvGen.kr(
		Env.pairs([[0,1],[0.005,1],[0.2,0]],\lin),
		gate:LFPulse.kr(
			freq:LFNoise0.kr(1).linlin(-1,1,0.001,10) ),
		doneAction: Done.none
	)
)}.play
)

{ Pan2.ar(SpruceBudworm.ar(	reset: 0.0,	rate: SinOsc.kr(0.1).linlin(-1, 1, 0.09, 0.1)).dup, Line.kr(-1, 1, 5)) }.play

(
{Out.ar(0, Pan2.ar(
	HenonC.ar(SampleRate.ir/32, MouseX.kr(1,1.4), MouseY.kr(0,0.3)) * 0.2
)
)}.play
){Out.ar(0, Pan2.ar(SinOsc.ar()))}.play







// to be expanded //
x = {Pulse.ar(freq:[50,51]) * 0.1 * LFPulse.kr(SinOsc.kr(0.1) + 1 * 20 )}.play
x.free








{SinOsc.ar}.play



