MIDI¶
MIDI I/O via embedded RtMidi: message types, MidiIn, MidiOut, and the MIDI clock bridge.
See the MIDI Guide for usage.
nanosynth.midi ¶
MIDI input and output via embedded RtMidi.
Provides parsed MIDI message types, MidiIn and MidiOut ports, and
MIDI clock send (MidiClockOut) and receive (MidiClockIn) bridged to a
pattern :class:~nanosynth.patterns.Clock.
This module requires the _midi C extension (built by default with
NANOSYNTH_EMBED_MIDI=ON). If unavailable, importing this module
raises ImportError.
Basic usage::
from nanosynth.midi import MidiIn, NoteOn
midi = MidiIn(port=0)
midi.on_note_on(lambda msg: print(f"Note {msg.note} vel {msg.velocity}"))
# ...
midi.close()
# Or as context manager:
with MidiIn(port=0) as midi:
midi.on_cc(lambda msg: print(f"CC {msg.control} = {msg.value}"))
input("Press Enter to quit...")
NoteOn
dataclass
¶
MIDI Note On message.
NoteOff
dataclass
¶
MIDI Note Off message.
ControlChange
dataclass
¶
MIDI Control Change (CC) message.
PitchBend
dataclass
¶
MIDI Pitch Bend message.
Value range is 0--16383, with 8192 as center (no bend).
ProgramChange
dataclass
¶
MIDI Program Change message.
Aftertouch
dataclass
¶
MIDI Channel Pressure (channel aftertouch) message.
PolyAftertouch
dataclass
¶
MIDI Polyphonic Key Pressure (per-note aftertouch) message.
SongPosition
dataclass
¶
MIDI Song Position Pointer, in sixteenth notes (0--16383).
TimingClock
dataclass
¶
MIDI Timing Clock tick (24 per quarter note).
Start
dataclass
¶
MIDI Start (transport).
Continue
dataclass
¶
MIDI Continue (transport).
Stop
dataclass
¶
MIDI Stop (transport).
MidiIn ¶
MIDI input port.
Args:
port: Port to open. None opens a virtual port,
int opens by index, str matches by name.
receive_clock: Deliver Timing Clock ticks (TimingClock), which
RtMidi drops by default. Transport messages arrive either way.
Raises:
ImportError: If the _midi C extension is not available.
RuntimeError: If the requested port cannot be opened.
on ¶
on(
msg_type: type[M], callback: Callable[[M], None]
) -> None
Register a handler for one message type, e.g. on(ProgramChange, f).
off ¶
off(
msg_type: type[M], callback: Callable[[M], None]
) -> None
Remove a handler registered with :meth:on. Unknown handlers are ignored.
on_note_on ¶
on_note_on(callback: Callable[[NoteOn], None]) -> None
Register a handler for Note On messages.
on_note_off ¶
on_note_off(callback: Callable[[NoteOff], None]) -> None
Register a handler for Note Off messages.
on_cc ¶
on_cc(callback: Callable[[ControlChange], None]) -> None
Register a handler for Control Change messages.
on_pitch_bend ¶
on_pitch_bend(
callback: Callable[[PitchBend], None],
) -> None
Register a handler for Pitch Bend messages.
off_pitch_bend ¶
off_pitch_bend(
callback: Callable[[PitchBend], None],
) -> None
Remove a Pitch Bend handler.
list_ports
staticmethod
¶
list_ports() -> list[str]
Return a list of available MIDI input port names.
MidiOut ¶
MIDI output port.
Args:
port: Port to open. None opens a virtual port,
int opens by index, str matches by name.
Example::
with MidiOut("Synth") as out:
out.send(ProgramChange(channel=0, program=5))
out.send(NoteOn(channel=0, note=60, velocity=100))
list_ports
staticmethod
¶
list_ports() -> list[str]
Return a list of available MIDI output port names.
MidiClockOut ¶
Send MIDI Timing Clock and transport, following a pattern Clock.
Ticks run on a daemon thread at PPQN per beat of clock.bpm; tempo
changes apply from the next tick. :meth:start sends Start and
begins ticking on the clock's next beat; :meth:stop sends Stop.
Args: midi_out: Destination port. clock: Tempo source.
MidiClockIn ¶
Slave a pattern Clock to incoming MIDI Timing Clock.
Sets clock.bpm from the mean tick interval over the last beat, and
re-anchors the clock's beat grid on each received beat so quantized
players stay in phase with the master. Start resets the grid to beat
0; SongPosition moves it.
The MidiIn must be opened with receive_clock=True.
Args: midi_in: Source port. clock: Clock to drive.
midi_note_map ¶
midi_note_map(
midi_in: MidiIn,
server: Server,
synthdef_name: str,
**fixed_params: float,
) -> Callable[[], None]
Map MIDI note-on to synth creation and note-off to gate release.
Creates a synth for each note-on with freq derived from the MIDI
note number. On note-off, sends gate=0 to the corresponding synth.
Args: midi_in: The MidiIn instance to listen on. server: The Server to create synths on. synthdef_name: Name of the SynthDef to instantiate. **fixed_params: Additional fixed parameters for all synths.
Returns: A cleanup function that removes the handlers.
midi_cc_map ¶
midi_cc_map(
midi_in: MidiIn,
server: Server,
synth: Synth | int,
cc_map: dict[int, str],
*,
range_min: float = 0.0,
range_max: float = 1.0,
) -> Callable[[], None]
Map MIDI CC numbers to synth parameters.
Each CC value (0--127) is linearly scaled to [range_min, range_max]
and sent as the mapped parameter name.
Args: midi_in: The MidiIn instance to listen on. server: The Server for parameter updates. synth: Target synth (Synth proxy or node ID). cc_map: Mapping of CC number to parameter name. range_min: Output range minimum. range_max: Output range maximum.
Returns: A cleanup function that removes the handler.