diff options
author | cbdev <cb@cbcdn.com> | 2021-01-10 19:10:01 +0100 |
---|---|---|
committer | cbdev <cb@cbcdn.com> | 2021-01-10 19:10:01 +0100 |
commit | 8ff86335bc9f5233564a0f791174a9cc49ae2df4 (patch) | |
tree | 7fba06d7df4bbfa59e0af0203a492bbc21f2ee25 | |
parent | a3a893f6b8b6c10ff281fcdfe0b4a4ddafe89023 (diff) | |
download | midimonster-8ff86335bc9f5233564a0f791174a9cc49ae2df4.tar.gz midimonster-8ff86335bc9f5233564a0f791174a9cc49ae2df4.tar.bz2 midimonster-8ff86335bc9f5233564a0f791174a9cc49ae2df4.zip |
Implement program change control for the rtpmidi backend (#79)
-rw-r--r-- | backends/rtpmidi.c | 23 | ||||
-rw-r--r-- | backends/rtpmidi.h | 3 | ||||
-rw-r--r-- | backends/rtpmidi.md | 4 |
3 files changed, 20 insertions, 10 deletions
diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c index 7c5aa69..8d5525c 100644 --- a/backends/rtpmidi.c +++ b/backends/rtpmidi.c @@ -427,6 +427,8 @@ static char* rtpmidi_type_name(uint8_t type){ return "aftertouch"; case pitchbend: return "pitch"; + case program: + return "program"; } return "unknown"; } @@ -552,7 +554,7 @@ static int rtpmidi_peer_applecommand(instance* inst, size_t peer, uint8_t contro memcpy(&dest_addr, &(data->peer[peer].dest), min(sizeof(dest_addr), data->peer[peer].dest_len)); if(control){ - //calculate remote control port from data port + //calculate remote control port from data port ((struct sockaddr_in*) &dest_addr)->sin_port = htobe16(be16toh(((struct sockaddr_in*) &dest_addr)->sin_port) - 1); } @@ -715,6 +717,9 @@ static channel* rtpmidi_channel(instance* inst, char* spec, uint8_t flags){ else if(!strncmp(next_token, "aftertouch", 10)){ ident.fields.type = aftertouch; } + else if(!strncmp(next_token, "program", 7)){ + ident.fields.type = program; + } else{ LOGPF("Unknown control type in spec %s", spec); return NULL; @@ -761,11 +766,11 @@ static int rtpmidi_set(instance* inst, size_t num, channel** c, channel_value* v payload[3] = v[u].normalised * 127.0; if(ident.fields.type == pitchbend){ - payload[2] = ((int)(v[u].normalised * 16384.0)) & 0x7F; - payload[3] = (((int)(v[u].normalised * 16384.0)) >> 7) & 0x7F; + payload[2] = ((int)(v[u].normalised * 16383.0)) & 0x7F; + payload[3] = (((int)(v[u].normalised * 16383.0)) >> 7) & 0x7F; } - //channel-wide aftertouch is only 2 bytes - else if(ident.fields.type == aftertouch){ + //channel-wides aftertouch and program are only 2 bytes + else if(ident.fields.type == aftertouch || ident.fields.type == program){ payload[2] = payload[3]; payload -= 1; offset -= 1; @@ -996,7 +1001,7 @@ static int rtpmidi_parse(instance* inst, uint8_t* frame, size_t bytes){ ident.fields.channel = midi_status & 0x0F; //single byte command - if(ident.fields.type == aftertouch){ + if(ident.fields.type == aftertouch || ident.fields.type == program){ ident.fields.control = 0; val.normalised = (double) frame[offset] / 127.0; offset++; @@ -1010,7 +1015,7 @@ static int rtpmidi_parse(instance* inst, uint8_t* frame, size_t bytes){ if(ident.fields.type == pitchbend){ ident.fields.control = 0; - val.normalised = (double)((frame[offset] << 7) | frame[offset - 1]) / 16384.0; + val.normalised = (double)((frame[offset] << 7) | frame[offset - 1]) / 16383.0; } else{ ident.fields.control = frame[offset - 1]; @@ -1030,7 +1035,9 @@ static int rtpmidi_parse(instance* inst, uint8_t* frame, size_t bytes){ ident.fields.type, ident.fields.channel, ident.fields.control, val.normalised); if(cfg.detect){ - if(ident.fields.type == pitchbend || ident.fields.type == aftertouch){ + if(ident.fields.type == pitchbend + || ident.fields.type == aftertouch + || ident.fields.type == program){ LOGPF("Incoming data on channel %s.ch%d.%s, value %f", inst->name, ident.fields.channel, rtpmidi_type_name(ident.fields.type), val.normalised); diff --git a/backends/rtpmidi.h b/backends/rtpmidi.h index 7e6eccc..5f1621e 100644 --- a/backends/rtpmidi.h +++ b/backends/rtpmidi.h @@ -35,8 +35,9 @@ static int rtpmidi_shutdown(size_t n, instance** inst); enum /*_rtpmidi_channel_type*/ { none = 0, note = 0x90, - cc = 0xB0, pressure = 0xA0, + cc = 0xB0, + program = 0xC0, aftertouch = 0xD0, pitchbend = 0xE0 }; diff --git a/backends/rtpmidi.md b/backends/rtpmidi.md index 82548bf..9f56f3d 100644 --- a/backends/rtpmidi.md +++ b/backends/rtpmidi.md @@ -63,11 +63,12 @@ The `rtpmidi` backend supports mapping different MIDI events to MIDIMonster chan * `pressure` - Note pressure/aftertouch messages * `aftertouch` - Channel-wide aftertouch messages * `pitch` - Channel pitchbend messages +* `program` - Channel program change messages A MIDIMonster channel is specified using the syntax `channel<channel>.<type><index>`. The shorthand `ch` may be used instead of the word `channel` (Note that `channel` here refers to the MIDI channel number). -The `pitch` and `aftertouch` events are channel-wide, thus they can be specified as `channel<channel>.<type>`. +The `pitch`, `aftertouch` program messages/events are channel-wide, thus they can be specified as `channel<channel>.<type>`. MIDI channels range from `0` to `15`. Each MIDI channel consists of 128 notes (numbered `0` through `127`), which additionally each have a pressure control, 128 CC's (numbered likewise), a channel pressure control (also called @@ -80,6 +81,7 @@ rmidi1.ch0.note9 > rmidi2.channel1.cc4 rmidi1.channel15.pressure1 > rmidi1.channel0.note0 rmidi1.ch1.aftertouch > rmidi2.ch2.cc0 rmidi1.ch0.pitch > rmidi2.ch1.pitch +rmidi2.ch15.note1 > rmidi2.ch2.program ``` #### Known bugs / problems |