Requirements

Install MIDI support: pip install audio_dsp[midi]

MIDI tools require the mido library for reading/writing MIDI files.

Polyrhythmic MIDI Generator

Polyrhythmic Patterns

midi.polyrhythmic_midi requires mido

Generate 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 mido

Loop 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 mido

Convert 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_tunings

Generate 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)
C23665.41
C348130.81
C4 (Middle C)60261.63
A4 (Concert A)69440.00
C572523.25
C6841046.50