jdxi_editor.ui.editors.pattern.learner ====================================== .. py:module:: jdxi_editor.ui.editors.pattern.learner .. autoapi-nested-parse:: Pattern Learner Module Handles MIDI input learning for the Pattern Sequencer. Captures incoming MIDI notes and records them into the pattern grid in real-time, supporting both note-on and note-off events with automatic step advancement. Attributes ---------- .. autoapisummary:: jdxi_editor.ui.editors.pattern.learner.converter Classes ------- .. autoapisummary:: jdxi_editor.ui.editors.pattern.learner.PatternLearnerState jdxi_editor.ui.editors.pattern.learner.PatternLearnerConfig jdxi_editor.ui.editors.pattern.learner.PatternLearnerEvent jdxi_editor.ui.editors.pattern.learner.PatternLearner Module Contents --------------- .. py:class:: PatternLearnerState Enumeration of learning states. .. py:attribute:: IDLE :value: 'idle' .. py:attribute:: LEARNING :value: 'learning' .. py:attribute:: STOPPED :value: 'stopped' .. py:class:: PatternLearnerConfig(total_steps: int = 16, total_rows: int = 4, default_velocity: int = 100, default_duration_ms: float = 120.0) Configuration for the pattern learner. .. py:attribute:: total_steps :value: 16 .. py:attribute:: total_rows :value: 4 .. py:attribute:: default_velocity :value: 100 .. py:attribute:: default_duration_ms :value: 120.0 .. py:class:: PatternLearnerEvent(step: int, row: int, note: int, velocity: int, duration_ms: float, midi_note: picomidi.messages.note.MidiNote | None = None) Represents a learned pattern event. .. py:attribute:: step .. py:attribute:: row .. py:attribute:: note .. py:attribute:: velocity .. py:attribute:: duration_ms .. py:attribute:: midi_note .. py:class:: PatternLearner(config: Optional[PatternLearnerConfig] = None, midi_converter: Optional[jdxi_editor.midi.conversion.note.MidiNoteConverter] = None, scope: str = 'PatternLearner') Learns pattern from incoming MIDI messages. Captures MIDI note-on and note-off events and records them into a pattern grid. Automatically advances through steps as notes are released. .. py:attribute:: config .. py:attribute:: midi_converter :value: None .. py:attribute:: scope :value: 'PatternLearner' .. py:attribute:: state :value: 'idle' .. py:attribute:: current_step :value: 0 .. py:attribute:: current_measure_index :value: 0 .. py:attribute:: learned_pattern :type: List[List[Optional[int]]] .. py:attribute:: active_notes :type: Dict[int, int] .. py:attribute:: midi_track .. py:attribute:: on_step_advance :type: Optional[Callable[[int], None]] :value: None .. py:attribute:: on_note_learned :type: Optional[Callable[[PatternLearnerEvent], None]] :value: None .. py:attribute:: on_learning_stopped :type: Optional[Callable[[], None]] :value: None .. py:attribute:: on_learning_started :type: Optional[Callable[[], None]] :value: None .. py:attribute:: learned_events :type: List[PatternLearnerEvent] :value: [] .. py:method:: start_learning() -> None Start the pattern learning process. .. py:method:: stop_learning() -> None Stop the pattern learning process. .. py:method:: process_midi_message(message: mido.Message) -> None Process an incoming MIDI message during learning. Handles NOTE_ON (velocity > 0) and NOTE_OFF messages. Automatically advances the step when a note-off is received. :param message: Mido Message object .. py:method:: _handle_note_on(message: mido.Message) -> None Handle a NOTE_ON message. Records the note in the learned pattern and marks it as active. :param message: Mido NOTE_ON message with velocity > 0 .. py:method:: _handle_note_off(message: mido.Message) -> None Handle a NOTE_OFF message or NOTE_ON with velocity 0. Marks the note as inactive and advances to the next step. :param message: Mido NOTE_OFF message or NOTE_ON with velocity 0 .. py:method:: _advance_step() -> None Advance to the next step in the pattern. .. py:method:: _find_row_for_note(midi_note: int) -> Optional[int] Find the row that corresponds to a MIDI note. Uses the MIDI converter if available, otherwise falls back to hardcoded ranges. :param midi_note: MIDI note number :return: Row index (0-3) or None if note doesn't match any row .. py:method:: clear_learned_pattern() -> None Clear the learned pattern and reset state. .. py:method:: get_learned_pattern() -> List[List[Optional[int]]] Get the learned pattern. :return: 2D list where pattern[row][step] = MIDI note number or None .. py:method:: get_learned_events() -> List[PatternLearnerEvent] Get all events that occurred during learning. :return: List of PatternLearnerEvent objects .. py:method:: get_pattern_for_row(row: int) -> List[Optional[int]] Get the learned pattern for a specific row. :param row: Row index (0-3) :return: List of MIDI notes for the row (or None for empty steps) .. py:method:: get_midi_track() Get the recorded MIDI track. :return: MidiTrack object with NOTE_ON and NOTE_OFF messages .. py:method:: is_learning() -> bool Check if currently learning. .. py:method:: set_config(config: PatternLearnerConfig) -> None Update the learner configuration. :param config: New configuration .. py:method:: set_midi_converter(converter: jdxi_editor.midi.conversion.note.MidiNoteConverter) -> None Set or update the MIDI converter. :param converter: MidiNoteConverter instance .. py:data:: converter