// =====================================================================
// SuperCollider Workspace
// =====================================================================


b = Buffer.readChannel(s, "non-oneshot-sample-path", channels:[0]);

b = Buffer.readChannel(s, "one-shot-sample-path", channels:[0]);

b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-Cantor_Samual_Malavsky_Shomea_Kol_Bichios.wav", [\bufnum: 0]);
b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/06-Cantor_Zevulun_Zavel_Kwartin_sings_Tiher.wav", [\bufnum: 1]);

b = Buffer.readChannel(s, "/home/lcoogan/snd/samples/harmonica-steenberge/09 Rip Van Winkle.wav", channels:[0]); //, [\bufnum: 0]);

b = Buffer.readChannel(s, "/home/lcoogan/Music/Musicians/My Bloody Valentine/Loveless/01 Only Shallow.opus", [\bufnum: 0]);

(
// b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-Acheinu_Kol_Beit_Israel.wav");
b = Buffer.readChannel(s, "/home/lcoogan/snd/ardour/hebrewian_rue/export/hebrewian_rue_r1_lead.wav", channels:[0], bufnum: 0);
b = Buffer.readChannel(s, "/home/lcoogan/snd/ardour/hebrewian_rue/export/hebrewian_rue_r1_harm.wav", channels:[0], bufnum: 1);
b = Buffer.readChannel(s, "/home/lcoogan/snd/ardour/hebrewian_rue/export/hebrewian_rue_r1_drums.wav", channels:[0], bufnum: 2);
)

(
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/crawling-stems/lead.wav", channels:[0], bufnum: 0);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/crawling-stems/perc mel solo.wav", channels:[0], bufnum: 1);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/crawling-stems/bass.wav", channels:[0], bufnum: 2);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/crawling-stems/drums.wav", channels:[0], bufnum: 3);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/crawling-stems/break.wav", channels:[0], bufnum: 4);
)


(
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-Cantor_Samual_Malavsky_Shomea_Kol_Bichios.wav", channels:[0], bufnum: 0);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/02-Cantor_Mordechai_Hershman_Baruch_Hashem_Bayom.wav", channels:[0], bufnum: 1);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/03-Acheinu_Kol_Beit_Israel.wav", channels:[0], bufnum: 2);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/04-Cantor_Samuel_Malavsky_Zechor.wav", channels:[0], bufnum: 3);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/05-Cantor_Zavel_Kwartin_Ribono_Shel_Olam.wav", channels:[0], bufnum: 4);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/06-Cantor_Zevulun_Zavel_Kwartin_sings_Tiher.wav", channels:[0], bufnum: 5);
Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/07-Izak_Algazi_Efendi_Kamti_Be_ashmoret.wav", channels:0, bufnum: 6);
)

Synth(\granulator).clear;

b.free;

b.play;

Ndef(\granulator).clear;
Ndef(\granulator).ar(2);
Ndef(\granulator).set(\bufnum, b.bufnum);


~granBus = Bus.audio(s, 2); // stereo bus


( // one-shot reverb

SynthDef(\granulator, { |bufnum, tFreq=20, overlap=2, rate=1, tFreqMF=0, tFreqMD=0,
rateMF=0, rateMD=0, posRateMD=0, posRateMF=0, granDur=4|


	var samplePhasor, phasor, gran, env, bufrd;
	var bufFrames = BufFrames.ir(bufnum);
	var t;

	var tFreqMod = {
		SinOsc.ar(tFreqMF, Rand(0.0,2pi)) * tFreqMD;
	};

	var rateMod = {
		SinOsc.ar(rateMF, Rand(0.0,2pi)) * rateMD;
	};


	var posRateMod = {
		SinOsc.ar(posRateMF, Rand(0.0,2pi)) * posRateMD;
	};



	var playTrig = Impulse.ar(\playTrFr.kr(0.5));

	tFreq = tFreq + tFreqMod.dup;
	rate = rate + rateMod.dup;


	t = Impulse.ar(tFreq);
	// t = In.ar(somebus);

	samplePhasor = EnvGen.ar(Env([0, 0, bufFrames], [0, bufFrames / SampleRate.ir], curve: 0), gate: playTrig);
	phasor = EnvGen.ar(Env([0, 0, 1], [0, granDur], curve: 0), gate: playTrig);


	bufrd = BufRd.ar(
		numChannels: 1,
		bufnum: bufnum,
		phase: samplePhasor,
		interpolation: 4
	);

	bufrd = LeakDC.ar(bufrd);

	gran = GrainBufJ.ar(
		numChannels: 1,
		trigger: t,
		dur: tFreq.reciprocal * overlap,
		sndbuf: bufnum,
		rate: rate,
		// pos: phasor + WhiteNoise.ar(posRateMD!2),
		pos: phasor + posRateMod.dup,
		interp: 2,
		pan: 0,
		envbufnum: -1,
		maxGrains: 512,
		loop: 0
	) * EnvGen.ar(Env.perc(0.001, granDur * \grainGate.kr(1), curve: \granCurve.kr(-4)), gate: playTrig);


	Out.ar(0, Mix([
		bufrd * \dry.kr(1.0),
		gran  * \wet.kr(0.5)
	]););

	// DetectSilence.ar(gran, doneAction: 2); // in case we lauch it without trigger Ugens (with Synth etc)
	// Out.ar(0,);

}).add;
)


x = Synth(\compressor_granulator, [\bufnum, b]);
x.free;

//
// Ndef(\granulator).addSpec(
// 	\overlap, [0.001, 40, \exp],
// 	\rate, [-2, 2],
// 	\posRate, [0, 4],
// 	\tFreq, \widefreq,
// 	\tFreqMF, [0.0,80],
// 	\tFreqMD, [0.0,20],
// 	\rateMF, [0.0,80],
// 	\rateMD, [0.0,2],
// 	\posRateMF, [0.0,80],
// 	\posRateMD, [0.0,2],
// 	\dry, [0.0,1],
// 	\wet, [0.0,1],
// 	\playTrFr, [0.0,1],
// 	\granDur, [0.0,8],
// 	\granCurve, [-10,10],
// 	\grainGate, [0,1],
// ).edit;




// 	\overlap, [0.001, 40, \exp],
// 	\rate, [-2, 2],
// 	\posRate, [0, 4],
// 	\tFreq, \widefreq,
// 	\tFreqMF, [0.0,80],
// 	\tFreqMD, [0.0,20],
// 	\rateMF, [0.0,80],
// 	\rateMD, [0.0,2],
// 	\posRateMF, [0.0,80],
// 	\posRateMD, [0.0,2],

// 	\playTrFr, [0.0,1],
// 	\granDur, [0.0,8],
// 	\granCurve, [-10,10],
// 	\grainGate, [0,1],

MIDIClient.init;
MIDIIn.connectAll;

(
MIDIIn.control = { |src, chan, num, val|
    if (chan == 2) {
        switch(num,
			0, { x.set(\wet, val.linlin(0, 127, 0, 1)); },
			1, { x.set(\bufnum, val.linlin(0, 127, 0, 2))},
            2, { x.set(\rate, val.linlin(0, 127, -2, 2)) },
            3, { x.set(\posRate, val.linlin(0, 127, 0, 4)) },
            4, { x.set(\tFreq, val.linlin(0, 127, 0, 80)) },
            5, { x.set(\tFreqMF, val.linlin(0, 127, 0, 80)) },
            6, { x.set(\tFreqMD, val.linlin(0, 127, 0, 20)) },
            7, { x.set(\rateMF, val.linlin(0, 127, 0, 80)) },
            8, { x.set(\rateMD, val.linlin(0, 127, 0, 2)) },
            9, { x.set(\posRateMF, val.linlin(0, 127, 0, 80)) },
            10, { x.set(\posRateMD, val.linlin(0, 127, 0, 2)) },
            11, { x.set(\playTrFr, val.linlin(0, 127, 0, 1)) },
            12, { x.set(\granDur, val.linlin(0, 127, 0, 8)) },
            13, { x.set(\granCurve, val.linlin(0, 127, -10, 10)) },
            14, { x.set(\grainGate, val.linlin(0, 127, 0, 1)) },
            15, { x.set(\overlap, val.exprand(0.001, 40)) },  // Exponential scaling for overlap
            // Add more cases if needed
        );
    };
};
)



(
var paramMap = (
    0: [\wet, 0, 1],
    1: [\bufnum, 0, 4],
    2: [\rate, -2, 2],
    3: [\posRate, 0, 4],
    4: [\tFreq, 0, 80],
    5: [\tFreqMF, 0, 80],
    6: [\tFreqMD, 0, 20],
    7: [\rateMF, 0, 80],
    8: [\rateMD, 0, 2],
    9: [\posRateMF, 0, 80],
    10: [\posRateMD, 0, 2],
    11: [\playTrFr, 0, 1],
    12: [\granDur, 0, 8],
    13: [\granCurve, -10, 10],
    14: [\grainGate, 0, 1],
    15: [\overlap, 0.001, 40, \exp],

    16: [\attack, 0.0000001, 0.1, \exp],
    17: [\release, 0.0000001, 0.4, \exp],
    18: [\threshold, -120, 0], // flipped key/value to array

    19: [\trim, 0, 60],
    20: [\gain, -40, 40],
    21: [\ratio, 1, 20, \exp],
    22: [\dry_wet, 0, 1],
    23: [\hpf, 10, 1000], // fixed missing bracket
    24: [\knee, 0.0, 10], // fixed missing bracket
    25: [\lookahead, 0.0, 1], // fixed missing bracket
    26: [\saturate, \switch], // you may want to define how to handle \switch
    27: [\bias, 0.0, 1.0]
);



MIDIIn.control = { |src, chan, num, val|
    if (chan == 2) {
        var mapping = paramMap[num];
        if (mapping.notNil) {
            var param = mapping[0];
            var min = mapping[1];
            var max = mapping[2];
            var scaleType = mapping[3] ?? \lin; // default to lin if not specified
            var mappedVal = (scaleType == \exp)
                .if { val.linexp(0, 127, min, max) }
                { val.linlin(0, 127, min, max) };
            x.set(param, mappedVal);
            ("Setting " ++ param ++ " to " ++ mappedVal).postln;
        };
    };
};
)

