Add Action to save mixer screenshot
[ardour.git] / scripts / midi_remap.lua
1 ardour {
2     ["type"]    = "dsp",
3     name        = "MIDI Note Mapper",
4     category    = "Utility",
5     license     = "MIT",
6     author      = "Alby Musaelian",
7     description = [[Map arbitrary MIDI notes to others. Affects Note On/Off and polyphonic key pressure. Note that if a single note is mapped multiple times, the last mapping wins -- MIDI events are never duplicated.]]
8 }
9
10 -- The number of remapping pairs to allow. Increasing this (at least in theory)
11 -- decreases performace, so it's set fairly low as a default. The user can
12 -- increase this if they have a need to.
13 N_REMAPINGS = 10
14
15 OFF_NOTE = -1
16
17 function dsp_ioconfig ()
18     return { { midi_in = 1, midi_out = 1, audio_in = 0, audio_out = 0}, }
19 end
20
21
22 function dsp_params ()
23
24     local map_scalepoints = {}
25     map_scalepoints["None"] = OFF_NOTE
26     for note=0,127 do
27         local name = ARDOUR.ParameterDescriptor.midi_note_name(note)
28         map_scalepoints[string.format("%03d (%s)", note, name)] = note
29     end
30
31     local map_params = {}
32
33     i = 1
34     for mapnum = 1,N_REMAPINGS do
35         -- From and to
36         for _,name in pairs({"| #" .. mapnum .. "  Map note", "|__   to"}) do
37             map_params[i] = {
38                 ["type"] = "input",
39                 name = name,
40                 min = -1,
41                 max = 127,
42                 default = OFF_NOTE,
43                 integer = true,
44                 enum = true,
45                 scalepoints = map_scalepoints
46             }
47             i = i + 1
48         end
49     end
50
51     return map_params
52 end
53
54 function dsp_run (_, _, n_samples)
55     assert (type(midiin) == "table")
56     assert (type(midiout) == "table")
57     local cnt = 1;
58
59     function tx_midi (time, data)
60         midiout[cnt] = {}
61         midiout[cnt]["time"] = time;
62         midiout[cnt]["data"] = data;
63         cnt = cnt + 1;
64     end
65
66     -- We build the translation table every buffer because, as far as I can tell,
67     -- there's no way to only rebuild it when the parameters have changed.
68     -- As a result, it has to be updated every buffer for the parameters to have
69     -- any effect.
70
71     -- Restore translation table
72     local translation_table = {}
73     local ctrl = CtrlPorts:array()
74     for i=1,N_REMAPINGS*2,2 do
75         if not (ctrl[i] == OFF_NOTE) then
76             translation_table[ctrl[i]] = ctrl[i + 1]
77         end
78     end
79
80     -- for each incoming midi event
81     for _,b in pairs (midiin) do
82         local t = b["time"] -- t = [ 1 .. n_samples ]
83         local d = b["data"] -- get midi-event
84         local event_type
85         if #d == 0 then event_type = -1 else event_type = d[1] >> 4 end
86
87         if (#d == 3) and (event_type == 9 or event_type == 8 or event_type == 10) then -- note on, note off, poly. afterpressure
88             -- Do the mapping - 2 is note byte for these types
89             d[2] = translation_table[d[2]] or d[2]
90             if not (d[2] == OFF_NOTE) then
91                 tx_midi (t, d)
92             end
93         else
94             tx_midi (t, d)
95         end
96     end
97 end