babymix/encoding.py
Brian Hrebec 04060ef5a1 Added basic functionality
- gain
- mute
- mixer
- channel setup options
- keybinds and mousebinds
- focus behavior
2026-03-12 23:33:13 -05:00

93 lines
No EOL
2.2 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
"""
Special level calculation for main/ph outputs
"""
def level_to_db(val):
return 6 + (val - 0xFF) / 2
"""
Special level calculation for main/ph outputs
"""
def db_to_level(val):
return int((val - 6) * 2) + 0xFF
def db_to_fader(db):
return int(10 ** (db / 20) * 0x40000)
def format_db(val, min_db=-120):
if math.isnan(val) or val <= min_db:
return ''
else:
return format(val, '.1f')
def map_range(val, min_, max_, low, high):
return ((clamp(val, min_, max_) - min_) / (max_ - min_)) * (high - low) + low
def clamp(val, low, high):
return max(min(val, high), low)