diff --git a/2025.05.10-mothers_day.scd b/2025.05.10-mothers_day.scd new file mode 100644 index 0000000..6ffd249 --- /dev/null +++ b/2025.05.10-mothers_day.scd @@ -0,0 +1,80 @@ +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/04-Cantor_Samuel_Malavsky_Zechor.wav"); +b.play; + +b = Buffer.read(s, "/home/lcoogan/Music/Musicians/My Bloody Valentine/Loveless/02 Loomer.wav"); + + +b = Buffer.read(s, "/home/lcoogan/Misc/my_grave.wav"); + +b = Buffer.read(s, "/home/lcoogan/Misc/loomer.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/releases/desolation-mountain/out.wav"); + +b = Buffer.read(s, "/home/lcoogan/snd/releases/2025.05.10-Mothers_Day/rem.wav"); + + +( +SynthDef(\brickwall, { + arg out=0, bufnum, fftSize=4096; + var source, chain, sig, noise; + // + source = PlayBuf.ar(1, b, loop: 1, doneAction: 2); + // source = XFade2.ar(source, WhiteNoise.ar(1)); + // + chain = FFT(LocalBuf(fftSize), source); + chain = PV_BrickWall(chain, Line.kr(SinOsc.kr(-0.95), -0.80, 1)); + chain = PV_BrickWall(chain, Line.kr(0.012, 0.003, 4)); + // chain= PV_BrickWall(chain, Line.kr(-1,0,10)); + + + // chain = PV_BinDelay(chain, 0.1, 0.01, chain, chain, 0.5); + // chain = PV_BinDelay(b,); + // chain = PV_BinScramble(chain, 0.1, 0.2, SinOsc.kr(1)); + // chain = PV_BrickWall(chain, -0.99); + // chain = PV_ConformalMap(chain, 0.1, Phasor.kr(8)); + // chain = PV_Conj(chain); + // chain = PV_Whiten(chain, b, 0.01, 0.5, Dust.kr(1), Dust.kr(0.5)); + // chain = PV_MagAbove(chain, Line.kr(30, 40, 1)); + // +/* chain= chain.pvcollect(b.numFrames,{|mag, phase, index| + // noise= LFNoise1.kr(rrand(0.5,1.1)); + noise = WhiteNoise.kr(2); + [noise*mag,noise.range(-pi,pi)] + + }, + // + frombin:80, tobin:100,zeroothers:0);*/ + + + + // chain = PV_MagBelow(chain, 10); + + chain = PV_LocalMax(chain, SinOsc.kr(440, SinOsc.kr(1))); + + // chain = PV_MagSmear(chain, Line.kr(0, 100, 1, SinOsc.kr(440))); + + sig = IFFT(chain); + + // sig = BPF.ar(sig, 4000, 0.1); + + // sig = Resonz.ar(sig, 200, 1); + // sig = BHiShelf.ar(sig, 10000, 1); + + /*sig = BHiShelf.ar( + sig, + 18000, + 1, + 6, // db + 3); // mul*/ + // sig = RLPF.ar(sig, 2000, 1, -1); + + sig = GVerb.ar(sig, 299, 4, 1, 0.5, 30, 1, 0.1, 0.5); + sig = Splay.ar(sig, 4); + sig = PitchShift.ar(sig, Line.kr(0.5, 1.0, 0.65, Line.kr(0, 3, 4)), 2.0, 0.0, 0.0, 1.0, 0 ); + sig = LPF.ar(sig, 800); + // sig = PitchShift.ar(sig, 0.1, 0.4, 0.2, 3); + + + Out.ar(out, sig.dup); + +}).play; +) diff --git a/CA.scd b/CA.scd new file mode 100644 index 0000000..f7e7190 --- /dev/null +++ b/CA.scd @@ -0,0 +1,48 @@ +{CA1x.ar(100 + LFNoise0.kr(2), 40 + SinOsc.kr(40), 2, mul:2)}.play; + +( +SynthDef(\ca, { + arg freq=180, amp = 2; + var sig, env; + sig = CA1.ar(freq + LFNoise0.kr(20), freq + SinOsc.kr(40), 2, mul:2) + CA2.ar(); + // sig = SinOsc.ar(freq); + env = EnvGen.kr(Env.adsr(0, 0.1, 0.2), doneAction:2); + Out.ar(0, sig.dup, amp * env); +}).add; +) + +Synth(\ca, [\freq, 120]); + + +{CA1.ar(440, 60, 18, ).dup}.play; + + +( +SynthDef(\ca2, { + arg freq=440, amp=1; + var sig, env, r; + + r = Pca.r2; + + sig = CA2.ar(freq, 50, r[10], trig:Impulse.kr(4 + SinOsc.kr(0.2))); + env = EnvGen.kr(Env.adsr(0, 0.1, 0.2), doneAction:2); + + // sig = LPF.ar(sig, 800); + + Out.ar(0, sig.dup * env * amp); +}).add; +) + + +{CA2.ar(2).dup}.play; + + +( +Pbind( + \instrument, \ca, + \dur, 0.25, + \freq, Pseq([60, 63, 65], inf), + \amp, 0.1, + \rel, 0.8, +).play; +) \ No newline at end of file diff --git a/algo22bass.scd b/algo22bass.scd new file mode 100644 index 0000000..ef45cff --- /dev/null +++ b/algo22bass.scd @@ -0,0 +1,55 @@ +( +Ndef(\algo22bass, { + var freq = \freq.kr(55); + var amp = \amp.kr(0.5); + var gate = \gate.kr(1); + var pan = \pan.kr(0); + var lfo, fb, op1, op2, op3, op4, op5, op6; + var env1, env2, env3, env4, env5, env6; + var sig; + + lfo = LFSaw.kr(8).range(0.1, 1.5); + + // Feedback loop + fb = LocalIn.ar(1); + + // Operator 6 + env6 = EnvGen.kr(Env.new([0, 1, 1, 1, 0], [0.01, 0.1, 0.1, 0.1], \lin, 3), gate); + op6 = SinOsc.ar((freq * 8) + (fb * 7), 0, env6 * lfo * 0.6); + LocalOut.ar(op6); + + // Operator 5 + env5 = EnvGen.kr(Env.new([0, 1, 1, 1, 0], [0.01, 0.2, 0.2, 0.2], \lin, 3), gate); + op5 = SinOsc.ar((freq * 0.5) + (op6 * 200), 0, env5); + + // Operator 4 + env4 = EnvGen.kr(Env.new([0, 1, 1, 1, 0], [0.01, 0.3, 0.3, 0.3], \lin, 3), gate); + op4 = SinOsc.ar((freq * 1.0) + (op5 * 200), 0, env4); + + // Operator 1 + env1 = EnvGen.kr(Env.new([\op1_env1_atk.kr(0);, 1, 1, 1, 0], [0.01, 0.2, 0.4, 0.2], \lin, 3), gate, doneAction:2); + op1 = SinOsc.ar(freq * 3.0, 0, env1 * 0.6); + + // Operator 2 + env2 = EnvGen.kr(Env.new([0, 1, 1, 1, 0], [0.01, 0.2, 0.2, 0.2], \lin, 3), gate); + op2 = SinOsc.ar(freq * 5.91, 0, env2 * 0.4); + + // Operator 3 + env3 = EnvGen.kr(Env.new([0, 1, 1, 1, 0], [0.01, 0.3, 0.2, 0.2], \lin, 3), gate); + op3 = SinOsc.ar(freq * 2.0, 0, env3 * 0.5); + + sig = (op1 + op2 + op3 + op4) * amp; + sig = RLPF.ar(sig, 1200, 0.4); + sig = sig.tanh * 1.5; + sig = CombL.ar(sig, 0.3, 0.15, 1.5, mul: 0.7); + Pan2.ar(sig, pan) +}); +) + +( +Ndef(\algo22bass).addSpec( + \freq, + \amp, + \op1_env1_atk, [0.0, 0.01], +).edit; +) \ No newline at end of file diff --git a/algorithmic.scd b/algorithmic.scd new file mode 100644 index 0000000..79f8931 --- /dev/null +++ b/algorithmic.scd @@ -0,0 +1,55 @@ +// Algorithmic + +( +Pbind( + \instrument, \fm_pulsar_terrain, + \dur, 0.25, + \midinote, Pseq([60, 63, 65], inf) + Prand([0, 5, 8], inf), + \amp, 0.1, + \rel, 0.8, +).play; +) + + +// J-Style pattern + +~base = [0, 3, 5]; +~transpose = [0, 5, 8]; + +( +Pbind( + \instrument, \fm_pulsar_terrain, + \dur, 0.25, + \midinote, Pseq(~base.collect(_ + 60), inf) + Prand(~transpose, inf), + \amp, 0.1, + \rel, 0.8 +).play; +) + + +~scale = [0, 3, 5]; + +( +Pbind( + \instrument, \fm_pulsar_terrain, + \dur, 0.25, + \midinote, Pfunc { ~scale.choose + 60 + [0, 5, 8].choose }, + \amp, 0.1, + \rel, 0.8 +).play; +) + + + + +~durs = [1, 0.5, 0.25].rotate(1).mirror1; + +( +Pbind( + \instrument, \fm_pulsar_terrain, + \dur, Pseq(~durs, inf), + \midinote, Pseq(~base.collect(_ + 60), inf) + Prand(~transpose, inf), + \amp, 0.1, + \rel, 0.8 +).play; +) diff --git a/alik_rustamoff_examples/5_wavetables.sc b/alik_rustamoff_examples/5_wavetables.sc new file mode 100644 index 0000000..9232c77 --- /dev/null +++ b/alik_rustamoff_examples/5_wavetables.sc @@ -0,0 +1,361 @@ + +( // run once to convert and resample wavetable files +var paths, file, data, n, newData, outFile; +paths = "/home/lcoogan/snd/wtables/AKWF/AKWF_0002/*.wav".pathMatch; +Routine({ + paths.do { |it i| + // 'protect' guarantees the file objects will be closed in case of error + protect { + // Read original size of data + file = SoundFile.openRead(paths[i]); + data = Signal.newClear(file.numFrames); + file.readData(data); + 0.1.wait; + // Convert to n = some power of 2 samples. + // n = data.size.nextPowerOfTwo; + n = 4096; + newData = data.resamp1(n); + 0.1.wait; + // Convert the resampled signal into a Wavetable. + // resamp1 outputs an Array, so we have to reconvert to Signal + newData = newData.as(Signal).asWavetable; + 0.1.wait; + + // save to disk. + outFile = SoundFile(paths[i] ++ "_4096.wtable") + .headerFormat_("WAV") + .sampleFormat_("float") + .numChannels_(1) + .sampleRate_(44100); + if(outFile.openWrite.notNil) { + outFile.writeData(newData); + 0.1.wait; + } { + "Couldn't write output file".warn; + }; + } { + file.close; + if(outFile.notNil) { outFile.close }; + }; + + } +}).play + +) + + +( // to be put to Platform.userConfigDir +/+ "startup.scd" + +~serverBootFunc = { |server| + + var wtsize, wtpaths, wtbuffers; + + "-----------wavetables begin-----------".postln; + + + wtsize = 4096; +wtpaths = "/home/lcoogan/snd/wtables/AKWF/AKWF_0002/*.wav_4096.wtable".pathMatch; + [wtpaths].postln; + wtbuffers = Buffer.allocConsecutive(wtpaths.size, s, wtsize * 2, 1, ); + wtpaths.do { |it i| wtbuffers[i].read(wtpaths[i])}; + + + ~wtbufnums = List[]; + ~wavetables = (); + + + wtpaths.do { |it i| + var name = wtbuffers[i].path.basename.findRegexp(".*\.wav")[0][1].splitext[0]; + var buffer = wtbuffers[i].bufnum; + ~wavetables[name.asSymbol] = buffer; + ~wtbufnums.add(buffer); + }; + + + "-----------wavetables end-----------".postln; +}; + +ServerBoot.add(~serverBootFunc, \default); +) + + + +( + +Spec.add(\bufn, ControlSpec(~wtbufnums.minItem, ~wtbufnums.maxItem, 'linear', 1, 0, "")); + +Spec.add(\wtmodbufn, \bufn); +Spec.add(\wtmodfreq,\widefreq); +Spec.add(\wtmodamp, [0,5]); + +Spec.add(\fmod, \bipolar); +Spec.add(\fmodbufn, \bufn); +Spec.add(\fltRange, \freq); +Spec.add(\res, \unipolar); +Spec.add(\driveDB, [-40,40,\lin,0,0.01,"dB"]); +) + +Ndef(\wtable_vosc_dual_t).edit + +~wtbufnums.postln; + + +( +Ndef(\wtable_vosc_dual_t, { + var env, freq; + var wtbufnumRange = [ ~wtbufnums.minItem, ~wtbufnums.maxItem ]; + var sig; + // var trg = Dust.kr(2); + var trg = Impulse.kr(0.5); + // trg = trg.lag(TRand.kr(0.0,0.2,trg)); + + + env = EnvGen.ar(Env.perc( + TRand.kr(0.2,1,trg), + TRand.kr(0.2,2,trg) + ), gate:trg).lag(0.1); + + + + // env = XFade2.ar(env,env * LFDNoise3.ar(env * 20 + 1).range(0,1), env*2-1); + + freq = TExpRand.kr(80,500,trg); + + sig = VOsc.ar( + ( + VOsc.ar(\wtmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.3), \wtmodfreq.kr(2), Rand(0,2pi), \wtmodamp.kr(1)) + + + env.pow(1.4) + + + \bufn.ar( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ) + ) .lag(1.8) .mod( wtbufnumRange[1] - wtbufnumRange[0] ) + wtbufnumRange[0], + freq + ) * env; + + + + sig!2 * 0.2 + +}).play + + +) + +(// low pass filtering the env +{ + [ + EnvGen.kr(Env.perc(0.02, 0.02)), + EnvGen.kr(Env.perc(0.02, 0.02)).lag(0.1) + ] +}.plot(0.1) +) + +({ // modulo plot +var a = Line.ar(8,150); +[ + a, + a.mod(107-8) +8 +] +}.plot(1)) + + + + + +Ndef(\wtable_vosc_dual_t_0).edit.nameView + +( +Ndef(\wtable_vosc_dual_t_0, {| vel=1| + var env, freq; + var wtbufnumRange = [ ~wtbufnums.minItem, ~wtbufnums.maxItem ]; + var sig; + var fenv; + var driveDB = \driveDB.kr(0); + var direct = \direct.kr(0.5); + // var trg = \trg.kr(1); + // var trg = Dust.kr(2); + var trg = Impulse.kr(1); + + + env = EnvGen.ar( + Env.adsr( + TExpRand.kr(0.001, 0.1, trg), + TExpRand.kr(0.001, 0.1, trg), + TExpRand.kr(0.1, 0.6, trg), + TExpRand.kr(1.5,4,trg), + curve: TRand.kr(-5.0,4,trg) + ), + gate:trg, + doneAction:0 + ).lag(0.1) * vel; + + + env = XFade2.ar(env,LFDNoise3.ar(env * 20 + 1).range(0,1), env*2-1); + + // env = env * WhiteNoise.ar(MouseX.kr(0,1)!2).range(0,1.0); + + // fenv = env * LFNoise0.kr(TRand.kr(1,21, trg)).range(0.5,1.4).lag(TRand.kr(0.0001,0.1, trg)); + fenv = env * VOsc.ar( + \fmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.4), + \fmodFreq.kr(11) + ).range(0.5,1.4) + .lag(TRand.kr(0.0001,0.01, trg)); + + + // freq = \freq.kr(111).lag(0.1); + // freq = LFNoise0.kr(1).exprange(80,1000).lag(0.1); + freq = TExpRand.kr(80,1000,trg); + + sig = VOsc.ar( + ( + VOsc.ar(\wtmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.3), \wtmodfreq.kr(2), Rand(0,2pi), \wtmodamp.kr(1)) + + + ( env * [ Rand(0.5,1.5), Rand(0.5,1.5) ]) + // ( env.pow(1.4) * [ LFNoise1.kr(3).range(1.5,9), LFNoise1.kr(3).range(1.5,9)] + 0.1) + + + \bufn.ar( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ) + ).lag(0.1).mod( wtbufnumRange[1] - wtbufnumRange[0] ) + wtbufnumRange[0], + freq + ) * env; + + sig = MoogVCF.ar( + sig * driveDB.dbamp, + XFade2.ar( env.pow(1.4), fenv.pow(1.4), \fmod.kr(0)) * \fltRange.kr(10000) + 50 , + \res.kr(0) + ); + + sig = sig * driveDB.neg.dbamp * 0.4; // compensate drive + + + sig * direct; + +}).play +) + + +( +SynthDef(\wtable_vosc_dual_t, {| vel=0.8| + var env, freq; + var wtbufnumRange = [ ~wtbufnums.minItem, ~wtbufnums.maxItem ]; + var sig; + var fenv; + var driveDB = \driveDB.kr(0); + var direct = \direct.kr(0.5).lag(0.2); + // var trg = \trg.kr(1); + var trg = Dust.kr(1); + // var trg = Impulse.kr(2); + + + env = EnvGen.ar( + Env.adsr( + TExpRand.kr(0.001, 0.1, trg), + TExpRand.kr(0.001, 0.1, trg), + TExpRand.kr(0.1, 0.6, trg), + TExpRand.kr(0.5,4,trg), + curve: TRand.kr(-5.0,4,trg)), + gate:trg, + doneAction:0 + ).lag(0.1) * vel; + + + env = XFade2.ar(env,env * LFDNoise3.ar(env * 20 + 1).range(0,1), env*2-1); + + // env = env * WhiteNoise.ar(MouseX.kr(0,1)!2).range(0,1.0); + + // fenv = env * LFNoise0.kr(TRand.kr(1,21, trg)).range(0.5,1.4).lag(TRand.kr(0.0001,0.1, trg)); + fenv = env * VOsc.ar( + \fmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.4), + // TRand.kr(1,21, trg) + \fmodFreq.kr(11) + ).range(0.5,1.4) + .lag(TRand.kr(0.0001,0.01, trg)); + + + freq = \freq.kr(111).lag(0.1); + // freq = LFNoise0.kr(1).exprange(80,1000).lag(0.1); + // freq = TExpRand.kr(80,1000,trg); + + sig = VOsc.ar( + ( + VOsc.ar(\wtmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.3), \wtmodfreq.kr(2), Rand(0,2pi), \wtmodamp.kr(1)) + + + // ( env * [ Rand(1.5,2), Rand(1.5,2) ]) + ( env.pow(1.4) * [ LFNoise1.kr(3).range(1.5,3), LFNoise1.kr(3).range(1.5,3)]) + + + \bufn.ar( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ) + ).lag(0.1).mod( wtbufnumRange[1] - wtbufnumRange[0] ) + wtbufnumRange[0], + freq + ) * env; + + sig = MoogVCF.ar( + sig * driveDB.dbamp, + XFade2.ar( env.pow(1.4), fenv.pow(1.4), \fmod.kr(0)) * \fltRange.kr(10000) + 50 , + \res.kr(0) + ); + + sig = sig * driveDB.neg.dbamp * 0.4; // compensate drive + + + Out.ar(\outBus.kr, sig * direct); + Out.ar(\effBus.kr, sig * (1-direct)) + + // }).play +}).add +) + + + + + +~reverbBus = Bus.audio(s,2); + + + + + +( +{ + var a; + + Ndef(\verb, {var a, n; + a = In.ar(~reverbBus, 2); + n = 8; + n.collect { |i| + a = AllpassC.ar( + a, + delaytime: LFNoise1.kr(0.03!2).range(0.01 , 0.02 * (i+1)), + // decaytime: n-i + decaytime: (i+1) + // decaytime: (n / 2 -i).abs + 0.1 + ).tanh + }.mean; + a + }).play; + + + a = [ + Synth(\wtable_vosc_dual_t, [\outBus, 0, \effBus, ~reverbBus, \bufn, ~wtbufnums.choose]), + Synth(\wtable_vosc_dual_t, [\outBus, 0, \effBus, ~reverbBus, \bufn, ~wtbufnums.choose]), + Synth(\wtable_vosc_dual_t, [\outBus, 0, \effBus, ~reverbBus, \bufn, ~wtbufnums.choose]), + // Synth(\wtable_vosc_dual_t, [\outBus, 0, \effBus, ~reverbBus, \bufn, ~wtbufnums.choose]), + ]; + + + + loop{ + a.choose.set( + \freq, ([0, 1, 2, 4, 5, 8, 11].choose + 60).midicps * 2.pow((-2..2).choose), + \wtmodfreq, exprand(1, 20), + // \wtmodamp, exprand(0.1,4).postln, + \fmod, rrand(-1.0,1), + // \fmodbufn, ~wtbufnums.choose, + \fmodFreq, exprand(2,20), + // \fltRange, rrand(1000,10000), + \vel, rrand(0.1,0.9), + \direct, rrand(0.1,0.6), + ); + 2.pow((-2..1).choose).wait; + } + +}.fork +) \ No newline at end of file diff --git a/bellFM.scd b/bellFM.scd new file mode 100644 index 0000000..7865416 --- /dev/null +++ b/bellFM.scd @@ -0,0 +1,119 @@ +~ir = Buffer.read(s, "/home/lcoogan/snd/ir/ForestScaleModel/ForestScaleModel/IR_ScaleModel/S1R1_ScaleModel.wav"); +~ir = Buffer.read(s, "/home/lcoogan/snd/ir/r1-nuclear-reactor-hall/stereo/r1_ortf-48k.wav"); + + +b = Buffer.read(s, "/home/lcoogan/snd/samples/scarlett/scarlett singing.wav"); +b.play; + +{Convolution.ar(b, ~ir)}.play; + + +s.options.memSize = 8192; + + +( +SynthDef(\bellFM, { + |freq = 440, amp = 0.1, gate = 1, ratioIndex = 0, out = 0, irBuf = 0, wet = 0.5, lfoRate = 20, lfoDepth = 1| + var car, mod, env, mFreq, mIndex, tunedFreq, tuning, dry, reverb, sig, lfo; + + tuning = [13/12, 55/48, 5/4, 65/48, 11/8, 143/96, 13/8, 5/3, 11/6, 2/1]; + tunedFreq = freq * Select.kr(ratioIndex.clip(0, tuning.size - 1), tuning); + + env = EnvGen.kr(Env.perc(0.01, 1.0, 1, 4), gate, doneAction: 2); + + mFreq = tunedFreq * 6.7; + mIndex = env * 5; + mod = Pulse.ar(mFreq) * (tunedFreq * mIndex); + dry = SinOsc.ar(tunedFreq + mod) * env * amp; + + // Initialize sig with the dry signal + // sig = dry; + + sig = + + // Create LFO and modulate + lfo = SinOsc.kr(lfoRate, 0, lfoDepth); // Low-frequency oscillator + + lfo = LFNoise0.kr(lfoRate * lfoDepth); + sig = sig + lfo; // Add LFO to the signal + + // Convolve and scale + reverb = Convolution2.ar(dry, ~ir, 512); + // Mix dry and wet signals + sig = XFade2.ar(dry, reverb, (wet * 2) + lfo); // -1 = all dry, +1 = all wet + + Out.ar(out, sig.dup); +}).add; +) + + +( +SynthDef(\pluckedSine, { + |out=0, freq=220, amp=0.4, decay=3, coef=0.5| + var trig, burst, pluck; + + trig = Impulse.kr(0); // trigger manually + + burst = SinOsc.ar(freq) * EnvGen.kr(Env.perc(0.001, 0.05), trig); + + pluck = Pluck.ar( + burst, + trig, + 0.2, // max delay time + 1 / freq, // delay time = 1 / freq + decay, + coef + ); + + Out.ar(out, pluck.dup * amp); +}).add; +) + + + +Synth(\bellFM, [\irBuf, ~ir.bufnum]); + + + + +Synth(\bellFM, [\freq, 440]); +Synth(\bellFM, [\freq, 660]); +Synth(\bellFM, [\freq, 550]); + + +( +SynthDef(\pluckedSine, { + |out = 0, freq = 220, amp = 0.4, decay = 3, coef = 0.5, wet = 0.5, lfoRate = 3, lfoDepth = 1, irBuf = 0| + var trig, burst, pluck, reverb, lfo, sig; + + trig = Impulse.kr(0); // trigger manually + + burst = LFSaw.ar(freq) * EnvGen.kr(Env.perc(0.001, 0.05), trig); + + pluck = Pluck.ar( + burst, + trig, + 0.2, // max delay time + 1 / freq, // delay time = 1 / freq + decay, + coef + ); + + // Initialize sig with the pluck signal + sig = pluck; + + // LFO modulation (Low-frequency noise oscillator) + lfo = LFNoise0.kr(lfoRate); // Low-frequency noise oscillator + sig = sig + lfo * lfoDepth; // Apply LFO to the signal + + // Convolve and scale + // reverb = Convolution2.ar(sig, irBuf, 512); // Apply convolution reverb + sig = XFade2.ar(sig, reverb, (wet * 2) + 0.1); // Mix dry and wet signals + + // sig = GVerb.ar(sig); + + // Output the signal + Out.ar(out, sig.dup); +}).add; +) + diff --git a/cantorial_deconstruction.scd b/cantorial_deconstruction.scd index ee312aa..577492c 100644 --- a/cantorial_deconstruction.scd +++ b/cantorial_deconstruction.scd @@ -1,17 +1,61 @@ -b = Buffer.read(s, "/Users/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/04-Cantor_Samuel_Malavsky_Zechor.wav"); b.play; +b = Buffer.read(s, "/home/lcoogan/Music/Musicians/My Bloody Valentine/Loveless/02 Loomer.wav"); + + +b = Buffer.read(s, "/home/lcoogan/Misc/my_grave.wav"); + +c = Buffer.read(s, "/home/lcoogan/Misc/loomer.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/releases/desolation-mountain/out.wav"); + + ( SynthDef(\brickwall, { arg out=0, bufnum, fftSize=4096; - var source, chain, sig; + var source, chain, sig, noise; + // + source = PlayBuf.ar(1, b, loop: 0, doneAction: 2); + // + chain = FFT(LocalBuf(fftSize), source); + chain = PV_BrickWall(chain, -0.95); + chain = PV_BrickWall(chain, 0.035); + // chain= PV_BrickWall(chain, Line.kr(-1,0,10)); + + + // chain = PV_BinDelay(chain, 0.01, 0.01, chain, chain, 0.5); + // chain = PV_BinScramble(chain, 0.1, 0.2, SinOsc.kr(1)); + // chain = PV_BrickWall(chain, -0.99); + // chain = PV_ConformalMap(chain, 0.1, Phasor.kr(8)); + // chain = PV_Conj(chain); + // chain = PV_Whiten(chain, b, 0.01, 0.5, Dust.kr(1), Dust.kr(0.5)); + chain = PV_MagAbove(chain, 10); + + // chain= chain.pvcollect(b.numFrames,{|mag, phase, index| + // noise= LFNoise1.kr(rrand(0.5,1.1)); + // [noise*mag,noise.range(-pi,pi)] + // + // }, + // + // frombin:0, tobin:10,zeroothers:1); - source = PlayBuf.ar(1, bufnum, loop: 0, doneAction: 2); - chain = FFT(LocalBuf(fftSize), source); - chain = PV_BrickWall(chain, -0.992); + + // chain = PV_MagBelow(chain, 40); + + // chain = PV_LocalMax(chain, 4); + + // chain = PV_MagSmear(chain, 4); sig = IFFT(chain); + + // sig = BPF.ar(sig, 4000, 0.1); + + /*sig = GVerb.ar(sig, 299, 4, 1, 0.5, 30, 1, 0.1, 0.5); + sig = Splay.ar(sig, 4);*/ + + Out.ar(out, sig.dup); + }).play; -) \ No newline at end of file +) diff --git a/fm pulsar wave terrain.scd b/fm pulsar wave terrain.scd index 3a4299e..6b7596d 100644 --- a/fm pulsar wave terrain.scd +++ b/fm pulsar wave terrain.scd @@ -88,33 +88,26 @@ MIDIdef.noteOff(\noteOffTest, { }); [ - [\freq, 0, 50, 4000], - [\amp, 1, 0.0, 1.5], - [\cf, 2, 0.1, 4.0], - [\mf, 3, 0.1, 4.0], - [\tblIndex, 4, 0.0, 1.0], - [\gain, 5, 0.01, 1.0], - [\att, 6, 0.001, 0.2], - [\dec, 7, 0.001, 0.2], - [\rel, 8, 0.1, 8.0], - [\susl, 9, 0.0, 1.0], - [\curve, 10, -8.0, 8.0], - [\kel, 11, 0.0, 1.0] + [\f0ratio, 0, 1], + [\f1ratio, 0, 1], + [\f2ratio, 0, 1], + [\modInd0, 0, 1], + [\modInd1, 0, 1], + [\modInd2, 0, 1], ].do { |spec| var param, cc, min, max; #param, cc, min, max = spec; MIDIdef.cc(param.asSymbol, { |val, num, chan, src| - if (chan == 2) { + if (chan == 0) { var mapped = val.linlin(0, 127, min, max); - ~pulsar.set(param, mapped); + \fm3mc_perc.set(param, mapped); } }, cc); }; ) -( + MIDIClient.init; MIDIIn.connectAll; -) \ No newline at end of file diff --git a/microtonality.scd b/microtonality.scd index 77b16b4..8755de3 100644 --- a/microtonality.scd +++ b/microtonality.scd @@ -4,7 +4,7 @@ SynthDef("sine_wave_non_et", { arg freq, amp, tuningRatio, outBus; - // Set up tuning - Just Intonation scale (can use different tuning ratios) + // Set up tuning - ET scale (can use different tuning ratios) var tuning = [ 33/32, 21/20, 11/10, 9/8, 7/6, 99/80, 77/60, 21/16, 11/8, 7/5, 231/160, 3/2, 63/40, 77/48, 33/20, 7/4, 9/5, 11/6, 77/40, 2/1]; // Example ratios for the 8-note scale diff --git a/midi for something.scd b/midi for something.scd new file mode 100644 index 0000000..65836bb --- /dev/null +++ b/midi for something.scd @@ -0,0 +1,74 @@ +MIDIIn.connectAll; + +~pulsar = 8388608; +~mellotron = 8388611; + +( + + +~notes = Array.newClear(128); // Initialize the array to store synths + +// Handle noteOn for MIDI device 8454149 (first device) +MIDIdef.noteOn(\noteOnTest_device1, { + arg vel, nn, chan, src; + [vel, nn, src].postln; // Post the velocity, note number, and source to thethe console + + // Only respond to MIDI input from source 8454149 (device 1) + if (src == ~pulsar, { + // Create a new synth for device 1 + ~notes[nn] = Synth.new( + \wtable_vosc_dual_clean, [ + \freq, nn.midicps, + \amp, vel.linexp(1,127,0.01,0.3), + ] + ); + }); +}); + +// Handle noteOff for MIDI device 8454149 (first device) +MIDIdef.noteOff(\noteOffTest_device1, { + arg vel, nn, chan, src; + [vel, nn, src].postln; + + // Only respond to MIDI input from source 8454149 (device 1) + if (src == ~pulsar, { + // Turn off the synth and free the memory for device 1 + ~notes[nn].set(\gate, 0); + ~notes[nn] = nil; + }); +}); + +// Handle noteOn for MIDI device 8454145 (second device) +MIDIdef.noteOn(\noteOnTest_device2, { + arg vel, nn, chan, src; + [vel, nn, src].postln; // Post the velocity, note number, and source to the console + + // Only respond to MIDI input from source 8454145 (device 2) + if (src == ~mellotron, { + // Create a new synth for device 2 + ~notes[nn] = Synth.new( + \mellotron, + [ + \freq, nn.midicps, + \amp, vel.linexp(1,127,0.01,0.3), + ] + ); + }); +}); + +// Handle noteOff for MIDI device 8454145 (second device) +MIDIdef.noteOff(\noteOffTest_device2, { + arg vel, nn, chan, src; + [vel, nn, src].postln; + + // Only respond to MIDI input from source 8454145 (dev + if (src == ~mellotron, { + // Turn off the synth and free the memory for device 2 + ~notes[nn].set(\gate, 0); + ~notes[nn] = nil; + }); +}); + +) + +MIDIIn.free; \ No newline at end of file diff --git a/midi for weeping.scd b/midi for weeping.scd index 326b5ea..5d6f0cf 100644 --- a/midi for weeping.scd +++ b/midi for weeping.scd @@ -1,17 +1,23 @@ +MIDIIn.connectAll; + +~pulsar = 8388610; +~mellotron = 8388611; + ( + + ~notes = Array.newClear(128); // Initialize the array to store synths // Handle noteOn for MIDI device 8454149 (first device) MIDIdef.noteOn(\noteOnTest_device1, { arg vel, nn, chan, src; - [vel, nn, src].postln; // Post the velocity, note number, and source to the console + [vel, nn, src].postln; // Post the velocity, note number, and source to thethe console // Only respond to MIDI input from source 8454149 (device 1) - if (src == 8454147, { + if (src == ~pulsar, { // Create a new synth for device 1 ~notes[nn] = Synth.new( - \mellotron, - [ + \fm_pulsar_terrain, [ \freq, nn.midicps, \amp, vel.linexp(1,127,0.01,0.3), ] @@ -25,10 +31,10 @@ MIDIdef.noteOff(\noteOffTest_device1, { [vel, nn, src].postln; // Only respond to MIDI input from source 8454149 (device 1) - if (src == 8454147, { + if (src == ~pulsar, { // Turn off the synth and free the memory for device 1 - ~notes[nn].set(\gate, 0); - ~notes[nn] = nil; + ~notes[nn].set(\gate, 0); + ~notes[nn] = nil; }); }); @@ -38,10 +44,10 @@ MIDIdef.noteOn(\noteOnTest_device2, { [vel, nn, src].postln; // Post the velocity, note number, and source to the console // Only respond to MIDI input from source 8454145 (device 2) - if (src == 8454146, { + if (src == ~mellotron, { // Create a new synth for device 2 ~notes[nn] = Synth.new( - \fm_pulsar_terrain, + \mellotron, [ \freq, nn.midicps, \amp, vel.linexp(1,127,0.01,0.3), @@ -55,12 +61,14 @@ MIDIdef.noteOff(\noteOffTest_device2, { arg vel, nn, chan, src; [vel, nn, src].postln; - // Only respond to MIDI input from source 8454145 (device 2) - if (src == 8454146, { + // Only respond to MIDI input from source 8454145 (dev + if (src == ~mellotron, { // Turn off the synth and free the memory for device 2 ~notes[nn].set(\gate, 0); ~notes[nn] = nil; }); }); -) \ No newline at end of file +) + +MIDIIn.free; \ No newline at end of file diff --git a/midi_helper.scd b/midi_helper.scd new file mode 100644 index 0000000..a3fb30c --- /dev/null +++ b/midi_helper.scd @@ -0,0 +1,51 @@ +~setupMidiForNdef = { |ndefName, midiChan = 0, ccMap| + var ndef = Ndef(ndefName); + + // Remove old defs if they exist + MIDIdef.noteOn((ndefName ++ "_On").asSymbol).clear; + MIDIdef.noteOff((ndefName ++ "_Off").asSymbol).clear; + MIDIdef.cc((ndefName ++ "_CC").asSymbol).clear; + + // Note on/off + MIDIdef.noteOn( + (ndefName ++ "_On").asSymbol, + { |vel, note, chan| + ndef.put( + note, + ndef.source, + 0, + [\freq, note.midicps, \gt, 1, \lev, vel / 127] + ); + }, + chan: midiChan + ).fix; + + MIDIdef.noteOff( + (ndefName ++ "_Off").asSymbol, + { |vel, note, chan| ndef.removeAt(note) }, + chan: midiChan + ).fix; + + // MIDI CC mapping + MIDIdef.cc( + (ndefName ++ "_CC").asSymbol, + { |val, num| + var param = ccMap[num]; + if (param.notNil) { + var spec = ndef.getSpec(param) ?? ControlSpec(0, 1); + ndef.set(param, spec.map(val / 127)); + }; + }, + ccNum: ccMap.keys, + chan: midiChan + ).fix; +}; + +~setupMidiForNdef.( + \, + 0, + ( + 0: \freq, 60; + ) +); + diff --git a/pads/mel.scd b/pads/mel.scd index 25a9397..4989efa 100644 --- a/pads/mel.scd +++ b/pads/mel.scd @@ -102,7 +102,8 @@ Pbind( \instrument, \mellotron, \freq, Pseq([ - // [65, 69, 71], // F Major (F, A, C) + + [65, 69, 71], // F Major (F, A, C) [80, 75,], [90, 70], [90, 70], diff --git a/phase modulation.scd b/phase modulation.scd new file mode 100644 index 0000000..f6ac75e --- /dev/null +++ b/phase modulation.scd @@ -0,0 +1,15 @@ +{max(SinOsc.ar(220), 0) !2}.play + + +( +SynthDef(\pm, { + var sig; + + sig = PMOsc.ar(\freq.ar(440), \modfreq.kr(0), \pmindex.kr(0), SinOsc.kr(\modphase.kr(1.0))); + + Out.ar(0, sig.dup); +}).add; + + +x = Synth(\pm, [\freq, 240, \modfreq, 20, \pmindex, 5, \modphase, 1]); +) \ No newline at end of file diff --git a/pluck.scd b/pluck.scd new file mode 100644 index 0000000..e6e632b --- /dev/null +++ b/pluck.scd @@ -0,0 +1,90 @@ +( +{ + var freq = 220; + var trig = Impulse.kr(1); // re-pluck every second + var burst = SinOsc.ar(freq) * EnvGen.kr(Env.perc(0.001, 0.05), trig); // short sine burst + Pluck.ar( + burst, + trig, + 0.2, // max delay time + 1/freq, // delay time = 1 / frequency + 3, // decay + 0.5 // damping + ) * 0.4; +}.play; +) + + + +( +SynthDef(\envPluckSine, { + |out=0, freq=220, amp=0.4, sustain=1.5| + var trig, env, sig; + + trig = Impulse.kr(1); // triggers every second + + env = EnvGen.kr(Env.perc(0.001, sustain), trig); + + sig = SinOsc.ar(freq) * env * amp; + + Out.ar(out, sig.dup); // stereo +}).add; +) + + + +( +SynthDef(\pluckedSine, { + |out=0, freq=220, amp=0.4, decay=3, coef=0.5| + var trig, burst, pluck; + + trig = Impulse.kr(0); // trigger manually + + burst = SinOsc.ar(freq) * EnvGen.kr(Env.perc(0.001, 0.05), trig); + + pluck = Pluck.ar( + burst, + trig, + 0.2, // max delay time + 1 / freq, // delay time = 1 / freq + decay, + coef + ); + + Out.ar(out, pluck.dup * amp); +}).add; +) + + + +( +~notes = Array.newClear(128); + +MIDIdef.noteOn(\noteOnTest, { + arg vel, nn, chan, src; + [vel, nn].postln; + + if (chan == 0, { + ~notes[nn] = Synth.new( + \prophet5style, + [ + \freq, nn.midicps, + \amp, vel.linexp(1,127,0.01,0.3), + // \gate, 1, + + ] + ); + }); +}); + +MIDIdef.noteOff(\noteOffTest, { + arg vel, nn, chan; + [vel, nn].postln; + + if (chan == 0, { + ~notes[nn].set(\gate, 0); + ~notes[nn] = nil; + }); +}); +) + diff --git a/prophet_v.scd b/prophet_v.scd new file mode 100644 index 0000000..8140122 --- /dev/null +++ b/prophet_v.scd @@ -0,0 +1,73 @@ +( +SynthDef(\prophet5style, { + |out=0, freq=440, amp=0.5, detune=0, osc1Wave=0, osc2Wave=1, filterCutoff=600, filterResonance=0.5, + attack=0.1, decay=1, sustain=0.7, release=0.3, lfoRate=0.5, lfoDepth=0.5, + lfoFreq=1, lfoWave=1, filterModDepth=0.3| + + // Oscillators + var osc1, osc2, lfo, env, filter, filteredSignal, drySignal; + + // Oscillator 1 & 2: Waveforms and detuning + osc1 = Select.ar(osc1Wave, [SinOsc.ar(freq), Saw.ar(freq), Pulse.ar(freq, 0.5)]); + osc2 = Select.ar(osc2Wave, [SinOsc.ar(freq + detune), Saw.ar(freq + detune), Pulse.ar(freq + detune, 0.5)]); + + // Envelope + env = EnvGen.kr(Env.perc(attack, decay, sustain, release), doneAction: 2); + + // LFO for modulation (filter or other params) + lfo = SinOsc.kr(lfoRate, 0, lfoDepth); + + // Filter + // filter = osc1 + osc2; + filter = BPF.ar(osc1 + osc2, filterCutoff, filterResonance); + + filteredSignal = filter * env; + + // Modulate filter with LFO + filteredSignal = filteredSignal * (1 + lfo * filterModDepth); + + // Dry signal (unfiltered) + drySignal = (osc1 + osc2) * env; + + // Output mixed signal + Out.ar(out, (filteredSignal + drySignal).dup * amp); +}).add; +) + +MIDIClient.init; +MIDIIn.connectAll; + +x = Synth(\prophet5style); + + + + +// Mapping MIDI CCs to synth parameters +( +~midiMap = { + |num, val| + var osc1Wave, osc2Wave, release, cutoff, resonance; + + // Conditional mappings for parameters + osc1Wave = num == 1 ifTrue: { val.linlin(0, 127, 0, 2).round } ifFalse: { 0 }; + osc2Wave = num == 2 ifTrue: { val.linlin(0, 127, 0, 2).round } ifFalse: { 0 }; + release = num == 8 ifTrue: { val.linlin(0, 127, 0.01, 3) } ifFalse: { 0.3 }; + cutoff = num == 74 ifTrue: { val.linlin(0, 127, 20, 2000) } ifFalse: { 1000 }; + resonance = num == 71 ifTrue: { val.linlin(0, 127, 0, 1) } ifFalse: { 0.5 }; + + // Return a dictionary with mapped parameters + ^( + \osc1Wave -> osc1Wave, + \osc2Wave -> osc2Wave, + \release -> release, + \cutoff -> cutoff, + \resonance -> resonance + ); +}; +) + +// Use the midi map to update synth parameters +MIDIIn.control = { |num, val| + var mappedParams = ~midiMap.(num, val); + Synth(\prophet5styleModular, mappedParams); +}; diff --git a/vocal_obfuscation.scd b/vocal_obfuscation.scd index 97abfbb..2f822cf 100644 --- a/vocal_obfuscation.scd +++ b/vocal_obfuscation.scd @@ -1,22 +1,17 @@ -b = Buffer.read(s, "/Users/lcoogan/snd/installation/zeitlin-six_lines.wav"); +b = Buffer.read(s, "/home/lcoogan/snd/installation/zeitlin-six_lines.wav"); ( SynthDef(\voiceObscured, { arg out=0, bufnum, rate=1, shift=0, cutoff=1200, amp = 40; var sig; sig = PlayBuf.ar(1, bufnum, BufRateScale.kr(bufnum) * rate, doneAction: 2); - sig = NoiseRepellent.ar(sig, learner:NRAverage(\isLearning.kr(0))); - - sig = PitchShift.ar(sig, 0.2, 2.pow(shift / 12), 0.01, 0.01); - sig = LPF.ar(sig, cutoff); // soften sibilance - // sig = BPF.ar(sig, 60, 0.001).neg + sig; // cancels 60Hz hum - // sig = BPF.ar(sig, 120, 0.001).neg + sig; // cancels 2nd harmonic - + // sig = NoiseRepellent.ar(sig, learner:NRAverage(\isLearning.kr(0)), reductionAmount:40); + sig = HPF.ar(sig, cutoff); // soften sibilance sig = sig * amp ; Out.ar(out, sig.dup); }).add; ) -Synth(\voiceObscured, [\bufnum, b, \shift, -7, \cutoff, 1000, \amp, 40]); -Synth(\voiceObscured, [\isLearning, 1]); // capture some noise -Synth(\voiceObscured, [\isLearning, 0]); // start the script \ No newline at end of file +x = Synth(\voiceObscured, [\bufnum, b, \amp, 60]); +x.set(\isLearning, 1); // capture some noise +x.set(\isLearning, 0); // start the script \ No newline at end of file diff --git a/wavetables.scd b/wavetables.scd new file mode 100644 index 0000000..eb36db8 --- /dev/null +++ b/wavetables.scd @@ -0,0 +1,123 @@ +( +// Run once to convert and resample wavetable files +var paths, file, data, n, newData, outFile; + +paths = PathName("/home/lcoogan/snd/wtables/AKWF").deepFiles.select { |f| + f.extension == "wav" +}; + +Routine({ + paths.do { |path, i| + var outputPath; + + // 'protect' ensures file cleanup on error + protect { + // Read original data + file = SoundFile.openRead(path.fullPath); + data = Signal.newClear(file.numFrames); + file.readData(data); + 0.1.wait; + + // Resample to n = 4096 samples (power of 2) + n = 4096; + newData = data.resamp1(n).as(Signal).asWavetable; + 0.1.wait; + + // Generate output file path + outputPath = path.fullPath ++ "_4096.wtable"; + + // Write to disk + outFile = SoundFile(outputPath) + .headerFormat_("WAV") + .sampleFormat_("float") + .numChannels_(1) + .sampleRate_(44100); + + if(outFile.openWrite.notNil) { + outFile.writeData(newData); + 0.1.wait; + } { + "Couldn't write output file: %".format(outputPath).warn; + }; + } { + file.close; + if(outFile.notNil) { outFile.close }; + }; + }; +}).play; +) + + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +( +SynthDef(\wtable_vosc_dual_t_0, {| vel=1| + var env, freq; + var wtbufnumRange = [ ~wtbufnums.minItem, ~wtbufnums.maxItem ]; + var sig; + var fenv; + var driveDB = \driveDB.kr(0); + var direct = \direct.kr(0.5); + // var trg = \trg.kr(1); + // var trg = Dust.kr(2); + var trg = Impulse.kr(1); + + + env = EnvGen.ar( + Env.adsr( + TExpRand.kr(0.001, 0.1, trg), + TExpRand.kr(0.001, 0.1, trg), + TExpRand.kr(0.1, 0.6, trg), + TExpRand.kr(1.5,4,trg), + curve: TRand.kr(-5.0,4,trg) + ), + gate:trg, + doneAction:0 + ).lag(0.1) * vel; + + + env = XFade2.ar(env,LFDNoise3.ar(env * 20 + 1).range(0,1), env*2-1); + + // env = env * WhiteNoise.ar(MouseX.kr(0,1)!2).range(0,1.0); + + // fenv = env * LFNoise0.kr(TRand.kr(1,21, trg)).range(0.5,1.4).lag(TRand.kr(0.0001,0.1, trg)); + fenv = env * VOsc.ar( + \fmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.4), + \fmodFreq.kr(11) + ).range(0.5,1.4) + .lag(TRand.kr(0.0001,0.01, trg)); + + + freq = \freq.kr(111).lag(0.1); + // freq = LFNoise0.kr(1).exprange(80,1000).lag(0.1); + // freq = TExpRand.kr(80,1000,trg); + + sig = VOsc.ar( + ( + VOsc.ar(\wtmodbufn.kr( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ).lag(0.3), \wtmodfreq.kr(2), Rand(0,2pi), \wtmodamp.kr(1)) + + + ( env * [ Rand(0.5,1.5), Rand(0.5,1.5) ]) + // ( env.pow(1.4) * [ LFNoise1.kr(3).range(1.5,9), LFNoise1.kr(3).range(1.5,9)] + 0.1) + + + \bufn.ar( rrand( wtbufnumRange[0],wtbufnumRange[1] ) ) + ).lag(0.1).mod( wtbufnumRange[1] - wtbufnumRange[0] ) + wtbufnumRange[0], + freq + ) * env; + + sig = MoogVCF.ar( + sig * driveDB.dbamp, + XFade2.ar( env.pow(1.4), fenv.pow(1.4), \fmod.kr(0)) * \fltRange.kr(10000) + 50 , + \res.kr(0) + ); + + sig = sig * driveDB.neg.dbamp * 0.4; // compensate drive + + + sig * direct; + + Out.ar(0, sig); + +}).add; +) diff --git a/wavetables/wtable_vosc_dual_clean.scd b/wavetables/wtable_vosc_dual_clean.scd new file mode 100644 index 0000000..a465304 --- /dev/null +++ b/wavetables/wtable_vosc_dual_clean.scd @@ -0,0 +1,55 @@ +( +SynthDef(\wtable_vosc_dual_clean, { |freq = 440, vel = 1, gate = 1, amp = 0.5, driveDB = 0, fmod = 0, res = 0.6, fltRange = 6000, direct = 1| + + var env, sig, wtbufnum, wtbufnMod, osc, modOsc, fenv; + var wtbufnumRange = [ ~wtbufnums.minItem, ~wtbufnums.maxItem ]; + + // Standard ADSR Envelope + env = EnvGen.kr( + Env.adsr(0.1, 0.5, 0.6, 1, peakLevel:1.0, curve:-1.0, bias:0.0), + gate, + doneAction: 2 + ) * vel; + + // Select a wavetable buffer in range + wtbufnum = \bufn.kr(wtbufnumRange[0]); + + // Optional modulation oscillator (wavetable-based) + modOsc = VOsc.ar( + \wtmodbufn.kr(wtbufnumRange[0]), + \wtmodfreq.kr(2), + \modPhase.kr(0), + \wtmodamp.kr(1) + ); + + // Main oscillator using VOsc + osc = VOsc.ar( + wtbufnum, + freq + ); + + // Optional filtered modulation of the filter cutoff + fenv = VOsc.ar( + \fmodbufn.kr(wtbufnumRange[0]), + \fmodFreq.kr(0) + ).range(0.5, 1.5); + + // Apply envelope and optional distortion/filtering + sig = osc * env; + sig = RLPF.ar( + sig * driveDB.dbamp, + (freq * fenv).clip(40, fltRange), + res + ); + + sig = Resonz.ar(sig, Line.kr(200, 840), bwr:Line.kr(0.5, 0.1), mul:1.0, add:0.0); + sig = CombL.ar(sig, maxdelaytime:0.8, delaytime:0.5, decaytime:0.5, mul:1.0, add:0.0); + + // Final level and output + sig = sig * amp * direct; + + + Out.ar(0, sig.dup); + +}).add; +) diff --git a/working_wavetable.scd b/working_wavetable.scd new file mode 100644 index 0000000..944f201 --- /dev/null +++ b/working_wavetable.scd @@ -0,0 +1,195 @@ +( +SynthDef(\wtable_vosc_dual, { + var env, sig, freq, buf, wtmod, wtpos; + + var wtbufnumRange = [ ~wtbufnums.minItem, ~wtbufnums.maxItem ]; + + // Main controls + var gate = \gate.kr(1); + freq = \freq.kr(120) / 2; + buf = \bufn.kr(wtbufnumRange[2]); + wtmod = \wtmodbufn.kr(wtbufnumRange[2]); + + // Envelope + env = EnvGen.kr( + Env.adsr( + \attack.kr(0.1), + \decay.kr(0.2), + \sustain.kr(3.0), + \release.kr(1.0) + ), + gate, + doneAction: 2 + ).lag(\envLag.kr(0.1)); + + + wtpos = ( + VOsc.ar(wtmod, \wtmodfreq.kr(0), \phase.kr(0), \wtmodamp.kr(1) + ) + + env.pow(1.4) + + buf + ).lag(1.8) + .mod(wtbufnumRange[1] - wtbufnumRange[0]) + + wtbufnumRange[0]; + + sig = VOsc.ar(wtpos, freq, \phase.kr(0), 1) * env * \amp.kr(0.2); + + // sig = BPF.ar(sig, \lpf.ar(800), \q.ar(1.0)); + sig = BLowShelf.ar(sig, \lpf.ar(800), \q.ar(1.0)); + + sig = AllpassN.ar(sig, 1, 1, 1); + + Out.ar(\out.kr(0), sig ! 2); +}).add; +) + +x = Synth(\wtable_vosc_dual, [\freq, 70.midicps]); + + +( +Pbind( + \instrument, \wtable_vosc_dual, // Choose SynthDef + \amp, Pwhite(0.2, 0.8, inf), // Random amplitude (0.2 to 0.8) + /* \mod1, Pwhite(5, 40, inf), // Random mod1 value (5 to 40) + \mod2, Pwhite(0.01, 0.3, inf), // Random mod2 value (0.01 to 0.3) + \mod3, Pwhite(1, 10, inf), // Random mod3 value (1 to 10) + \mod4, Pwhite(0.1, 0.8, inf), // Random mod4 value (0.1 to 0.8) + \mod5, Pwhite(0.01, 0.4, inf), // Random mod5 value (0.01 to 0.4)*/ + \freq, Pwhite(40, 70, inf), + \dur, Pseq([1], inf) // Sequence of durations +).play; +) + + +( +~chords = ( + "Csus4": [0, 5, 7], // Root, fourth, fifth + "Cmaj7": [0, 4, 7, 11], + "Cmin7": [0, 3, 7, 10], + "C5": [0, 7], // Power chord + "C": [0, 4, 7] +); +) + +( +~chords = ( + \Csus4: [0, 5, 7], + \Cmaj7: [0, 4, 7, 11], + \Cmin7: [0, 3, 7, 10], + \C5: [0, 7], + \C: [0, 4, 7] +); +) + + + +( +Pbind( + \instrument, \wtable_vosc_dual, + \amp, 0.5, + \dur, 1, + \midinote, Pseq([ + ~chords["Csus4"] + 60, // Transpose to MIDI note 60 (C4) + ].flat, inf) +).play; +) + + +x = Synth(\wtable_vosc_dual [\freq, Pseq((~chords["Csus4"] + 60).midicps, inf)]); + + +( +~chords = ( + \Csus4: [[2, 4]], + \Cmaj7: [[0, 4, 7, 11]], + \Cmin7: [[0, 3, 7, 10]], + \C5: [[0, 7]], + \C: [[0, 4, 7]] +); + +Pbind( + \instrument, \wtable_vosc_dual, + \amp, 0.4, + \dur, Pwhite(0.4, 0.8), + // add freq ratio + \midinote, Pwhite(40, 80), + // \midinote, Pseq((~chords[\Cmin7, ~chords[\Cmaj7]] + 60), inf) +).play; +) + +( +~chords = ( + /*\Csus4: [[ 3, 5]], + // \Cmaj7: [0, 1, 3, 7], + \Cmin7: [[3, 7]], + \whatever: [3, 5], + \whateer: [12, 15],*/ + + \Fm: [[0, 3, 7]], + \Bbm: [[-1, 2, 6]], // Relative to C + \F: [[0, 4, 7]], + \Eb: [[-4, 0, 3]], + \Ebm: [[-4, -1, 3]] + + +/* \C5: [0, 7], + \C: [0, 4, 7],*/ +); + +~chordKeys = ~chords.keys; + +Pbind( + \instrument, \wtable_vosc_dual, + \amp, 0.4, + \dur, Pwhite(0.1, 1), + \midinote, Pfunc({ + var chordName = ~chordKeys.choose; // Randomly pick a chord + var chord = ~chords[chordName]; // Get its intervals + var note = chord.choose + 60; // Pick one and transpose + note; + }), + \attack, Pwhite(0.01, 0.1), + \decay, Pwhite(0.1, 0.3), + \sustain, Pwhite(0.2, 0.8), + \release, Pwhite(0.1, 2.0), + \lpf, Pwhite(800, 2000), + \q, Pwhite(0.3, 1.0), +).play; +) + + +( +~freygish = [0, 1, 4, 5, 7, 8, 10]; // Freygish scale in C +~root = 60; // Middle C + +Pbind( + \instrument, \wtable_vosc_dual, + \amp, 0.4, + \dur, Pwhite(1, 2), + \midinote, Pfunc({ + ~root + ~freygish.choose; + }) +).play; +) + + + +( +~chords = ( + \Csus4: [0, 5, 7], + \Cmaj7: [0, 4, 7, 11], + \Cmin7: [0, 3, 7, 10], + \C5: [0, 7], + \C: [0, 4, 7] +); + +Pbind( + \instrument, \wtable_vosc_dual, + \amp, 0.4, + \dur, 1, + \midinote, Pcollect( + Pseq([\Cmin7, \Cmaj7, \C5], inf), // sequence of chord names + { |chordName| ~chords[chordName] + 60 } // map to MIDI notes + ) +).play; +) diff --git a/wt_exposed.scd b/wt_exposed.scd new file mode 100644 index 0000000..8ac89a9 --- /dev/null +++ b/wt_exposed.scd @@ -0,0 +1,41 @@ +( +SynthDef(\wtable_vosc_dual, { + var env, sig, freq, buf, wtmod, wtpos; + + var wtbufnumRange = [ ~wtbufnums.minItem, ~wtbufnums.maxItem ]; + + // Main controls + var gate = \gate.kr(1); + freq = \freq.kr(220); + buf = \bufn.kr(wtbufnumRange[0]); + wtmod = \wtmodbufn.kr(wtbufnumRange[1]); + + // Envelope + env = EnvGen.kr( + Env.perc( + \attack.kr(0.1), + \release.kr(1.0) + ), + gate, + doneAction: 2 + ).lag(\envLag.kr(0.1)); + + // Wavetable oscillator modulation + wtpos = VOsc.ar( + wtmod, + \wtmodfreq.kr(2), + \phase.kr(0), + \wtmodamp.kr(1) + ) + + env.pow(1.4) + + buf; + + wtpos = wtpos.lag(1.8).mod(wtbufnumRange[1] - wtbufnumRange[0]) + wtbufnumRange[0]; + + // Final signal + sig = VOsc.ar(wtpos, freq, \phase.kr(0), 1) * env * \amp.kr(0.2); + + // Output + Out.ar(\out.kr(0), sig ! 2); +}).add; +)