subsequence.pattern =================== .. py:module:: subsequence.pattern .. autoapi-nested-parse:: Immutable note and pattern data types — the rendered output layer. Defines ``Note`` (a single scheduled MIDI event) alongside the control-event records (``CcEvent``, ``RawNoteEvent``, ``OscEvent``) and ``Pattern``, the ordered bag of events that ``PatternBuilder`` produces and the sequencer schedules. These are plain data; the building verbs live in ``pattern_builder``. Module Contents --------------- .. py:class:: CcEvent A MIDI non-note event (CC, pitch bend, program change, SysEx) at a pulse position. .. py:class:: Note Represents a single MIDI note. .. py:class:: OscEvent An OSC message scheduled at a pulse position within a pattern. .. py:class:: Pattern(channel: int, length: float = 16, reschedule_lookahead: float = 1, device: int = 0, mirrors: Optional[Iterable[MirrorSpec]] = None) Allows us to define and manipulate music pattern objects. Initialize a new pattern with MIDI channel, length in beats, and reschedule lookahead. :param channel: The MIDI channel (0-15) this pattern will output to. :param length: The duration of the pattern before it loops/rebuilds, measured in beats (e.g., 16 = 4 bars in 4/4 time). Defaults to 16. :param reschedule_lookahead: How many beats before the end of the pattern the next cycle is built. Defaults to 1 beat. This provides a safe computational buffer so events are queued before the clock actually needs them. :param device: Output device index (0-indexed). 0 = primary device (default). :param mirrors: Additional ``(device, channel)`` destinations to duplicate every note, CC, pitch bend, program change, SysEx, NRPN/RPN burst, and drone event onto. Both ``device`` and ``channel`` are 0-indexed in canonical form; the user-facing entry points (decorator and runtime API on ``Composition``) translate the user's channel-numbering convention before storing here. An entry may carry an optional third element — a ``drum_note_map`` — so a mirrored drum hit is re-resolved by name to that device's own note number (see ``Sequencer.schedule_pattern``). .. py:method:: add_arpeggio_beats(pitches: List[int], spacing_beats: float, velocity: int = subsequence.constants.velocity.DEFAULT_VELOCITY, duration_beats: Optional[float] = None, pulses_per_beat: int = subsequence.constants.MIDI_QUARTER_NOTE) -> None Add an arpeggio that cycles through pitches at regular intervals. .. py:method:: add_note(position: int, pitch: int, velocity: int, duration: int, origin: Optional[str] = None, primary_unmapped: bool = False) -> None Add a note to the pattern at a specific pulse position. ``origin`` is the original drum-name string when the pitch was named (e.g. ``"hi_hat_closed"``), or ``None`` for numeric pitches. It is carried on the Note so mirror destinations can re-resolve the name through their own ``drum_note_map`` — see ``Sequencer.schedule_pattern``. ``primary_unmapped`` marks a named hit whose ``origin`` is absent from this pattern's own ``drum_note_map`` but present in a mirror's — the primary device can't voice it, so it stays silent and only the mapping mirror(s) sound it. .. py:method:: add_note_beats(beat_position: float, pitch: int, velocity: int, duration_beats: float, pulses_per_beat: int = subsequence.constants.MIDI_QUARTER_NOTE, origin: Optional[str] = None, primary_unmapped: bool = False) -> None Add a note to the pattern at a beat position. ``origin`` and ``primary_unmapped`` are forwarded to ``add_note`` so the resulting Note carries the drum name and its primary-map status. .. py:method:: add_raw_note_beats(message_type: str, beat_position: float, pitch: int, velocity: int = 0, pulses_per_beat: int = subsequence.constants.MIDI_QUARTER_NOTE) -> None Add a raw Note On or Note Off event at a beat position (ignores duration). .. py:method:: add_sequence(sequence: List[int], spacing_pulses: int, pitch: int, velocity: Union[int, List[int]] = subsequence.constants.velocity.DEFAULT_VELOCITY, note_duration: int = 6) -> None Add a sequence of notes to the pattern. .. py:method:: add_sequence_beats(sequence: List[int], spacing_beats: float, pitch: int, velocity: Union[int, List[int]] = subsequence.constants.velocity.DEFAULT_VELOCITY, note_duration_beats: float = 0.25, pulses_per_beat: int = subsequence.constants.MIDI_QUARTER_NOTE) -> None Add a sequence of notes using beat durations. .. py:method:: on_reschedule() -> None Hook called immediately before the pattern is rescheduled. .. py:class:: RawNoteEvent An explicit Note On or Note Off event at a pulse position, ignoring durations. Used for drones and infinite notes. .. py:class:: Step Represents a collection of notes at a single point in time.