Ndef( \compressor).clear; Ndef( \compressor).ar(2); b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/stereo/Acheinu Kol Beit Israel [28iaQrr3X8g].wav"); ( SynthDef( \compressor, { var local; var attack = \attack.kr(0.01); var release = \release.kr(0.1); var dry, drywet, in, t, o, r, c, e, lookahead; var kneelag; var bias; t = \threshold.kr(-6); // dry = SoundIn.ar([0,1]); dry = PlayBuf.ar(2, b, BufRateScale.kr(b), loop: 1); // 2 = stereo // dry = b; in = dry * \trim.kr(0).dbamp; e = in.mean; e = HPF.ar( e, \hpf.kr(50) ); e = EnvDetect.ar(e, attack, release); // smooth abs values // how much we are over by o = e.ampdb.excess(t); // scale the excess value by ratio r = \ratio.kr(4); c = ( max(o, 0.0) ) * (r.reciprocal - 1); kneelag = attack * \knee.kr(0.0); c = c.lag( kneelag ); c = c.dbamp; lookahead = \lookahead.kr(0); in = DelayC.ar( in, 0.5, lookahead.lag(0.4) ); // lookahead in = in * c; in = in * \gain.kr(0).dbamp; bias = K2A.ar(\bias.kr(0.0)); in = Select.ar( \saturate.kr(1), [in, (in + bias).softclip - bias] ); in = LeakDC.ar(in); drywet = \dry_wet.kr(1); Out.ar(0, Mix([ in * drywet, DelayC.ar( dry * (1 - drywet), 0.5, lookahead.lag(0.4) ) ])); } ).add; /*( Spec.add(\attack, [0.0000001,0.1, \exp]); Spec.add(\release, [0.0000001,0.4, \exp]); Spec.add(\threshold, [0,-120]); Spec.add(\trim, [0,60]); Spec.add(\gain, [-40,40]); Spec.add(\ratio, [1,20, \exp]); Spec.add(\dry_wet, [0,1]); Spec.add(\hpf, [10, 1000]); Spec.add(\knee, [0.0, 10]); Spec.add(\lookahead, [0.0,1]); Spec.add(\saturate, \switch); Spec.add(\bias, [0.0, 1.0]);*/ ); x = Synth(\compressor, [\bufnum, 0]); x = Synth(\comp, [\bufnum, 0]); x = Synth(\granular_comp, [\bufnum, 0]); inAmp=1, gain=0, lookahead = 0, tFreq=20, overlap=2, rate=1, lpf=0 ( var paramMap = ( 0: [\inAmp, 0, 2], 1: [\gain, -40, 40], 2: [\lookahead, 0.0, 1.0], 3: [\tFreq, 0, 80], 4: [\overlap, 0.001, 40, \exp], 5: [\rate, -2, 2], 6: [\lpf, 20, 20000, \exp] ); MIDIIn.control = { |src, chan, num, val| if (chan == 3) { 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; }; }; }; ) ( var paramMap = ( 0: [\attack, 0.0000001, 0.1, \exp], 1: [\release, 0.0000001, 0.4, \exp], 2: [\threshold, 0, -120], 3: [\trim, 0, 60], 4: [\gain, -40, 40], 5: [\ratio, 1, 20, \exp], 6: [\dry_wet, 0, 1], 7: [\hpf, 10, 1000], 8: [\knee, 0.0, 10], 9: [\lookahead, 0.0, 1], 10: [\saturate, 0, 1], // since \switch is not numeric, using 0 or 1 (off/on) 11: [\bias, 0.0, 1.0] ); MIDIIn.control = { |src, chan, num, val| if (chan == 3) { 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; }; }; }; ) Ndef('compressor').set('threshold', -58.604651162791, 'saturate', 0.0, 'lookahead', 0.037037037037037, 'gain', 34.448135843484, 'release', 0.053953680737862, 'bias', 0.0, 'dry_wet', 1.0, 'knee', 1.0077519379845); Ndef( \compressor).edit; ) //// Analysis plots --begin ({ EnvDetect.ar(SinOsc.ar, 0.01,0.01); }.plot(1)) ({ EnvDetect.ar(SinOsc.ar, 0.01,0.01).ampdb; }.plot(1)) ({ max( EnvDetect.ar(SinOsc.ar, 0.01,0.01).ampdb.excess(-10), 0); }.plot(1)) ({ var r = 2; max( EnvDetect.ar(SinOsc.ar, 0.01,0.01).ampdb.excess(-10), 0) * (r.reciprocal - 1); }.plot(1)) ({ var r = 10; var db = max( EnvDetect.ar(SinOsc.ar, 0.01,0.01).ampdb.excess(-10), 0) * (r.reciprocal - 1); db.dbamp }.plot(1)) ///// Analysis plots --end Ndef(\analysis).clear; Ndef(\analysis).ar(1); ( Ndef(\analysis, { var input, in, e, thresh, c, attack, release, kneelag; input = SoundIn.ar([0,1]); attack = \attack.kr(0.01); release = \release.kr(0.1); thresh = \threshold.kr(-6); in = input * \trim.kr(0).dbamp; e = in.mean; e = HPF.ar( e, \hpf.kr(50) ); e = EnvDetect.ar(e, attack, release); // how much we are over by o = e.ampdb.excess(thresh); // scale the excess value by ratio r = \ratio.kr(4); c = ( max(o, 0.0) ) * (r.reciprocal - 1); kneelag = attack * \knee.kr(0.0); c = c.lag( kneelag ); c = c.dbamp; }); Ndef('analysis').set('threshold', -58.6, 'release', 0.05, 'knee', 1.01); Ndef(\analysis).edit; ) Ndef( \comp).clear; Ndef( \comp).ar(2); ( SynthDef( \comp, { var dry, in, c, lookahead; var bias; var gain = \gain.kr(0).dbamp; // dry = SoundIn.ar([0,1]); dry = PlayBuf.ar(2, b, BufRateScale.kr(b), loop: 1); // 2 = stereo in = dry; c = Ndef(\analysis).ar; lookahead = \lookahead.kr(0); in = DelayC.ar( in, 0.5, lookahead); // lookahead in = in * c; in = in * gain; bias = K2A.ar(\bias.kr(0.0)); in = Select.ar( \saturate.kr(1), [in, (in + bias).softclip - bias] ); in = LeakDC.ar(in); Out.ar(0, Mix([ in * \wet.kr(1), DelayC.ar( dry * gain * \dry.kr(1), 0.5, lookahead ) ])); } ).play; // Ndef('comp').set('gain', 33.0, 'lookahead', 0.015503875968992, 'dry', 0.0); // // Ndef( \comp).edit; ) Ndef(\granular_comp).clear Ndef(\granular_comp).ar(2) ( Ndef('granular_comp').addSpec( \lookahead, [0.0,1], \saturate, \switch, \lpf, [0.0, 0.2], \inAmp, \inAmp, \wet, \bipolar, \inputAmp, [0,30], \lookahead, [0.0,4100], \rate, [0,1], \tFreq, [1,22050, \exp], \overlap, [0.01,512.0, \exp], \hpf, \freq, \wet, [0.0,1], \dry, [0.0,1], \gain, [0.0,40], ) ) ( ( SynthDef('granular_comp', {| inAmp=1, gain=0, lookahead = 0, tFreq=20, overlap=2, rate=1, lpf=0 | var input; var readPos, signal, writePos, grained, balance; var t, bufFrames; var buf, bufdur; var sc; bufFrames = 2**16; buf = {LocalBuf(bufFrames).clear}!2; bufdur = BufDur.ir(buf); writePos = Phasor.ar( 0, rate, 0, bufFrames ); input = PlayBuf.ar(2, b, BufRateScale.kr(b), loop: 1) * inAmp; // 2 = stereo // input = SoundIn.ar([0,1]) * inAmp; // input = b; // writing input to grain buffer buf.do { |b i| BufWr.ar( input[i], b, writePos) }; t = Impulse.ar(tFreq); readPos = Wrap.ar( writePos - 64 - lookahead / bufFrames, 0, 1 ); sc = Ndef(\analysis).ar; grained = GrainBufJ.ar( numChannels:1, loop: 1, trigger:t, // dur: overlap / tFreq, dur: sc * overlap / tFreq, sndbuf: buf, rate: rate - lpf, pos:readPos, interp: 4, // grainAmp: sc, pan: 0, envbufnum:-1 ); grained = HPF.ar( grained, \hpf.kr(40) ); signal = Mix([ LeakDC.ar( grained ) * \wet.kr(1), DelayC.ar( input, 0.5, (64 + lookahead / SampleRate.ir ) ) * \dry.kr(0) ]) * gain.dbamp; signal.tanh; Out.ar(0, signal); }).add; // Ndef('granular_comp').edit ) ) ( // using overlap Ndef('analysis').set('threshold', -58.6, 'ratio', 4.0, 'release', 0.095152954811494, 'knee', 1.01); Ndef('granular_comp').set('lookahead', 2288.3720930233, 'wet', 0.96124031007752, 'rate', 1.0, 'tFreq', 5054.5412673637, 'lpf', 0.024338624338624, 'inAmp', 0.7751938, 'gain', 1.0542635658915, 'overlap', 337.20506220588, 'dry', 0.0); ) ( // lofi Ndef('granular_comp').set('lookahead', 127.13178294574, 'wet', 0.66666666666667, 'rate', 0.2, 'tFreq', 4328.5464121672, 0.7751938, 'overlap', 157.82885262499, 'gain', 1.3643410852713, 'dry', 0.0); Ndef('analysis').set('threshold', -58.6, 'ratio', 1.7870536713698, 'release', 0.068293378346003, 'attack', 0.0055486335881451, 'knee', 1.01); )