aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgretchen <gretchen@gnar.cool>2019-11-19 01:54:03 -0800
committergretchen <gretchen@gnar.cool>2019-11-19 01:54:03 -0800
commit8795f0a601e790b3bd859426367c46b55ff845dc (patch)
tree7b062cb75d0708e6fc01175659f2d1a1d8890e2d
parent389d32638b24186bbf6c0b76642edbd7cd2467b9 (diff)
downloadrhodes-0.3.tar.gz
rhodes-0.3.zip
Expose parametersv0.3
-rw-r--r--README.org2
-rw-r--r--lib/Engine_Rhodes.sc61
-rw-r--r--rhodes.lua99
3 files changed, 155 insertions, 7 deletions
diff --git a/README.org b/README.org
index 806b799..f4ca030 100644
--- a/README.org
+++ b/README.org
@@ -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 {
}
diff --git a/rhodes.lua b/rhodes.lua
index ab2a49f..fc88e35 100644
--- a/rhodes.lua
+++ b/rhodes.lua
@@ -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)