--- name: 90s-midi-composer description: Create authentic 90s-style MIDI music files with General MIDI/SC-55 aesthetic. Use when creating MIDI music, composing dance/electronic tracks, or making 90s retro-sounding songs. license: MIT compatibility: Linux with Python3, mido library --- # 90s MIDI Composer Create authentic early-to-mid 90s-style MIDI music using Linux tools and Python + mido. ## Prerequisites Install required tools (one-time setup, requires sudo): ```bash sudo apt-get install -y fluidsynth fluid-soundfont-gm pip3 install --break-system-packages mido ``` ## The Tool: Python + Mido Mido is a Python library for working with MIDI files. Key classes: - `MidiFile(ticks_per_beat=480)` — MIDI file container - `MidiTrack()` — list of Message objects (one per instrument) - `Message('note_on', note=N, velocity=V, channel=C, time=T)` — start a note - `Message('note_off', note=N, velocity=V, channel=C, time=T)` — stop a note - `Message('program_change', program=N, channel=C, time=T)` — change instrument - `Message('control_change', control=N, value=V, channel=C, time=T)` — CC control - `MetaMessage('set_tempo', tempo=μs_per_beat, time=0)` — set tempo (μs/beat) ## Timing in Mido Mido uses **relative** timing. Each message has `time` = ticks since the previous one. ``` ticks_per_beat = 480 (PPQ) 1 sixteenth-note = 120 ticks 1 eighth-note = 240 ticks 1 quarter-note = 480 ticks (1 beat) 1 bar (4/4) = 1920 ticks (4 beats × 480) ``` ### Absolute → Relative Conversion Build events with absolute tick offsets, then convert: ```python def rel(items): # items = [(abs_tick, Message), ...] items.sort(key=lambda x: x[0]) out, prev = [], 0 for at, msg in items: msg.time = at - prev out.append(msg) prev = at return out ``` ## Creating a Basic MIDI File ```python from mido import MidiFile, MidiTrack, Message as M, MetaMessage PPQ = 480 # pulses per quarter note (ticks/beat) BPM = 128 TEMPO = 60_000_000 // BPM mid = MidiFile(ticks_per_beat=PPQ) # Track 0: Tempo trk = MidiTrack() trk.append(MetaMessage('set_tempo', tempo=TEMPO, time=0)) mid.tracks.append(trk) # Track 1: Drums (channel 10 = 9) drums = MidiTrack() # ... add drum messages ... mid.tracks.append(drums) mid.save('output.mid') ``` ## 90s Aesthetic Guide ### Essential GM Patches (General MIDI) | Patch | Name | 90s Role | |-------|-------------------|-----------------------| | 1 | Acoustic Grand | Piano / melodic | | 37 | Synth Bass 1 | Driving synth bass | | 59 | Brass Section | Hits, accents | | 80 | Lead 1 Synth | **Arpeggio lead** | | 88 | Pad 4 (Choir) | Warm atmospheric pads | | 49 | Strings | Harmonic texture | | 16 | Electric Piano 1 | Rhodes-style | ### GM Drum Set (Channel 10 = channel 9) | Note | Voice | Note | Voice | |------|--------------------|------|--------------------| | 36 | **Kick 1** | 38 | **Snare 1** | | 42 | **Hi-hat closed** | 46 | Hi-hat open | | 49 | Crash cymbal | 57 | Tambourine | | 51 | Ride cymbal | 50 | Low bongo | ### Classic 90s Dance Beat (120-140 BPM) ``` Kick on every quarter note (1, 2, 3, 4) Snare on beats 2 & 4 Hi-hat on every eighth note Open hi-hat on off-beats for groove ``` ### 90s Chord Progressions - **Am | F | G | E7** — vi-IV-V-I in C (the quintessential 90s pop progression) - **C | G | Am | F** — I-V-vi-IV (the "axis of awesome") - **Em | C | G | D** — vi-IV-I-V (melancholy 90s feel) - **Am | C | G | E7** — i-III-VII-V (minor-key drama) ### Instrument Patterns - **Arpeggio lead**: 16th-note chords cycling root-3rd-5th-octave, ascending and descending - **Walking bass**: Quarter-note chord tone movement, alternating arpeggio directions - **Pad chords**: 3-voice voicings, hold ~90% of bar for smooth crossfading - **Piano melody**: Pentatonic or natural minor scale, sparse 4-note phrases per bar ### Effects (Control Changes) - **Reverb**: CC91, value 40-80 (higher = more spacious hall) - **Chorus**: CC93, value 50-90 - **Filter**: CC5 or CC74, value 40-127 - **Expression**: CC11, value 100-127 ### Song Structure Template ``` Intro (4 bars) — Pads only, dreamy and sparse Verse (8 bars) — Drums enter, bass + pads + arpeggio (no piano) Chorus (8 bars) — Full arrangement, piano melody joins Bridge (4 bars) — Breakdown or key change Final Chorus (8 bars) — Return, full energy Outro (8 bars) — Drums simplify, piano arpeggio fade ``` At 128 BPM: 40 bars ≈ 1.25 minutes. Example: 48 bars = 1.5 minutes. ### BPM Recommendations | Genre | Typical BPM | |--------------------|-----------| | 90s slow jam | 80-100 | | House / dance | 120-130 | | Trance / techno | 130-150 | | Drum & bass | 170-180 | ## Playing MIDI Files ```bash # With fluidsynth fluidsynth -a alsa /usr/share/sounds/sf2/FluidR3_GM.sf2 output.mid # On macOS fluidsynth -a core /path/to/FluidR3_GM.sf2 output.mid ``` ## See Also - Drum reference: `/drum_reference.md` in this skill directory