Add a MIDI_OCTAVE directive which enables the user to choose the preferred octave numbering scheme.
This commit is contained in:
parent
baf25584c9
commit
1b1edeea1a
|
@ -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.
|
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.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,18 @@
|
||||||
# <A..G><#b><0..10> (MIDI notes): MIDI note (on or off)
|
# <A..G><#b><0..10> (MIDI notes): MIDI note (on or off)
|
||||||
|
|
||||||
# Note messages are specified using the cutomary notation (note name
|
# Note messages are specified using the cutomary notation (note name
|
||||||
# A..G, optionally followed by an accidental, # or b, followed by a
|
# A..G, optionally followed by an accidental, # or b, followed by a MIDI
|
||||||
# (zero-based) MIDI octave number. Note that all MIDI octaves start at
|
# octave number. Enharmonic spellings are equivalent, so, e.g., D# and
|
||||||
# the note C, so B0 comes before C1. C5 denotes middle C, A5 is the
|
# Eb denote exactly the same MIDI note. All MIDI octaves start at the
|
||||||
# chamber pitch (usually at 440 Hz). Enharmonic spellings are
|
# note C, so B0 comes before C1. By default, octave numbers are
|
||||||
# equivalent, so, e.g., D# and Eb denote exactly the same MIDI note.
|
# 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
|
# The program distinguishes between messages on different MIDI
|
||||||
# channels. By default, messages are assumed to be on MIDI channel 1,
|
# channels. By default, messages are assumed to be on MIDI channel 1,
|
||||||
|
|
|
@ -230,7 +230,8 @@ send_strokes(translation *tr, uint8_t portno, int status, int chan, int data,
|
||||||
char name[100] = "??", *suffix = "";
|
char name[100] = "??", *suffix = "";
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 0x90:
|
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;
|
break;
|
||||||
case 0xb0: {
|
case 0xb0: {
|
||||||
int step = tr->cc_step[chan][data][dir>0];
|
int step = tr->cc_step[chan][data][dir>0];
|
||||||
|
|
|
@ -93,3 +93,4 @@ extern int debug_regex, debug_strokes, debug_keys;
|
||||||
extern int default_debug_regex, default_debug_strokes, default_debug_keys;
|
extern int default_debug_regex, default_debug_strokes, default_debug_keys;
|
||||||
extern char *config_file_name;
|
extern char *config_file_name;
|
||||||
extern int enable_jack_output;
|
extern int enable_jack_output;
|
||||||
|
extern int midi_octave;
|
||||||
|
|
30
readconfig.c
30
readconfig.c
|
@ -195,6 +195,8 @@ int debug_regex = 0;
|
||||||
int debug_strokes = 0;
|
int debug_strokes = 0;
|
||||||
int debug_keys = 0;
|
int debug_keys = 0;
|
||||||
|
|
||||||
|
int midi_octave = 0;
|
||||||
|
|
||||||
char *
|
char *
|
||||||
allocate(size_t len)
|
allocate(size_t len)
|
||||||
{
|
{
|
||||||
|
@ -509,7 +511,8 @@ print_stroke(stroke *s)
|
||||||
int channel = (s->status & 0x0f) + 1;
|
int channel = (s->status & 0x0f) + 1;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 0x90:
|
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;
|
break;
|
||||||
case 0xb0:
|
case 0xb0:
|
||||||
if (s->step != 1)
|
if (s->step != 1)
|
||||||
|
@ -740,11 +743,13 @@ parse_midi(char *tok, char *s, int lhs,
|
||||||
// normalize to lowercase
|
// normalize to lowercase
|
||||||
for (t = s; *t; t++) *t = tolower(*t);
|
for (t = s; *t; t++) *t = tolower(*t);
|
||||||
// octave number or data byte (not permitted with 'pb', otherwise required)
|
// 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")) {
|
||||||
if (strcmp(s, "pb") == 0) return 0;
|
if ((*p == '-' || isdigit(*p)) &&
|
||||||
p += n;
|
sscanf(p, "%d%n", &m, &n) == 1) {
|
||||||
} else if (strcmp(s, "pb")) {
|
p += n;
|
||||||
return 0;
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// step size ('cc' and 'pb' only)
|
// step size ('cc' and 'pb' only)
|
||||||
if (*p == '[') {
|
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
|
// 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,
|
// number; first character is the note name (must be a..g); optionally,
|
||||||
// the second character may denote an accidental (# or b)
|
// 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;
|
if (n < 0 || n > 127) return 0;
|
||||||
*status = 0x90 | k; *data = n;
|
*status = 0x90 | k; *data = n;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1143,6 +1148,7 @@ read_config_file(void)
|
||||||
debug_regex = default_debug_regex;
|
debug_regex = default_debug_regex;
|
||||||
debug_strokes = default_debug_strokes;
|
debug_strokes = default_debug_strokes;
|
||||||
debug_keys = default_debug_keys;
|
debug_keys = default_debug_keys;
|
||||||
|
midi_octave = 0;
|
||||||
|
|
||||||
while ((line=read_line(f, config_file_name)) != NULL) {
|
while ((line=read_line(f, config_file_name)) != NULL) {
|
||||||
//printf("line: %s", line);
|
//printf("line: %s", line);
|
||||||
|
@ -1197,6 +1203,16 @@ read_config_file(void)
|
||||||
debug_keys = 1;
|
debug_keys = 1;
|
||||||
continue;
|
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;
|
which_key = tok;
|
||||||
if (start_translation(tr, which_key)) {
|
if (start_translation(tr, which_key)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue