Add 3 composed MIDI tracks (midi_output)
- midnight_drive.mid: 90s House/Dance at 128 BPM (75s, 5-track) Arpeggiated synth lead, driving bass, pads, brass stabs, dance beat - starlit_conversation.mid: 90s Slow Jam/Love Song at 88 BPM (99s, 4-track) Rhodes electric piano, strings, choir pads, soft drum groove - tronica.mid: 90s Trance/EBM at 138 BPM (69s, 4-track) Multi-section arpeggiated lead, wide pads, trance beat, accent lead Each .mid has a corresponding .py source showing how to compose it with MIDIUtil.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Tronica - 90s Trance / EBM
|
||||
Driving hypnotic 90s trance with arpeggiated leads, wide choir pads,
|
||||
and propulsive rhythm. 138 BPM.
|
||||
|
||||
Structure: 40 bars
|
||||
Intro (4 bars) - sparse 16th-notes
|
||||
Build (8 bars) - speed to 32nd-notes
|
||||
Drop (8 bars) - full 32nd-notes
|
||||
Break (8 bars) - back to 16th-notes
|
||||
Drop2 (8 bars) - full 32nd-notes
|
||||
Outro (4 bars) - fade out
|
||||
|
||||
Instruments:
|
||||
T0: Lead 1 Synth GM 80 - driving arpeggio
|
||||
T1: Pad 4 Choir GM 88 - sustained pads
|
||||
T2: Drum set Ch 10 - trance dance beat
|
||||
T3: Lead 3 Synth GM 84 - accent in drops
|
||||
"""
|
||||
from midiutil import MIDIFile
|
||||
|
||||
BPM = 138
|
||||
PPQ = 960
|
||||
|
||||
CHORDS = [
|
||||
{"root": 48, "arp": (0, 3, 7, 12)},
|
||||
{"root": 45, "arp": (0, 4, 7, 12)},
|
||||
{"root": 50, "arp": (0, 4, 7, 12)},
|
||||
{"root": 46, "arp": (0, 2, 7, 12)},
|
||||
]
|
||||
|
||||
total_bars = 40
|
||||
fill_bars = {3, 11, 19, 27}
|
||||
|
||||
def sp(v):
|
||||
"""Safe pitch: return only if 0-127."""
|
||||
return v if 0 <= v < 128 else None
|
||||
|
||||
# ========= Create MIDI File =========
|
||||
midi = MIDIFile(4, file_format=1, ticks_per_quarternote=PPQ)
|
||||
midi.addTempo(0, 0, BPM)
|
||||
midi.addProgramChange(0, 0, 0, 80)
|
||||
midi.addProgramChange(1, 0, 0, 88)
|
||||
midi.addProgramChange(3, 9, 0, 84)
|
||||
|
||||
# ========= Track 0: Arpeggio =========
|
||||
for start, num, spd in [(0,4,4), (4,8,8), (12,8,8), (20,8,4), (28,8,8)]:
|
||||
dt = 1.0 / spd
|
||||
for bar in range(start, start + num):
|
||||
chord = CHORDS[bar % 4]
|
||||
r = chord["root"]
|
||||
ints = chord["arp"]
|
||||
for i in range(4 * spd):
|
||||
p = sp(r + ints[i % 4] + (i // 4) * 12)
|
||||
if p is not None:
|
||||
v = 88 if i % 4 else 93
|
||||
midi.addNote(0, 0, p, bar * 4 + i * dt, dt * 0.85, v)
|
||||
|
||||
# Outro fade (4 bars, decrescendo)
|
||||
for bar in range(36, 40):
|
||||
chord = CHORDS[bar % 4]
|
||||
for i in range(4):
|
||||
p = sp(chord["root"] + chord["arp"][i % 4])
|
||||
if p is not None:
|
||||
midi.addNote(0, 0, p, bar * 4 + i * 0.25, 0.2, max(35, 75 - (bar-36)*15))
|
||||
|
||||
# ========= Track 1: Pads =========
|
||||
midi.addControllerEvent(1, 0, 0, 91, 75) # Reverb
|
||||
midi.addControllerEvent(1, 0, 0, 93, 85) # Chorus
|
||||
midi.addControllerEvent(1, 0, 0, 11, 127) # Expression
|
||||
for bar in range(total_bars):
|
||||
r = CHORDS[bar % 4]["root"]
|
||||
for n in [r+7, r+12, r+19]:
|
||||
midi.addNote(1, 0, n, bar*4, 3.9 if bar%2==0 else 3.7, 50)
|
||||
|
||||
# ========= Track 2: Drums =========
|
||||
for bar in range(total_bars):
|
||||
base = bar * 4
|
||||
for beat in range(4):
|
||||
bt = base + beat
|
||||
midi.addNote(2, 9, 36, bt, 0.2, 115 if beat==0 else 105)
|
||||
if beat in (1, 3):
|
||||
midi.addNote(2, 9, 38, bt, 0.2, 110 if bar in fill_bars else 90)
|
||||
midi.addNote(2, 9, 42, bt + 0.5, 0.1, 70)
|
||||
if bar in fill_bars:
|
||||
midi.addNote(2, 9, 46, base + 3.5, 0.3, 80)
|
||||
midi.addNote(2, 9, 46, base + 3.75, 0.2, 75)
|
||||
|
||||
# ========= Track 3: Lead Cues =========
|
||||
for bar in range(8):
|
||||
bt = (12 + bar) * 4
|
||||
r = CHORDS[(12 + bar) % 4]["root"]
|
||||
for bp, off in [(0,12),(0.5,16),(1.0,19),(2.0,16),(2.5,19),(3.0,24)]:
|
||||
midi.addNote(3, 9, r+off, bt+bp, 0.5, 90)
|
||||
for bar in range(8):
|
||||
bt = (28 + bar) * 4
|
||||
r = CHORDS[(28 + bar) % 4]["root"]
|
||||
for bp, off in [(0,12),(0.5,16),(1.0,19),(2.0,16),(2.5,19),(3.0,24)]:
|
||||
midi.addNote(3, 9, r+off, bt+bp, 0.5, 90)
|
||||
|
||||
# Pitch bend
|
||||
for bar in range(8):
|
||||
bt = (4 + bar) * 4
|
||||
midi.addPitchWheelEvent(0, 0, bt, 3000 + bar*500)
|
||||
midi.addPitchWheelEvent(0, 0, bt + 2, -(3000 + bar*500))
|
||||
|
||||
# ========= Write =========
|
||||
output_file = "/home/paperclip/projects/gitea/pi-midi-zone/midi_output/tronica.mid"
|
||||
with open(output_file, "wb") as f:
|
||||
midi.writeFile(f)
|
||||
|
||||
print(f"Written: {output_file}")
|
||||
print(f" 4-track, {total_bars} bars at {BPM} BPM")
|
||||
print(f" Style: 90s Trance / EBM")
|
||||
Reference in New Issue
Block a user