aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Hanspeter Portner <dev@open-music-kontrollers.ch>2017-05-14 20:05:42 +0200
committerGravatar Hanspeter Portner <dev@open-music-kontrollers.ch>2017-05-14 20:05:42 +0200
commit87ceeb7619ea9353f08edb0278c67d497e4f33e0 (patch)
treebd5935d90b55ddc3e9c7d553af17446c80dae51b
parent906b28e196c0dee377d7e4017d73699c562135f7 (diff)
downloadmoony.lv2-87ceeb7619ea9353f08edb0278c67d497e4f33e0.zip
moony.lv2-87ceeb7619ea9353f08edb0278c67d497e4f33e0.tar.gz
moony.lv2-87ceeb7619ea9353f08edb0278c67d497e4f33e0.tar.bz2
moony.lv2-87ceeb7619ea9353f08edb0278c67d497e4f33e0.tar.xz
pset: add lindenmayer preset to time bank.
-rw-r--r--VERSION2
-rw-r--r--plugin/manifest.ttl.in11
-rw-r--r--plugin/presets.ttl100
3 files changed, 112 insertions, 1 deletions
diff --git a/VERSION b/VERSION
index 14846e6..f3e1870 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.21.387
+0.21.389
diff --git a/plugin/manifest.ttl.in b/plugin/manifest.ttl.in
index cc68e31..ce11e2a 100644
--- a/plugin/manifest.ttl.in
+++ b/plugin/manifest.ttl.in
@@ -213,6 +213,17 @@ moony:bank-time_midi-sequencer
pset:bank moony:bank-time ;
rdfs:label "Time: Sequencer" ;
rdfs:seeAlso <presets.ttl> .
+moony:bank-time_lindenmayer-system
+ a pset:Preset ;
+ lv2:appliesTo moony:a1xa1 ,
+ moony:a2xa2 ,
+ moony:a4xa4 ,
+ moony:c1a1xc1a1 ,
+ moony:c2a1xc2a1 ,
+ moony:c4a1xc4a1 ;
+ pset:bank moony:bank-time ;
+ rdfs:label "Time: Lindenmayer" ;
+ rdfs:seeAlso <presets.ttl> .
# Bank OSC
moony:bank-osc_osc-responder
diff --git a/plugin/presets.ttl b/plugin/presets.ttl
index 61fd6af..3bc84fe 100644
--- a/plugin/presets.ttl
+++ b/plugin/presets.ttl
@@ -288,6 +288,106 @@ function run(n, control, notify, seq, forge)
end"""
] .
+moony:bank-time_lindenmayer-system
+ a pset:Preset ;
+ doap:license lic:Artistic-2.0 ;
+ state:state [
+ moony:editorHidden false ;
+ moony:logHidden false ;
+ moony:logFollow true ;
+ moony:paramHidden true ;
+ moony:paramCols 3 ;
+ moony:paramRows 4 ;
+ moony:code """local mtointeger = math.tointeger -- reference locally
+
+local rolling = false -- transport state
+local oldNote = nil -- currently palying note
+local velocity = 0x7f -- default note-on velocity value
+
+-- Lindenmayer pattern-rule iterator
+local function iterate(pattern, rules, n)
+ for i = 1, n do -- iterate n-times
+ pattern = string.gsub(pattern, '.', function(c) -- replace every single character with ...
+ return rules[c] or c -- ... matching rule or itself
+ end)
+ end
+ return pattern -- resulting iterated over pattern
+end
+
+local rules = {
+ ['n'] = 'n.[.n..]', -- replacement string for character 'n'
+ ['.'] = '[[..n]]' -- replacement string for character '.'
+}
+
+local start = 'n' -- initial pattern
+local pattern = iterate(start, rules, 4) -- pattern after 4 iterations
+
+local refNote = Note['C#+4'] -- initial reference note
+local incNote = 3 -- reference note increment in MIDI semitones
+
+local actions = {
+ ['n'] = function() -- action for character 'n'
+ coroutine.yield(refNote) -- return current reference note
+ end,
+ ['.'] = function() -- action for character '.'
+ coroutine.yield(nil) -- return nil, e.g. this note is a pause
+ end,
+ ['['] = function() -- action for character '['
+ refNote = (refNote + incNote) & 0x7f -- increase reference note by increment
+ end,
+ [']'] = function() -- action for character ']'
+ refNote = (refNote - incNote) & 0x7f -- decrease reference note by increment
+ end
+}
+
+local nextNote = coroutine.wrap(function() -- create iterator to get action from pattern
+ while true do -- enter infinite loop
+ for c in string.gmatch(pattern, '.') do -- iteratore over each single character in pattern
+ local action = actions[c] -- look up action for character
+ if action then
+ action() -- execute action if defined
+ end
+ end
+ end
+end)
+
+local timeR = TimeResponder({
+ [Time.speed] = function(self, frames, forge, speed)
+ rolling = speed ~= 0.0 -- update transport state
+
+ if not rolling and oldNote then -- if at transport stop and currently playing a note
+ forge:time(frames):midi(MIDI.NoteOff, oldNote, 0x0) -- send note-off
+ oldNote = nil -- invalidate oldNote
+ end
+ end,
+ [Time.barBeat] = function(self, frames, forge, barBeat)
+ if rolling and mtointeger(barBeat) then -- if transport is rolling and barBeat being a whole integer
+ if oldNote then -- if currently playing a note
+ forge:time(frames):midi(MIDI.NoteOff, oldNote, 0x0) -- send note-off
+ oldNote = nil -- invalidate oldNote
+ end
+
+ local newNote = nextNote() -- get new note or nil from pattern iterator
+ if newNote then -- if not a pause
+ forge:time(frames):midi(MIDI.NoteOn, newNote, velocity) -- send note-on
+ oldNote = newNote -- update currently playing note
+ end
+ end
+ end
+}, 16) -- run 16x faster than host time
+
+function run(n, control, notify, seq, forge)
+ local from = 0 -- initialize reference frame time
+
+ for frames, atom in seq:foreach() do -- iterate over input event sequence
+ timeR(from, frames, forge, atom) -- let time responder handle the event
+ from = frames -- advance reference frame time
+ end
+
+ timeR(from, n, forge) -- tell time responder about remaining frames of cycle
+end"""
+ ] .
+
moony:bank-osc_osc-responder
a pset:Preset ;
doap:license lic:Artistic-2.0 ;