diff options
| author | gretchen <gretchen@gnar.cool> | 2019-11-19 01:54:03 -0800 | 
|---|---|---|
| committer | gretchen <gretchen@gnar.cool> | 2019-11-19 01:54:03 -0800 | 
| commit | 8795f0a601e790b3bd859426367c46b55ff845dc (patch) | |
| tree | 7b062cb75d0708e6fc01175659f2d1a1d8890e2d | |
| parent | 389d32638b24186bbf6c0b76642edbd7cd2467b9 (diff) | |
| download | rhodes-0.3.tar.gz rhodes-0.3.zip  | |
Expose parametersv0.3
| -rw-r--r-- | README.org | 2 | ||||
| -rw-r--r-- | lib/Engine_Rhodes.sc | 61 | ||||
| -rw-r--r-- | rhodes.lua | 99 | 
3 files changed, 155 insertions, 7 deletions
@@ -4,4 +4,4 @@ midi FM rhodes simulation for norns.  Adapted for norns from [[https://sccode.org/1-522][this supercollider snippet]] by user 'snapizz', which is adapted from [[https://github.com/thestk/stk/blob/master/include/Rhodey.h][STK's rhodey]], which Perry R. Cook and Gary P. Scavone adapted from a Yamaha TX81z algorithm. -Needs some visualization, some parameters (tremolo and vibrato? chorus? brightness?), maybe mod wheel and pitch bend support. Email patches to [[mailto:gretchen@gnar.cool][<gretchen@gnar.cool>]]. +Needs some visualization and more parameters (chorus? brightness? tube amp?). Email patches to [[mailto:gretchen@gnar.cool][<gretchen@gnar.cool>]]. diff --git a/lib/Engine_Rhodes.sc b/lib/Engine_Rhodes.sc index ad55cd3..a644c96 100644 --- a/lib/Engine_Rhodes.sc +++ b/lib/Engine_Rhodes.sc @@ -4,6 +4,10 @@  Engine_Rhodes : CroneEngine {      var <notes; +    var <lfoSpeed; +    var <lfoDepth; +    var <modIndex; +    var <mix;      *new { arg context, doneCallback;          ^super.new(context, doneCallback); @@ -22,7 +26,6 @@ Engine_Rhodes : CroneEngine {                 |                 var env1, env2, env3, env4;                 var osc1, osc2, osc3, osc4, snd; -               lfoSpeed = lfoSpeed * 12;                 freq = freq * 2;                 env1 = EnvGen.ar(Env.adsr(0.001, 1.25, 0.0, 0.04, curve: \lin)); @@ -37,7 +40,7 @@ Engine_Rhodes : CroneEngine {                 snd = Mix((osc3 * (1 - mix)) + (osc1 * mix));                 snd = snd * (SinOsc.ar(lfoSpeed) * lfoDepth + 1); -               snd = snd * EnvGen.ar(Env.asr(0, 1, 0.2)); +               snd = snd * EnvGen.ar(Env.asr(0, 1, 0.25), gate);                 snd = Pan2.ar(snd, pan, amp);                 DetectSilence.ar(snd, doneAction: Done.freeSelf);                 Out.ar(out, snd); @@ -45,6 +48,10 @@ Engine_Rhodes : CroneEngine {          });      }      alloc { +        lfoSpeed = 2.0; +        lfoDepth = 0.1; +        modIndex = 0.1; +        mix = 0.2;          notes = nil!128;          this.addCommand("note_on", "ii", {              arg msg; @@ -55,7 +62,11 @@ Engine_Rhodes : CroneEngine {                                      [                                          \out, context.out_b,                                          \freq, note.midicps, -                                        \vel, vel/127.0 +                                        \vel, vel/127.0, +                                        \lfoSpeed, lfoSpeed, +                                        \modIndex, modIndex, +                                        \lfoDepth, lfoDepth, +                                        \mix, mix                                      ],                                      target: context.xg);              } @@ -69,6 +80,50 @@ Engine_Rhodes : CroneEngine {                  notes[note] = nil;              }          }); +        this.addCommand("set_lfo_speed", "f", { +            arg msg; +            lfoSpeed = msg[1]; +            // there has to be a better way to do this +            for (0, 128, { +                arg i; +                if (notes[i].notNil) { +                    notes[i].set(\lfoSpeed, msg[1]); +                } +            }) +        }); +        this.addCommand("set_lfo_depth", "f", { +            arg msg; +            lfoDepth = msg[1]; +            // there has to be a better way to do this +            for (0, 128, { +                arg i; +                if (notes[i].notNil) { +                    notes[i].set(\lfoDepth, msg[1]); +                } +            }) +        }); +        this.addCommand("set_mod_index", "f", { +            arg msg; +            modIndex = msg[1]; +            // there has to be a better way to do this +            for (0, 128, { +                arg i; +                if (notes[i].notNil) { +                    notes[i].set(\modIndex, msg[1]); +                } +            }) +        }); +        this.addCommand("set_mix", "f", { +            arg msg; +            mix = msg[1]; +            // there has to be a better way to do this +            for (0, 128, { +                arg i; +                if (notes[i].notNil) { +                    notes[i].set(\mix, msg[1]); +                } +            }) +        });      }      free {      } @@ -5,6 +5,7 @@  engine.name = "Rhodes"  local MusicUtil = require "musicutil" +local ControlSpec = require "controlspec"  function redraw()    screen.clear() @@ -14,16 +15,108 @@ function redraw()  end  function init () -  redraw() -  m = midi.connect(1) -  m.event = function (a) +  local mod_wheel_controls = 2 +  local base_mod_index = 0.1 +  local base_trem_speed = 2.0 +  local base_trem_depth = 0.1 +  local operator_mix = 0.2 + +  local m = nil +  local midi_event = function (a)      b = midi.to_msg(a)      if b.type == "note_on" then        engine.note_on(b.note, b.vel or 60)      elseif b.type == "note_off" then        engine.note_off(b.note)      end +    -- mod wheel +    if b.type == "cc" and b.ch == 1 then +      if mod_wheel_controls == 1 then +	engine.set_mod_index(base_mod_index + (b.val / 127) * (1.0 - base_mod_index)) +      elseif mod_wheel_controls == 2 then +	engine.set_lfo_speed(base_trem_speed + (b.val / 127) * (60.0 - base_trem_speed)) +      elseif mod_wheel_controls == 3 then +	engine.set_lfo_depth(base_trem_depth + (b.val / 127) * (1.0 - base_trem_depth)) +      end +    end    end + +  -- midi settings +  params:add({ +    type = "option", +    id = "mod_controls", +    name = "Mod Wheel", +    default = mod_wheel_controls, +    options={"Mod Index", "Tremolo Speed", "Tremolo Depth"}, +    action = function(value) do +	mod_wheel_controls = value; +	engine.set_mod_index(base_mod_index); +	engine.set_lfo_speed(base_trem_speed); +	engine.set_lfo_depth(base_trem_depth); +     end +  end}) +  params:add({ +    type = "control", +    id = "midi_in_vport", +    name = "Midi In", +    default=60, +    controlspec = ControlSpec.new(1, 4, 'lin', 1, 1), +    action = function(value) +      -- clear the old connection +      if m then +	m.event = nil +      end +      m = midi.connect(value) +      m.event = midi_event +  end}) +  params:add_separator() + +  -- modulation settings +  params:add({ +    type = "control", +    id = "base_mod_index", +    name = "Mod Index", +    controlspec = ControlSpec.new(0.0, 100.0, 'lin', 0.5, base_mod_index * 100.0, "%"), +    action = function(value) do +	base_mod_index = value/100.0; +	engine.set_mod_index(value/100.0); +    end +  end}) +  params:add({ +    type = "control", +    id = "operator_mix", +    name = "Operator Mix", +    controlspec = ControlSpec.new(0.0, 100.0, 'lin', 0.1, operator_mix * 100.0, "%"), +    action = function(value) do +	operator_mix = value/100.0; +	engine.set_mix(value/100.0); +    end +  end}) +  params:add_separator() + +  -- tremolo +  params:add({ +    type = "control", +    id = "base_trem_speed", +    name = "Tremolo Speed", +    controlspec = ControlSpec.new(0.001, 60.0, 'lin', 0.1, base_trem_speed, "hz"), +    action = function(value) do +	base_trem_speed = value; +	engine.set_lfo_speed(value); +    end +  end}) +  params:add({ +    type = "control", +    id = "base_trem_depth", +    name = "Tremolo Depth", +    controlspec = ControlSpec.new(0.00, 100.0, 'lin', 0.1, base_trem_depth * 100.0, "%"), +    action = function(value) do +	base_trem_depth = value/100.0; +	engine.set_lfo_depth(value/100.00); +    end +  end}) +  params:default() +  redraw()  end  function key (n, x)  | 
