or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

format-export.mdindex.mdmidi-operations.mdmusic-theory-core.mdmusical-containers.md

midi-operations.mddocs/

0

# MIDI Operations

1

2

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.

3

4

## Capabilities

5

6

### MIDI Sequencer

7

8

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

9

10

```python { .api }

11

class Sequencer:

12

"""Main MIDI sequencer for real-time playback."""

13

14

def __init__(self):

15

"""Create Sequencer object."""

16

17

def init(self) -> None:

18

"""Initialize sequencer for playback."""

19

20

def play_Note(self, note: Note, channel: int = 1, velocity: int = 100) -> None:

21

"""

22

Play Note object.

23

24

Parameters:

25

- note: Note object to play

26

- channel: MIDI channel (1-16)

27

- velocity: MIDI velocity (0-127)

28

"""

29

30

def stop_Note(self, note: Note, channel: int = 1) -> None:

31

"""

32

Stop Note object.

33

34

Parameters:

35

- note: Note object to stop

36

- channel: MIDI channel (1-16)

37

"""

38

39

def play_NoteContainer(self, nc: NoteContainer, channel: int = 1, velocity: int = 100) -> None:

40

"""

41

Play NoteContainer (chord).

42

43

Parameters:

44

- nc: NoteContainer to play

45

- channel: MIDI channel

46

- velocity: MIDI velocity

47

"""

48

49

def stop_NoteContainer(self, nc: NoteContainer, channel: int = 1) -> None:

50

"""

51

Stop NoteContainer.

52

53

Parameters:

54

- nc: NoteContainer to stop

55

- channel: MIDI channel

56

"""

57

58

def play_Bar(self, bar: Bar, channel: int = 1, bpm: int = 120) -> None:

59

"""

60

Play Bar with timing.

61

62

Parameters:

63

- bar: Bar object to play

64

- channel: MIDI channel

65

- bpm: Beats per minute tempo

66

"""

67

68

def play_Track(self, track: Track, channel: int = 1, bpm: int = 120) -> None:

69

"""

70

Play Track.

71

72

Parameters:

73

- track: Track object to play

74

- channel: MIDI channel

75

- bpm: Beats per minute tempo

76

"""

77

78

def play_Composition(self, composition: Composition, channels: List[int] = None, bpm: int = 120) -> None:

79

"""

80

Play Composition with multiple tracks.

81

82

Parameters:

83

- composition: Composition to play

84

- channels: List of MIDI channels for each track

85

- bpm: Beats per minute tempo

86

"""

87

88

def set_instrument(self, channel: int, instr: int, bank: int = 0) -> None:

89

"""

90

Set instrument for channel.

91

92

Parameters:

93

- channel: MIDI channel (1-16)

94

- instr: MIDI instrument number (0-127)

95

- bank: Bank number for instrument selection

96

"""

97

98

def control_change(self, channel: int, control: int, value: int) -> None:

99

"""

100

Send control change message.

101

102

Parameters:

103

- channel: MIDI channel (1-16)

104

- control: Controller number (0-127)

105

- value: Controller value (0-127)

106

"""

107

108

def modulation(self, channel: int, value: int) -> None:

109

"""

110

Set modulation (CC1).

111

112

Parameters:

113

- channel: MIDI channel

114

- value: Modulation amount (0-127)

115

"""

116

117

def main_volume(self, channel: int, value: int) -> None:

118

"""

119

Set main volume (CC7).

120

121

Parameters:

122

- channel: MIDI channel

123

- value: Volume level (0-127)

124

"""

125

126

def pan(self, channel: int, value: int) -> None:

127

"""

128

Set pan position (CC10).

129

130

Parameters:

131

- channel: MIDI channel

132

- value: Pan position (0=left, 64=center, 127=right)

133

"""

134

135

def stop_everything(self) -> None:

136

"""Stop all playing notes and reset sequencer."""

137

138

def sleep(self, seconds: float) -> None:

139

"""

140

Sleep for specified duration.

141

142

Parameters:

143

- seconds: Sleep duration in seconds

144

"""

145

146

def attach(self, observer: 'SequencerObserver') -> None:

147

"""

148

Attach observer for event notifications.

149

150

Parameters:

151

- observer: Observer object to attach

152

"""

153

154

def detach(self, observer: 'SequencerObserver') -> None:

155

"""

156

Detach observer.

157

158

Parameters:

159

- observer: Observer object to detach

160

"""

161

162

class SequencerObserver:

163

"""Observer for sequencer events."""

164

165

def play_int_note_event(self, int_note: int, channel: int, velocity: int) -> None:

166

"""

167

Handle note on event.

168

169

Parameters:

170

- int_note: MIDI note number (0-127)

171

- channel: MIDI channel

172

- velocity: Note velocity

173

"""

174

175

def stop_int_note_event(self, int_note: int, channel: int) -> None:

176

"""

177

Handle note off event.

178

179

Parameters:

180

- int_note: MIDI note number

181

- channel: MIDI channel

182

"""

183

184

def cc_event(self, channel: int, control: int, value: int) -> None:

185

"""

186

Handle control change event.

187

188

Parameters:

189

- channel: MIDI channel

190

- control: Controller number

191

- value: Controller value

192

"""

193

194

def instr_event(self, channel: int, instr: int, bank: int) -> None:

195

"""

196

Handle instrument change event.

197

198

Parameters:

199

- channel: MIDI channel

200

- instr: Instrument number

201

- bank: Bank number

202

"""

203

204

def sleep(self, seconds: float) -> None:

205

"""

206

Handle sleep event.

207

208

Parameters:

209

- seconds: Sleep duration

210

"""

211

```

212

213

### MIDI File Operations

214

215

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

216

217

```python { .api }

218

# MIDI file export

219

def write_Note(file: str, note: Note, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:

220

"""

221

Export Note to MIDI file.

222

223

Parameters:

224

- file: Output filename

225

- note: Note object to export

226

- bpm: Beats per minute

227

- repeat: Number of repeats

228

- verbose: Print export information

229

"""

230

231

def write_NoteContainer(file: str, notecontainer: NoteContainer, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:

232

"""

233

Export NoteContainer to MIDI file.

234

235

Parameters:

236

- file: Output filename

237

- notecontainer: NoteContainer to export

238

- bpm: Beats per minute

239

- repeat: Number of repeats

240

- verbose: Print export information

241

"""

242

243

def write_Bar(file: str, bar: Bar, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:

244

"""

245

Export Bar to MIDI file.

246

247

Parameters:

248

- file: Output filename

249

- bar: Bar object to export

250

- bpm: Beats per minute

251

- repeat: Number of repeats

252

- verbose: Print export information

253

"""

254

255

def write_Track(file: str, track: Track, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:

256

"""

257

Export Track to MIDI file.

258

259

Parameters:

260

- file: Output filename

261

- track: Track object to export

262

- bpm: Beats per minute

263

- repeat: Number of repeats

264

- verbose: Print export information

265

"""

266

267

def write_Composition(file: str, composition: Composition, bpm: int = 120, repeat: int = 0, verbose: bool = False) -> None:

268

"""

269

Export Composition to MIDI file.

270

271

Parameters:

272

- file: Output filename

273

- composition: Composition to export

274

- bpm: Beats per minute

275

- repeat: Number of repeats

276

- verbose: Print export information

277

"""

278

279

# MIDI file import

280

def MIDI_to_Composition(file: str) -> Composition:

281

"""

282

Import MIDI file to Composition.

283

284

Parameters:

285

- file: MIDI filename to import

286

287

Returns:

288

Composition object containing imported data

289

"""

290

```

291

292

### FluidSynth Integration

293

294

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

295

296

```python { .api }

297

def init(sf2: str, driver: str = None, file: str = None) -> bool:

298

"""

299

Initialize FluidSynth with soundfont.

300

301

Parameters:

302

- sf2: Path to SoundFont file (.sf2)

303

- driver: Audio driver to use (auto-detect if None)

304

- file: Output file for rendering (real-time if None)

305

306

Returns:

307

True if initialization successful

308

"""

309

310

def play_Note(note: Note, channel: int = 1, velocity: int = 100) -> None:

311

"""

312

Play Note through FluidSynth.

313

314

Parameters:

315

- note: Note object to play

316

- channel: MIDI channel (1-16)

317

- velocity: Note velocity (0-127)

318

"""

319

320

def stop_Note(note: Note, channel: int = 1) -> None:

321

"""

322

Stop Note.

323

324

Parameters:

325

- note: Note object to stop

326

- channel: MIDI channel

327

"""

328

329

def play_NoteContainer(nc: NoteContainer, channel: int = 1, velocity: int = 100) -> None:

330

"""

331

Play NoteContainer (chord).

332

333

Parameters:

334

- nc: NoteContainer to play

335

- channel: MIDI channel

336

- velocity: Note velocity

337

"""

338

339

def stop_NoteContainer(nc: NoteContainer, channel: int = 1) -> None:

340

"""

341

Stop NoteContainer.

342

343

Parameters:

344

- nc: NoteContainer to stop

345

- channel: MIDI channel

346

"""

347

348

def play_Bar(bar: Bar, channel: int = 1, bpm: int = 120) -> None:

349

"""

350

Play Bar with timing.

351

352

Parameters:

353

- bar: Bar object to play

354

- channel: MIDI channel

355

- bpm: Beats per minute

356

"""

357

358

def play_Track(track: Track, channel: int = 1, bpm: int = 120) -> None:

359

"""

360

Play Track.

361

362

Parameters:

363

- track: Track to play

364

- channel: MIDI channel

365

- bpm: Beats per minute

366

"""

367

368

def play_Composition(composition: Composition, channels: List[int] = None, bpm: int = 120) -> None:

369

"""

370

Play Composition.

371

372

Parameters:

373

- composition: Composition to play

374

- channels: Channel assignments for tracks

375

- bpm: Beats per minute

376

"""

377

378

def set_instrument(channel: int, midi_instr: int, bank: int = 0) -> None:

379

"""

380

Set instrument for channel.

381

382

Parameters:

383

- channel: MIDI channel (1-16)

384

- midi_instr: MIDI instrument number (0-127)

385

- bank: Bank select for instrument

386

"""

387

388

def control_change(channel: int, control: int, value: int) -> None:

389

"""

390

Send control change message.

391

392

Parameters:

393

- channel: MIDI channel

394

- control: Controller number (0-127)

395

- value: Controller value (0-127)

396

"""

397

398

def modulation(channel: int, value: int) -> None:

399

"""

400

Set modulation wheel (CC1).

401

402

Parameters:

403

- channel: MIDI channel

404

- value: Modulation amount (0-127)

405

"""

406

407

def pan(channel: int, value: int) -> None:

408

"""

409

Set pan position (CC10).

410

411

Parameters:

412

- channel: MIDI channel

413

- value: Pan position (0-127, 64=center)

414

"""

415

416

def main_volume(channel: int, value: int) -> None:

417

"""

418

Set main volume (CC7).

419

420

Parameters:

421

- channel: MIDI channel

422

- value: Volume level (0-127)

423

"""

424

425

def stop_everything() -> None:

426

"""Stop all playback and reset FluidSynth."""

427

```

428

429

### Low-Level MIDI Track Generation

430

431

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

432

433

```python { .api }

434

class MidiTrack:

435

"""Low-level MIDI track generator."""

436

437

def __init__(self, start_bpm: int = 120):

438

"""

439

Create MIDI track generator.

440

441

Parameters:

442

- start_bpm: Initial tempo

443

"""

444

445

def note_on(self, channel: int, note: int, velocity: int) -> None:

446

"""

447

Add note on event.

448

449

Parameters:

450

- channel: MIDI channel (0-15)

451

- note: MIDI note number (0-127)

452

- velocity: Note velocity (0-127)

453

"""

454

455

def note_off(self, channel: int, note: int) -> None:

456

"""

457

Add note off event.

458

459

Parameters:

460

- channel: MIDI channel (0-15)

461

- note: MIDI note number (0-127)

462

"""

463

464

def program_change(self, channel: int, program: int) -> None:

465

"""

466

Add program change event.

467

468

Parameters:

469

- channel: MIDI channel (0-15)

470

- program: Program number (0-127)

471

"""

472

473

def control_change(self, channel: int, control: int, value: int) -> None:

474

"""

475

Add control change event.

476

477

Parameters:

478

- channel: MIDI channel (0-15)

479

- control: Controller number (0-127)

480

- value: Controller value (0-127)

481

"""

482

483

def set_tempo(self, bpm: int) -> None:

484

"""

485

Set tempo.

486

487

Parameters:

488

- bpm: Beats per minute

489

"""

490

491

def time_signature(self, numerator: int, denominator: int) -> None:

492

"""

493

Set time signature.

494

495

Parameters:

496

- numerator: Time signature numerator

497

- denominator: Time signature denominator

498

"""

499

500

def key_signature(self, key: int, mode: int) -> None:

501

"""

502

Set key signature.

503

504

Parameters:

505

- key: Key signature (-7 to 7)

506

- mode: Mode (0=major, 1=minor)

507

"""

508

509

def play_Note(self, note: Note, channel: int, velocity: int) -> None:

510

"""

511

Add Note to track.

512

513

Parameters:

514

- note: Note object

515

- channel: MIDI channel

516

- velocity: Note velocity

517

"""

518

519

def play_NoteContainer(self, nc: NoteContainer, channel: int, velocity: int) -> None:

520

"""

521

Add NoteContainer to track.

522

523

Parameters:

524

- nc: NoteContainer object

525

- channel: MIDI channel

526

- velocity: Note velocity

527

"""

528

529

def get_midi_data(self) -> bytes:

530

"""

531

Get raw MIDI data.

532

533

Returns:

534

Raw MIDI track data as bytes

535

"""

536

```

537

538

## Usage Examples

539

540

### Basic MIDI Playback

541

542

```python

543

from mingus.midi import Sequencer

544

from mingus.containers import Note, NoteContainer

545

546

# Initialize sequencer

547

seq = Sequencer()

548

seq.init()

549

550

# Play individual notes

551

note = Note("C", 4)

552

seq.play_Note(note, channel=1, velocity=100)

553

seq.sleep(1.0) # Wait 1 second

554

seq.stop_Note(note, channel=1)

555

556

# Play chords

557

chord = NoteContainer(["C", "E", "G"])

558

seq.play_NoteContainer(chord, channel=1, velocity=80)

559

seq.sleep(2.0)

560

seq.stop_NoteContainer(chord, channel=1)

561

```

562

563

### FluidSynth Audio Output

564

565

```python

566

from mingus.midi import fluidsynth

567

from mingus.containers import Track, Bar

568

569

# Initialize FluidSynth with soundfont

570

fluidsynth.init("/path/to/soundfont.sf2")

571

572

# Set piano instrument

573

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

574

575

# Create and play musical content

576

bar = Bar()

577

bar.place_notes("C", 4)

578

bar.place_notes("E", 4)

579

bar.place_notes("G", 2)

580

581

track = Track()

582

track.add_bar(bar)

583

584

# Play track with audio output

585

fluidsynth.play_Track(track, channel=1, bpm=120)

586

```

587

588

### MIDI File Export

589

590

```python

591

from mingus.midi import midi_file_out

592

from mingus.containers import Composition, Track, Bar

593

594

# Create composition

595

composition = Composition()

596

composition.set_title("My Song")

597

598

# Create track with content

599

track = Track()

600

bar = Bar()

601

bar.place_notes(["C", "E", "G"], 4) # Quarter note chord

602

bar.place_notes("F", 2) # Half note

603

track.add_bar(bar)

604

605

composition.add_track(track)

606

607

# Export to MIDI file

608

midi_file_out.write_Composition("my_song.mid", composition, bpm=120)

609

```

610

611

### MIDI File Import

612

613

```python

614

from mingus.midi import midi_file_in

615

616

# Import MIDI file

617

composition = midi_file_in.MIDI_to_Composition("input.mid")

618

619

# Access imported data

620

for i, track in enumerate(composition.tracks):

621

print(f"Track {i}: {len(track.bars)} bars")

622

for j, bar in enumerate(track.bars):

623

print(f" Bar {j}: {len(bar)} notes")

624

```

625

626

### Advanced MIDI Control

627

628

```python

629

from mingus.midi import Sequencer

630

631

seq = Sequencer()

632

seq.init()

633

634

# Set up instruments on different channels

635

seq.set_instrument(1, 0) # Piano on channel 1

636

seq.set_instrument(2, 32) # Bass on channel 2

637

seq.set_instrument(10, 128) # Drums on channel 10

638

639

# Control expression

640

seq.main_volume(1, 100) # Full volume

641

seq.pan(1, 64) # Center pan

642

seq.modulation(1, 20) # Light modulation

643

644

# Advanced control changes

645

seq.control_change(1, 64, 127) # Sustain pedal on

646

seq.control_change(1, 91, 40) # Reverb send

647

```