From 0aed7d5205443fff0d85c0acf50e4e9751f709eb Mon Sep 17 00:00:00 2001 From: Leo Coogan Date: Sun, 30 Mar 2025 00:05:29 -0400 Subject: [PATCH] show prep wip --- 808.scd | 32 ++-- convolution.scd | 3 + .../og.granular_EF-edit.scd | 78 +++++++++ girder.scd | 16 ++ granular leftovers.scd | 114 +++++++++++++ granular.scd | 159 +++++++++++++++++ juno.scd | 34 ++++ live/additive practice.scd | 77 +++++++++ live/granular_EF-edit.scd | 113 +++++++++++++ live/olson.scd | 19 +++ live/tr08 EF-edit.scd | 160 ++++++++++++++++++ my world.scd | 77 +++++++++ padsynth practice EF-edit.scd | 95 +++++++++++ padsynth practice.scd | 130 +++----------- random.scd | 7 + taste of freedom.scd | 26 +++ tr08.scd | 95 +++++++++++ 17 files changed, 1117 insertions(+), 118 deletions(-) create mode 100644 convolution.scd create mode 100644 eli_fieldsteel_examples/og.granular_EF-edit.scd create mode 100644 girder.scd create mode 100644 granular leftovers.scd create mode 100644 granular.scd create mode 100644 juno.scd create mode 100644 live/additive practice.scd create mode 100644 live/granular_EF-edit.scd create mode 100644 live/olson.scd create mode 100644 live/tr08 EF-edit.scd create mode 100644 my world.scd create mode 100644 padsynth practice EF-edit.scd create mode 100644 random.scd create mode 100644 taste of freedom.scd create mode 100644 tr08.scd diff --git a/808.scd b/808.scd index d45014d..6bdf37c 100644 --- a/808.scd +++ b/808.scd @@ -9,22 +9,22 @@ MIDIIn.connectAll; ~sampleDir = PathName("~/snd/samples/808/").fullPath; ~samples = ( - 42: Buffer.read(s, ~sampleDir +/+ "Cls'dHihat.wav"), - 46: Buffer.read(s, ~sampleDir +/+ "OpenHiHat.wav"), - 49: Buffer.read(s, ~sampleDir +/+ "CYmbal.wav"), - 56: Buffer.read(s, ~sampleDir +/+ "CowBell.wav"), - 39: Buffer.read(s, ~sampleDir +/+ "handClaP.wav"), - 37: Buffer.read(s, ~sampleDir +/+ "RimShot.wav"), - 50: Buffer.read(s, ~sampleDir +/+ "HiTom.wav"), - 47: Buffer.read(s, ~sampleDir +/+ "MidTom.wav"), - 43: Buffer.read(s, ~sampleDir +/+ "LowTom.wav"), - 38: Buffer.read(s, ~sampleDir +/+ "SnareDrum.wav"), - 36: Buffer.read(s, ~sampleDir +/+ "BassDrum.wav"), - 70: Buffer.read(s, ~sampleDir +/+ "MAracas.wav"), - 75: Buffer.read(s, ~sampleDir +/+ "CLaves.wav"), - 62: Buffer.read(s, ~sampleDir +/+ "HiConga.wav"), - 63: Buffer.read(s, ~sampleDir +/+ "MidConga.wav"), - 64: Buffer.read(s, ~sampleDir +/+ "LowConga.wav") + 42: Buffer.read(s, ~sampleDir +/+ "ch.wav"), + 46: Buffer.read(s, ~sampleDir +/+ "oh.wav"), + 49: Buffer.read(s, ~sampleDir +/+ "cy.wav"), + 56: Buffer.read(s, ~sampleDir +/+ "cb.wav"), + 39: Buffer.read(s, ~sampleDir +/+ "cp.wav"), + 37: Buffer.read(s, ~sampleDir +/+ "rs.wav"), + 50: Buffer.read(s, ~sampleDir +/+ "ht.wav"), + 47: Buffer.read(s, ~sampleDir +/+ "mt.wav"), + 43: Buffer.read(s, ~sampleDir +/+ "lt.wav"), + 38: Buffer.read(s, ~sampleDir +/+ "sd.wav"), + 36: Buffer.read(s, ~sampleDir +/+ "bd.wav"), + 70: Buffer.read(s, ~sampleDir +/+ "ma.wav"), + 75: Buffer.read(s, ~sampleDir +/+ "cl.wav"), + 62: Buffer.read(s, ~sampleDir +/+ "hc.wav"), + 63: Buffer.read(s, ~sampleDir +/+ "mc.wav"), + 64: Buffer.read(s, ~sampleDir +/+ "lc.wav") ); ); diff --git a/convolution.scd b/convolution.scd new file mode 100644 index 0000000..ec4fd97 --- /dev/null +++ b/convolution.scd @@ -0,0 +1,3 @@ +// var ir = Buffer.read(s, "/home/lcoogan/snd/ir/ForestScaleModel/ForestScaleModel/IR_ScaleModel/S1R1_ScaleModel.wav"); // Load an impulse response file + +// sig = Convolution2.ar(sig, ir, 512) * 0.5; // Apply convolution reverb with buffer size 512''' \ No newline at end of file diff --git a/eli_fieldsteel_examples/og.granular_EF-edit.scd b/eli_fieldsteel_examples/og.granular_EF-edit.scd new file mode 100644 index 0000000..2638ebb --- /dev/null +++ b/eli_fieldsteel_examples/og.granular_EF-edit.scd @@ -0,0 +1,78 @@ + + +// Don't touch! + +~klezmer = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Acheinu_Kol_Beit_Israel.wav", channels:[0]); + + +b = Buffer.read(s,"/Users/eli/Sounds/scaudio/groh/metal/metalPipe/metalPipeLow02.aiff"); + +( +x = { + var sig; + sig = GrainBuf.ar( + numChannels: 2, + trigger: Impulse.kr(2), + dur: 1, + sndbuf: b, + rate: \trnsp.kr(0).midiratio, + pos: 0.1, + interp: 2, + pan: 0, + envbufnum: -1, + maxGrains: 512 + ); + // sig = sig * 10; +}.play; +) + +x.set(\trnsp, 12) +x.free; + +( +{ + var sig; + sig = GrainBuf.ar( + 1, + Dust.ar(40), + 0.8, + ~klezmer, + 1, + 1.25, + 2, + 0, + -1, + 512 + ); + + sig = sig!2; +}.play; +) + + + + + + +~klezmer = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Acheinu_Kol_Beit_Israel.wav", channels:[0]); +~klezmer = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Cantor_Samuel_Malavsky_Zechor.wav", channels:[0]); +~klezmer = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/yiddish_chuasdel.wav", channels:[0]); + + + +( +// MIDI sequencing by MIDI file + +var m1, m2, x1, x2; + +// Read each MIDI file separately +m1 = SimpleMIDIFile.read("/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-borrowed flesh/midi/fuzzy gameboy.mid"); +m2 = SimpleMIDIFile.read("/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-borrowed flesh/midi/pad organ.mid"); + +// Play both MIDI sequences simultaneously +x1 = m1.p(\granular).play; +x2 = m2.p(\granular).play; + +// Store them in a global variable so you can stop them later +~midiPlayers = [x1, x2]; +) \ No newline at end of file diff --git a/girder.scd b/girder.scd new file mode 100644 index 0000000..b3c20ac --- /dev/null +++ b/girder.scd @@ -0,0 +1,16 @@ +( + +x = { + + var sig = WhiteNoise.ar(1!2); + + sig = CombL.ar(sig, 0.05, 1/[36.7, 37.3], 1, 0.2); + + sig = sig.blend(BPF.ar(sig, 1500, 0.5), 0.9); + +}.play(fadeTime: 2); + +) + + +x.release; \ No newline at end of file diff --git a/granular leftovers.scd b/granular leftovers.scd new file mode 100644 index 0000000..413cc8a --- /dev/null +++ b/granular leftovers.scd @@ -0,0 +1,114 @@ +// Granular leftovers from granular_EF-edit.scd + + +// Transposition. Doesn't sound good, not readily controllable from an artistic perspective. + +~klezmer = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Acheinu_Kol_Beit_Israel.wav", channels:[0]); + +( +x = { + arg amp = 0.1; + var sig; + sig = GrainBuf.ar( + numChannels: 2, + trigger: Impulse.kr(1), + dur: 1, + sndbuf: ~klezmer, + rate: \trnsp.kr(0).midiratio, + pos: 0.1, + interp: 2, + pan: 0, + envbufnum: -1, + maxGrains: 512 + ); + sig = sig; +}.play; +) + +x.set(\trnsp, 20) +x.free; + + + +( +// MIDI + +MIDIClient.init; +MIDIIn.connectAll; +) + +( +~notes = Array.newClear(128); + + +// Handle MIDI note on (when a note is pressed) +MIDIdef.noteOn(\noteOnTest, { + arg vel, nn, chan, src; + // Post the velocity and note for debugging + // [vel, nn].postln; + + // Create a Synth for the note with the correct argument names + ~notes[nn] = Synth.new( + \granular, + [ + \note, nn, // Use \note, not \freq + \amp, vel.linexp(1, 127, 0.01, 0.3), // Map velocity to amplitude + \gate, 1, // Trigger the envelope + ] + ); +}); + +// Handle MIDI note off (when a note is released) +MIDIdef.noteOff(\noteOffTest, { + arg vel, nn; + // Set gate to 0 to stop the sound + ~notes[nn].set(\gate, 0); + // Clear the reference to the Synth object for the note + ~notes[nn] = nil; +}); +) + + +( +~granularSynth = Synth(\granular, [ + \note, 60, // C4 + // \dur, 1, + \pan, 0 +]); +) + + +( +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Cantor_Samuel_Malavsky_Zechor.wav"); + +( +SynthDef(\cantorial_tremolo, { + |out, pan = 0, dur = 0.1, atk=0.3, dec=0.4, sus=0.1, rel=0, amp=1, crf=1200| + var sig, rate, env, filter; + + env = EnvGen.ar( + Env.new( + [0, 1, 1, 0], + [atk, dec, sus, rel], + ), + gate: 1, + doneAction: 2 + ); + sig = GrainBuf.ar( + numChannels: 2, + trigger: Impulse.kr(10), + dur: dur, + sndbuf: b, + rate: 1, + pos: 0.1, + interp: 2, + pan: pan, + envbufnum: -1, + maxGrains: 512 + ); + sig = sig * env * amp; + filter = MoogVCF.ar(sig, crf, 0.3); + Out.ar(out, filter); +}).play; +) +) diff --git a/granular.scd b/granular.scd new file mode 100644 index 0000000..b6ea627 --- /dev/null +++ b/granular.scd @@ -0,0 +1,159 @@ +~klezmer = "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Acheinu_Kol_Beit_Israel.wav" + +( +{ + var sig; + sig = GrainBuf.ar( + 1, + Impulse.ar(2), + 1, + ~klezmer, + 1, + 1.2, + 1, + 0, + -1, + 512 + ); + + sig = sig!2; +}.play; +) + +( +{ + var sig; + sig = GrainBuf.ar( + 1, + Dust.ar(40), + 0.8, + ~klezmer, + 1, + 1.25, + 2, + 0, + -1, + 512 + ); + + sig = sig!2; +}.play; +) + + + +~organ = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Cantor_Samuel_Malavsky_Zechor.wav"); + +( +{ + var sig; + sig = TGrains2 +}) + + + + + + +~klezmer = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Acheinu_Kol_Beit_Israel.wav", channels:[0]); +~klezmer = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Cantor_Samuel_Malavsky_Zechor.wav", channels:[0]); +~klezmer = Buffer.readChannel(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/yiddish_chuasdel.wav", channels:[0]); + + +( +SynthDef(\granular, { + arg freq = 410, amp = 4, pan = 0, gate = 1, baseFreq = 600, lpfFreq = 8000, rq = 0.3, drive = 1, pitchRatio = 1; + var sig, env, trig, waveshapedSig, filteredSig, shiftedSig; + + trig = Impulse.kr(10, 0.5, 1.0, 0.0) + Dust.kr(1); // Regular grain trigger + env = EnvGen.kr(Env.adsr(0, 0.2, 0.4, 1), gate, doneAction: 2); + + // Random panning for each grain + pan = 0; + + // Granular synthesis without internal rate control (rate = 1) + sig = GrainBuf.ar( + 1, + trig, + 0.8, + ~klezmer, + 1, + 1.25, + 2, + 0, + -1, + 512 + ) * env; + + // Apply pitch shifting externally + shiftedSig = PitchShift.ar(sig, 0.2, 580 / baseFreq); // Shifting the pitch after the grain is generated + + // Apply waveshaper: Tanh saturation (soft clipping) + waveshapedSig = (shiftedSig * drive).tanh; + + // Apply a resonant low-pass filter + filteredSig = SVF.ar(waveshapedSig, lpfFreq, rq); + + // Apply panning and amplitude + filteredSig = Pan2.ar(filteredSig, pan) * amp; + + // Output the final signal + Out.ar(0, filteredSig); +}).play; +) + + + + + +( +SynthDef(\granular, { + arg freq = 400, amp = 1, pan = 8, gate = 1, baseFreq = 600; + var sig, env, trig, rate; + + trig = Impulse.kr(10); // Regular grain trigger + env = EnvGen.kr(Env.adsr(0, 0.4, 0.8, 1), gate, doneAction: 2); + + // Rate scales playback relative to a known base frequency of the buffer + rate = freq / baseFreq; + + // Random panning for each grain + pan = LFNoise1.kr(8); + + sig = GrainBuf.ar( + 1, + trig, + 0.8, + ~klezmer, + rate, // Control pitch via rate + 1.25, + 2, + 0, + -1, + 512 + ) * amp * env; + + sig = Pan2.ar(sig, pan); + + Out.ar(0, sig); +}).play; +) + + + +( +// MIDI sequencing by MIDI file + +var m1, m2, x1, x2; + +// Read each MIDI file separately +m1 = SimpleMIDIFile.read("/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-borrowed flesh/midi/fuzzy gameboy.mid"); +m2 = SimpleMIDIFile.read("/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-borrowed flesh/midi/pad organ.mid"); + +// Play both MIDI sequences simultaneously +x1 = m1.p(\granular).play; +x2 = m2.p(\granular).play; + +// Store them in a global variable so you can stop them later +~midiPlayers = [x1, x2]; +) \ No newline at end of file diff --git a/juno.scd b/juno.scd new file mode 100644 index 0000000..2887f26 --- /dev/null +++ b/juno.scd @@ -0,0 +1,34 @@ +( +SynthDef(\junoPad, { + arg gate=1, freq=220, atk=4, sus=2, rel=6, amp=0.3; + var sig, env, freqs, lfo, chorus, modRate, modDepth; + + // Slightly detuned saw waves + freqs = freq * [1, 1.01, 0.99]; // Small detune + sig = Mix(Saw.ar(freqs)); // Stack saw waves + + // LFO to slowly move filter cutoff + lfo = SinOsc.kr(0.1).range(500, 2000); + sig = RLPF.ar(sig, lfo, 0.3); // Low-pass filter with modulation + . + // Envelope for smooth rise + env = EnvGen.kr(Env.asr(atk, 1, rel), gate, doneAction:2); + sig = sig * env * amp; + + // Chorus effect (emulates Juno-chorus) + modRate = [0.3, 0.4]; // Two different modulation rates + modDepth = 0.01; // Small pitch variation + chorus = sig + DelayC.ar(sig, 0.02, SinOsc.kr(modRate).range(0, modDepth)); + + // Reverb for space + // sig = FreeVerb.ar(chorus, mix: 0.5, room: 0.8, damp: 0.5); + + sig = sig * chorus; + + Out.ar(0, sig); +}).play; +) + + + + diff --git a/live/additive practice.scd b/live/additive practice.scd new file mode 100644 index 0000000..744eff2 --- /dev/null +++ b/live/additive practice.scd @@ -0,0 +1,77 @@ +( +SynthDef(\add_do, { + arg freq = 440, amp = 0.5, out = 0; + var sig = 0, freqs = Array.series(15, 1, 2); + freqs.do({ |f, i| + var pulse; + pulse = Pulse.ar( + freq * f * ExpRand(0.91, 0.90), + mul: i.linexp(0, freqs.size - 1, 1, 0.0001) + ); + pulse = Pan2.ar(pulse, Rand(-0.9, 0.9)); + sig = sig + pulse; + }); + sig = sig * Env([0, 1, 0], [5, 5], [1, -2]).kr(2); + sig = sig.blend(GVerb.ar(sig.sum, 100, 4), 0.15); + sig = LPF.ar(sig, (freq.midicps * XLine.kr(2, 10, 16)).clip(20, 20000)); + sig = Splay.ar(sig.scramble, 0.5); + sig = sig * 0.1 * amp; + Out.ar(out, sig); +}).add; +) + +// We can use iteration to create multiple Synths. Because of the randomness (ExpRand) applied to the frequencies of the sine waves, we'll hear beating patterns. + +23.do({ Synth(\add_do, [freq: 40.midicps]) }); + + + +( +[38, 50, 57, 59, 66].do({ |note, index| + 3.do({ + Synth( + \add_do, [ + freq: note.midicps, + amp: index.linexp(0, 4, 0.6, 0.2), + ] + ) + }); +}); +) + + + +( +SynthDef(\add_do, { + arg freq = 440, amp = 0.1, out = 0; + var sig = 0, freqs = Array.series(15, 1, 2); + freqs.do({ |f, i| + var osc; + osc = PulseDPW.ar( + freq * f * ExpRand(0.99, 1.01), + mul: i.linexp(0, freqs.size - 1, 1, 0.0001) + ); + osc = Pan2.ar(osc, Rand(-0.9, 0.9)); + sig = sig + osc; + }); + sig = sig * Env([0, 1, 0], [5, 5], [1, -2]).kr(2); + sig = sig * amp; + Out.ar(out, sig); +}).play; +) + + +( +SynthDef(\add_do, { + arg freq = 440, amp = 0.1, out = 0; + var sig = 0, freqs = Array.series(15, 1, 2); + + sig = Pulse.ar(freq)!2; + + + sig = sig * amp; + Out.ar(out,sig); +}).play; +) + +3.do({ Synth(\add_do, [freq: 64.midicps]) }); diff --git a/live/granular_EF-edit.scd b/live/granular_EF-edit.scd new file mode 100644 index 0000000..f962121 --- /dev/null +++ b/live/granular_EF-edit.scd @@ -0,0 +1,113 @@ +// TODO: connect MIDI CC knobs to an array of defined pos, also connect amp, possibly rate though probably not + + +( +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Cantor_Samuel_Malavsky_Zechor.wav"); + +( +SynthDef(\cantorial_tremolo, { |out, pan = 0, dur = 0.1, atk=0.3, dec=0.4, sus=0.1, rel=0, amp=1, crf=1100| + var sig, rate, env, filter; + + env = EnvGen.ar( + Env.new( + [0, 1, 1, 0], + [atk, dec, sus, rel], + ), + gate: 1, + doneAction: 2 + ); + + sig = GrainBuf.ar( + numChannels: 2, + trigger: Impulse.kr(10), + dur: dur, + sndbuf: b, + rate: 1, + pos: 0.1, + interp: 2, + pan: pan, + envbufnum: -1, + maxGrains: 512 + ); + + sig = sig * env * amp; + + filter = MoogVCF.ar(sig, crf, 0.3); + + Out.ar(out, filter); +}).play; +) +) + + +( +// Becoming satisfactory granular synth + +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Cantor_Samuel_Malavsky_Zechor.wav"); + +( +SynthDef(\cantorial_trill, { |out, pan = 0, dur = 0.5, atk=0.3, dec=0.4, sus=0.1, rel=0, amp=1, crf=1000, grainRate=5| + var sig, rate, env, filt; + + env = EnvGen.ar( + Env.new( + [0, 1, 1, 0], + [atk, dec, sus, rel], + ), + gate: 1, + doneAction: 2 + ); + + rate = (note.midicps / 60.midicps); + + sig = GrainBuf.ar( + numChannels: 2, + trigger: Impulse.kr(grainRate), + dur: dur, + sndbuf: b, + rate: rate, + pos: 0.01, + interp: 2, + pan: pan, + envbufnum: -1, + maxGrains: 512 + ); + + sig = sig * env * amp; + + sig = LPF.ar(sig, crf); + + Out.ar(out, sig); +}).play; +) +) + + +( +// IMPORTANT! + +b = Buffer.read(s, "/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/granular/Cantorial/Acheinu_Kol_Beit_Israel.wav"); + +( +SynthDef(\cantorial_reed , +{ + arg amp = 0.3, pan = 0; + var sig; + sig = GrainBuf.ar( + numChannels: 2, + trigger: Dust.ar(40), + dur: 0.8, + sndbuf: b, + rate: 1, + pos: 1.25, // 1.25, 1.20 + interp: 2, + pan: pan, + envbufnum: -1, + maxGrains: 512 + ); + + sig = sig * amp; + Out.ar(0, sig); +}).play; +) +) \ No newline at end of file diff --git a/live/olson.scd b/live/olson.scd new file mode 100644 index 0000000..8a44a80 --- /dev/null +++ b/live/olson.scd @@ -0,0 +1,19 @@ +( +{ + var sig, nn = 39.6, seq; + seq = Demand.kr( + trig: Impulse.kr(0.21) + Impulse.kr(0.105, 5/8), + reset: 0, + // demandUGens: Dseq([[0, 12, 16, 19], [2, 14, 18, 21], [-3, 13, 16, 21]], inf); + demandUGens: Dseq([[0, 12, 16, 21], [2, 20], [-4, 12, 24], [30, 40], [23, 38]], inf); + ); + nn = nn * LFDNoise3.kr(LFNoise0.kr(8).exprange(1, 4)).bipolar(0.06).midiratio; + sig = Saw.ar((seq + nn).midicps); + sig = LPF.ar(sig, (nn.midicps * XLine.kr(2, 10, 16)).clip(20, 20000)); + sig = BLowShelf.ar(sig, 300, 0.5, 9); + sig = Splay.ar(sig.scramble, 0.5); + sig = sig * LFDNoise0.kr(LFNoise2.kr(8).exprange(1, 30)).exprange(0.6, 1).lag(0.1); + sig = sig.blend(GVerb.ar(sig.sum, 299, 4), 0.15); + sig = sig * 0.15; +}.play; +) \ No newline at end of file diff --git a/live/tr08 EF-edit.scd b/live/tr08 EF-edit.scd new file mode 100644 index 0000000..5b34c35 --- /dev/null +++ b/live/tr08 EF-edit.scd @@ -0,0 +1,160 @@ +MIDIClient.init; +MIDIIn.connectAll; + +MIDIdef.noteOn(\noteOnTest, {"key down".postln}); + + +// Print MIDI debug info + +( +MIDIdef.noteOn(\noteOnTest, { + arg nn, chan, src; + [nn, chan, src].postln; +}); + + +MIDIdef.cc(\ccTest, { + arg val, num, chan, src; + ["CC:", num, "Value:", val, "Channel:", chan, "Source:", src].postln; +}); +) + + +// Load samples + +( +~sampleDir = PathName("/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-borrowed flesh/seq/808").fullPath; + +~samples = Dictionary.newFrom( + ( + 42: "ch.wav", 46: "oh.wav", 49: "cy.wav", + 56: "cb.wav", 39: "cp.wav", 37: "rs.wav", + 50: "ht.wav", 47: "mt.wav", 43: "lt.wav", + 38: "sd.wav", 36: "bd.wav", 70: "ma.wav", + 75: "cl.wav", 62: "hc.wav", 63: "mc.wav", + 64: "lc.wav" + + ).collect { |file, key| + key -> Buffer.read(s, ~sampleDir +/+ file) + } +); +) + + + +~samples.class +~samples[39].class +~samples[39]. + +( +~sampleDir = PathName("/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-borrowed flesh/seq/808"); +~sample = (); +~sampleDir.entries.do({ |pn| + var sym; + sym = pn.fileNameWithoutExtension.asSymbol; + ~sample[sym] = Buffer.read(s, pn.fullPath); +}); +) + +( +// Define the Synth for sample triggering (if not defined already) +SynthDef(\sampleTrigger, { |buf, ampin = 0| + var sound, amp; + amp = In.kr(ampin, 1); + sound = PlayBuf.ar(1, buf, BufRateScale.ir(buf), doneAction: 2); // doneAction: 2 will free the synth when it's done + sound = sound * amp; + Out.ar(0, sound); // Send to audio output +}).add; +) + + + /* + 75: "cl.wav", 62: "hc.wav", 63: "mc.wav", + 64: "lc.wav"*/ + +( +s.newBusAllocators; +~bdampbus = Bus.control(s, 1); +// ~bdampbus.value = 0.8; +~sdampbus = Bus.control(s, 1); +~ltampbus = Bus.control(s, 1); +~mtampbus = Bus.control(s, 1); +~htampbus = Bus.control(s, 1); +~rsampbus = Bus.control(s, 1); +~cpampbus = Bus.control(s, 1); +~champbus = Bus.control(s, 1); +~ohampbus = Bus.control(s, 1); +~cyampbus = Bus.control(s, 1); +~cbampbus = Bus.control(s, 1); + +MIDIIn.connectAll; +MIDIdef.noteOn('808trig', { |vel, nn| + // nn.postln; + switch(nn) + {36} { + Synth(\sampleTrigger, [buf: ~sample.bd, ampin: ~bdampbus]); + } + {37} { + Synth(\sampleTrigger, [buf: ~sample.rs, ampin: ~rsampbus]); + } + {38} { + Synth(\sampleTrigger, [buf: ~sample.sd, ampin: ~sdampbus]); + } + {39} { + Synth(\sampleTrigger, [buf: ~sample.cp, ampin: ~cpampbus]); + } + {42} { + Synth(\sampleTrigger, [buf: ~sample.ch, ampin: ~champbus]); + } + {43} { + Synth(\sampleTrigger, [buf: ~sample.lt, ampin: ~ltampbus]); + } + {46} { + Synth(\sampleTrigger, [buf: ~sample.oh, ampin: ~ohampbus]); + } + {47} { + Synth(\sampleTrigger, [buf: ~sample.mt, ampin: ~mtampbus]); + } + {49} { + Synth(\sampleTrigger, [buf: ~sample.cy, ampin: ~cyampbus]); + } + {50} { + Synth(\sampleTrigger, [buf: ~sample.ht, ampin: ~htampbus]); + } + {56} { + Synth(\sampleTrigger, [buf: ~sample.cb, ampin: ~cbampbus]); + } + {62} { + Synth(\sampleTrigger, [buf: ~sample.hc, ampin: ~hcampbus]); + } + {63} { + Synth(\sampleTrigger, [buf: ~sample.mc, ampin: ~mcampbus]); + } + {64} { + Synth(\sampleTrigger, [buf: ~sample.lc, ampin: ~lcampbus]); + } + {70} { + Synth(\sampleTrigger, [buf: ~sample.ma, ampin: ~maampbus]); + } + {75} { + Synth(\sampleTrigger, [buf: ~sample.cl, ampin: ~clampbus]); + } +}, noteNum: [36, 38, 39, 42, 46, 49], chan: [9]); + +MIDIdef.cc('808amp', { |val, num| + switch(num) + {24} {~bdampbus.value = val / 127} + {29} {~sdampbus.value = val / 127} + {48} {~ltampbus.value = val / 127} + {51} {~mtampbus.value = val / 127} + {54} {~htampbus.value = val / 127} + {57} {~rsampbus.value = val / 127} + {60} {~cpampbus.value = val / 127} + {63} {~champbus.value = val / 127} + {82} {~ohampbus.value = val / 127} + {85} {~cyampbus.value = val / 127} + {88} {~cbampbus.value = val / 127}; + +}, ccNum: [24, 29, 48, 51, 54, 57, 60, 63, 82, 85, 88], chan: [9]); +) +MIDIFunc.trace(false) \ No newline at end of file diff --git a/my world.scd b/my world.scd new file mode 100644 index 0000000..6ef5eba --- /dev/null +++ b/my world.scd @@ -0,0 +1,77 @@ +( +SynthDef(\rhubarb, { + |freq = 440, gate = 1, cutoff = 600, rq = 0.3, amp = 4, modDepth = 0.3, modDepth2 = 0.5, noiseLevel = 0.8, ringFreq = 400| + var env, sig1, sig2, sig3, filt1, filt2, filt3, lfo, lfo2, pan1, pan2, pan3, mix, saturatedSig; + + // Using GrainBuf for granular synthesis + var grainBuf1, grainBuf2, grainBuf3; + + // Grains for the three channels, modulating playback speed for pitch control + grainBuf1 = GrainBuf.ar( + 2, + Impulse.ar(10), // Control grain density + 0.1, // Grain duration + ~klezmer, // Sound source buffer + 2, // Pitch shift factor + 1.19, // Frequency modulation + 2, // Grain density variation + 0, // Start position (set dynamically for random play) + -1, // Reverse playback (for added texture) + 512 // Buffer size + ); + + grainBuf2 = GrainBuf.ar( + 2, + Dust.ar(10), + 0.08, + ~klezmer, + -2, // Different pitch for variety + 1.25, + 2, + 0, + -1, + 512 + ); + + grainBuf3 = GrainBuf.ar( + 2, + Dust.ar(10), + 0.8, + ~klezmer, + 2, // Higher pitch for more brightness + 1.25, + 2, + 0, + -1, + 512 + ); + + // LFO to modulate filter frequency (similar to previous LFO setup) + lfo = LFNoise0.kr(10).range(1 - modDepth, 1 + modDepth); + lfo2 = LFNoise2.kr(4).range(1 - modDepth, 1 + modDepth); + + // Apply Different Filters to Each GrainBuf Signal + filt1 = SVF.ar(grainBuf1, cutoff * lfo, rq); + filt2 = LPF.ar(grainBuf2, 400 * lfo, rq); + filt3 = HPF.ar(grainBuf3, cutoff * lfo2, rq); + + // ADSR Envelope for modulation + env = EnvGen.kr(Env.adsr(0.0, 0.3, 0.3, 0.1), gate, doneAction: 2); + + // Panning each signal for stereo effect + pan1 = Pan2.ar(filt1 * env * amp, -0.3); // Slightly left + pan2 = Pan2.ar(filt2 * env * amp, 0.3); // Slightly right + pan3 = Pan2.ar(filt3 * env * amp, 0); // Centered + + // Mixing the signals together + mix = pan1 + pan2 + pan3; // Add all three signals + + saturatedSig = mix.tanh; + + // Output the final mixed signal + Out.ar(0, saturatedSig); +}).play; +) + + + diff --git a/padsynth practice EF-edit.scd b/padsynth practice EF-edit.scd new file mode 100644 index 0000000..0f83d62 --- /dev/null +++ b/padsynth practice EF-edit.scd @@ -0,0 +1,95 @@ +s.boot; + +MIDIClient.init; +MIDIIn.connectAll; +MIDIClient.sources.do; + +( +SynthDef(\rhubarb, { + |freq = 440, gate = 1, cutoff = 1e4, rq = 0.3, amp = 0.05, modDepth = 0.3, modDepth2 = 0.5, noiseLevel = 0.8, ringFreq = 80| + var env, osc1, osc2, osc3, filt1, filt2, filt3, lfo, lfo2, noise, noiseFilt, sig1, sig2, sig3, mix; + + // Slightly Different Oscillators + osc1 = SinOsc.ar(freq); + osc2 = SinOsc.ar(freq * 0.5); // Slight detune for variation + osc3 = SawDPW.ar(freq * 2); + + // LFO to Modulate Filter Frequency + lfo = LFNoise0.kr(4).range(1 - modDepth, 1 + modDepth); + lfo2 = LFNoise2.kr(4).range(1 - modDepth, 1 + modDepth); + // lfo2 = noise; + + // Apply Different Filters to Each Oscillator + filt1 = SVF.ar(osc1, cutoff * lfo, rq); + filt2 = LPF.ar(osc2, cutoff * lfo, rq); + filt3 = BPF.ar(osc3, cutoff * lfo2, rq); + + + // ADSR Envelope + env = EnvGen.kr(Env.adsr(0.0, 0.3, 0.3, 0.1), gate, doneAction: 2); + + // Panning and Mixing + sig1 = Pan2.ar(filt1 * env * amp, -0.3); + sig2 = Pan2.ar(filt2 * env * amp, 0.3); + sig3 = Pan2.ar(filt3 * env * amp, 0); + + mix = sig1 + sig2; // Mix main signals + // mix = mix + (noise * env * noiseLevel); // Add noise with envelope control + + // mix = DelayC.ar(mix, maxdelaytime: 0.2, delaytime: 0.3); + + // Output + Out.ar(0, mix); +}).add; +) + +Synth(\rhubarb) + + +( +// Test pattern + +Pbind( + \instrument, \rhubarb, + /*\degree, Pseq([ + [2, 4, 7, 12], [1, 5, 9], [4, 7, 11], [5, 9, 8] + ], inf), // Chord progression*/ + \degree, Pseq([[2, 7, 11], [1, 5, 9], [3, 9], [1,3,5]], inf), + // \degree, Pseq([2, 4, 11,], inf), + // \dur, 0.5, // Duration of each chord + \amp, 0.08, // Volume + // \cutoff, 1200, + \detune, 0, // Slight detune + \pan, Pwhite(-0.3, 0.3), // Random stereo width +).play; +) + + + + +( +// MIDI +// EMF: one major issue here is that ~notes is never actually initialized as an array, so it's nil. when you try to store a Synth at index nn, SC throws an error, because you can't put an item into nil. So, we first initialize ~notes as an array of size 128. After I add this line, your polyphonic MIDI code seems to work fine (no stuck notes) + +~notes = Array.newClear(128); + +MIDIdef.noteOn(\noteOnTest, { + arg vel, nn, chan, src; + [vel, nn].postln; + ~notes[nn] = Synth.new( + \rhubarb, + [ + \freq, nn.midicps, + \amp, vel.linexp(1,127,0.01,0.3), + \gate, 1, + ] + ); +}); + +MIDIdef.noteOff(\noteOffTest, { + arg vel, nn; + [vel, nn].postln; + ~notes[nn].set(\gate, 0); + ~notes[nn] = nil; +}); +) \ No newline at end of file diff --git a/padsynth practice.scd b/padsynth practice.scd index 62e1c92..79b1184 100644 --- a/padsynth practice.scd +++ b/padsynth practice.scd @@ -1,87 +1,7 @@ -( -SynthDef(\junoPad, { - arg gate=1, freq=220, atk=4, sus=2, rel=6, amp=0.3; - var sig, env, freqs, lfo, chorus, modRate, modDepth; - - // Slightly detuned saw waves - freqs = freq * [1, 1.01, 0.99]; // Small detune - sig = Mix(Saw.ar(freqs)); // Stack saw waves - - // LFO to slowly move filter cutoff - lfo = SinOsc.kr(0.1).range(500, 2000); - sig = RLPF.ar(sig, lfo, 0.3); // Low-pass filter with modulation - - // Envelope for smooth rise - env = EnvGen.kr(Env.asr(atk, 1, rel), gate, doneAction:2); - sig = sig * env * amp; - - // Chorus effect (emulates Juno-chorus) - modRate = [0.3, 0.4]; // Two different modulation rates - modDepth = 0.01; // Small pitch variation - chorus = sig + DelayC.ar(sig, 0.02, SinOsc.kr(modRate).range(0, modDepth)); - - // Reverb for space - // sig = FreeVerb.ar(chorus, mix: 0.5, room: 0.8, damp: 0.5); - - sig = sig * chorus; - - Out.ar(0, sig); -}).play; -) - - -( - -x = { - - var sig = WhiteNoise.ar(1!2); - - sig = CombL.ar(sig, 0.05, 1/[36.7, 37.3], 1, 0.2); - - sig = sig.blend(BPF.ar(sig, 1500, 0.5), 0.9); - -}.play(fadeTime: 2); - -) - - -x.release; - - MIDIClient.init; +MIDIIn.connectAll; MIDIClient.sources.do; - -( -SynthDef(\rhubarb, { - |freq = 440, gate = 1, cutoff = 1000, rq = 0.3, amp = 0.05, modDepth = 1, noiseLevel = 0.05| - var env, osc, filt, lfo, noise, sig; - - // Single Sawtooth Oscillator - osc = SinOsc.ar(freq); - osc2 = SinOsc.ar(freq); - - // Subtle Noise Layer - // noise = PinkNoise.ar(noiseLevel); - - // LFO to Modulate Filter - lfo = LFNoise0.kr(4).range(1 - modDepth, 1 + modDepth); // Triangle LFO at 2.94 Hz - - // Low-pass filter modulated by LFO - filt = SVF.ar(osc, cutoff * lfo, rq);u - filt2 = BMoog.ar(osc, freq * lfo, rq); - - // ADSR Envelope with Long Attack & Release - env = EnvGen.kr(Env.adsr(0.0, 0.3, 0.8, 2.0), gate, doneAction: 2); - - sig = Pan2.ar(filt * env * amp, 0); - sig2 = Pan2.ar(filt * env * amp, 0); - - // Output - Out.ar(0, sig); -}).add; -) - ( SynthDef(\rhubarb, { |freq = 440, gate = 1, cutoff = 1e4, rq = 0.3, amp = 0.05, modDepth = 0.3, modDepth2 = 0.5, noiseLevel = 0.8, ringFreq = 80| @@ -119,28 +39,19 @@ SynthDef(\rhubarb, { // Output Out.ar(0, mix); }).add; - - -~synths = Dictionary.new; // Store active notes - -MIDIFunc.noteOn({ |vel, num, chan, src| - var freq = num.midicps; // Convert MIDI note to Hz - var amp = vel.linexp(1, 127, 0.05, 0.5); // Velocity mapping - - ~synths[num] = Synth(\rhubarb, [\freq, freq, \amp, amp]); // Store synth instance -}); ) - ( +// Test pattern + Pbind( \instrument, \rhubarb, /*\degree, Pseq([ [2, 4, 7, 12], [1, 5, 9], [4, 7, 11], [5, 9, 8] ], inf), // Chord progression*/ - // \degree, Pseq([[2, 7, 11], [1, 5, 9], [3, 9], [1,3,5]], inf), - \degree, Pseq([2, 4, 11,], inf), + \degree, Pseq([[2, 7, 11], [1, 5, 9], [3, 9], [1,3,5]], inf), + // \degree, Pseq([2, 4, 11,], inf), // \dur, 0.5, // Duration of each chord \amp, 0.08, // Volume // \cutoff, 1200, @@ -151,13 +62,28 @@ Pbind( ( -SynthDef(\pad, { - var sig; - - sig = Mix( - - Out.ar(0, sig); -}).play; -) +~notes = Array.newClear(128); + +// MIDI + +MIDIdef.noteOn(\noteOnTest, { + arg vel, nn, chan, src; + [vel, nn].postln; + ~notes[nn] = Synth.new( + \rhubarb, + [ + \freq, nn.midicps, + \amp, vel.linexp(1,127,0.01,0.3), + \gate, 1, + ] + ); +}); +MIDIdef.noteOff(\noteOffTest, { + arg vel, nn; + [vel, nn].postln; + ~notes[nn].set(\gate, 0); + ~notes[nn] = nil; +}); +) \ No newline at end of file diff --git a/random.scd b/random.scd new file mode 100644 index 0000000..df34a6b --- /dev/null +++ b/random.scd @@ -0,0 +1,7 @@ +( +SynthDef( "organ", { |freq = 440, sustain = 1, amp = 0.03| + var sig; + sig = LFPar.ar( freq * [1,2,3,5], 0, amp/[2,4,5,7] ); + Out.ar( 0, Env([0,1,1,0], [0.025,sustain,0.025]).kr(2) * sig.dup ) +}).add; +); \ No newline at end of file diff --git a/taste of freedom.scd b/taste of freedom.scd new file mode 100644 index 0000000..9c66000 --- /dev/null +++ b/taste of freedom.scd @@ -0,0 +1,26 @@ +// src: https://tranceaddict.com/forums/showthread.php?threadid=361228 + +( +// select everything between the two parentheses +{ +CombN.ar( +SinOsc.ar( +LFNoise1.kr( +1, // LFO +24, // range in MIDI +LFSaw.kr( +[8,7.23],//second LFO +0, +3, // range in MIDI +80 // offset in MIDI +) +).midicps, +0, +0.04 +), +0.2, // max delay +0.2, // actual delay +4 // decay +) +}.play +) diff --git a/tr08.scd b/tr08.scd new file mode 100644 index 0000000..654d4ef --- /dev/null +++ b/tr08.scd @@ -0,0 +1,95 @@ +MIDIClient.init; +MIDIIn.connectAll; + +MIDIdef.noteOn(\noteOnTest, {"key down".postln}); + + +// Print MIDI debug info + +( +MIDIdef.noteOn(\noteOnTest, { + arg nn, chan, src; + [nn, chan, src].postln; +}); + + +MIDIdef.cc(\ccTest, { + arg val, num, chan, src; + ["CC:", num, "Value:", val, "Channel:", chan, "Source:", src].postln; +}); +) + + +// Load samples + +( +~sampleDir = PathName("/home/lcoogan/snd/live/2025-04-26.Basic_City_Brewery/trax/01-borrowed flesh/seq/808/").fullPath; + +~samples = Dictionary.newFrom( + ( + 42: "ch.wav", 46: "oh.wav", 49: "cy.wav", + 56: "cb.wav", 39: "cp.wav", 37: "rs.wav", + 50: "ht.wav", 47: "mt.wav", 43: "lt.wav", + 38: "sd.wav", 36: "bd.wav", 70: "ma.wav", + 75: "cl.wav", 62: "hc.wav", 63: "mc.wav", + 64: "lc.wav" + ).collect { |file, key| + key -> Buffer.read(s, ~sampleDir +/+ file) + } +); +) + + +// Testing ~samples + + + +( +// For some reason, nn and vel are swapped on the tr-08 MIDIIn +// if vel isn't in the enclosure, then nn doesn't work +// still figuring out how to do polyphony +// set it to if == 9 when everything else is working +MIDIdef.noteOn(\noteOnTest, {|vel, nn| + [nn].postln; + + Synth(\sampleTrigger, [\buf, ~samples[nn]]); +}); +) + + + + + + + + +( +// Define the Synth for sample triggering (if not defined already) +SynthDef(\sampleTrigger, { |buf| + var sound; + sound = PlayBuf.ar(1, buf, doneAction: 2); // doneAction: 2 will free the synth when it's done + Out.ar(0, sound); // Send to audio output +}).add; +) + + + +// Manually trigger a sample for note number 42 +( +var noteNumber = 39; // The MIDI note number to play +if (~samples.includesKey(noteNumber), { + ("Triggering sample for note: " + noteNumber).postln; + Synth(\sampleTrigger, [\buf, ~samples[noteNumber]]); +}, { + ("No sample found for note: " + noteNumber).postln; +}); +) + + + + + +MIDIFunc.trace; + + +