Source code for jdxi_editor.ui.editors.digital.utils

"""
This module contains utility functions for handling SysEx data related to digital synths.
"""

import logging

from decologr import Decologr as log

from jdxi_editor.midi.data.address.address import (
    AddressOffsetTemporaryToneUMB,
    AddressStartMSB,
)
from jdxi_editor.midi.map.temporary_area import TEMPORARY_AREA_MAP
from jdxi_editor.midi.sysex.request.data import IGNORED_KEYS, SYNTH_PARTIAL_MAP


[docs] def filter_sysex_keys(sysex_data: dict) -> dict: """ Filter out unwanted keys from the SysEx data. :param sysex_data: dict :return: dict """ return {k: v for k, v in sysex_data.items() if k not in IGNORED_KEYS}
[docs] def _get_synth_number(synth_tone: str) -> int: """ Get the synth number based on the synth tone. :param synth_tone: str :return: int """ synth_map = { AddressStartMSB.TEMPORARY_TONE: 1, AddressStartMSB.DIGITAL_2: 2, } synth_no = synth_map.get(synth_tone) if synth_no is None: logging.warning(f"Unknown synth tone: {synth_tone}") else: log.parameter("Synth number:", synth_no) return synth_no
[docs] def get_partial_number(synth_tone: str, partial_map: dict = SYNTH_PARTIAL_MAP) -> int: """ Get the partial number based on the synth tone. :param synth_tone: str :param partial_map: str :return: int """ partial_no = partial_map.get(synth_tone) if partial_no is None: log.message(f"Unknown synth tone: {synth_tone}", level=logging.WARNING) return partial_no
[docs] def _is_valid_sysex_area(sysex_data: dict) -> bool: """ Check if the SysEx data is from a valid digital synth area. :param sysex_data: dict :return: bool """ temporary_area = sysex_data.get("TEMPORARY_AREA") return temporary_area in [ "DIGITAL_SYNTH_1", "DIGITAL_SYNTH_2", ]
[docs] def log_synth_area_info(sysex_data: dict) -> None: """ Log information about the SysEx area. :param sysex_data: dict :return: None """ if not _is_valid_sysex_area(sysex_data): log.message( "SysEx data not from a valid digital synth area. Skipping.", level=logging.WARNING, ) return
[docs] def _is_digital_synth_area(area_code: int) -> bool: """ Check if the area code corresponds to a digital synth area. :param area_code: int :return: bool """ return area_code in [AddressStartMSB.TEMPORARY_TONE]
[docs] def _sysex_area_matches(sysex_data: dict, area: int) -> bool: """ Check if the SysEx data matches the expected area. :param sysex_data: dict :param area: int :return: bool """ temp_area = sysex_data.get("TEMPORARY_AREA") area_map = { AddressStartMSB.TEMPORARY_TONE: "DIGITAL_SYNTH_1", } expected_area = area_map.get(area) match = temp_area == expected_area log.message( f"SysEx TEMP_AREA: {temp_area}, expected: {expected_area}, match: {match}" ) return match
[docs] def _sysex_area2_matches(sysex_data: dict, area: int) -> bool: """ Check if the SysEx data matches the expected area. :param sysex_data: dict :param area: int :return: bool """ temp_area = sysex_data.get("TEMPORARY_AREA") area_map = { AddressStartMSB.DIGITAL_2: "DIGITAL_SYNTH_2", } expected_area = area_map.get(area) match = temp_area == expected_area log.message( f"SysEx TEMP_AREA: {temp_area}, expected: {expected_area}, match: {match}" ) return match
[docs] def _sysex_tone_matches(sysex_data: dict, tone: int) -> bool: """ Check if the SysEx data matches the expected area. :param sysex_data: dict :param tone: int :return: bool """ log.message(f"looking for tone {tone}") temp_part = sysex_data.get("SYNTH_TONE") log.message(f"found part {temp_part}") part_map = { AddressOffsetTemporaryToneUMB.DIGITAL_SYNTH_1: "PARTIAL_1", AddressOffsetTemporaryToneUMB.DIGITAL_SYNTH_2: "PARTIAL_2", } expected_part = part_map.get(tone) match = tone == expected_part log.message(f"SysEx PART: {temp_part}, expected: {expected_part}, match: {match}") return match
[docs] def get_area(data: list) -> str: """ Map address bytes to corresponding temporary area. :param data: list[int, int] :return: str """ return TEMPORARY_AREA_MAP.get(tuple(data), "Unknown")
[docs] def to_hex(value: int, width: int = 2) -> str: """ Convert a value to a hex string. :param value: int :param width: int :return: str """ try: int_value = int(value, 0) if isinstance(value, str) else value hex_str = f"{int_value:0{width}X}" log.message(f"to_hex: value: {value} -> 0x{int(int_value):02X} (width={width})") return hex_str except Exception as ex: log.error(f"Error {ex} occurred in to_hex with value: {value}") return "??"