CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-mingus

Python music theory and MIDI processing library for programmers, musicians, composers, and researchers.

Pending
Overview
Eval results
Files

midi-operations.mddocs/

MIDI Operations

MIDI sequencing, playback, file I/O, and FluidSynth integration for real-time audio synthesis and MIDI file processing. These modules enable mingus to interface with MIDI devices, generate MIDI files, and provide audio output through software synthesizers.

Capabilities

MIDI Sequencer

Core MIDI sequencer for real-time playback and MIDI event handling with observer pattern support.

class Sequencer:
    """Main MIDI sequencer for real-time playback."""
    
    def __init__(self):
        """Create Sequencer object."""
    
    def init(self) -> None:
        """Initialize sequencer for playback."""
    
    def play_Note(self, note: Note, channel: int = 1, velocity: int = 100) -> None:
        """
        Play Note object.
        
        Parameters:
        - note: Note object to play
        - channel: MIDI channel (1-16)
        - velocity: MIDI velocity (0-127)
        """
    
    def stop_Note(self, note: Note, channel: int = 1) -> None:
        """
        Stop Note object.
        
        Parameters:
        - note: Note object to stop
        - channel: MIDI channel (1-16)
        """
    
    def play_NoteContainer(self, nc: NoteContainer, channel: int = 1, velocity: int = 100) -> None:
        """
        Play NoteContainer (chord).
        
        Parameters:
        - nc: NoteContainer to play
        - channel: MIDI channel
        - velocity: MIDI velocity
        """
    
    def stop_NoteContainer(self, nc: NoteContainer, channel: int = 1) -> None:
        """
        Stop NoteContainer.
        
        Parameters:
        - nc: NoteContainer to stop
        - channel: MIDI channel
        """
    
    def play_Bar(self, bar: Bar, channel: int = 1, bpm: int = 120) -> None:
        """
        Play Bar with timing.
        
        Parameters:
        - bar: Bar object to play
        - channel: MIDI channel
        - bpm: Beats per minute tempo
        """
    
    def play_Track(self, track: Track, channel: int = 1, bpm: int = 120) -> None:
        """
        Play Track.
        
        Parameters:
        - track: Track object to play
        - channel: MIDI channel
        - bpm: Beats per minute tempo
        """
    
    def play_Composition(self, composition: Composition, channels: List[int] = None, bpm: int = 120) -> None:
        """
        Play Composition with multiple tracks.
        
        Parameters:
        - composition: Composition to play
        - channels: List of MIDI channels for each track
        - bpm: Beats per minute tempo
        """
    
    def set_instrument(self, channel: int, instr: int, bank: int = 0) -> None:
        """
        Set instrument for channel.
        
        Parameters:
        - channel: MIDI channel (1-16)
        - instr: MIDI instrument number (0-127)
        - bank: Bank number for instrument selection
        """
    
    def control_change(self, channel: int, control: int, value: int) -> None:
        """
        Send control change message.
        
        Parameters:
        - channel: MIDI channel (1-16)
        - control: Controller number (0-127)
        - value: Controller value (0-127)
        """
    
    def modulation(self, channel: int, value: int) -> None:
        """
        Set modulation (CC1).
        
        Parameters:
        - channel: MIDI channel
        - value: Modulation amount (0-127)
        """
    
    def main_volume(self, channel: int, value: int) -> None:
        """
        Set main volume (CC7).
        
        Parameters:
        - channel: MIDI channel
        - value: Volume level (0-127)
        """
    
    def pan(self, channel: int, value: int) -> None:
        """
        Set pan position (CC10).
        
        Parameters:
        - channel: MIDI channel
        - value: Pan position (0=left, 64=center, 127=right)
        """
    
    def stop_everything(self) -> None:
        """Stop all playing notes and reset sequencer."""
    
    def sleep(self, seconds: float) -> None:
        """
        Sleep for specified duration.
        
        Parameters:
        - seconds: Sleep duration in seconds
        """
    
    def attach(self, observer: 'SequencerObserver') -> None:
        """
        Attach observer for event notifications.
        
        Parameters:
        - observer: Observer object to attach
        """
    
    def detach(self, observer: 'SequencerObserver') -> None:
        """
        Detach observer.
        
        Parameters:
        - observer: Observer object to detach
        """

class SequencerObserver:
    """Observer for sequencer events."""
    
    def play_int_note_event(self, int_note: int, channel: int, velocity: int) -> None:
        """
        Handle note on event.
        
        Parameters:
        - int_note: MIDI note number (0-127)
        - channel: MIDI channel
        - velocity: Note velocity
        """
    
    def stop_int_note_event(self, int_note: int, channel: int) -> None:
        """
        Handle note off event.
        
        Parameters:
        - int_note: MIDI note number
        - channel: MIDI channel
        """
    
    def cc_event(self, channel: int, control: int, value: int) -> None:
        """
        Handle control change event.
        
        Parameters:
        - channel: MIDI channel
        - control: Controller number
        - value: Controller value
        """
    
    def instr_event(self, channel: int, instr: int, bank: int) -> None:
        """
        Handle instrument change event.
        
        Parameters:
        - channel: MIDI channel
        - instr: Instrument number
        - bank: Bank number
        """
    
    def sleep(self, seconds: float) -> None:
        """
        Handle sleep event.
        
        Parameters:
        - seconds: Sleep duration
        """

MIDI File Operations

Functions for importing and exporting MIDI files with mingus musical structures.

# MIDI file export
def write_Note(file: str, note: Note, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:
    """
    Export Note to MIDI file.
    
    Parameters:
    - file: Output filename
    - note: Note object to export
    - bpm: Beats per minute
    - repeat: Number of repeats
    - verbose: Print export information
    """

def write_NoteContainer(file: str, notecontainer: NoteContainer, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:
    """
    Export NoteContainer to MIDI file.
    
    Parameters:
    - file: Output filename
    - notecontainer: NoteContainer to export
    - bpm: Beats per minute
    - repeat: Number of repeats
    - verbose: Print export information
    """

def write_Bar(file: str, bar: Bar, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:
    """
    Export Bar to MIDI file.
    
    Parameters:
    - file: Output filename
    - bar: Bar object to export
    - bpm: Beats per minute
    - repeat: Number of repeats
    - verbose: Print export information
    """

def write_Track(file: str, track: Track, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:
    """
    Export Track to MIDI file.
    
    Parameters:
    - file: Output filename
    - track: Track object to export
    - bpm: Beats per minute
    - repeat: Number of repeats
    - verbose: Print export information
    """

def write_Composition(file: str, composition: Composition, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:
    """
    Export Composition to MIDI file.
    
    Parameters:
    - file: Output filename
    - composition: Composition to export
    - bpm: Beats per minute
    - repeat: Number of repeats
    - verbose: Print export information
    """

# MIDI file import
def MIDI_to_Composition(file: str) -> Composition:
    """
    Import MIDI file to Composition.
    
    Parameters:
    - file: MIDI filename to import
    
    Returns:
    Composition object containing imported data
    """

FluidSynth Integration

High-level interface to FluidSynth software synthesizer for real-time audio playback.

def init(sf2: str, driver: str = None, file: str = None) -> bool:
    """
    Initialize FluidSynth with soundfont.
    
    Parameters:
    - sf2: Path to SoundFont file (.sf2)
    - driver: Audio driver to use (auto-detect if None)
    - file: Output file for rendering (real-time if None)
    
    Returns:
    True if initialization successful
    """

def play_Note(note: Note, channel: int = 1, velocity: int = 100) -> None:
    """
    Play Note through FluidSynth.
    
    Parameters:
    - note: Note object to play
    - channel: MIDI channel (1-16)
    - velocity: Note velocity (0-127)
    """

def stop_Note(note: Note, channel: int = 1) -> None:
    """
    Stop Note.
    
    Parameters:
    - note: Note object to stop
    - channel: MIDI channel
    """

def play_NoteContainer(nc: NoteContainer, channel: int = 1, velocity: int = 100) -> None:
    """
    Play NoteContainer (chord).
    
    Parameters:
    - nc: NoteContainer to play
    - channel: MIDI channel
    - velocity: Note velocity
    """

def stop_NoteContainer(nc: NoteContainer, channel: int = 1) -> None:
    """
    Stop NoteContainer.
    
    Parameters:
    - nc: NoteContainer to stop
    - channel: MIDI channel
    """

def play_Bar(bar: Bar, channel: int = 1, bpm: int = 120) -> None:
    """
    Play Bar with timing.
    
    Parameters:
    - bar: Bar object to play
    - channel: MIDI channel
    - bpm: Beats per minute
    """

def play_Track(track: Track, channel: int = 1, bpm: int = 120) -> None:
    """
    Play Track.
    
    Parameters:
    - track: Track to play
    - channel: MIDI channel
    - bpm: Beats per minute
    """

def play_Composition(composition: Composition, channels: List[int] = None, bpm: int = 120) -> None:
    """
    Play Composition.
    
    Parameters:
    - composition: Composition to play
    - channels: Channel assignments for tracks
    - bpm: Beats per minute
    """

def set_instrument(channel: int, midi_instr: int, bank: int = 0) -> None:
    """
    Set instrument for channel.
    
    Parameters:
    - channel: MIDI channel (1-16)
    - midi_instr: MIDI instrument number (0-127)
    - bank: Bank select for instrument
    """

def control_change(channel: int, control: int, value: int) -> None:
    """
    Send control change message.
    
    Parameters:
    - channel: MIDI channel
    - control: Controller number (0-127)
    - value: Controller value (0-127)
    """

def modulation(channel: int, value: int) -> None:
    """
    Set modulation wheel (CC1).
    
    Parameters:
    - channel: MIDI channel
    - value: Modulation amount (0-127)
    """

def pan(channel: int, value: int) -> None:
    """
    Set pan position (CC10).
    
    Parameters:
    - channel: MIDI channel
    - value: Pan position (0-127, 64=center)
    """

def main_volume(channel: int, value: int) -> None:
    """
    Set main volume (CC7).
    
    Parameters:
    - channel: MIDI channel
    - value: Volume level (0-127)
    """

def stop_everything() -> None:
    """Stop all playback and reset FluidSynth."""

Low-Level MIDI Track Generation

Advanced MIDI track generation with precise control over MIDI events and timing.

class MidiTrack:
    """Low-level MIDI track generator."""
    
    def __init__(self, start_bpm: int = 120):
        """
        Create MIDI track generator.
        
        Parameters:
        - start_bpm: Initial tempo
        """
    
    def note_on(self, channel: int, note: int, velocity: int) -> None:
        """
        Add note on event.
        
        Parameters:
        - channel: MIDI channel (0-15)
        - note: MIDI note number (0-127)
        - velocity: Note velocity (0-127)
        """
    
    def note_off(self, channel: int, note: int) -> None:
        """
        Add note off event.
        
        Parameters:
        - channel: MIDI channel (0-15)
        - note: MIDI note number (0-127)
        """
    
    def program_change(self, channel: int, program: int) -> None:
        """
        Add program change event.
        
        Parameters:
        - channel: MIDI channel (0-15)
        - program: Program number (0-127)
        """
    
    def control_change(self, channel: int, control: int, value: int) -> None:
        """
        Add control change event.
        
        Parameters:
        - channel: MIDI channel (0-15)
        - control: Controller number (0-127)
        - value: Controller value (0-127)
        """
    
    def set_tempo(self, bpm: int) -> None:
        """
        Set tempo.
        
        Parameters:
        - bpm: Beats per minute
        """
    
    def time_signature(self, numerator: int, denominator: int) -> None:
        """
        Set time signature.
        
        Parameters:
        - numerator: Time signature numerator
        - denominator: Time signature denominator
        """
    
    def key_signature(self, key: int, mode: int) -> None:
        """
        Set key signature.
        
        Parameters:
        - key: Key signature (-7 to 7)
        - mode: Mode (0=major, 1=minor)
        """
    
    def play_Note(self, note: Note, channel: int, velocity: int) -> None:
        """
        Add Note to track.
        
        Parameters:
        - note: Note object
        - channel: MIDI channel
        - velocity: Note velocity
        """
    
    def play_NoteContainer(self, nc: NoteContainer, channel: int, velocity: int) -> None:
        """
        Add NoteContainer to track.
        
        Parameters:
        - nc: NoteContainer object
        - channel: MIDI channel
        - velocity: Note velocity
        """
    
    def get_midi_data(self) -> bytes:
        """
        Get raw MIDI data.
        
        Returns:
        Raw MIDI track data as bytes
        """

Usage Examples

Basic MIDI Playback

from mingus.midi import Sequencer
from mingus.containers import Note, NoteContainer

# Initialize sequencer
seq = Sequencer()
seq.init()

# Play individual notes
note = Note("C", 4)
seq.play_Note(note, channel=1, velocity=100)
seq.sleep(1.0)  # Wait 1 second
seq.stop_Note(note, channel=1)

# Play chords
chord = NoteContainer(["C", "E", "G"])
seq.play_NoteContainer(chord, channel=1, velocity=80)
seq.sleep(2.0)
seq.stop_NoteContainer(chord, channel=1)

FluidSynth Audio Output

from mingus.midi import fluidsynth
from mingus.containers import Track, Bar

# Initialize FluidSynth with soundfont
fluidsynth.init("/path/to/soundfont.sf2")

# Set piano instrument
fluidsynth.set_instrument(1, 0)  # Channel 1, piano

# Create and play musical content
bar = Bar()
bar.place_notes("C", 4)
bar.place_notes("E", 4)
bar.place_notes("G", 2)

track = Track()
track.add_bar(bar)

# Play track with audio output
fluidsynth.play_Track(track, channel=1, bpm=120)

MIDI File Export

from mingus.midi import midi_file_out
from mingus.containers import Composition, Track, Bar

# Create composition
composition = Composition()
composition.set_title("My Song")

# Create track with content
track = Track()
bar = Bar()
bar.place_notes(["C", "E", "G"], 4)  # Quarter note chord
bar.place_notes("F", 2)              # Half note
track.add_bar(bar)

composition.add_track(track)

# Export to MIDI file
midi_file_out.write_Composition("my_song.mid", composition, bpm=120)

MIDI File Import

from mingus.midi import midi_file_in

# Import MIDI file
composition = midi_file_in.MIDI_to_Composition("input.mid")

# Access imported data
for i, track in enumerate(composition.tracks):
    print(f"Track {i}: {len(track.bars)} bars")
    for j, bar in enumerate(track.bars):
        print(f"  Bar {j}: {len(bar)} notes")

Advanced MIDI Control

from mingus.midi import Sequencer

seq = Sequencer()
seq.init()

# Set up instruments on different channels
seq.set_instrument(1, 0)   # Piano on channel 1
seq.set_instrument(2, 32)  # Bass on channel 2
seq.set_instrument(10, 128) # Drums on channel 10

# Control expression
seq.main_volume(1, 100)    # Full volume
seq.pan(1, 64)             # Center pan
seq.modulation(1, 20)      # Light modulation

# Advanced control changes
seq.control_change(1, 64, 127)  # Sustain pedal on
seq.control_change(1, 91, 40)   # Reverb send

Install with Tessl CLI

npx tessl i tessl/pypi-mingus

docs

format-export.md

index.md

midi-operations.md

music-theory-core.md

musical-containers.md

tile.json