"""
Analog Oscillator Section
"""
from typing import Callable
from decologr import Decologr as log
from jdxi_editor.midi.data.address.address import JDXiSysExAddress
from jdxi_editor.midi.data.analog.oscillator import AnalogOscillatorWidgetTypes
from jdxi_editor.midi.data.parameter.analog.spec import JDXiMidiAnalog as Analog
from jdxi_editor.midi.io.helper import MidiIOHelper
from jdxi_editor.ui.editors.analog.oscillator.widget import AnalogOscillatorWidgets
from jdxi_editor.ui.editors.analog.oscillator.widget_spec import (
AnalogOscillatorLayoutSpec,
)
from jdxi_editor.ui.editors.base.layout.spec import OscillatorFeature
from jdxi_editor.ui.editors.base.oscillator.section import BaseOscillatorSection
from jdxi_editor.ui.editors.base.oscillator.widget import OscillatorWidgets
from jdxi_editor.ui.widgets.editor import IconType
from jdxi_editor.ui.widgets.spec import (
PitchEnvelopeSpec,
PWMSpec,
SliderSpec,
SwitchSpec,
)
[docs]
class AnalogOscillatorSection(BaseOscillatorSection):
"""Analog Oscillator Section"""
def __init__(
self,
waveform_selected_callback: Callable,
wave_buttons: dict,
midi_helper: MidiIOHelper,
address: JDXiSysExAddress,
send_midi_parameter: Callable = None,
):
"""
Initialize the AnalogOscillatorSection
:param waveform_selected_callback: Callable
:param wave_buttons: dict to store waveform buttons (waveform -> button mapping)
:param midi_helper: MidiIOHelper
:param address: RolandSysExAddress
:param send_midi_parameter: Callable to send MIDI parameter updates
"""
log.info(
scope=self.__class__.__name__,
message="AnalogOscillatorSection __init__ start (address=%s)"
% (getattr(address, "__repr__", lambda: address)(),),
)
[docs]
self.analog: bool = True
[docs]
self.wave_shapes = self.generate_mode_button_specs()
log.info(scope=self.__class__.__name__, message="_define_spec ...")
self._define_spec()
log.info(scope=self.__class__.__name__, message="calling super().__init__ ...")
super().__init__(
icons_row_type=IconType.OSCILLATOR,
analog=True,
midi_helper=midi_helper,
address=address,
send_midi_parameter=send_midi_parameter,
)
log.info(
scope=self.__class__.__name__,
message="after super().__init__ (controls keys: %s)"
% (list(self.controls.keys()) if getattr(self, "controls", None) else [],),
)
log.info(scope=self.__class__.__name__, message="calling finalize() ...")
self.finalize()
log.info(
scope=self.__class__.__name__,
message="AnalogOscillatorSection __init__ done.",
)
[docs]
def _define_spec(self):
self.spec: AnalogOscillatorLayoutSpec = self._build_layout_spec()
[docs]
def _create_suboscillator_switches(self):
"""Sub Oscillator Type switch; optional when SWITCH_SPECS is empty"""
if not hasattr(self, "spec") or not hasattr(self.spec, "switches"):
switches = []
else:
switches = self._build_switches(self.spec.switches)
self.sub_oscillator_type_switch = switches[0] if len(switches) == 1 else None
[docs]
def _create_env_slider(self):
"""Create env sliders"""
# Only one slider BTW, despite the plural name
env_sliders = self._build_sliders(self.spec.env)
self.osc_pitch_env_velocity_sensitivity_slider = (
env_sliders[0] if len(env_sliders) == 1 else None
)
[docs]
def _build_layout_spec(self) -> AnalogOscillatorLayoutSpec:
"""Build Analog Oscillator Layout Spec"""
S = self.SYNTH_SPEC
switches = [
SwitchSpec(
S.Param.SUB_OSCILLATOR_TYPE,
S.Param.SUB_OSCILLATOR_TYPE.display_name,
options=S.Display.Options.SUB_OSCILLATOR_TYPE,
),
]
tuning = [
SliderSpec(
S.Param.OSC_PITCH_COARSE,
S.Display.Name.OSC_PITCH_COARSE,
vertical=True,
),
SliderSpec(
S.Param.OSC_PITCH_FINE,
S.Display.Name.OSC_PITCH_FINE,
vertical=True,
),
]
# --- Analog has this extra parameter, so here is the slider
env = [
SliderSpec(
S.Param.OSC_PITCH_ENV_VELOCITY_SENSITIVITY,
S.Display.Name.OSC_PITCH_ENV_VELOCITY_SENSITIVITY,
vertical=True,
)
]
pwm = PWMSpec(
pulse_width_param=Analog.Param.OSC_PULSE_WIDTH,
mod_depth_param=Analog.Param.OSC_PULSE_WIDTH_MOD_DEPTH,
)
pitch_env = PitchEnvelopeSpec(
attack_param=Analog.Param.OSC_PITCH_ENV_ATTACK_TIME,
decay_param=Analog.Param.OSC_PITCH_ENV_DECAY_TIME,
depth_param=Analog.Param.OSC_PITCH_ENV_DEPTH,
)
return AnalogOscillatorLayoutSpec(
switches=switches,
tuning=tuning,
env=env,
pwm=pwm,
pitch_env=pitch_env,
features={
OscillatorFeature.WAVEFORM,
OscillatorFeature.TUNING,
OscillatorFeature.PWM,
OscillatorFeature.PITCH_ENV,
OscillatorFeature.PW_SHIFT,
},
feature_tabs={
OscillatorFeature.TUNING: "_add_tuning_tab",
OscillatorFeature.PWM: "_add_pwm_tab",
OscillatorFeature.PITCH_ENV: "_add_pitch_env_tab",
},
)