Source code for jdxi_editor.midi.data.parameter.program.part

"""
Program Part Parameters
======================

Defines the PartParam enum for Program Part parameters (0x18 00 20-23 00).
Per Roland Parameter Address Map (midi_parameters.txt), Program Part has
offsets 0x00-0x4B. Total size 0x4C.

Used for: Digital Synth Part 1 (0x20), Part 2 (0x21), Analog Synth Part (0x22),
Drums Part (0x23).
"""

from typing import Optional, Tuple

from jdxi_editor.midi.parameter.spec import ParameterSpec
from picomidi.sysex.parameter.address import AddressParameter


[docs] class PartParam(AddressParameter): """Program Part parameters (per Roland Parameter Address Map)""" def __init__( self, address: int, min_val: Optional[int] = None, max_val: Optional[int] = None, display_min: Optional[int] = None, display_max: Optional[int] = None, tooltip: Optional[str] = None, display_name: Optional[str] = None, ): super().__init__(address, min_val, max_val)
[docs] self.display_min = display_min if display_min is not None else min_val
[docs] self.display_max = display_max if display_max is not None else max_val
[docs] self.tooltip = tooltip if tooltip is not None else ""
[docs] self._display_name = display_name
# 0x00-0x05
[docs] RECEIVE_CHANNEL = ParameterSpec(0x00, 0, 15) # 1-16
[docs] PART_SWITCH = ParameterSpec(0x01, 0, 1) # OFF, ON
# 0x02-0x05 reserve
[docs] TONE_BANK_SELECT_MSB = ParameterSpec(0x06, 0, 127) # CC# 0
[docs] TONE_BANK_SELECT_LSB = ParameterSpec(0x07, 0, 127) # CC# 32
[docs] TONE_PROGRAM_NUMBER = ParameterSpec(0x08, 0, 127) # PC
# 0x09-0x1A
[docs] PART_LEVEL = ParameterSpec(0x09, 0, 127) # CC# 7
[docs] PART_PAN = ParameterSpec(0x0A, 0, 127) # CC# 10, L64-63R
[docs] PART_COARSE_TUNE = ParameterSpec(0x0B, 16, 112, -48, 48) # RPN# 2
[docs] PART_FINE_TUNE = ParameterSpec(0x0C, 14, 114, -50, 50) # RPN# 1
[docs] PART_MONO_POLY = ParameterSpec(0x0D, 0, 2) # MONO, POLY, TONE
[docs] PART_LEGATO_SWITCH = ParameterSpec(0x0E, 0, 2) # OFF, ON, TONE
[docs] PART_PITCH_BEND_RANGE = ParameterSpec(0x0F, 0, 25) # 0-24, TONE
[docs] PART_PORTAMENTO_SWITCH = ParameterSpec(0x10, 0, 2) # OFF, ON, TONE
[docs] PART_PORTAMENTO_TIME = ParameterSpec(0x11, 0, 128) # 0-127, TONE (2 bytes)
# 0x12 reserve
[docs] PART_CUTOFF_OFFSET = ParameterSpec(0x13, 0, 127, -64, 63) # CC# 74
[docs] PART_RESONANCE_OFFSET = ParameterSpec(0x14, 0, 127, -64, 63) # CC# 71
[docs] PART_ATTACK_TIME_OFFSET = ParameterSpec(0x15, 0, 127, -64, 63) # CC# 73
[docs] PART_DECAY_TIME_OFFSET = ParameterSpec(0x16, 0, 127, -64, 63) # CC# 75
[docs] PART_RELEASE_TIME_OFFSET = ParameterSpec(0x17, 0, 127, -64, 63) # CC# 72
[docs] PART_VIBRATO_RATE = ParameterSpec(0x18, 0, 127, -64, 63) # CC# 76
[docs] PART_VIBRATO_DEPTH = ParameterSpec(0x19, 0, 127, -64, 63) # CC# 77
[docs] PART_VIBRATO_DELAY = ParameterSpec(0x1A, 0, 127, -64, 63) # CC# 78
# 0x1B-0x2E
[docs] PART_OCTAVE_SHIFT = ParameterSpec(0x1B, 61, 67, -3, 3)
[docs] PART_VELOCITY_SENS_OFFSET = ParameterSpec(0x1C, 1, 127, -63, 63)
# 0x1D-0x20 reserve
[docs] VELOCITY_RANGE_LOWER = ParameterSpec(0x21, 1, 127)
[docs] VELOCITY_RANGE_UPPER = ParameterSpec(0x22, 0, 127)
[docs] VELOCITY_FADE_WIDTH_LOWER = ParameterSpec(0x23, 0, 127)
[docs] VELOCITY_FADE_WIDTH_UPPER = ParameterSpec(0x24, 0, 127)
[docs] MUTE_SWITCH = ParameterSpec(0x25, 0, 1) # OFF, MUTE
# 0x26-0x29 reserve # 0x2A reserve
[docs] PART_DELAY_SEND_LEVEL = ParameterSpec(0x2B, 0, 127) # CC# 94
[docs] PART_REVERB_SEND_LEVEL = ParameterSpec(0x2C, 0, 127) # CC# 91
[docs] PART_OUTPUT_ASSIGN = ParameterSpec(0x2D, 0, 4) # EFX1, EFX2, DLY, REV, DIR
# 0x2E reserve # Scale Tune 0x2F-0x3C
[docs] PART_SCALE_TUNE_TYPE = ParameterSpec(0x2F, 0, 8)
[docs] PART_SCALE_TUNE_KEY = ParameterSpec(0x30, 0, 11)
[docs] PART_SCALE_TUNE_C = ParameterSpec(0x31, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_CS = ParameterSpec(0x32, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_D = ParameterSpec(0x33, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_DS = ParameterSpec(0x34, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_E = ParameterSpec(0x35, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_F = ParameterSpec(0x36, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_FS = ParameterSpec(0x37, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_G = ParameterSpec(0x38, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_GS = ParameterSpec(0x39, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_A = ParameterSpec(0x3A, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_AS = ParameterSpec(0x3B, 0, 127, -64, 63)
[docs] PART_SCALE_TUNE_B = ParameterSpec(0x3C, 0, 127, -64, 63)
# Receive switches 0x3D-0x46
[docs] RECEIVE_PROGRAM_CHANGE = ParameterSpec(0x3D, 0, 1)
[docs] RECEIVE_BANK_SELECT = ParameterSpec(0x3E, 0, 1)
[docs] RECEIVE_PITCH_BEND = ParameterSpec(0x3F, 0, 1)
[docs] RECEIVE_POLYPHONIC_KEY_PRESSURE = ParameterSpec(0x40, 0, 1)
[docs] RECEIVE_CHANNEL_PRESSURE = ParameterSpec(0x41, 0, 1)
[docs] RECEIVE_MODULATION = ParameterSpec(0x42, 0, 1)
[docs] RECEIVE_VOLUME = ParameterSpec(0x43, 0, 1)
[docs] RECEIVE_PAN = ParameterSpec(0x44, 0, 1)
[docs] RECEIVE_EXPRESSION = ParameterSpec(0x45, 0, 1)
[docs] RECEIVE_HOLD_1 = ParameterSpec(0x46, 0, 1)
[docs] def get_display_value(self) -> Tuple[int, int]: """Get the digital value range (min, max) for the parameter""" if hasattr(self, "display_min") and hasattr(self, "display_max"): return self.display_min, self.display_max return self.min_val, self.max_val
@property
[docs] def display_name(self) -> str: """Get display name for the parameter.""" if getattr(self, "_display_name", None) is not None: return self._display_name return self.name.replace("_", " ").title()
[docs] def get_address_for_partial(self, partial_number: int = 0) -> Tuple[int, int]: """Get parameter area and address adjusted for part number (0-3).""" group_map = {0: 0x20, 1: 0x21, 2: 0x22, 3: 0x23} group = group_map.get(partial_number, 0x20) return group, self.address
@staticmethod
[docs] def get_by_name(param_name: str) -> Optional["PartParam"]: """Get the Parameter by name.""" return PartParam.__members__.get(param_name, None)