Last active
October 26, 2022 19:31
-
-
Save ssj71/0e839f99e5163804ad005773827fc71b to your computer and use it in GitHub Desktop.
Revisions
-
ssj71 revised this gist
Oct 26, 2022 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ -- MIDI Note Event random dropper --- -- This is an example that randomly doesn't let notes through. -- affected MIDI channels -- 0..15 or set to -1 to apply to events on all channels @@ -13,7 +13,7 @@ local note_ranges = "0-127" -- whether to pass non-note events or note events outside of affected range(s) local pass_other = true -- the probability (percent) that the note is dropped local drop_prob = 20 -- NO NEED TO CHANGE ANYTHING BELOW -
ssj71 revised this gist
Oct 26, 2022 . 1 changed file with 4 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -44,8 +44,9 @@ function expand_ranges(rspec) return t end local c --random number storage local function send_note() if random.value(c,100) > drop_prob then return true else return false @@ -66,14 +67,14 @@ local function note_responder(cmd) if pass then -- send event forge:time(frames):midi(cmd | chan, note, vel) end end end function once(n, control, notify, seq, forge) filter_notes = expand_ranges(note_ranges) c = random.new() -- define a MIDIResponder object to handle note-on and note-off events midiR = MIDIResponder({ [MIDI.NoteOn] = note_responder(MIDI.NoteOn), -
ssj71 revised this gist
Oct 25, 2022 . 1 changed file with 8 additions and 99 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -13,103 +13,7 @@ local note_ranges = "0-127" -- whether to pass non-note events or note events outside of affected range(s) local pass_other = true -- the probability (percent) that the note is dropped local drop_prob = 50 -- NO NEED TO CHANGE ANYTHING BELOW @@ -140,19 +44,24 @@ function expand_ranges(rspec) return t end local function send_note() if math.random(1,100) > drop_prob then return true else return false end end -- note responder function factory local function note_responder(cmd) return function(self, frames, forge, chan, note, vel) local pass = pass_other if (filter_chan == -1 or chan == filter_chan) and filter_notes[note] ~= nil then if cmd == MIDI.NoteOn then pass = send_note(vel) else pass = true end end if pass then -
ssj71 revised this gist
Oct 25, 2022 . 1 changed file with 114 additions and 27 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,6 @@ -- MIDI Note Event random dropper --- -- This is an example, that randomly doesn't let notes through. -- affected MIDI channels -- 0..15 or set to -1 to apply to events on all channels @@ -17,14 +16,103 @@ local pass_other = true local drop_prob = 10 -- MIDI Velocity Scaling for Note Range -- MIDI Velocity Scaling for Note Range -- 0..15 or set to -1 to apply to events on all channels local filter_chan = -1 -- whether to pass non-note events local pass_other = true -- affected note range(s) -- string with comma-separated list of single MIDI note numbers or -- ranges (min-max separated by a dash, whitespace is ignored) -- example: local note_ranges = "0-12, 36,48, 60 - 96" local note_ranges = "0-127" -- scale incoming velocity values by this factor -- (affects note-on and note-off events) local vel_scale = 0.9 -- offset value to add to velocity after scaling local vel_offset = 0 -- clamp resulting velocity to this range local vel_min = 0 local vel_max = 127 -- NO NEED TO CHANGE ANYTHING BELOW -- http://rosettacode.org/wiki/Range_expansion#Lua function range(i, j) local t = {} for n = i, j, i<j and 1 or -1 do t[#t+1] = n end return t end function expand_ranges(rspec) local ptn = "([-+]?%d+)%s?-%s?([-+]?%d+)" local t = {} for v in string.gmatch(rspec, '[^,]+') do local s, e = v:match(ptn) if s == nil then t[tonumber(v)] = true else for _, n in ipairs(range(tonumber(s), tonumber(e))) do t[n] = true end end end return t end local function scale_velocity(val) -- round to lower integer val = math.floor(val * vel_scale) + vel_offset -- clamp to [vel_min, vel_max] return val < vel_min and vel_min or (val > vel_max and vel_max or val) end -- note responder function factory local function note_responder(cmd) return function(self, frames, forge, chan, note, vel) local vel_new if (filter_chan == -1 or chan == filter_chan) and filter_notes[note] ~= nil then vel_new = scale_velocity(vel) else vel_new = vel end -- set absolute minimum velocity value for NoteOn events to 1 if vel and (cmd == MIDI.NoteOn and vel_new == 0) then vel_new = 1 end -- send event forge:time(frames):midi(cmd | chan, note, vel_new) end end function once(n, control, notify, seq, forge) filter_notes = expand_ranges(note_ranges) -- define a MIDIResponder object to handle note-on and note-off events midiR = MIDIResponder({ [MIDI.NoteOn] = note_responder(MIDI.NoteOn), [MIDI.NoteOff] = note_responder(MIDI.NoteOff) }, pass_other) end function run(n, control, notify, seq, forge) -- iterate over incoming events for frames, atom in seq:foreach() do -- call responder for event local handled = midiR(frames, forge, atom) end end -- NO NEED TO CHANGE ANYTHING BELOW -- http://rosettacode.org/wiki/Range_expansion#Lua function range(i, j) local t = {} @@ -44,51 +132,50 @@ function expand_ranges(rspec) if s == nil then t[tonumber(v)] = true else for _, n in ipairs(range(tonumber(s), tonumber(e))) do t[n] = true end end end return t end local function drop_note() if math.random(1,100) > drop_prob then return true else return false end -- note responder function factory local function note_responder(cmd) return function(self, frames, forge, chan, note, vel) local pass = pass_other if (filter_chan == -1 or chan == filter_chan) and filter_notes[note] ~= nil then pass = drop_note(vel) end if pass then -- send event forge:time(frames):midi(cmd | chan, note, vel_new) end end end function once(n, control, notify, seq, forge) filter_notes = expand_ranges(note_ranges) -- define a MIDIResponder object to handle note-on and note-off events midiR = MIDIResponder({ [MIDI.NoteOn] = note_responder(MIDI.NoteOn), [MIDI.NoteOff] = note_responder(MIDI.NoteOff) }, pass_other) end function run(n, control, notify, seq, forge) -- iterate over incoming events for frames, atom in seq:foreach() do -- call responder for event local handled = midiR(frames, forge, atom) end end -
ssj71 created this gist
Oct 25, 2022 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,94 @@ -- MIDI Note Event Filter/Processor --- -- This is an example, which passes all events unfiltered / unaltered. -- Change the 'do_filter' function to customize the filter. -- affected MIDI channels -- 0..15 or set to -1 to apply to events on all channels local filter_chan = -1 -- affected note range(s) -- string with comma-separated list of single MIDI note numbers or -- ranges (min-max separated by a dash, whitespace is ignored) -- example: local note_ranges = "0-12, 36,48, 60 - 96" local note_ranges = "0-127" -- whether to pass non-note events or note events outside of affected range(s) local pass_other = true -- the probability (percent) that the note is dropped local drop_prob = 10 -- NO NEED TO CHANGE ANYTHING BELOW local _filter_notes local function clamp(val, min, max) return val < min and min or (val > max and max or val) end -- http://rosettacode.org/wiki/Range_expansion#Lua function range(i, j) local t = {} for n = i, j, i<j and 1 or -1 do t[#t+1] = n end return t end function expand_ranges(rspec) local ptn = "([-+]?%d+)%s?-%s?([-+]?%d+)" local t = {} for v in string.gmatch(rspec, '[^,]+') do local s, e = v:match(ptn) if s == nil then t[tonumber(v)] = true else for i, n in ipairs(range(tonumber(s), tonumber(e))) do t[] = true end end end return t end local function do_filter(frames, forge, chan, note, vel) -- decide randomly whether to drop the note if math.random() > drop_prob then return true, clamp(chan, 0, 16), clamp(note, 0, 127), clamp(vel, 0, 127) else return false, 0, 0, 0 end -- note responder function factory local function note_responder(cmd) return function(self, frames, forge, chan, note, vel) local pass = pass_other if (filter_chan == -1 or chan == filter_chan) and _filter_notes[note] then pass, chan, note, vel = do_filter(frames, forge, chan, note, vel) end if (pass) -- send event forge:time(frames):midi(cmd | chan, note, vel) end end end function once(n, control, notify, seq, forge) _filter_notes = expand_ranges(note_ranges) math.randomseed(os.time()) -- define a MIDIResponder object to handle note-on and note-off events _midiR = MIDIResponder({ [MIDI.NoteOn] = note_responder(MIDI.NoteOn), [MIDI.NoteOff] = note_responder(MIDI.NoteOff) }, pass_other) end function run(n, control, notify, seq, forge) -- iterate over incoming events for frames, atom in seq:foreach() do -- call responder for event local handled = _midiR(frames, forge, atom) end end