diff --git a/omnichord.scd b/omnichord.scd new file mode 100644 index 0000000..2fc7c87 --- /dev/null +++ b/omnichord.scd @@ -0,0 +1,20 @@ +( +SynthDef(\omnichord, { + arg freq = 440, amp = 0.3, releaseTime = 2.0, fmIndex = 1.0, fmRatio = 2, gate = 1; + + var sig, env, osc1, osc2; + + osc1 = Saw.ar(freq); + osc1 = RLPF.ar(osc1, 1200, 0.1); + + osc2 = SinOsc.ar(freq * fmRatio, 0, fmIndex); + + sig = osc1 + osc2; + + env = EnvGen.ar(Env.adsr(attackTime: 0.01, decayTime: 0.3, sustainLevel: 0.5, releaseTime: 0), gate, doneAction: 2); + + sig = sig * env * amp; + + Out.ar(0, sig!2); +}).add; +) \ No newline at end of file diff --git a/pads/mel.scd b/pads/mel.scd index ce1678b..6138f13 100644 --- a/pads/mel.scd +++ b/pads/mel.scd @@ -8,8 +8,8 @@ SynthDef(\mellotron, { vibrato = SinOsc.kr(vibratoRate, 0, vibratoDepth).range(0.98, 1.02); - freq1 = freq * (0.99); - freq2 = freq * (1.01); + freq1 = (freq * (0.99))/4; + freq2 = (freq * (1.01))/2; osc1 = Mix([ LFTri.ar(freq1 * vibrato), @@ -40,15 +40,26 @@ SynthDef(\mellotron, { }).add; ) - ( Pbind( \instrument, \mellotron, - \freq, Pseq([ - [48, 20, 53], [10, 58, 60], [10, 55, 63], [12, 55, 58], - [48, 20, 53], [10, 58, 60], [55, 72, 74], [10, 63, 70], - ].midicps, inf), - \dur, 2, + \freq, Pseq([ + + // [65, 69, 71], // F Major (F, A, C) + [80, 75,], + [90, 70], + [90, 70], + [80, 65] + + ].midicps, inf), // Use MIDI note numbers for frequencies + \dur, Pseq([2, 0.5, 0.5, 1],inf), + \vibratoRate, 5, // Adding more vibrato (changeable) + \vibratoDepth, 0.15, // Keep vibrato depth as is + \lpfFreq, 1200, // LPF for smoothing + \lpfLfoRate, 0.1, // Slow LFO modulation for LPF + \lpfLfoDepth, 100, // Depth of LPF modulation + // \detune, -12, // Slight detuning for realism + \pan, Pseq([0.5, -0.5], inf), // Panning left and right for stereo spread ).play; ) diff --git a/padsynth practice.scd b/padsynth practice.scd index 7511558..5787573 100644 --- a/padsynth practice.scd +++ b/padsynth practice.scd @@ -1,125 +1,13 @@ 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; -) ( +// 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); -// MIDI - MIDIdef.noteOn(\noteOnTest, { arg vel, nn, chan, src; // [vel, nn].postln; @@ -129,17 +17,9 @@ MIDIdef.noteOn(\noteOnTest, { \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 + \detune, 2, + \cutoff, 400, + \rq, 0.7, ] ); }); @@ -156,56 +36,18 @@ MIDIdef.noteOff(\noteOffTest, { -( -~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 +( +SynthDef(\rhubarb, { + |freq = 440, gate = 1, cutoff = 1e4, rq = 0.3, amp = 0.3, modDepth = 0.3, detune = 0| + var env, osc, osc2, filt, lfo, lfo2, sig; - // Stop both instruments - ~notes[nn].set(\gate, 0); - ~notes[nn] = nil; + sig = Pulse.ar(freq + detune); + env = EnvGen.kr(Env.adsr(0.1, 0.3, 0.3, 0.1), gate, doneAction: 2); + lfo = LFNoise2.kr(20).range(1 - modDepth, 1 + modDepth); + filt = RLPF.ar(sig, cutoff * lfo, rq); + sig = filt * env * amp; - // For the second instrument (rhubarb2), clear the reference as well - ~notes[nn] = nil; -}); -) + Out.ar(0, sig!2); +}).add; +) \ No newline at end of file