MIDI Tools
MIDI generation, processing, looping, and alternative tuning systems.
Requirements
MIDI tools require the mido library for reading/writing MIDI files.
Polyrhythmic MIDI Generator
Polyrhythmic Patterns
midi.polyrhythmic_midi requires midoGenerate complex polyrhythmic MIDI patterns with multiple overlapping time signatures.
Concept
Polyrhythms occur when two or more rhythmic patterns with different subdivisions play simultaneously. Common examples include 3:2 (three against two), 4:3, 5:4, and more complex ratios. This module generates MIDI files with multiple tracks, each following its own rhythmic subdivision.
Example Usage
from audio_dsp.midi.polyrhythmic_midi import generate_polyrhythmic_midi
# Generate 3:2 polyrhythm
generate_polyrhythmic_midi(
output_file="polyrhythm_3_2.mid",
ratios=[3, 2],
bars=4,
bpm=120,
notes=[60, 64] # C4, E4
)
# Complex 5:4:3 polyrhythm
generate_polyrhythmic_midi(
output_file="complex_poly.mid",
ratios=[5, 4, 3],
bars=8,
bpm=100,
notes=[48, 55, 62] # C3, G3, D4
)
# African-style 12:8 feel
generate_polyrhythmic_midi(
output_file="african_12_8.mid",
ratios=[4, 3], # 4 against 3
bars=4,
bpm=110,
notes=[36, 42], # Kick and hi-hat
channel=10 # Drum channel
)
MIDI Looper
Loop & Process MIDI
midi.midi_looper requires midoLoop MIDI files with optional transformations like transposition, time-stretching, and velocity changes.
Example Usage
from audio_dsp.midi.midi_looper import midi_looper
# Create audio loop from MIDI file
midi_looper(
midi_file="melody.mid",
output_file="midi_loop.wav",
start=0, # Starting note index
length=16, # Number of notes to include
speed=1.0, # Playback speed
reverse=False, # Reverse the loop
loop_count=4, # Number of repetitions
transpose=0, # Semitones to transpose
randomise_notes=0.0 # Note shuffle amount (0-1)
)
# Create randomized variation
midi_looper(
midi_file="bassline.mid",
output_file="randomized_loop.wav",
start=50,
length=10,
speed=2.0, # Double speed
loop_count=8,
randomise_notes=0.3 # 30% note shuffling per loop
)
MIDI Retuning
MIDI to Audio with Custom Tuning
midi.midi_retune requires midoConvert MIDI files to audio with customizable octave ratio for stretched or compressed tunings.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| midi_file | str | required | Path to input MIDI file |
| output_file | str | "output.wav" | Output WAV file path |
| tuning_offset | float | 0.0 | Octave ratio offset (0.0 = standard 2:1) |
The tuning offset modifies the octave ratio from the standard 2:1. Positive values stretch intervals (wider octaves), negative values compress them.
Example Usage
from audio_dsp.midi.midi_retune.midi_retune import midi_to_wav
# Convert MIDI to audio with standard tuning
midi_to_wav(
midi_file="piano.mid",
output_file="piano.wav",
tuning_offset=0.0 # Standard 2:1 octave
)
# Apply stretched octave tuning
# Positive offset = wider octave, negative = narrower
midi_to_wav(
midi_file="strings.mid",
output_file="strings_stretched.wav",
tuning_offset=0.02 # Slightly wide octaves
)
# Create compressed tuning effect
midi_to_wav(
midi_file="melody.mid",
output_file="melody_compressed.wav",
tuning_offset=-0.5 # Dramatically compressed intervals
)
# Command line usage:
# python midi_retune.py input.mid -o output.wav -t -0.05
Logarithmic Tunings
Exotic Tuning Systems
midi.logarithmic_tuningsGenerate frequency tables and MIDI mappings for non-standard equal temperaments.
EDO (Equal Division of Octave) Systems
| EDO | Step Size (cents) | Notable Intervals |
|---|---|---|
| 12-EDO | 100 | Standard Western (reference) |
| 19-EDO | 63.16 | Better major thirds, minor sevenths |
| 22-EDO | 54.55 | Excellent approximation of 7-limit intervals |
| 24-EDO | 50 | Quarter tones (Arabic music) |
| 31-EDO | 38.71 | Near-just major/minor thirds |
| 41-EDO | 29.27 | Excellent fifth and third approximations |
| 53-EDO | 22.64 | Very close to just intonation |
Example Usage
from audio_dsp.midi.logarithmic_tunings import (
generate_edo_frequencies,
create_midi_mapping,
cents_to_ratio
)
# Generate 19-EDO frequency table
freqs_19 = generate_edo_frequencies(
divisions=19,
base_freq=440, # A4
octaves=2
)
print(freqs_19)
# Create MIDI note mapping for 31-EDO
# Maps 31 notes per octave to MIDI note numbers
mapping_31 = create_midi_mapping(
divisions=31,
base_note=60 # Middle C
)
# Convert cents to frequency ratio
ratio = cents_to_ratio(386) # Just major third
print(f"Just major third ratio: {ratio:.4f}") # ~1.25
# Generate Bohlen-Pierce scale (tritave-based)
from audio_dsp.midi.logarithmic_tunings import generate_bp_frequencies
bp_freqs = generate_bp_frequencies(
base_freq=220,
steps=13 # 13 steps per tritave (3:1)
)
MIDI Tips
Working with MIDI
Basic MIDI Operations
import mido
# Create a new MIDI file
mid = mido.MidiFile()
track = mido.MidiTrack()
mid.tracks.append(track)
# Add tempo (500000 microseconds = 120 BPM)
track.append(mido.MetaMessage('set_tempo', tempo=500000))
# Add notes
track.append(mido.Message('note_on', note=60, velocity=64, time=0))
track.append(mido.Message('note_off', note=60, velocity=64, time=480))
# Save
mid.save('output.mid')
# Read existing MIDI
mid = mido.MidiFile('input.mid')
for track in mid.tracks:
for msg in track:
if msg.type == 'note_on':
print(f"Note: {msg.note}, Velocity: {msg.velocity}")
MIDI Note Reference
| Note | MIDI # | Frequency (Hz) |
|---|---|---|
| C2 | 36 | 65.41 |
| C3 | 48 | 130.81 |
| C4 (Middle C) | 60 | 261.63 |
| A4 (Concert A) | 69 | 440.00 |
| C5 | 72 | 523.25 |
| C6 | 84 | 1046.50 |