diff --git a/better_spectral.scd b/better_spectral.scd new file mode 100644 index 0000000..cfadea1 --- /dev/null +++ b/better_spectral.scd @@ -0,0 +1,91 @@ +( +// ========== Spectral SynthDef with expanded modulation ========== +SynthDef(\pv16knob, { + arg bufnum, fftSize = 1024, + amp = 0.3, smearAmt = 5, randRate = 6, binScrambleAmt = 0.5, + pvRouting = 0, grainSize = 0.1, + delTime = 0.3, delFeedback = 0.4, verbMix = 0.2, + lfoFreq = 0.2, bitcrushAmt = 0.0, distAmt = 1.0, + ringFreq = 200, freezeAmt = 0.5, + transpose = 1.0, filterCutoff = 8000; + + var in, chain, lfo, dry, fx, delay, verb; + var chain0, chain1, chain2, chain3, chain4; + + // Audio input and bitcrushing + in = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum) * transpose, loop: 1); + in = Decimator.ar(in, (1 - bitcrushAmt).linexp(0, 1, 44100, 1000), 8 - (bitcrushAmt * 7)); + + // FFT + chain = FFT(LocalBuf(fftSize), in); + lfo = SinOsc.kr(lfoFreq).range(0.1, 1.0); + chain = PV_MagFreeze(chain, freezeAmt); + + // Spectral branches + chain0 = PV_BinScramble(PV_MagSmear(PV_RandComb(chain, 0.1, Impulse.kr(randRate)), smearAmt + lfo), binScrambleAmt, 0); + chain1 = PV_BrickWall(chain, lfo.range(0.05, 0.2)); + chain2 = PV_BinShift(chain, lfo * 20, 0.5); + chain3 = PV_BinWipe(chain, lfo); + chain4 = PV_SpectralEnhance(chain, 0.8, 1.5, 0.2); + + // Select + chain = SelectX.kr(pvRouting.clip(0, 4), [chain0, chain1, chain2, chain3, chain4]); + dry = IFFT(chain); + + // Post-PV grain + dry = TGrains.ar(2, Impulse.ar(20), bufnum, 1, Phasor.ar(0, 1, 0, BufFrames.ir(bufnum)), grainSize, 0, 0.1, 1); + dry = Ringz.ar(dry, ringFreq, 0.2); + dry = (dry * distAmt).tanh; + dry = LPF.ar(dry, filterCutoff); + + // 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; +) + +( +// ========== Load buffer ========== +b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav"); // Use your own file if you want +) + +( +// ========== Instantiate synth ========== +~pvSynth = Synth(\pv16knob, [\bufnum, b]); +) + +( +// ========== MIDI CC Mapping (channel 2) ========== +[ + [\amp, 0, 0.0, 1.5], + [\smearAmt, 1, 1, 40], + [\randRate, 2, 0.5, 20], + [\binScrambleAmt, 3, 0.0, 1.0], + [\pvRouting, 4, 0, 4], + [\grainSize, 5, 0.01, 0.2], + [\delTime, 6, 0.05, 1.0], + [\delFeedback, 7, 0.0, 0.95], + [\verbMix, 8, 0.0, 1.0], + [\lfoFreq, 9, 0.01, 5.0], + [\bitcrushAmt, 10, 0.0, 1.0], + [\distAmt, 11, 0.5, 10.0], + [\ringFreq, 12, 50, 2000], + [\freezeAmt, 13, 0.0, 1.0], + [\transpose, 14, 0.25, 2.0], + [\filterCutoff, 15, 100, 15000] +].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); +}; +)