Add a MIDI_OCTAVE directive which enables the user to choose the preferred octave numbering scheme.

master
Albert Graef 2018-08-12 01:21:11 +02:00
parent baf25584c9
commit 1b1edeea1a
5 changed files with 40 additions and 15 deletions

View File

@ -122,9 +122,9 @@ Note the `-10` suffix on the output messages in the above example, which indicat
E.g., the input note `C4` is mapped to `C3-10`, the note C in the third MIDI octave, which on channel 10 will produce the sound of a bass drum, at least on GM compatible synthesizers like Fluidsynth. The binding for the volume controller (`CC7`) at the end of the entry sends volume changes to the same drum channel (`CC7-10`), so that you can use the volume control on your keyboard to dial in the volume on the drum channel that you want. The program keeps track of the values of both input and output controllers on all MIDI channels internally, so with the translations above all that happens automagically.
A note on the MIDI octave numbers is in order here. There are various different standards for numbering octaves, and different programs use different standards, which can be rather confusing. There's the Helmholtz standard, which is still widely used, but only in German-speaking countries, and the ASA (Acoustical Society of America) standard where middle C is C4 (one less than zero-based octave numbers, so the sub-contra octave starts at C-1). At least two standards exist for MIDI octave numbering, one in which middle C is C3 (so the sub-contra octave starts at C-2), and zero-based octave numbers, where the sub-contra octave starts at C0. The latter is what we use in the midizaprc file. It probably appeals most to mathematically-inclined and computer-science people, but it also relates nicely to MIDI note numbers in the range 0..127, since the octave number is just the MIDI note number divided by 12, with the remainder of the division telling you which note in the octave it is (0 = C, 1 = C#, ..., 10 = Bb, 11 = B).
A note on the MIDI octave numbers is in order here. There are various different standards for numbering octaves, and different programs use different standards, which can be rather confusing. E.g., there's the ASA (Acoustical Society of America) standard where middle C is C4, also known as "scientific" or "American standard" pitch notation. At least two standards exist for MIDI octave numbering, one in which middle C is C3 (so the lowest MIDI octave starts at C-2), and zero-based octave numbers, which start at C0 and have middle C at C5. There's not really a single "best" standard here, but the latter tends to appeal to mathematically inclined and computer-savvy people, and is also what is used by default in the midizaprc file.
Thus, if you use some MIDI monitoring software to figure out which notes to put into your midizaprc file, first check how the program prints middle C, so that you know how to adjust the octave numbers reported by the monitoring program.
However, you can easily change this with a special `MIDI_OCTAVE` directive in the configuration file, please check example.midizaprc for details. Also, if you use some MIDI monitoring software to figure out which notes to put into your midizaprc file, first check how the program prints middle C, so that you know how to adjust the octave numbers reported by the monitoring program (or which `MIDI_OCTAVE` offset to use in your midizaprc file).
Besides MIDI notes and control change (`CC`) messages, the `midizap` program also supports receiving and sending program change (`PC`) and pitch bend (`PB`) messages. This should cover most common use cases. Other messages (in particular, aftertouch and system messages) are not supported right now, but may be added in the future. Again, please refer to the example.midizaprc file and the comments in the readconfig.c for further details.

View File

@ -31,11 +31,18 @@
# <A..G><#b><0..10> (MIDI notes): MIDI note (on or off)
# Note messages are specified using the cutomary notation (note name
# A..G, optionally followed by an accidental, # or b, followed by a
# (zero-based) MIDI octave number. Note that all MIDI octaves start at
# the note C, so B0 comes before C1. C5 denotes middle C, A5 is the
# chamber pitch (usually at 440 Hz). Enharmonic spellings are
# equivalent, so, e.g., D# and Eb denote exactly the same MIDI note.
# A..G, optionally followed by an accidental, # or b, followed by a MIDI
# octave number. Enharmonic spellings are equivalent, so, e.g., D# and
# Eb denote exactly the same MIDI note. All MIDI octaves start at the
# note C, so B0 comes before C1. By default, octave numbers are
# zero-based, so C0 is MIDI note 0, C5 denotes middle C, A5 is the
# chamber pitch (usually at 440 Hz), etc. However, you can adjust this
# to your liking by specifying the offset of the lowest MIDI octave.
# Two of the most common alternatives are listed below (uncomment one of
# the following lines to use these):
#MIDI_OCTAVE-1 # ASA (Acoustical Society of America; middle C is C4)
#MIDI_OCTAVE-2 # alternate MIDI (various manufacturers; middle C is C3)
# The program distinguishes between messages on different MIDI
# channels. By default, messages are assumed to be on MIDI channel 1,

View File

@ -230,7 +230,8 @@ send_strokes(translation *tr, uint8_t portno, int status, int chan, int data,
char name[100] = "??", *suffix = "";
switch (status) {
case 0x90:
sprintf(name, "%s%d-%d", note_names[data % 12], data / 12, chan+1);
sprintf(name, "%s%d-%d", note_names[data % 12],
data / 12 + midi_octave, chan+1);
break;
case 0xb0: {
int step = tr->cc_step[chan][data][dir>0];

View File

@ -93,3 +93,4 @@ extern int debug_regex, debug_strokes, debug_keys;
extern int default_debug_regex, default_debug_strokes, default_debug_keys;
extern char *config_file_name;
extern int enable_jack_output;
extern int midi_octave;

View File

@ -195,6 +195,8 @@ int debug_regex = 0;
int debug_strokes = 0;
int debug_keys = 0;
int midi_octave = 0;
char *
allocate(size_t len)
{
@ -509,7 +511,8 @@ print_stroke(stroke *s)
int channel = (s->status & 0x0f) + 1;
switch (status) {
case 0x90:
printf("%s%d-%d ", note_names[s->data % 12], s->data / 12, channel);
printf("%s%d-%d ", note_names[s->data % 12],
s->data / 12 + midi_octave, channel);
break;
case 0xb0:
if (s->step != 1)
@ -740,11 +743,13 @@ parse_midi(char *tok, char *s, int lhs,
// normalize to lowercase
for (t = s; *t; t++) *t = tolower(*t);
// octave number or data byte (not permitted with 'pb', otherwise required)
if (isdigit(*p) && sscanf(p, "%d%n", &m, &n) == 1) {
if (strcmp(s, "pb") == 0) return 0;
p += n;
} else if (strcmp(s, "pb")) {
return 0;
if (strcmp(s, "pb")) {
if ((*p == '-' || isdigit(*p)) &&
sscanf(p, "%d%n", &m, &n) == 1) {
p += n;
} else {
return 0;
}
}
// step size ('cc' and 'pb' only)
if (*p == '[') {
@ -821,7 +826,7 @@ parse_midi(char *tok, char *s, int lhs,
// we must be looking at a MIDI note here, with m denoting the octave
// number; first character is the note name (must be a..g); optionally,
// the second character may denote an accidental (# or b)
n = note_number(s[0], s[1], m);
n = note_number(s[0], s[1], m - midi_octave);
if (n < 0 || n > 127) return 0;
*status = 0x90 | k; *data = n;
return 1;
@ -1143,6 +1148,7 @@ read_config_file(void)
debug_regex = default_debug_regex;
debug_strokes = default_debug_strokes;
debug_keys = default_debug_keys;
midi_octave = 0;
while ((line=read_line(f, config_file_name)) != NULL) {
//printf("line: %s", line);
@ -1197,6 +1203,16 @@ read_config_file(void)
debug_keys = 1;
continue;
}
if (!strncmp(tok, "MIDI_OCTAVE", 11)) {
char *a = tok+11;
int k, n;
if (sscanf(a, "%d%n", &k, &n) == 1 && !a[n]) {
midi_octave = k;
} else {
fprintf(stderr, "invalid octave offset: %s\n", a);
}
continue;
}
which_key = tok;
if (start_translation(tr, which_key)) {
continue;