Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
330 lines (269 sloc) 6.1 KB
-- meadowphysics
-- midi out capability
-- engine PolyPerc
--
-- key2 toggle scale mode^
-- key3 save meadowphysics
-- key3^ save scales
-- enc1 volume
-- enc2 root note
-- enc3 bpm
--
engine.name = "PolyPerc"
local shift = 0
local MeadowPhysics = require "ansible/meadowphysics"
local mp
local GridScales = require "ansible/gridscales"
local gridscales
local MusicUtil = require "mark_eats/musicutil"
local g = grid.connect()
local BeatClock = require "beatclock"
local m = midi.connect()
local options = {}
options.OUTPUT = {"audio", "midi", "audio + midi"}
options.STEP_LENGTH_NAMES = {"1 bar", "1/2", "1/3", "1/4", "1/6", "1/8", "1/12", "1/16", "1/24", "1/32", "1/48", "1/64"}
options.STEP_LENGTH_DIVIDERS = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64}
local midi_out_device
local midi_out_channel
local notes = {}
local active notes = {}
local clk = BeatClock.new()
local clk_midi = midi.connect()
clk_midi.event = function(data) clk:process_midi(data) end
local notes_off_metro = metro.alloc()
local function all_notes_off()
if (params:get("output") == 2 or params:get("output") == 3) then
for _,a in pairs(active_notes) do
midi_out_device.note_off(a, nil, midi_out_channel)
end
end
active_notes = {}
end
local function step()
all_notes_off()
mp:clock()
for _,n in pairs(notes) do
local f = MusicUtil.note_num_to_freq(n)
if (params:get("output") == 1 or params:get("output") == 3) then
engine.hz(f)
end
if (params:get("output") == 2 or params:get("output") == 3) then
midi_out_device.note_on(n, 96, midi_out_channel)
table.insert(active_notes, 1)
end
end
notes = {}
if params:get("note_length") < 4 then
notes_off_metro:start((60 / clk.bpm / clk.steps_per_beat / 4) * params:get("note_length"), 1)
end
end
local function stop()
all_notes_off()
end
local function reset_pattern()
clk:reset()
end
local grid_clk
local screen_clk
function init()
-- meadowphysics
mp = MeadowPhysics.loadornew("alphacactus/mp.data")
mp.mp_event = event
-- gridscales
gridscales = GridScales.loadornew("alphacactus/gridscales.data")
gridscales:add_params()
-- metro / midi
midi_out_device = midi.connect(1)
midi_out_device.event = function() end
clk.on_step = step
clk.on_stop = stop
clk.on_select_internal = function() clk:start() end
clk.on_select_external = reset_pattern
clk:add_clock_params()
params:set("bpm", 60)
notes_off_metro.callback = all_notes_off
params:add {
type = "option",
id = "output",
name = "output",
options = options.OUTPUT,
action = all_notes_off
}
params:add {
type = "number",
id = "midi_out_device",
name = "midi out device",
min = 1, max = 4, default = 1,
action = function(value) midi_out_device:reconnect(value) end
}
params:add {
type = "number",
id = "midi_out_channel",
name = "midi out channel",
min = 1, max = 16, default = 1,
action = function(value)
all_notes_off()
midi_out_channel = value
end
}
params:add_separator()
params:add {
type = "option",
id = "step_length",
name = "step length",
options = options.STEP_LENGTH_NAMES,
default = 4,
action = function(value)
clk.ticks_per_step = 96 / options.STEP_LENGTH_DIVIDERS[value]
clk.steps_per_beat = options.STEP_LENGTH_DIVIDERS[value] / 4
clk:bpm_change(clk.bpm)
end
}
params:add {
type = "option",
id = "note_length",
name = "note length",
options = {"25%", "50%", "75%", "100%"},
default = 4
}
-- metro
grid_clk = metro.alloc()
grid_clk.callback = gridredraw
grid_clk.time = 1 / 30
screen_clk = metro.alloc()
screen_clk.callback = function() redraw() end
screen_clk.time = 1 / 15
-- engine
params:add {
type = "control",
id = "amp",
controlspec = controlspec.new(0,1,'lin',0,0.5,''),
action = function(x) engine.amp(x) end
}
params:add {
type = "control",
id = "pw",
controlspec = controlspec.new(0,100,'lin',0,50,'%'),
action = function(x) engine.pw(x/100) end
}
params:add {
type = "control",
id = "release",
controlspec = controlspec.new(0.1,3.2,'lin',0,1.2,'s'),
action = function(x) engine.release(x) end
}
params:add {
type = "control",
id = "cutoff",
controlspec = controlspec.new(50,5000,'exp',0,555,'hz'),
action = function(x) engine.cutoff(x) end
}
params:add {
type = "control",
id = "gain",
controlspec = controlspec.new(0,4,'lin',0,1,''),
action = function(x) engine.gain(x) end
}
params:bang()
params:add_separator()
-- grid
if g then mp:gridredraw(g) end
screen_clk:start()
grid_clk:start()
clk:start()
end
function event(row, state)
if state == 1 then
table.insert(notes, params:get("root_note") + gridscales:note(row))
end
end
function redraw()
if shift == 1 then
draw_gridscales()
else
draw_mp()
end
end
function draw_gridscales()
gridscales:redraw()
end
function draw_mp()
screen.clear()
screen.aa(1)
for i=1,8 do
if mp.position[i] >= 1 then
local y = (i-1)*8
local x = 0
x = (mp.position[i]-1)*8
screen.level(15)
screen.move(x, y)
screen.rect(x, y, 8, 8)
screen.fill()
screen.stroke()
end
end
screen.level(4)
for i=0,8 do
local y = i*8
screen.move(0,y)
screen.line(128,y)
screen.stroke()
screen.close()
end
for i=0,16 do
local x = i*8
screen.move(x, 0)
screen.line(x, 64)
screen.stroke()
screen.close()
end
screen.update()
end
function draw_bpm()
screen.clear()
screen.aa(1)
screen.move(64,32)
screen.font_size(32)
screen.text(params:get("bpm"))
screen.stroke()
screen.update()
end
function g.event(x, y, z)
if shift == 1 then
gridscales:gridevent(x, y, z)
else
mp:gridevent(x, y, z)
end
end
function gridredraw()
if shift == 1 then
gridscales:gridredraw(g)
else
mp:gridredraw(g)
end
end
function enc(n, d)
if n == 1 then
mix:delta("output", d)
elseif n == 2 then
params:delta("root_note", d)
draw_gridscales()
elseif n == 3 then
params:delta("bpm", d)
draw_bpm()
end
end
function key(n, z)
if n == 1 and z == 1 then
gridscales:set_scale(8)
end
if n == 2 and z == 1 then
shift = shift ~ 1
elseif n == 3 and z == 1 then
if shift == 1 then
gridscales:save("alphacactus/gridscales.data")
else
mp:save("alphacactus/mp.data")
end
end
end