Live Performance

Real-time MIDI synthesis. See the Live Performance guide for a tutorial.

Note

Live MIDI input requires python-rtmidi — install with pip install "pytheory[live]".

Real-time MIDI-driven synthesis engine.

Listens for MIDI input (e.g. from an OP-XY, keyboard, or DAW) and synthesizes audio in real-time through pytheory’s synth engine.

Usage:

from pytheory.live import LiveEngine

engine = LiveEngine()
engine.channel(1, instrument="electric_piano")
engine.channel(2, instrument="bass_guitar", lowpass=800)
engine.channel(10, drums=True)
engine.start()  # blocks until Ctrl-C

Notes are pre-rendered to a 3-second wavetable. Sustaining instruments (organ, pads, strings — any envelope with a nonzero sustain level) loop seamlessly inside the wavetable, so held keys ring for as long as you hold them. Percussive instruments (piano, plucks) decay naturally and end.

Effects (lowpass, reverb, chorus, delay, tremolo, distortion, saturation) run on each channel’s bus in real time, so MIDI CC sweeps are smooth and instant — no wavetable re-rendering.

class pytheory.live.LiveEngine(buffer_size=512, sample_rate=44100)[source]

Bases: object

Real-time MIDI-to-audio engine.

Maps MIDI channels to pytheory instruments and synthesizes audio in real-time via sounddevice.

Example:

engine = LiveEngine()
engine.channel(1, instrument="electric_piano")
engine.channel(2, instrument="bass_guitar")
engine.channel(10, drums=True)
engine.start()
channel(ch, *, instrument=None, synth=None, envelope=None, drums=False, **kwargs)[source]

Configure a MIDI channel.

Parameters:
  • ch – MIDI channel number (1-16). Channel 10 = drums by convention.

  • instrument – Instrument preset name (e.g. “electric_piano”).

  • synth – Synth waveform name (overrides instrument).

  • envelope – Envelope name (overrides instrument).

  • drums – If True, this channel triggers drum sounds by MIDI note.

  • **kwargs – Any Part parameter (lowpass, reverb, volume, etc.)

drums(pattern_name, *, volume=0.5)[source]

Add a drum pattern that syncs to MIDI clock.

The pattern plays in sync with the OP-XY’s transport - starts on Start, stops on Stop, tempo from MIDI clock.

Parameters:
  • pattern_name – Drum pattern preset name (e.g. “rock”, “house”).

  • volume – Drum volume (0.0-1.0).

cc(cc_number, param, *, min_val=0.0, max_val=1.0, ch=None)[source]

Map a MIDI CC to a channel parameter.

Parameters:
  • cc_number – MIDI CC number (0-127).

  • param – Parameter name (“volume”, “lowpass”, “reverb”, etc.)

  • min_val – Value when CC = 0.

  • max_val – Value when CC = 127.

  • ch – MIDI channel (None = all channels).

Example:

>>> engine.cc(11, "lowpass", min_val=200, max_val=8000)
>>> engine.cc(12, "volume", min_val=0.0, max_val=1.0)
>>> engine.cc(13, "reverb", min_val=0.0, max_val=0.8)
>>> engine.cc(14, "distortion", min_val=0.0, max_val=0.8)
list_ports()[source]

List available MIDI input ports.

start(port=None)[source]

Start the engine - opens MIDI input and audio output.

Parameters:

port – MIDI port index or name. None = first available.

Blocks until Ctrl-C or stop() is called.

keyboard_play(ch=1)[source]

Enable computer keyboard as MIDI input on a channel.

keyboard_note(key, on=True)[source]

Translate a keyboard key to a MIDI note and play it.

QWERTY layout: ZSXDCVGBHNJM = C through B (lower octave)

Q2W3ER5T6Y7U = C through B (upper octave)

start_recording()[source]

Start recording MIDI events.

stop_recording()[source]

Stop recording.

export_recording(filename='recording.mid', bpm=None)[source]

Export recorded events to a MIDI file.

Returns a pytheory Score if no filename given.

save_config(filename)[source]

Save current configuration to JSON.

load_config(filename)[source]

Load configuration from JSON.

stop()[source]

Stop the engine.