-- 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 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 = 50 -- NO NEED TO CHANGE ANYTHING BELOW -- http://rosettacode.org/wiki/Range_expansion#Lua function range(i, j) local t = {} for n = i, j, i 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 -- 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), [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