-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
220 additions
and
336 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,252 +1,83 @@ | ||
-- ~~ grendy ~~ | ||
-- ~ grendy 2 ~ | ||
-- a simple drone synth | ||
-- grendel drone commander inspired | ||
-- v1.0.0 @cfd90 | ||
-- by: @cfd90 | ||
-- | ||
-- KEY2: randomize OSC/MIXER | ||
-- KEY3: randomize FILTER/LFO | ||
-- grendel drone commander | ||
-- inspired | ||
-- | ||
-- ENC1: FILTER freq | ||
-- ENC2: OSC1 freq | ||
-- ENC3: OSC2 freq | ||
-- | ||
-- KEY1+ENC1: FILTER res | ||
-- KEY1+ENC2: LFO freq | ||
-- KEY1+ENC3: LFO depth | ||
-- | ||
-- Further tweak parameters via [EDIT] page | ||
-- | ||
-- MIDI input round-robin sets OSC1 and OSC2 freq | ||
-- KEY 2 prev page | ||
-- KEY 3 next page | ||
-- ENC 1/2/3 page params | ||
|
||
music = require 'musicutil' | ||
local ez = include "lib/ezscript" | ||
|
||
engine.name = "Grendy" | ||
|
||
------ | ||
------ STATE | ||
------ | ||
|
||
local shift = false | ||
local midiFirstOsc = true | ||
|
||
------ | ||
------ INITIALIZATION | ||
------ | ||
ez.pages = { | ||
{ name = "oscillators", e1 = "slop", e2 = "pitch1", e3 = "pitch2" }, | ||
{ name = "oscillators", e1 = "oscmix", e2 = "shape1", e3 = "shape2" }, | ||
{ name = "filter", e1 = nil, e2 = "filterFreq", e3 = "filterRes" }, | ||
{ name = "lfo", e1 = nil, e2 = "lfoRate", e3 = "lfo2Rate"}, | ||
{ name = "lfo", e1 = nil, e2 = "lfo2Level", e3 = "lfoDepth"}, | ||
{ name = "output", e1 = "amp", e2 = "panRate", e3 = "autoPan" } | ||
} | ||
|
||
function init() | ||
print("unleashing grendy...") | ||
setup_params() | ||
setup_midi() | ||
end | ||
|
||
function setup_params() | ||
-- OSC1 | ||
params:add_separator() | ||
params:add_control("freq1", "osc1 freq", controlspec.new(20, 360, 'exp', 0.5, 220, 'hz')) | ||
params:set_action("freq1", function(x) engine.freq1(x) end) | ||
params:add_group("GRENDY", 19) | ||
params:add_separator("oscillators") | ||
|
||
params:add_control("shape1", "osc1 shape [tri=>sqr]", controlspec.new(-1, 1, 'lin', 0.01, 1, '')) | ||
params:set_action("shape1", function(x) engine.shape1(x) end) | ||
params:add_control("pitch1", "1 freq", controlspec.new(30, 500, 'exp', 0.01, 60, 'hz', 1/500)) | ||
params:set_action("pitch1", function(x) engine.pitch1(x) end) | ||
|
||
-- OSC2 | ||
params:add_separator() | ||
params:add_control("freq2", "osc2 freq", controlspec.new(20, 360, 'exp', 0.5, 220, 'hz')) | ||
params:set_action("freq2", function(x) engine.freq2(x) end) | ||
params:add_option("shape1", "1 shape", {"square", "saw"}, 1) | ||
params:set_action("shape1", function(x) engine.shape1(x - 1) end) | ||
|
||
params:add_control("shape2", "osc2 shape [tri=>sqr]", controlspec.new(-1, 1, 'lin', 0.01, 1, '')) | ||
params:set_action("shape2", function(x) engine.shape2(x) end) | ||
params:add_control("pitch2", "2 freq", controlspec.new(30, 500, 'exp', 0.01, 90, 'hz', 1/500)) | ||
params:set_action("pitch2", function(x) engine.pitch2(x) end) | ||
|
||
-- MIXER | ||
params:add_separator() | ||
params:add_control("mix", "osc mix [osc1=>osc2]", controlspec.new(-1, 1, 'lin', 0.1, 0, '')) | ||
params:set_action("mix", function(x) engine.mix(x) end) | ||
params:add_option("shape2", "2 shape", {"square", "saw"}, 1) | ||
params:set_action("shape2", function(x) engine.shape2(x - 1) end) | ||
|
||
-- FILTER | ||
params:add_separator() | ||
params:add_control("ffreq", "filter frequency", controlspec.new(20, 2000, 'exp', 0.5, 440, 'hz')) | ||
params:set_action("ffreq", function(x) engine.ffreq(x) end) | ||
params:add_taper("oscmix", "* mix", 0, 1, 0.5, 0.1, "") | ||
params:set_action("oscmix", function(x) engine.oscmix((x * 2) - 1) end) | ||
|
||
params:add_control("fres", "filter res", controlspec.new(0, 4, 'lin', 0.1, 1, '')) | ||
params:set_action("fres", function(x) engine.fres(x) end) | ||
params:add_control("slop", "* slop", controlspec.new(0, 1, 'lin', 0.01, 0.1, '', 0.01)) | ||
params:set_action("slop", function(x) engine.slopLevel(x) end) | ||
|
||
-- LFO | ||
params:add_separator() | ||
params:add_control("lfreq", "lfo frequency", controlspec.new(0.1, 20, 'lin', 0.1, 0.1, 'hz')) | ||
params:set_action("lfreq", function(x) engine.lfreq(x) end) | ||
params:add_separator("filter") | ||
|
||
params:add_control("cspeed", "lfo click rate", controlspec.new(1, 16, 'lin', 1, 1, 'x')) | ||
params:set_action("cspeed", function(x) engine.cspeed(x) end) | ||
params:add_control("filterFreq", "freq", controlspec.new(100, 8000, 'exp', 0.01, 300, '', 10/8000)) | ||
params:set_action("filterFreq", function(x) engine.filterFreq(x) end) | ||
|
||
params:add_control("cwidth", "lfo click width", controlspec.new(0.1, 0.9, 'lin', 0.1, 0.2, '')) | ||
params:set_action("cwidth", function(x) engine.cwidth(x) end) | ||
params:add_control("filterRes", "q", controlspec.new(1, 3, 'lin', 0.01, 2, '')) | ||
params:set_action("filterRes", function(x) engine.filterRes(x) end) | ||
|
||
params:add_control("lshape", "lfo shape [ramp=>click]", controlspec.new(-1, 1, 'lin', 0.1, -1, '')) | ||
params:set_action("lshape", function(x) engine.lshape(x) end) | ||
params:add_separator("lfo") | ||
|
||
params:add_control("ldepth", "lfo depth", controlspec.new(0, 1000, 'lin', 0.1, 0, '')) | ||
params:set_action("ldepth", function(x) engine.ldepth(x) end) | ||
|
||
-- AMP | ||
params:add_separator() | ||
params:add_control("amp", "amp", controlspec.new(0, 1, 'lin', 0.01, 1, '')) | ||
params:add_control("lfoRate", "1 rate", controlspec.new(0, 1, 'lin', 0.01, 0.1, '', 0.01)) | ||
params:set_action("lfoRate", function(x) engine.lfoRate(x) end) | ||
|
||
local rates = {2, 4, 8, 16} | ||
params:add_option("lfo2Rate", "2 rate", rates, 1) | ||
params:set_action("lfo2Rate", function(x) engine.lfo2Rate(rates[x]) end) | ||
|
||
params:add_control("lfo2Level", "2 level", controlspec.new(0, 1, 'lin', 0.01, 0.5, '', 0.01)) | ||
params:set_action("lfo2Level", function(x) engine.lfo2Level(x) end) | ||
|
||
params:add_control("lfoDepth", "* depth", controlspec.new(0, 500, 'lin', 0.01, 200, '', 0.01)) | ||
params:set_action("lfoDepth", function(x) engine.lfoDepth(x) end) | ||
|
||
params:add_separator("output") | ||
|
||
params:add_taper("panRate", "pan rate", 0.1, 1, 0.1, 0.1, "") | ||
params:set_action("panRate", function(x) engine.panRate(x) end) | ||
|
||
params:add_taper("autoPan", "pan amt", 0.0, 1, 0, 0.1, "") | ||
params:set_action("autoPan", function(x) engine.autoPan(x) end) | ||
|
||
params:add_taper("amp", "volume", 0.0, 1, 1, 0.1, "") | ||
params:set_action("amp", function(x) engine.amp(x) end) | ||
end | ||
|
||
function setup_midi() | ||
m = midi.connect() | ||
|
||
m.event = function(data) | ||
local d = midi.to_msg(data) | ||
|
||
if d.type == "note_on" then | ||
-- Round-robin set OSC1 and OSC2 | ||
hz = music.note_num_to_freq(d.note) | ||
|
||
if midiFirstOsc then | ||
params:set("freq1", hz) | ||
else | ||
params:set("freq2", hz) | ||
end | ||
|
||
midiFirstOsc = not midiFirstOsc | ||
end | ||
end | ||
end | ||
|
||
------ | ||
------ INPUT | ||
------ | ||
|
||
function key(n, z) | ||
-- Shift key | ||
if n == 1 then | ||
if z > 0 then | ||
shift = true | ||
else | ||
shift = false | ||
end | ||
|
||
redraw() | ||
end | ||
|
||
-- Parameter randomization | ||
if n == 2 and z == 1 then | ||
randomize_osc() | ||
elseif n == 3 and z == 1 then | ||
randomize_filter() | ||
end | ||
end | ||
|
||
function enc(n, d) | ||
if shift then | ||
-- SHIFT mode | ||
-- Control filter res, LFO freq, LFO depth | ||
if n == 1 then | ||
params:delta("fres", d) | ||
elseif n == 2 then | ||
params:delta("lfreq", d) | ||
elseif n == 3 then | ||
params:delta("ldepth", d) | ||
end | ||
else | ||
-- REGULAR mode | ||
-- Control filter freq, OSC1 freq, OSC2 freq | ||
if n == 1 then | ||
params:delta("ffreq", d) | ||
elseif n == 2 then | ||
params:delta("freq1", d) | ||
elseif n == 3 then | ||
params:delta("freq2", d) | ||
end | ||
end | ||
end | ||
|
||
------ | ||
------ DRAWING | ||
------ | ||
|
||
function redraw() | ||
screen.clear() | ||
|
||
-- Encoder documentation | ||
if shift then | ||
screen.move(0, 10) | ||
screen.level(1) | ||
screen.text("[ENC1] ") | ||
screen.level(5) | ||
screen.text("filter res") | ||
screen.move(0, 20) | ||
screen.level(1) | ||
screen.text("[ENC2] ") | ||
screen.level(5) | ||
screen.text("lfo freq") | ||
screen.move(0, 30) | ||
screen.level(1) | ||
screen.text("[ENC3] ") | ||
screen.level(5) | ||
screen.text("lfo depth") | ||
else | ||
screen.move(0, 10) | ||
screen.level(1) | ||
screen.text("[ENC1] ") | ||
screen.level(5) | ||
screen.text("filter freq") | ||
screen.move(0, 20) | ||
screen.level(1) | ||
screen.text("[ENC2] ") | ||
screen.level(5) | ||
screen.text("osc1 freq") | ||
screen.move(0, 30) | ||
screen.level(1) | ||
screen.text("[ENC3] ") | ||
screen.level(5) | ||
screen.text("osc2 freq") | ||
end | ||
|
||
-- Key documentation | ||
if not shift then | ||
screen.move(0, 40) | ||
screen.level(1) | ||
screen.text("[KEY1] ") | ||
screen.level(5) | ||
screen.text("held, toggle page 2") | ||
else | ||
screen.move(0, 40) | ||
screen.level(1) | ||
screen.text("see params page for more") | ||
end | ||
|
||
screen.move(0, 50) | ||
screen.level(1) | ||
screen.text("[KEY2] ") | ||
screen.level(5) | ||
screen.text("randomize OSC/MIXER") | ||
screen.move(0, 60) | ||
screen.level(1) | ||
screen.text("[KEY3] ") | ||
screen.level(5) | ||
screen.text("randomize FILTER/LFO") | ||
|
||
screen.update() | ||
end | ||
|
||
------ | ||
------ HELPERS | ||
------ | ||
|
||
function randomize_osc() | ||
params:set("freq1", 20 + (math.random() * (360 - 20))) | ||
params:set("shape1", (math.random() * 2) - 1) | ||
params:set("freq2", 20 + (math.random() * (360 - 20))) | ||
params:set("shape2", (math.random() * 2) - 1) | ||
params:set("mix", (math.random() * 2) - 1) | ||
end | ||
|
||
function randomize_filter() | ||
params:set("ffreq", 20 + (math.random() * (2000 - 20))) | ||
params:set("fres", math.random() * 3.5) -- Don't go to 4, don't want to blast the user's ear with self-oscillation... | ||
params:set("cspeed", 1 + (math.random() * (16 - 1))) | ||
params:set("cwidth", 0.1 + (math.random() * (1 - 0.1))) | ||
params:set("lshape", (math.random() * 2) - 1) | ||
params:set("ldepth", math.random() * 1000) | ||
end | ||
params:read() | ||
params:bang() | ||
end |
Oops, something went wrong.