From 53018120f4fe164942a9b862a9bdc4a3902d5873 Mon Sep 17 00:00:00 2001 From: Leo Coogan Date: Mon, 21 Apr 2025 11:19:31 -0400 Subject: [PATCH] approaching completion on spectral synth --- neo-hasidic_brainsex/better_spectral.scd | 272 +++++++++++++++++ neo-hasidic_brainsex/revised spectral.scd | 344 ++++++++++++++++++++++ neo-hasidic_brainsex/spectral n.scd | 60 ++++ 3 files changed, 676 insertions(+) create mode 100644 neo-hasidic_brainsex/better_spectral.scd create mode 100644 neo-hasidic_brainsex/revised spectral.scd create mode 100644 neo-hasidic_brainsex/spectral n.scd diff --git a/neo-hasidic_brainsex/better_spectral.scd b/neo-hasidic_brainsex/better_spectral.scd new file mode 100644 index 0000000..0fbcdbb --- /dev/null +++ b/neo-hasidic_brainsex/better_spectral.scd @@ -0,0 +1,272 @@ +Server.supernova; +s.boot; +MIDIClient.init; +MIDIIn.connectAll; + +// Set list +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-Acheinu_Kol_Beit_Israel.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/02-Cantor_Mordechai_Hershman_Baruch_Hashem_Bayom.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/03-Cantor_Samual_Malavsky_Shomea_Kol_Bichios.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/04-Cantor_Samuel_Malavsky_Zechor.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/05-Cantor_Zavel_Kwartin_Ribono_Shel_Olam.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/06-Cantor_Zevulun_Zavel_Kwartin_sings_Tiher.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/07-Izak_Algazi_Efendi_Kamti_Be_ashmoret.wav"); + + + + + +( +// ========== Spectral SynthDef with expanded modulation ========== +SynthDef(\pv16knob, { + arg bufnum, fftSize = 1024, + amp = 0.3, delTime = 0.3, delFeedback = 0.4, verbMix = 0.2, transpose = 1.0; + + var in, chain, lfo, dry, fx, delay, verb; + var wipe, trig; + + // Audio input and bitcrushing + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum) * transpose, loop: 1); + + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + // wipe = SinOsc.kr(0.1).range(0.1, 0.9); + wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + chain = PV_RandComb(chain, wipe, trig); + chain = PV_BrickWall(chain); + + + +/* chain = PV_RandComb(chain, wipe, trig); + chain = PV_BinShift(chain, stretch, shift, interp); + + chain = PV_MagFreeze(chain, freeze); + chain = PV_BrickWall(chain, wipe); + + chain = PV_MaxMagN(chain, numbins); + chain = PV_MagSmooth(chain, factor); + + chain = PV_PhaseShift90(chain, buffer); + chain = PV_Diffuser(chain, trig); + + + // Layer 2 combos: texture + + chain = PV_RandComb(chain); + chain = PV_BinScramble(chain); + chain = PV_BinWipe(chain); + + chain = PV_RandComb(chain); + chain = PV_BinShift(chain); + chain = PV_Diffuser(chain); + + chain = PV_MagFreeze(chain); + chain = PV_BinWipe(chain); + + chain = PV_BrickWall(chain); + chain = PV_MagSmooth(chain);*/ + + + + // Select + // chain = SelectX.kr(pvRouting.clip(0, 4), [chain0, chain1]); + dry = IFFT(chain); + + // FX + delay = CombC.ar(dry, 1, delTime, delFeedback); + verb = FreeVerb.ar(dry, verbMix, 0.8, 0.3); + + // Mix and output + fx = Mix([dry, delay, verb]); + Out.ar(0, fx.dup * amp); +}).add; +) + +( +// ========== Spectral SynthDef with expanded modulation ========== +SynthDef(\pv16knob_1, { + arg bufnum, fftSize = 1024, + amp = 0.3, delTime = 0.3, delFeedback = 0.4, verbMix = 0.2, transpose = 1.0; + + var in, chain, lfo, dry, fx, delay, verb; + var wipe, trig; + + // Audio input and bitcrushing + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum) * transpose, loop: 1); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + // wipe = SinOsc.kr(0.1).range(0.1, 0.9); + wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + +/* chain = PV_RandComb(chain, wipe, trig); + chain = PV_BrickWall(chain);*/ + + chain = PV_RandComb(chain, wipe, trig); + chain = PV_BinScramble(chain, wipe, 0.2, trig); + chain = PV_BinWipe(chain, chain, wipe); + + + + +/* chain = PV_RandComb(chain, wipe, trig); + chain = PV_BinShift(chain, stretch, shift, interp); + + chain = PV_MagFreeze(chain, freeze); + chain = PV_BrickWall(chain, wipe); + + chain = PV_MaxMagN(chain, numbins); + chain = PV_MagSmooth(chain, factor); + + chain = PV_PhaseShift90(chain, buffer); + chain = PV_Diffuser(chain, trig); + + + // Layer 2 combos: texture + + chain = PV_RandComb(chain); + chain = PV_BinScramble(chain); + chain = PV_BinWipe(chain); + + chain = PV_RandComb(chain); + chain = PV_BinShift(chain); + chain = PV_Diffuser(chain); + + chain = PV_MagFreeze(chain); + chain = PV_BinWipe(chain); + + chain = PV_BrickWall(chain); + chain = PV_MagSmooth(chain);*/ + + + + // Select + // chain = SelectX.kr(pvRouting.clip(0, 4), [chain0, chain1]); + dry = IFFT(chain); + + // FX + delay = CombC.ar(dry, 1, delTime, delFeedback); + verb = FreeVerb.ar(dry, verbMix, 0.8, 0.3); + + // Mix and output + fx = Mix([dry, delay, verb]); + Out.ar(0, fx.dup * amp); +}).add; +) + + + +( +// ========== Instantiate synth ========== +~pvSynth = Synth(\pv16knob, [\bufnum, b, \amp, 0.1]); +~pvSynth = Synth(\pv16knob_1, [\bufnum, b, \amp, 0.1]); +) + + +( +// it needs a control for mixing between the original and the granular, try adding the Dust & Impulse switch first + +// ========== MIDI CC Mapping (channel 2) ========== +[ +// remember to make the signal flow conventional +// what are other ways I can rhythmically distort this? Pulsar? FM? + + [\amp, 0, 0.0, 1.5], // keep + // add tr08 mix control + [\grainSize, 5, 0.01, 0.2], // yes, maybe add a switch for impulse or dust + + [\smearAmt, 1, 1, 40], // don't know + [\randRate, 2, 0.5, 20], // don't know + [\binScrambleAmt, 3, 0.0, 1.0], // don't know + [\pvRouting, 4, 0, 4], // don't know + [\delFeedback, 7, 0.0, 0.95], // don't know + + [\delTime, 6, 0.05, 1.0], // yes, but more + + + [\verbMix, 8, 0.0, 1.0], // yes, but convolution and maybe switches for types + [\lfoFreq, 9, 0.01, 5.0], // yes + [\bitcrushAmt, 10, 0.0, 1.0], + [\distAmt, 11, 0.5, 10.0], // yes, but varied forms + // needs splay control + + [\ringFreq, 12, 50, 2000], // yes, but more + [\freezeAmt, 13, 0.0, 1.0], + [\transpose, 14, 0.25, 2.0], // not working + [\filterCutoff, 15, 100, 15000] // yes, more filters, add type switch + // needs to be a resonance control here +].do { |spec| + var param, cc, min, max; + #param, cc, min, max = spec; + + MIDIdef.cc(param.asSymbol, { |val, num, chan, src| + if(chan == 2) { + var mapped = val.linlin(0, 127, min, max); + ~pvSynth.set(param, mapped); + } + }, cc); +}; +) + + + + +( +// it needs a control for mixing between the original and the granular, try adding the Dust & Impulse switch first + +// ========== MIDI CC Mapping (channel 2) ========== +[ +// remember to make the signal flow conventional +// what are other ways I can rhythmically distort this? Pulsar? FM? + + [\amp, 0, 0.0, 1.5], // keep + // add tr08 mix control + + [\layer1_amp], + [\layer1_index], + [\layer2_amp], + [\layer2_index], + + [\filt1_crf], + [\filt2_res], + [\filt1_crf], + [\filt2_res], + + [\verb], + [\comb], + [\fold], + [\splay], + + + +].do { |spec| + var param, cc, min, max; + #param, cc, min, max = spec; + + MIDIdef.cc(param.asSymbol, { |val, num, chan, src| + if(chan == 2) { + var mapped = val.linlin(0, 127, min, max); + ~pvSynth.set(param, mapped); + } + }, cc); +}; +) + + + + diff --git a/neo-hasidic_brainsex/revised spectral.scd b/neo-hasidic_brainsex/revised spectral.scd new file mode 100644 index 0000000..20ff5b5 --- /dev/null +++ b/neo-hasidic_brainsex/revised spectral.scd @@ -0,0 +1,344 @@ +// TODO: add modulation to chain params + +( +SynthDef(\layer0_struct0, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + chain = PV_RandComb(chain, wipe, trig); + chain = PV_BrickWall(chain); + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + +x = Synth(\layer0_textur0, [\bufnum, b, \amp, 0.3]); +x.free; + + + + + +( +SynthDef(\layer0_struct1, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + chain = PV_RandComb(chain, wipe, trig); + chain = PV_BinShift(chain); + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + + +( +SynthDef(\layer0_struct2, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + + chain = PV_MagFreeze(chain); + chain = PV_BrickWall(chain); + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + + +( +SynthDef(\layer0_struct3, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + + chain = PV_MagAbove(chain); + chain = PV_MagSmooth(chain); + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + + + +( +SynthDef(\layer0_struct4, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + chain = PV_PhaseShift90(chain); + chain = PV_Diffuser(chain, trig); + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +( +SynthDef(\layer1_textur0, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + chain = PV_RandComb(chain); + chain = PV_BinScramble(chain); + chain = PV_BinWipe(chain, chain); + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + +( +SynthDef(\layer1_textur1, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + chain = PV_RandComb(chain); + chain = PV_BinShift(chain); + chain = PV_Diffuser(chain); + + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + +( +SynthDef(\layer1_textur2, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + chain = PV_MagSquared(chain); + chain = PV_RectComb(chain); + + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + + +( +SynthDef(\layer1_textur3, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + chain = PV_MagFreeze(chain); + chain = PV_BinWipe(chain, chain); + + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) + + +( +SynthDef(\layer1_textur4, { + arg bufnum, fftSize = 1024, amp = 0.3; + + var in, chain, dry, fx; + var wipe, trig; + var sig; + + // Audio input + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum)); + + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + + // Layer 1 combos: structure + + wipe = SinOsc.kr(0.1).range(0.1, 0.9); + // wipe = Lag.kr(TRand.kr(0.0, 1.0, Impulse.kr(0.2)), 1.0); + trig = Impulse.kr(SinOsc.kr(0.1).range(1, 10)); + + + chain = PV_BrickWall(chain); + chain = PV_MagSmooth(chain); + + + sig = IFFT(chain); + + Out.ar(0, sig.dup * amp); +}).add; +) diff --git a/neo-hasidic_brainsex/spectral n.scd b/neo-hasidic_brainsex/spectral n.scd new file mode 100644 index 0000000..c3e969b --- /dev/null +++ b/neo-hasidic_brainsex/spectral n.scd @@ -0,0 +1,60 @@ +( +SynthDef(\layer0_struct0, { + arg bufnum, fftSize = 1024, amp = 0.3, + wipeFreq = 0.1, wipeDepth = 0.4, + trigFreq = 2.0, threshold = 0.3, smoothAmt = 0.2, + mix = 1.0; + + var in, dry, sig, chain; + var wipe, trig; + + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum), loop: 1); + dry = in; + + // FFT + chain = FFT(LocalBuf(fftSize), in); + + // Modulated parameters + wipe = SinOsc.kr(wipeFreq).range(wipeDepth, 0.9); + trig = Impulse.kr(trigFreq); + + // Processing chain + chain = PV_RandComb(chain, wipe, trig); + chain = PV_MagAbove(chain, threshold); + chain = PV_MagSmooth(chain, smoothAmt); + chain = PV_BrickWall(chain); + + sig = IFFT(chain); + + // Mix dry/wet + sig = XFade2.ar(dry, sig, mix.linlin(0, 1, -1, 1)); + + Out.ar(0, sig.dup * amp); +}).add; +) + + +( +~midiControlMap = ( + 16: \wipeFreq, // CC16 + 17: \wipeDepth, // CC17 + 18: \trigFreq, // CC18 + 19: \threshold, // CC19 + 20: \smoothAmt, // CC20 + 21: \mix // CC21 +); + +// Replace this with your actual Synth instance +~layer0 = Synth(\layer0_struct0, [\bufnum, b]); + +// Connect MIDI CCs on channel 2 +~midiControlMap.keysValuesDo { |cc, param| + MIDIFunc.cc({ |val, num, chan, src| + if (chan == 2) { // Channel 2 (zero-indexed) + var mappedVal = val.linlin(0, 127, 0.0, 1.0); + ~layer0.set(param, mappedVal); + ("CC" ++ cc ++ " (" ++ param ++ ") → " ++ mappedVal).postln; + } + }, cc); +}; +)