aboutsummaryrefslogtreecommitdiff
path: root/rhodes.lua
blob: fdd92af0826eb3cbc0c809f9c9755f6a6c42a5c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
-- midi fm rhodes
--
-- key 2: play a C4

engine.name = "Rhodes"

local MusicUtil = require "musicutil"
local ControlSpec = require "controlspec"

local _dirname
function dir(f)
  if not _dirname then
    source = string.gsub(debug.getinfo(1,'S').source, "@", "")
    _dirname = string.gsub(source, "[^/.]+.lua", "")
  end
  return _dirname.."/"..f
end

function redraw(level)
  screen.clear();
  screen.display_png(dir("rhodes.png"), 0, 0);

  -- draw the jewel light level meter
  -- do this here so it won't overdraw the screen
  screen.circle(104, 32, 6)
  screen.level(math.floor(level or 0))
  screen.fill()
  screen.circle(104, 32, 6)
  screen.level(15)
  screen.stroke()

  screen.update()
end

function init ()
  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()

  -- set a poll to draw the jewel light level meter
  p = poll.set("amp_out_l")
  p.callback = function (val)
    -- log this so it trails off naturally
    level = math.log(10 * val + 1) * 15;
    -- actually draw it in redraw, so it won't
    -- draw over the menu
    redraw(level)
  end
  p.time = 0.025
  p:start()

end

function key (n, x)
  if n == 2 and x == 1 then
    engine.note_on(60, 50)
  elseif n == 2 and x == 0 then
    engine.note_off(60)
  end
end

-- Local Variables:
-- compile-command: "make upload"
-- End: