Skip to content

Instantly share code, notes, and snippets.

@phonk
Created March 9, 2019 10:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phonk/7fe45b5a6e8e6b63851011bf9c15929e to your computer and use it in GitHub Desktop.
Save phonk/7fe45b5a6e8e6b63851011bf9c15929e to your computer and use it in GitHub Desktop.
-- kayan: probabalistic
-- melody discovery
--
-- ENC2 = reveal melody
-- KEY2 = discover new melody
--
-- support your local
-- rainforest
--
-- created by @burn
engine.name = 'KarplusRings'
local cs = require 'controlspec'
local sequence = {
pos = 0,
note_data = {},
prob_data = {}
}
local reveal_level = 35;
local octave_range = 2;
local transpose = 2;
local seq_length = 32;
local scale_data = {};
local animation_counter = 0;
local animation_flipflop = true;
local pluck_distance = 0;
function init()
params:add_number("tempo", "tempo", 20, 240, 48)
params:set_action("tempo", function(n)
t.time = 15/n
end)
params:add_number("length", "length", 4, 64, 32)
params:set_action("length", function(n)
seq_length = n;
end)
params:add_number("transpose", "transpose", 0, 5, 2)
params:set_action("transpose", function(n)
transpose = n;
end)
params:add_number("octave_range", "octave_range", 1, 4, 2)
params:set_action("octave_range", function(n)
octave_range = n;
end)
params:add_separator()
cs.AMP = cs.new(0,1,'lin',0,0.5,'')
params:add_control("amp", "amp", cs.AMP)
params:set_action("amp",
function(x) engine.amp(x) end)
cs.DECAY = cs.new(0.1,15,'lin',0,3.6,'s')
params:add_control("damping", "damping", cs.DECAY)
params:set_action("damping",
function(x) engine.decay(x) end)
cs.COEF = cs.new(0,1,'lin',0,0.11,'')
params:add_control("brightness", "brightness", cs.COEF)
params:set_action("brightness",
function(x) engine.coef(x) end)
cs.LPF_FREQ = cs.new(100,10000,'lin',0,4500,'')
params:add_control("lpf_freq", "lpf_freq", cs.LPF_FREQ)
params:set_action("lpf_freq",
function(x) engine.lpf_freq(x) end)
cs.LPF_GAIN = cs.new(0,3.2,'lin',0,0.5,'')
params:add_control("lpf_gain", "lpf_gain", cs.LPF_GAIN)
params:set_action("lpf_gain",
function(x) engine.lpf_gain(x) end)
cs.BPF_FREQ = cs.new(100,10000,'lin',0,0.5,'')
params:add_control("bpf_freq", "bpf_freq", cs.BPF_FREQ)
params:set_action("bpf_freq",
function(x) engine.bpf_freq(x) end)
cs.BPF_RES = cs.new(0,4,'lin',0,0.5,'')
params:add_control("bpf_res", "bpf_res", cs.BPF_RES)
params:set_action("bpf_res",
function(x) engine.bpf_res(x) end)
create_scale_data();
create_sequence_data();
create_playloop_metro()
create_animation_metro()
params:bang()
end
function create_scale_data()
-- want a custom scale? define it here.
scale = {0,2,3,5,7,10}
scale_data = {}
-- copy the scale over 4 octaves
for octave=0,3 do
for scale_note = 1,#scale do
if scale[scale_note] > 11 then error("Note values must be between 0 and 11 inclusive") end
table.insert(scale_data, (scale[scale_note]+(octave*12)))
end
end
-- scale_data = {0,2,3,5,7,10,12,14,15,17,19,22,24,26,27,29,31,34,36,38,39,41,43,46}
end
-- create all of the note and probability data on init
function create_sequence_data()
for i=1, 64 do
sequence.note_data[i] = scale_data[math.random (1, #scale_data)];
sequence.prob_data[i] = math.random (1, 100);
end
end
function create_playloop_metro()
t = metro.init()
t.count = -1
t.time = 15/params:get("tempo")
t.event = function(stage)
sequence.pos = sequence.pos + 1
if sequence.pos > seq_length then sequence.pos = 1 end
-- does the note playing
if sequence.prob_data[sequence.pos] <= reveal_level then
animation_counter = 30;
engine.hz((55*2^(((transpose * 12)+(sequence.note_data[sequence.pos] % (octave_range*12)))/12)))
end
end
t:start()
end
function create_animation_metro()
x = metro.init()
x.event = function(stage)
if norns.menu.status() == false then draw_screen() end
end
x:start(0.0224)
end
function key(n, z)
if n == 2 and z == 0 then
create_sequence_data();
end
end
function enc(n, delta)
if n == 2 then
animation_counter = 0
reveal_level = reveal_level + delta
if reveal_level > 100 then reveal_level = 100 end
if reveal_level < 0 then reveal_level = 0 end
draw_screen()
end
end
function draw_screen()
if animation_counter >= 0 then
screen.clear()
screen.level(15)
screen.aa(2)
screen.move(0,32)
if animation_flipflop == true then
pluck_distance = 30-(animation_counter/3)
animation_flipflop = false
else
pluck_distance = 30+(animation_counter/3)
screen.stroke()
animation_flipflop = true
end
screen.curve(-5,32,60,pluck_distance,130,32)
screen.stroke()
end
screen.font_face(0)
screen.font_size(8)
screen.level(15)
-- draw right aligned text
screen.move(127,63)
screen.text_right("reveal " .. reveal_level.."%")
screen.update()
animation_counter = animation_counter - 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment