From ca4e82ca7a4b13ee53292376e2c6f7a5af10321c Mon Sep 17 00:00:00 2001 From: Albert Graef Date: Sat, 25 Aug 2018 22:55:02 +0200 Subject: [PATCH] Comment changes, update the manual. --- README.md | 106 +++++++++++++++++++-- midizap.1 | 256 ++++++++++++++++++++++++++++++++++++++++++++++++--- readconfig.c | 11 +-- 3 files changed, 346 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index ee41728..03a4568 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ midizap [-h] [-k] [-o[2]] [-j *name*] [-r *rcfile*] [-d[rskmj]] : Keep track of key (on/off) status of MIDI notes and control switches. This isn't generally recommended, but may occasionally be useful to deal with quirky controllers sending note- or control-ons without corresponding off messages. -o[2] -: Enable MIDI output. Add "2" for a second pair of MIDI ports to be used, e.g., for controller feedback. See Sections *MIDI Output* and *Secondary MIDI Ports*. +: Enable MIDI output. Add "2" for a second pair of MIDI ports to be used, e.g., for controller feedback. See Sections *MIDI Output* and *MIDI Feedback*. -j *name* : Set the Jack client name. Default: "midizap". See Section *Jack-Related Options*. @@ -153,13 +153,13 @@ The translations define what output should be produced for the given MIDI input. Note messages are specified using the customary notation (note name `A..G`, optionally followed by an accidental, `#` or `b`, followed by the MIDI octave number). The same notation is used for key pressure (`KP`) messages. Note that all MIDI octaves start at the note C, so `B0` comes before `C1`. By default, `C5` denotes middle C. Enharmonic spellings are equivalent, so, e.g., `D#` and `Eb` denote exactly the same MIDI note. -We will go into most of the other syntactic bits and pieces of MIDI message designations later, but it's good to have the following grammar in EBNF notation handy for reference: +We will go into most of the other syntactic bits and pieces of MIDI message designations later, but it's good to have the following grammar in EBNF notation handy for reference. (To keep things simple, the grammar is somewhat abridged, but it covers all the frequently used notation. There is some additional syntax for some special forms of translations which will be introduced later.) ~~~ -token ::= ( note | msg ) [ number ] [ "[" number "]" ] - [ "-" number] [ incr ] +token ::= msg [ "[" number "]" ] [ "-" number ] [ incr ] +msg ::= ( note | other ) [ number ] note ::= ( "A" | ... | "G" ) [ "#" | "b" ] -msg ::= "CH" | "PB" | "PC" | "CC" | "CP" | "KP:" note +other ::= "CH" | "PB" | "PC" | "CC" | "CP" | "KP:" note incr ::= "-" | "+" | "=" | "<" | ">" | "~" ~~~ @@ -255,13 +255,13 @@ CC7[4]- XK_Left CC7[4]+ XK_Right ~~~ -Note that there is no step size with input messages in key mode. The message is either just "on" or "off", with any nonzero value denoting off. +Note that there is no step size with input messages in (standard) key mode. The message is either just "on" or "off", with any nonzero value denoting off. There is a special variation of key mode which has a step size associated with it, but it functions differently. As these translations are somewhat esoteric and mostly used with MIDI feedback generated by the host application, we'll have a look at them later, see the *MIDI Feedback* section near the end of the manual. ## MIDI Translations Most of the notation for MIDI messages on the left-hand side of a translation rule also carry over to the output side. The only real difference is that the increment suffixes `+-=<>` aren't permitted here, as they are only used to determine the input mode (key or data) of the entire translation. (The `~` suffix *is* allowed, however, to indicate output in incremental bit-sign format in data translations, see below.) -The output sequence can involve as many MIDI messages as you want, and these can be combined freely with keyboard and mouse events in any order. There's no limitation on the type or number of MIDI messages that you can put into a translation rule. However, as already discussed in Section *MIDI Output* above, you need to invoke the midizap program with the `-o` option to make MIDI output work. (Otherwise, MIDI messages in the output translations will just be silently ignored.) +The output sequence can involve as many MIDI messages as you want, and these can be combined freely with keyboard and mouse events in any order. However, as already discussed in Section *MIDI Output* above, you need to invoke the midizap program with the `-o` option to make MIDI output work. Otherwise, MIDI messages in the output translations will just be silently ignored. There is one special MIDI token `CH` which can only be used on the output side. The `CH` token, which is followed by a MIDI channel number in the range 1..16, doesn't actually generate any MIDI message, but merely sets the default MIDI channel for subsequent MIDI messages in the same output sequence. This is convenient if multiple messages are output to the same MIDI channel. For instance, the sequence `C5-2 E5-2 G5-2`, which outputs a C major chord on MIDI channel 2, can also be abbreviated as `CH2 C5 E5 G5`. @@ -377,11 +377,99 @@ You may want to place this directive directly into a configuration file if the c Last but not least, midizap also supports Jack session management, which makes it possible to record the options the program was invoked with, along with all the MIDI connections. This feature can be used with any Jack session management software. Specifically, QjackCtl has its own built-in Jack session manager which is available in its Session dialog. To use this, launch midizap and any other Jack applications you want to have in the session, use QjackCtl to set up all the connections as needed, and then hit the "Save" (or "Save and Quit") button in the Session dialog to have the session recorded. Now, at any later time you can relaunch the same session with the "Load" (or "Recent") button in the same dialog. -# Secondary MIDI Ports +# MIDI Feedback Some MIDI controllers need a more elaborate setup than what we've seen so far, because they have motor faders, LEDs, etc. requiring feedback from the application. To accommodate these, you can use the `-o2` option of midizap, or the `JACK_PORTS 2` directive in the midizaprc file, to create a second pair of MIDI input and output ports, named `midi_in2` and `midi_out2`. Use of this option also activates a second MIDI default section in the midizaprc file, labeled `[MIDI2]`, which is used exclusively for translating MIDI input from the second input port and sending the resulting MIDI output to the second output port. Typically, the translations in the `[MIDI2]` section will be the inverse of those in the `[MIDI]` section, or whatever it takes to translate the MIDI feedback from the application back to MIDI data which the controller understands. -You then wire up midizap's `midi_in` and `midi_out` ports to controller and application as before, but in addition you also connect the application back to midizap's `midi_in2` port, and the `midi_out2` port to the controller. This reverse path is what is needed to translate the feedback from the application and send it back to the controller. A full-blown example for this kind of setup can be found in examples/APCmini.midizaprc in the sources, which shows how to emulate a Mackie controller with AKAI's APCmini device, so that it readily works with DAW software such as Ardour and Reaper. +You then wire up midizap's `midi_in` and `midi_out` ports to controller and application as before, but in addition you also connect the application back to midizap's `midi_in2` port, and the `midi_out2` port to the controller. This reverse path is what is needed to translate the feedback from the application and send it back to the controller. A full-blown example for this kind of setup can be found in examples/APCmini.midizaprc in the sources, which shows how to emulate a Mackie controller with AKAI's APCmini device, so that it readily works with DAW software such as Ardour. + +## Specialized Key Translations for MIDI Feedback + +Most of the time, MIDI feedback uses just the standard kinds of MIDI messages readily supported by midizap, such as note messages which make buttons light up in different colors, or control change messages which set the positions of motor faders. However, there are some encodings of MIDI messages employed in feedback, such as time and meter displays, which combine different bits of information in a single message, making them difficult or even impossible to translate using the simple kinds of rules we've seen so far. + +midizap offers a special variation of key mode to help decoding at least some of these special messages. For reasons which will become obvious in a moment, we also call these *mod key translations*, or just *mod translations* for short. The extended MIDI syntax being used here is described by the following grammar rules (please refer to the beginning of Section *Translation Syntax* for the parts of the syntax not explicitly defined here): + +~~~ +token ::= msg [ steps ] [ "-" number] +steps ::= "[" list "]" | "[" number "]" "[" list "]" +list ::= number { "," number | ":" number } +~~~ + +To explain the meaning of these translations, we take the mapping of channel pressure to notes as a running example here. But the same works with any kind of message having a parameter value (i.e., anything but `PC`). In its most basic form, the translation looks as follows: + +~~~ +CP[16] C0 +~~~ + +This looks like a key translation with a step size, but is treated differently. Firstly, there are no separate press and release sequences like in other key translations, only a single output sequence. Thus, like in data mode, all down keys will be released immediately (there aren't any in this example, but in general, all kinds of output events are allowed, like in other translations). Secondly, there's no "on"/"off" status here to determine the output values either. Rather, the output messages are constructed directly from the input value by some arithmetic calculations. To these ends, the step size actually denotes a *modulus* which is used to decompose the input value into two separate quantities, *quotient* and *remainder*. Only the latter becomes the value of the output message, while the former is used as an *offset* to modify the output message. + +More precisely, the input value *v*, say, is divided by the given step size *k*, yielding the offset *p* = *v/k* (rounded down to the nearest integer), and the remainder *q* of that division. E.g., with *k* = 16 and *v* = 21, you'll get *p* = 1 and *q* = 5 (21 divided by 16 yields 1 with remainder 5, because 16×1 + 5 = 21). The offset *p* is then applied to the note itself, and the remainder *q* becomes the velocity of that note. So in the example the output would be the note `C#0` (`C0` offset by 1) with a velocity of 5. + +The above might seem a bit esoteric, but this is in fact exactly how you decode meter information in the Mackie control protocol, which consists of a mixer channel index 0..7 in the high nibble (bits 4..6) and the corresponding meter value in the low nibble (bits 0..3) of a key pressure message, which is why we use 16 as the modulus here. There are also some variations of the syntax which make this kind of translation more flexible. In particular, on the right-hand side of the rule you can specify a step size if the remainder value needs to be scaled: + +~~~ +CP[16] C0[2] +~~~ + +Or you can specify a list of discrete velocity values instead. E.g., the APCmini uses the velocities 1, 3 and 5 to denote the colors green, red and yellow, respectively, and a zero velocity denotes "off", so you can encode the meter value in different colors, like so: + +~~~ +CP[16] C0[0,1,1,1,1,5,5,5,3] +~~~ + +There are a lot of repeated values there. For convenience, it's also possible to abbreviate these with the colon, which also improves readability: + +~~~ +CP[16] C0[0,1:4,5:3,3] +~~~ + +This denotes exactly the same list. Also note that when using discrete value lists, the remainder of the input value will be used as an index into the list, and the last value in the list will be used for any index which runs past the end of the list. Thus in the above example, if for some reason you'd receive a meter value of 10, say, the output will still be 3, since it's the last value in the list. + +You can also scale the *offset* value, by adding a second step size to the left-hand side: + +~~~ +CP[16][8] C0[0,1:4,5:3,3] +~~~ + +Now, a channel pressure value of 24 (denoting a meter value of 8 on the second mixer channel) will output the note `A0` (`C0` offset by 8) with velocity 3, which on the APCmini will light up the first LED in the second row in red. Instead of a single step size, it's also possible to specify a list of discrete offset values, so that you can achieve any regular or irregular output pattern that you like: + +~~~ +CP[16][1,8,17,24] C0[0,1:4,5:3,3] +~~~ + +You might also output several notes at once, to show a horizontal or vertical strip of LEDs for each mixer channel. For instance, suppose that we'd like to use an LED in the bottom row of the APCmini for the green, and the LEDs in the two rows above it for the yellow and red values, respectively, you can do that as follows: + +~~~ +CP[16] C0[0,1] G#0[0:5,5] E1[0:8,3] +~~~ + +Note that in this case each of the output notes will be offset by the same amount, so that an input value of 24 will cause the second LED in the bottom row to light up in green, and the two LEDs above it in yellow and red, respectively. Please also have a look at the APCmini.midizaprc example which has a collection of similar rules to implement the meter display. + +It goes without saying that this is not a universal solution, but it handles at least one important real-world use case, and should work with almost any other kind of "scrambled" MIDI feedback which packs two separate values together. The case of Mackie meter feedback certainly seemed important enough, and was easy to support without complicating the syntax too much. Although we try to keep midizap lean and mean, we might add some more special-case key translations like these in the future. + +## Other Uses of Mod Translations + +The mod key translations explained above work with all other kinds of output events, too, so that you can also output X11 key and mouse events and `PC` messages along with the transformed MIDI data if needed; these won't be modified, however. Also note that if you use `CP` and `PB` messages on the output side, which don't have a modifiable offset, the offset part of the input value will be ignored for these messages; only the remainder part will be used, becoming the output value of the message. + +Of course, mod translations can also be used for other purposes, not just MIDI feedback. The input message may be anything which has a parameter value, i.e., any MIDI message but `PC`. You can also choose the modulus large enough (8192 for `PB`, 128 for other messages) so that the offset is always zero, if you just want to employ the discrete value lists for your translations. These offer a great deal of flexibility, more than can be achieved with simple step sizes. In fact, they can be used to realize just about any mapping between input and output values. For instance, suppose that we'd like to map controller values to the the first few Fibonacci numbers: + +~~~ +CC1[128] CC1[0,1,1,2,3,5,8,13,21,34,55,89] +~~~ + +You can also use a modulus of 1 if you'd like to map, say, controller values to note *numbers* (rather than velocities): + +~~~ +CC1[1] C0 +~~~ + +This will output the note with the same number as the controller value, `C0` for value 0, `C#0` for value 1, etc. Note that the remainder value, which becomes the velocity of the output note in this case, will always be zero here, so if you want a nonzero velocity, you will have to specify a value list for that: + +~~~ +CC1[1] C0[127:1] +~~~ + +Note that we added a repeat count in the list on the right-hand side, so that the parser recognizes it as a value list rather than a simple step size (which wouldn't help much since the remainder value to be scaled is always zero here). # Bugs diff --git a/midizap.1 b/midizap.1 index 89241bb..0895420 100644 --- a/midizap.1 +++ b/midizap.1 @@ -28,7 +28,7 @@ corresponding off messages. Enable MIDI output. Add \[lq]2\[rq] for a second pair of MIDI ports to be used, e.g., for controller feedback. -See Sections \f[I]MIDI Output\f[] and \f[I]Secondary MIDI Ports\f[]. +See Sections \f[I]MIDI Output\f[] and \f[I]MIDI Feedback\f[]. .RS .RE .TP @@ -410,14 +410,18 @@ Enharmonic spellings are equivalent, so, e.g., \f[C]D#\f[] and .PP We will go into most of the other syntactic bits and pieces of MIDI message designations later, but it's good to have the following grammar -in EBNF notation handy for reference: +in EBNF notation handy for reference. +(To keep things simple, the grammar is somewhat abridged, but it covers +all the frequently used notation. +There is some additional syntax for some special forms of translations +which will be introduced later.) .IP .nf \f[C] -token\ ::=\ (\ note\ |\ msg\ )\ [\ number\ ]\ [\ "["\ number\ "]"\ ] -\ \ \ \ \ \ \ \ \ \ [\ "\-"\ number]\ [\ incr\ ] +token\ ::=\ msg\ [\ "["\ number\ "]"\ ]\ [\ "\-"\ number\ ]\ [\ incr\ ] +msg\ \ \ ::=\ (\ note\ |\ other\ )\ [\ number\ ] note\ \ ::=\ (\ "A"\ |\ ...\ |\ "G"\ )\ [\ "#"\ |\ "b"\ ] -msg\ \ \ ::=\ "CH"\ |\ "PB"\ |\ "PC"\ |\ "CC"\ |\ "CP"\ |\ "KP:"\ note +other\ ::=\ "CH"\ |\ "PB"\ |\ "PC"\ |\ "CC"\ |\ "CP"\ |\ "KP:"\ note incr\ \ ::=\ "\-"\ |\ "+"\ |\ "="\ |\ "<"\ |\ ">"\ |\ "~" \f[] .fi @@ -711,9 +715,16 @@ CC7[4]+\ XK_Right \f[] .fi .PP -Note that there is no step size with input messages in key mode. +Note that there is no step size with input messages in (standard) key +mode. The message is either just \[lq]on\[rq] or \[lq]off\[rq], with any nonzero value denoting off. +There is a special variation of key mode which has a step size +associated with it, but it functions differently. +As these translations are somewhat esoteric and mostly used with MIDI +feedback generated by the host application, we'll have a look at them +later, see the \f[I]MIDI Feedback\f[] section near the end of the +manual. .SS MIDI Translations .PP Most of the notation for MIDI messages on the left\-hand side of a @@ -727,13 +738,11 @@ in incremental bit\-sign format in data translations, see below.) The output sequence can involve as many MIDI messages as you want, and these can be combined freely with keyboard and mouse events in any order. -There's no limitation on the type or number of MIDI messages that you -can put into a translation rule. However, as already discussed in Section \f[I]MIDI Output\f[] above, you need to invoke the midizap program with the \f[C]\-o\f[] option to make MIDI output work. -(Otherwise, MIDI messages in the output translations will just be -silently ignored.) +Otherwise, MIDI messages in the output translations will just be +silently ignored. .PP There is one special MIDI token \f[C]CH\f[] which can only be used on the output side. @@ -993,7 +1002,7 @@ needed, and then hit the \[lq]Save\[rq] (or \[lq]Save and Quit\[rq]) button in the Session dialog to have the session recorded. Now, at any later time you can relaunch the same session with the \[lq]Load\[rq] (or \[lq]Recent\[rq]) button in the same dialog. -.SH Secondary MIDI Ports +.SH MIDI Feedback .PP Some MIDI controllers need a more elaborate setup than what we've seen so far, because they have motor faders, LEDs, etc. @@ -1020,7 +1029,230 @@ application and send it back to the controller. A full\-blown example for this kind of setup can be found in examples/APCmini.midizaprc in the sources, which shows how to emulate a Mackie controller with AKAI's APCmini device, so that it readily works -with DAW software such as Ardour and Reaper. +with DAW software such as Ardour. +.SS Specialized Key Translations for MIDI Feedback +.PP +Most of the time, MIDI feedback uses just the standard kinds of MIDI +messages readily supported by midizap, such as note messages which make +buttons light up in different colors, or control change messages which +set the positions of motor faders. +However, there are some encodings of MIDI messages employed in feedback, +such as time and meter displays, which combine different bits of +information in a single message, making them difficult or even +impossible to translate using the simple kinds of rules we've seen so +far. +.PP +midizap offers a special variation of key mode to help decoding at least +some of these special messages. +For reasons which will become obvious in a moment, we also call these +\f[I]mod key translations\f[], or just \f[I]mod translations\f[] for +short. +The extended MIDI syntax being used here is described by the following +grammar rules (please refer to the beginning of Section \f[I]Translation +Syntax\f[] for the parts of the syntax not explicitly defined here): +.IP +.nf +\f[C] +token\ ::=\ msg\ [\ steps\ ]\ [\ "\-"\ number] +steps\ ::=\ "["\ list\ "]"\ |\ "["\ number\ "]"\ "["\ list\ "]" +list\ \ ::=\ number\ {\ ","\ number\ |\ ":"\ number\ } +\f[] +.fi +.PP +To explain the meaning of these translations, we take the mapping of +channel pressure to notes as a running example here. +But the same works with any kind of message having a parameter value +(i.e., anything but \f[C]PC\f[]). +In its most basic form, the translation looks as follows: +.IP +.nf +\f[C] +CP[16]\ C0 +\f[] +.fi +.PP +This looks like a key translation with a step size, but is treated +differently. +Firstly, there are no separate press and release sequences like in other +key translations, only a single output sequence. +Thus, like in data mode, all down keys will be released immediately +(there aren't any in this example, but in general, all kinds of output +events are allowed, like in other translations). +Secondly, there's no \[lq]on\[rq]/\[lq]off\[rq] status here to determine +the output values either. +Rather, the output messages are constructed directly from the input +value by some arithmetic calculations. +To these ends, the step size actually denotes a \f[I]modulus\f[] which +is used to decompose the input value into two separate quantities, +\f[I]quotient\f[] and \f[I]remainder\f[]. +Only the latter becomes the value of the output message, while the +former is used as an \f[I]offset\f[] to modify the output message. +.PP +More precisely, the input value \f[I]v\f[], say, is divided by the given +step size \f[I]k\f[], yielding the offset \f[I]p\f[] = \f[I]v/k\f[] +(rounded down to the nearest integer), and the remainder \f[I]q\f[] of +that division. +E.g., with \f[I]k\f[] = 16 and \f[I]v\f[] = 21, you'll get \f[I]p\f[] = +1 and \f[I]q\f[] = 5 (21 divided by 16 yields 1 with remainder 5, +because 16×1 + 5 = 21). +The offset \f[I]p\f[] is then applied to the note itself, and the +remainder \f[I]q\f[] becomes the velocity of that note. +So in the example the output would be the note \f[C]C#0\f[] (\f[C]C0\f[] +offset by 1) with a velocity of 5. +.PP +The above might seem a bit esoteric, but this is in fact exactly how you +decode meter information in the Mackie control protocol, which consists +of a mixer channel index 0..7 in the high nibble (bits 4..6) and the +corresponding meter value in the low nibble (bits 0..3) of a key +pressure message, which is why we use 16 as the modulus here. +There are also some variations of the syntax which make this kind of +translation more flexible. +In particular, on the right\-hand side of the rule you can specify a +step size if the remainder value needs to be scaled: +.IP +.nf +\f[C] +CP[16]\ C0[2] +\f[] +.fi +.PP +Or you can specify a list of discrete velocity values instead. +E.g., the APCmini uses the velocities 1, 3 and 5 to denote the colors +green, red and yellow, respectively, and a zero velocity denotes +\[lq]off\[rq], so you can encode the meter value in different colors, +like so: +.IP +.nf +\f[C] +CP[16]\ C0[0,1,1,1,1,5,5,5,3] +\f[] +.fi +.PP +There are a lot of repeated values there. +For convenience, it's also possible to abbreviate these with the colon, +which also improves readability: +.IP +.nf +\f[C] +CP[16]\ C0[0,1:4,5:3,3] +\f[] +.fi +.PP +This denotes exactly the same list. +Also note that when using discrete value lists, the remainder of the +input value will be used as an index into the list, and the last value +in the list will be used for any index which runs past the end of the +list. +Thus in the above example, if for some reason you'd receive a meter +value of 10, say, the output will still be 3, since it's the last value +in the list. +.PP +You can also scale the \f[I]offset\f[] value, by adding a second step +size to the left\-hand side: +.IP +.nf +\f[C] +CP[16][8]\ C0[0,1:4,5:3,3] +\f[] +.fi +.PP +Now, a channel pressure value of 24 (denoting a meter value of 8 on the +second mixer channel) will output the note \f[C]A0\f[] (\f[C]C0\f[] +offset by 8) with velocity 3, which on the APCmini will light up the +first LED in the second row in red. +Instead of a single step size, it's also possible to specify a list of +discrete offset values, so that you can achieve any regular or irregular +output pattern that you like: +.IP +.nf +\f[C] +CP[16][1,8,17,24]\ C0[0,1:4,5:3,3] +\f[] +.fi +.PP +You might also output several notes at once, to show a horizontal or +vertical strip of LEDs for each mixer channel. +For instance, suppose that we'd like to use an LED in the bottom row of +the APCmini for the green, and the LEDs in the two rows above it for the +yellow and red values, respectively, you can do that as follows: +.IP +.nf +\f[C] +CP[16]\ C0[0,1]\ G#0[0:5,5]\ E1[0:8,3] +\f[] +.fi +.PP +Note that in this case each of the output notes will be offset by the +same amount, so that an input value of 24 will cause the second LED in +the bottom row to light up in green, and the two LEDs above it in yellow +and red, respectively. +Please also have a look at the APCmini.midizaprc example which has a +collection of similar rules to implement the meter display. +.PP +It goes without saying that this is not a universal solution, but it +handles at least one important real\-world use case, and should work +with almost any other kind of \[lq]scrambled\[rq] MIDI feedback which +packs two separate values together. +The case of Mackie meter feedback certainly seemed important enough, and +was easy to support without complicating the syntax too much. +Although we try to keep midizap lean and mean, we might add some more +special\-case key translations like these in the future. +.SS Other Uses of Mod Translations +.PP +The mod key translations explained above work with all other kinds of +output events, too, so that you can also output X11 key and mouse events +and \f[C]PC\f[] messages along with the transformed MIDI data if needed; +these won't be modified, however. +Also note that if you use \f[C]CP\f[] and \f[C]PB\f[] messages on the +output side, which don't have a modifiable offset, the offset part of +the input value will be ignored for these messages; only the remainder +part will be used, becoming the output value of the message. +.PP +Of course, mod translations can also be used for other purposes, not +just MIDI feedback. +The input message may be anything which has a parameter value, i.e., any +MIDI message but \f[C]PC\f[]. +You can also choose the modulus large enough (8192 for \f[C]PB\f[], 128 +for other messages) so that the offset is always zero, if you just want +to employ the discrete value lists for your translations. +These offer a great deal of flexibility, more than can be achieved with +simple step sizes. +In fact, they can be used to realize just about any mapping between +input and output values. +For instance, suppose that we'd like to map controller values to the the +first few Fibonacci numbers: +.IP +.nf +\f[C] +CC1[128]\ CC1[0,1,1,2,3,5,8,13,21,34,55,89] +\f[] +.fi +.PP +You can also use a modulus of 1 if you'd like to map, say, controller +values to note \f[I]numbers\f[] (rather than velocities): +.IP +.nf +\f[C] +CC1[1]\ C0 +\f[] +.fi +.PP +This will output the note with the same number as the controller value, +\f[C]C0\f[] for value 0, \f[C]C#0\f[] for value 1, etc. +Note that the remainder value, which becomes the velocity of the output +note in this case, will always be zero here, so if you want a nonzero +velocity, you will have to specify a value list for that: +.IP +.nf +\f[C] +CC1[1]\ C0[127:1] +\f[] +.fi +.PP +Note that we added a repeat count in the list on the right\-hand side, +so that the parser recognizes it as a value list rather than a simple +step size (which wouldn't help much since the remainder value to be +scaled is always zero here). .SH Bugs .PP There probably are some. diff --git a/readconfig.c b/readconfig.c index b81fb36..566c0b0 100644 --- a/readconfig.c +++ b/readconfig.c @@ -836,7 +836,7 @@ re_press_temp_modifiers(void) /* Parser for the MIDI message syntax. The same parser is used for both the left-hand side (lhs) and the right-hand side (rhs) of a translation. - The syntax we actually parse here is: + The syntax we actually parse here is, somewhat abridged: tok ::= ( note | msg ) [ number ] [ "[" number "]" ] [ "-" number] [ incr ] note ::= ( "a" | ... | "g" ) [ "#" | "b" ] @@ -852,11 +852,10 @@ re_press_temp_modifiers(void) used. Note that not all combinations are possible -- "pb" and "cp" have no - data byte; on the lhs, a step size in brackets is only permitted with - "cc", "pb", "cp" and "kp"; and "ch" must *not* occur on the lhs at - all, and is followed by just a channel number. (In fact, "ch" is no - real MIDI message at all; it just sets the default MIDI channel for - subsequent messages in the output sequence.) + data byte; and "ch" must *not* occur on the lhs at all, and is + followed by just a channel number. (In fact, "ch" is no real MIDI + message at all; it just sets the default MIDI channel for subsequent + messages in the output sequence.) The incr flag indicates an "incremental" controller or pitch bend value which responds to up ("+") and down ("-") changes; it is only