Quick Start (Read This First!)
IMPORTANT: This file is located at /mnt/skills/private/music-generation/SKILL.md
If you need to reference this skill again during your session, read that exact path directly. Do not explore directories or use find commands - just read the file path above.
Philosophy
This skill provides tools and patterns for music composition, not pre-baked solutions. You should use your intelligence and the music21 library to compose dynamically based on user requests.
Core Principle: Write custom code that composes music algorithmically rather than calling functions with hardcoded melodies.
Installation & Setup
Quick Installation
Run the automated installer for complete setup:
bash /mnt/skills/private/music-generation/install.sh
This installs all system dependencies, Python packages, and verifies the installation.
Note: The install script may display "error: externally-managed-environment" messages at the end. These are expected and can be safely ignored - the dependencies are already installed. If you see these messages, the installation was successful.
Manual Installation
Alternatively, install dependencies manually:
System Dependencies:
apt-get update
apt-get install -y fluidsynth fluid-soundfont-gm fluid-soundfont-gs ffmpeg
Python Dependencies:
pip install -r /mnt/skills/private/music-generation/requirements.txt
The requirements.txt includes: music21, midi2audio, pydub, mido, numpy, scipy.
Available SoundFonts
Traditional Pipeline (Orchestral/Acoustic):
/usr/share/sounds/sf2/FluidR3_GM.sf2(141MB, General MIDI soundfont for orchestral/classical)/usr/share/sounds/sf2/default.sf2(symlink to best available)
Electronic Pipeline:
- No soundfonts required - uses real-time synthesis for all electronic sounds
Quick Start: Write Custom Compositions
Basic Music Generation Pattern
from music21 import stream, note, chord, instrument, tempo, dynamics
from midi2audio import FluidSynth
from pydub import AudioSegment
# 1. Create score and parts
score = stream.Score()
violin_part = stream.Part()
violin_part.insert(0, instrument.Violin())
violin_part.insert(0, tempo.MetronomeMark(number=120))
# 2. Generate notes algorithmically
for measure in range(16):
violin_part.append(note.Note('E5', quarterLength=1.0))
violin_part.append(note.Note('G5', quarterLength=1.0))
violin_part.append(note.Note('A5', quarterLength=2.0))
# 3. Export to MIDI
score.append(violin_part)
midi_path = '/mnt/user-data/outputs/composition.mid'
score.write('midi', fp=midi_path)
# 4. Render with FluidSynth
fs = FluidSynth('/usr/share/sounds/sf2/FluidR3_GM.sf2')
wav_path = '/mnt/user-data/outputs/composition.wav'
fs.midi_to_audio(midi_path, wav_path)
# 5. Convert to MP3
audio = AudioSegment.from_wav(wav_path)
mp3_path = '/mnt/user-data/outputs/composition.mp3'
audio.export(mp3_path, format='mp3', bitrate='192k')
Key Concepts
- Always create downloadable MP3 files (not HTML players)
- All output goes to
/mnt/user-data/outputs/ - Use music21.instrument classes:
instrument.Violin(),instrument.Violoncello(),instrument.Piano(),instrument.Trumpet(), etc. - Generate notes programmatically - avoid hardcoded sequences
Choosing the Right Rendering Pipeline
CRITICAL: This skill supports TWO rendering pipelines. You MUST choose based on the musical genre:
Traditional Pipeline (Orchestral, Classical, Acoustic)
Use when creating:
- Orchestral music (violin, cello, trumpet, etc.)
- Classical compositions (Mozart, Beethoven style)
- Piano music, chamber music, symphonies
- Acoustic guitar, brass ensembles
- Any music with traditional/acoustic instruments
How to render:
# After composing with music21 and exporting MIDI...
from midi2audio import FluidSynth
from pydub import AudioSegment
fs = FluidSynth('/usr/share/sounds/sf2/FluidR3_GM.sf2')
fs.midi_to_audio(midi_path, wav_path)
audio = AudioSegment.from_wav(wav_path)
audio.export(mp3_path, format='mp3', bitrate='192k')
Electronic Pipeline (House, Techno, EDM, Electronic)
Use when creating:
- House, techno, trance, EDM
- Electronic dance music with synth bass/pads/leads
- DJ beats, club music
- Any music described as "electronic" or "synth-heavy"
- Music referencing DJs like Keinemusik, Black Coffee, etc.
How to render:
# After composing with music21, using mido for instruments, and exporting MIDI...
import subprocess
# Use the electronic rendering script
result = subprocess.run([
'python',
'/mnt/skills/private/music-generation/scripts/render_electronic.py',
midi_path,
mp3_path
], capture_output=True, text=True)
print(result.stdout)
if result.returncode != 0:
print(f"Error: {result.stderr}")
Why this matters:
- The orchestral soundfont (FluidR3_GM.sf2) sounds terrible for electronic music
- Its "synth" instruments are basic 1990s approximations
- The electronic pipeline uses real-time synthesis for authentic electronic sound
- Synthesizes 808-style kicks, electronic snares, and hi-hats on-the-fly (NO external samples required)
- Bass/pads/leads use subtractive synthesis with filters and ADSR envelopes
- Genre presets (deep_house, techno, trance, ambient) tune synthesis parameters automatically
Drum Synthesis:
The electronic renderer uses real-time drum synthesis (no external samples needed). All drum sounds (kicks, snares, hi-hats, claps) are synthesized on-the-fly with genre-specific parameters.
Example: House Track
# 1. Compose with music21 (same as always)
score = stream.Score()
drums = stream.Part()
bass = stream.Part()
pads = stream.Part()
# ... compose your music
# 2. Export MIDI
midi_path = '/mnt/user-data/outputs/deep_house.mid'
score.write('midi', fp=midi_path)
# 3. Fix instruments with mido (INSERT program_change messages)
from mido import MidiFile, Message
mid = MidiFile(midi_path)
for i, track in enumerate(mid.tracks):
if i == 1: # Drums
for msg in track:
if hasattr(msg, 'channel'):
msg.channel = 9
elif i == 2: # Bass - INSERT program_change
insert_pos = 0
for j, msg in enumerate(track):
if msg.type == 'track_name':
insert_pos = j + 1
break
track.insert(insert_pos, Message('program_change', program=38, time=0))
mid.save(midi_path)
# 4. Render with ELECTRONIC pipeline with deep_house preset!
import subprocess
subprocess.run([
'python',
'/mnt/skills/private/music-generation/scripts/render_electronic.py',
midi_path,
'/mnt/user-data/outputs/deep_house.mp3',
'--genre', 'deep_house'
])
Available Genre Presets
The electronic renderer includes pre-tuned synthesis presets with supersaw lead synthesis for thick, professional EDM sounds:
- deep_house: Warm bass with 3-voice leads (120-125 BPM)
- techno: Hard-hitting with 7-voice supersaw leads (125-135 BPM)
- trance: Uplifting with massive 9-voice supersaw leads (130-140 BPM)
- ambient: Soft, atmospheric with 5-voice pads (60-90 BPM)
- acid_house: Squelchy TB-303 bass with 5-voice leads (120-130 BPM)
- default: Balanced 5-voice leads (120-130 BPM)
Supersaw Synthesis (Swedish House Mafia / Progressive House Sound):
The electronic renderer now includes unison voice synthesis for fat, buzzy leads:
- Multiple detuned oscillators: 3-9 sawtooth waves per note (genre-dependent)
- Aggressive detuning: 6-15 cents spread creates buzzy chorus effect
- Enhanced saturation: 2.5x distortion for punch and aggression
- Phase spreading: Creates wide stereo image
How It Works:
- House: 3 voices, ±8 cents (subtle, warm)
- Techno: 7 voices, ±12 cents (aggressive, punchy)
- Trance: 9 voices, ±15 cents (massive, soaring)
- Acid house: 5 voices, ±12 cents (squelchy, aggressive)
This replicates t