MIDIClient.init; MIDIIn.connectAll; MIDIClient.sources.do; ( SynthDef(\rhubarb, { |freq = 440, gate = 1, cutoff = 1e4, rq = 0.3, amp = 0.3, modDepth = 0.3, modDepth2 = 0.5, noiseLevel = 0.8, ringFreq = 80, detune = 0| var env, osc1, osc2, osc3, filt1, filt2, filt3, lfo, lfo2, noise, noiseFilt, sig1, sig2, sig3, mix; // Slightly Different Oscillators osc1 = SinOsc.ar(freq + detune); osc2 = SinOsc.ar(freq + detune * 0.5); // Slight detune for variation osc3 = SawDPW.ar(freq * 2); // LFO to Modulate Filter Frequency lfo = LFDNoise3.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(1, 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.blend(GVerb.ar(mix.sum, 299, 4), 0.15); // 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; ) ( SynthDef(\rhubarb, { |freq = 440, gate = 1, cutoff = 1e4, rq = 0.3, amp = 0.1, modDepth = 0.3, modDepth2 = 0.5, noiseLevel = 0.8, ringFreq = 80, detune = 0| var env, osc1, osc2, osc3, filt1, filt2, filt3, lfo, lfo2, noise, noiseFilt, sig1, sig2, sig3, mix, chorus, chorusDepth = 20, chorusRate = 80, chorusedSignal; // Slightly Different Oscillators osc1 = SinOsc.ar(freq + detune); osc2 = SinOsc.ar(freq + detune * 0.5); // Slight detune for variation osc3 = SawDPW.ar(freq * 2); // LFO to Modulate Filter Frequency lfo = LFDNoise3.kr(4).range(1 - modDepth, 1 + modDepth); lfo2 = LFNoise2.kr(4).range(1 - modDepth, 1 + modDepth); // 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 // Chorusing effect using CombN (no delay added, just detuned voices) chorusDepth = LFDNoise3.kr(0.2).range(0.01, 0.05); // Depth of modulation chorusRate = LFDNoise3.kr(0.2).range(0.1, 0.3); // Rate of modulation // Apply CombN for chorusing chorusedSignal = CombN.ar(mix, maxdelaytime: 0.01, decaytime: chorusDepth, feedback: chorusRate); // Output Out.ar(0, chorusedSignal); // Send the chorused signal to the output }).add; ) ( // Test pattern Pbind( \instrument, \rhubarb, \degree, Pseq([ [2, 4, 7, 12], [1, 5, 9], [4, 7, 11], [5, 9, 8], // [2, 7, 11], [1, 5, 9], [3, 9], [1,3,5] ], inf), // Chord progression // \degree, Pseq([], inf), // \degree, Pseq([2, 4, 11,], inf), \dur, 4, // Duration of each chord \amp, 0.06, // Volume \cutoff, 1200, \rq, 0.6, \detune, Pseq([4.1, 4], inf), // Slight detune \pan, Pwhite(-0.3, 0.3), // Random stereo width ).play; ) ( MIDIClient.init; MIDIIn.connectAll; ) ( ~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, // \instrument, \rhubarb, // \degree, Pseq([], inf), // \degree, Pseq([2, 4, 11,], inf), \dur, 2 , // Duration of each chord \amp, 0.06, // Volume \cutoff, 800, \rq, 0.2, \detune, Pseq([4.1, 4], inf), // Slight detune \pan, Pwhite(-0.3, 0.3), // Random stereo width ] ); }); MIDIdef.noteOff(\noteOffTest, { arg vel, nn; // [vel, nn].postln; ~notes[nn].set(\gate, 0); ~notes[nn] = nil; }); ) ( ~notes = Array.newClear(128); // MIDI definitions MIDIdef.noteOn(\noteOnTest, { arg vel, nn, chan, src; // [vel, nn].postln; // Uncomment to debug // Create the first instrument (rhubarb) ~notes[nn] = Synth.new( \rhubarb, [ \freq, nn.midicps, \amp, vel.linexp(1, 127, 0.01, 0.3), \gate, 1, \dur, 2, // Duration of each chord \amp, 0.06, // Volume \cutoff, 800, \rq, 0.8, \detune, Pseq([4.1, 4], inf), // Slight detune \pan, Pwhite(-0.3, 0.3), // Random stereo width ] ); // Create the second instrument (rhubarb2) with the same parameters ~notes[nn] = Synth.new( \rhubarb2, [ \freq, nn.midicps, \amp, vel.linexp(1, 127, 0.01, 0.3), \gate, 1, \dur, 2, // Duration of each chord \amp, 0.06, // Volume \cutoff, 400, \rq, 0.1, \detune, Pseq([4.1, 4], inf), // Slight detune \pan, Pwhite(-0.3, 0.3), // Random stereo width ] ); }); MIDIdef.noteOff(\noteOffTest, { arg vel, nn; // [vel, nn].postln; // Uncomment to debug // Stop both instruments ~notes[nn].set(\gate, 0); ~notes[nn] = nil; // For the second instrument (rhubarb2), clear the reference as well ~notes[nn] = nil; }); )