78 lines
1.8 KiB
Python
78 lines
1.8 KiB
Python
import math
|
|
from typing import Optional, List
|
|
|
|
import mido
|
|
|
|
PREFIX = [0x00, 0x20, 0x0D, 0x10]
|
|
SUBID_IN_STATUS = 0
|
|
SUBID_IN_RMS = 1
|
|
SUBID_IN_PEAK = 2
|
|
|
|
SUBID_OPTIONS = 0
|
|
SUBID_MIXER = 1
|
|
SUBID_LOOPBACK = 2
|
|
SUBID_INPUT_OUTS = 3
|
|
SUBID_GAIN = 4
|
|
|
|
def decode_message(msg: mido.Message) -> tuple[Optional[int], Optional[List[int]]]:
|
|
msg_bytes = msg.bytes()
|
|
if msg_bytes[:5] != [0xF0] + PREFIX:
|
|
return None, None # noop
|
|
|
|
result_words = []
|
|
try:
|
|
chunks = zip(*[iter(msg_bytes[6:-1])] * 5, strict=True)
|
|
for packed in chunks:
|
|
value = packed[4] << 28 | packed[3] << 21 | packed[2] << 14 | packed[1] << 7 | packed[0]
|
|
result_words.append(value)
|
|
except ValueError:
|
|
pass # invalid message
|
|
|
|
return msg_bytes[5], result_words
|
|
|
|
|
|
def encode_message(subid: int, payload: List[int]) -> mido.Message:
|
|
data = [subid]
|
|
for word in payload:
|
|
data += [
|
|
word & 0x7F,
|
|
word >> 7 & 0x7F,
|
|
word >> 14 & 0x7F,
|
|
word >> 21 & 0x7F,
|
|
word >> 28 & 0x7F,
|
|
]
|
|
|
|
return mido.Message('sysex', data=PREFIX + data)
|
|
|
|
|
|
def hex_format(msg, width=2):
|
|
return ' '.join([("{x:0" + str(width) + "x}").format(x=x) for x in msg])
|
|
|
|
|
|
def bin_format(msg, width=32):
|
|
return ' '.join([("{x:0" + str(width) + "b}").format(x=x) for x in msg])
|
|
|
|
|
|
def get_bitfield(word, position, length):
|
|
return (word >> position) & ((1 << length) - 1)
|
|
|
|
|
|
def set_bitfield(word, val, position, length):
|
|
mask = ((1 << length) - 1)
|
|
val = (val & mask) << position
|
|
return (word & mask << position) | val
|
|
|
|
|
|
def level_to_db(val):
|
|
return 6 + (val - 0xFF) / 2
|
|
|
|
|
|
def fader_to_db(val):
|
|
return 6 + (abs(val) - 0xFF) / 2
|
|
|
|
|
|
def format_db(val, min_db=-120):
|
|
if math.isnan(val) or val <= min_db:
|
|
return '∞'
|
|
else:
|
|
return format(val, '.1f')
|