"Performers" can handle melodies
This commit is contained in:
31
shared/instrument.lua
Normal file
31
shared/instrument.lua
Normal file
@ -0,0 +1,31 @@
|
||||
instrument=klass()
|
||||
function instrument:init(callback)
|
||||
self.callback=callback
|
||||
self.volume=1.0
|
||||
end
|
||||
|
||||
function instrument:spackle(track,channel,t0,t1,note,verbs)
|
||||
-- a one-indexed table of note data
|
||||
-- (one-indexed because Lua kind of sucks)
|
||||
local nflagses,keep_silence=self.callback(t1-t0,note,instrument_split_verbs(verbs))
|
||||
for i,nflags in pairs(nflagses) do
|
||||
if nflags.v>0 or keep_silence then
|
||||
nflags = nflags:clone() -- avoid breaking instrument
|
||||
|
||||
local min_v=0
|
||||
if (nflags.v>0) min_v = 1
|
||||
nflags.v = mid(flr(nflags.v * self.volume + 0.5),min_v,7)
|
||||
|
||||
track:plot(channel,t0+i-1,nflags)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
instrument_split_verbs=function(x)
|
||||
if (not x) return {}
|
||||
local t={}
|
||||
for i in all(split(x)) do
|
||||
t[i]=true
|
||||
end
|
||||
return t
|
||||
end
|
@ -9,6 +9,10 @@ function nflags:init(o)
|
||||
self:validate()
|
||||
end
|
||||
|
||||
function nflags:clone()
|
||||
return nflags:new(self)
|
||||
end
|
||||
|
||||
function nflags:validate()
|
||||
local c,e,v,w,p
|
||||
=self.c,self.e,self.v,self.w,self.p
|
||||
|
28
shared/performer.lua
Normal file
28
shared/performer.lua
Normal file
@ -0,0 +1,28 @@
|
||||
performer=klass()
|
||||
function performer:init(track,channel,instrument,time,roots)
|
||||
assert_range(#roots,1,33,"#roots")
|
||||
|
||||
self.track=track
|
||||
self.channel=channel
|
||||
self.instrument=instrument
|
||||
self.time=time
|
||||
self.roots=roots
|
||||
self.selected_root=1
|
||||
end
|
||||
|
||||
function performer:root(root)
|
||||
assert_range(root,1,#self.roots,"root")
|
||||
self.selected_root=root
|
||||
end
|
||||
function performer:play(duration,note,verbs)
|
||||
local base=self.roots[self.selected_root]
|
||||
local note=base+note
|
||||
local t0=self.time
|
||||
local t1=t0+duration
|
||||
self.time+=duration
|
||||
self.instrument:spackle(self.track,self.channel,t0,t1,note,verbs)
|
||||
end
|
||||
function performer:rest(duration)
|
||||
self.time+=duration
|
||||
end
|
||||
|
@ -31,13 +31,13 @@ function track:pattern(channel,offset)
|
||||
return self.frames[offset+1][channel+1]
|
||||
end
|
||||
|
||||
function track:plot(channel,offset,inst)
|
||||
function track:plot(channel,offset,ndata)
|
||||
assert_range(channel,0,4,"channel")
|
||||
assert_range(offset,0,self.next_frame_start,"offset")
|
||||
local tup=self.ix_to_frame[offset]
|
||||
assert(tup) -- should be unable to fail
|
||||
local frame,offset=unpack(tup)
|
||||
self.frames[frame+1][channel+1]:plot(offset,inst)
|
||||
self.frames[frame+1][channel+1]:plot(offset,ndata)
|
||||
end
|
||||
|
||||
function track:build(
|
||||
@ -73,6 +73,6 @@ function track:build(
|
||||
for i=0,3 do
|
||||
poke(fmaddr+i,map_to_real_pattern(self.frames[frame][i+1]))
|
||||
end
|
||||
fmaddr+=1
|
||||
fmaddr+=4
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user