Skip to content

Instantly share code, notes, and snippets.

@SpotlightKid
Last active November 23, 2017 10:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SpotlightKid/e614801b9260142191788a05e5e3ff77 to your computer and use it in GitHub Desktop.
Save SpotlightKid/e614801b9260142191788a05e5e3ff77 to your computer and use it in GitHub Desktop.
Decode received MIDI RPN messages
import time
from collections import defaultdict
import rtmidi
from rtmidi.midiconstants import *
from rtmidi.midiutil import open_midiinput
class RPNDecoder:
def __init__(self, channel=1):
self.channel = (channel - 1) & 0xF
self.rpn = 0
self.values = defaultdict(int)
self.last_changed = None
def __call__(self, event, data=None):
msg, deltatime = event
# event type = upper four bits of first byte
if msg[0] == (CONTROL_CHANGE | self.channel):
cc, value = msg[1], msg[2]
if cc == RPN_LSB:
self.rpn = (self.rpn >> 7) * 128 + value
elif cc == RPN_MSB:
self.rpn = value * 128 + (self.rpn & 0x7F)
elif cc == DATA_INCREMENT:
self.set_rpn(self.rpn, min(2 ** 14, self.values[self.rpn] + 1))
elif cc == DATA_DECREMENT:
self.set_rpn(self.rpn, max(0, self.values[self.rpn] - 1))
elif cc == DATA_ENTRY_LSB:
self.set_rpn(self.rpn, (self.values[self.rpn] >> 7) * 128 + value)
elif cc == DATA_ENTRY_MSB:
self.set_rpn(self.rpn, value * 128 + (self.values[self.rpn] & 0x7F))
def set_rpn(self, rpn, value):
self.values[rpn] = value
self.last_changed = rpn
decoder = RPNDecoder()
m_in, port_name = open_midiinput()
m_in.set_callback(decoder)
while True:
rpn = decoder.last_changed
if rpn:
print("RPN %i: %i" % (rpn, decoder.values[rpn]))
decoder.last_changed = None
time.sleep(0.1)
@SpotlightKid
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment