Loading...
Loading...
Tools, patterns, and utilities for creating music with code. Output as a .mp3 file with realistic instrument sounds. Write custom compositions to bring creativity to life through music. This skill should be used whenever the user asks for music to be created. Never use this skill for replicating songs, beats, riffs, or other sensitive works. The skill is not suitable for vocal/lyrical music, audio mixing/mastering (reverb, EQ, compression), real-time MIDI playback, or professional studio recording quality.
npx skill4agent add cam10001110101/claude-skills-base code-to-musicinstall.sh/usr/share/sounds/sf2/FluidR3_GM.sf2/usr/share/sounds/sf2/default.sf2instrument.Violin()instrument.Violoncello()instrument.Piano()instrument.Trumpet()electronic-music-pipeline.mdelectronic-music-pipeline.mdtraditional-music-pipeline.mdtraditional-music-pipeline.md./scriptsmidi_inventory.pymidi_render.pymidi_utils.pyaudio_validate.py# Piano (0-7)
0: "Acoustic Grand Piano"
1: "Bright Acoustic Piano"
2: "Electric Grand Piano"
3: "Honky-tonk Piano"
4: "Electric Piano 1"
5: "Electric Piano 2"
6: "Harpsichord"
7: "Clavinet"
# Chromatic Percussion (8-15)
8: "Celesta"
9: "Glockenspiel"
10: "Music Box"
11: "Vibraphone"
12: "Marimba"
13: "Xylophone"
14: "Tubular Bells"
15: "Dulcimer"
# Organ (16-23)
16: "Drawbar Organ"
17: "Percussive Organ"
18: "Rock Organ"
19: "Church Organ"
20: "Reed Organ"
21: "Accordion"
22: "Harmonica"
23: "Tango Accordion"
# Guitar (24-31)
24: "Acoustic Guitar (nylon)"
25: "Acoustic Guitar (steel)"
26: "Electric Guitar (jazz)"
27: "Electric Guitar (clean)"
28: "Electric Guitar (muted)"
29: "Overdriven Guitar"
30: "Distortion Guitar"
31: "Guitar Harmonics"
# Bass (32-39)
32: "Acoustic Bass"
33: "Electric Bass (finger)"
34: "Electric Bass (pick)"
35: "Fretless Bass"
36: "Slap Bass 1"
37: "Slap Bass 2"
38: "Synth Bass 1"
39: "Synth Bass 2"
# Strings (40-47)
40: "Violin"
41: "Viola"
42: "Cello"
43: "Contrabass"
44: "Tremolo Strings"
45: "Pizzicato Strings"
46: "Orchestral Harp"
47: "Timpani"
# Ensemble (48-55)
48: "String Ensemble 1"
49: "String Ensemble 2"
50: "Synth Strings 1"
51: "Synth Strings 2"
52: "Choir Aahs"
53: "Voice Oohs"
54: "Synth Voice"
55: "Orchestra Hit"
# Brass (56-63)
56: "Trumpet"
57: "Trombone"
58: "Tuba"
59: "Muted Trumpet"
60: "French Horn"
61: "Brass Section"
62: "Synth Brass 1"
63: "Synth Brass 2"
# Reed (64-71)
64: "Soprano Sax"
65: "Alto Sax"
66: "Tenor Sax"
67: "Baritone Sax"
68: "Oboe"
69: "English Horn"
70: "Bassoon"
71: "Clarinet"
# Pipe (72-79)
72: "Piccolo"
73: "Flute"
74: "Recorder"
75: "Pan Flute"
76: "Blown Bottle"
77: "Shakuhachi"
78: "Whistle"
79: "Ocarina"
# Synth Lead (80-87)
80: "Lead 1 (square)"
81: "Lead 2 (sawtooth)"
82: "Lead 3 (calliope)"
83: "Lead 4 (chiff)"
84: "Lead 5 (charang)"
85: "Lead 6 (voice)"
86: "Lead 7 (fifths)"
87: "Lead 8 (bass + lead)"
# Synth Pad (88-95)
88: "Pad 1 (new age)"
89: "Pad 2 (warm)"
90: "Pad 3 (polysynth)"
91: "Pad 4 (choir)"
92: "Pad 5 (bowed)"
93: "Pad 6 (metallic)"
94: "Pad 7 (halo)"
95: "Pad 8 (sweep)"
# Synth Effects (96-103)
96: "FX 1 (rain)"
97: "FX 2 (soundtrack)"
98: "FX 3 (crystal)"
99: "FX 4 (atmosphere)"
100: "FX 5 (brightness)"
101: "FX 6 (goblins)"
102: "FX 7 (echoes)"
103: "FX 8 (sci-fi)"
# Ethnic (104-111)
104: "Sitar"
105: "Banjo"
106: "Shamisen"
107: "Koto"
108: "Kalimba"
109: "Bag pipe"
110: "Fiddle"
111: "Shanai"
# Percussive (112-119)
112: "Tinkle Bell"
113: "Agogo"
114: "Steel Drums"
115: "Woodblock"
116: "Taiko Drum"
117: "Melodic Tom"
118: "Synth Drum"
119: "Reverse Cymbal"
# Sound Effects (120-127)
120: "Guitar Fret Noise"
121: "Breath Noise"
122: "Seashore"
123: "Bird Tweet"
124: "Telephone Ring"
125: "Helicopter"
126: "Applause"
127: "Gunshot"# Bass Drums
35: "Acoustic Bass Drum"
36: "Bass Drum 1" # Most common kick
# Snares
38: "Acoustic Snare" # Standard snare
40: "Electric Snare"
# Toms
41: "Low Floor Tom"
43: "High Floor Tom"
45: "Low Tom"
47: "Low-Mid Tom"
48: "Hi-Mid Tom"
50: "High Tom"
# Hi-Hats
42: "Closed Hi-Hat" # Most used
44: "Pedal Hi-Hat"
46: "Open Hi-Hat"
# Cymbals
49: "Crash Cymbal 1"
51: "Ride Cymbal 1"
52: "Chinese Cymbal"
53: "Ride Bell"
55: "Splash Cymbal"
57: "Crash Cymbal 2"
59: "Ride Cymbal 2"
# Percussion
37: "Side Stick"
39: "Hand Clap"
54: "Tambourine"
56: "Cowbell"
58: "Vibraslap"
60: "Hi Bongo"
61: "Low Bongo"
62: "Mute Hi Conga"
63: "Open Hi Conga"
64: "Low Conga"
65: "High Timbale"
66: "Low Timbale"
67: "High Agogo"
68: "Low Agogo"
69: "Cabasa"
70: "Maracas"
71: "Short Whistle"
72: "Long Whistle"
73: "Short Guiro"
74: "Long Guiro"
75: "Claves"
76: "Hi Wood Block"
77: "Low Wood Block"
78: "Mute Cuica"
79: "Open Cuica"
80: "Mute Triangle"
81: "Open Triangle"program_changeinstrument.TenorSaxophone()instrument.AcousticGuitar()sax_part.insert(0, instrument.TenorSaxophone())from mido import Message
def set_track_instrument(track, program):
"""Insert a program_change message at the beginning of a MIDI track."""
# Find position after all meta messages (track_name, etc.)
insert_pos = 0
for j, msg in enumerate(track):
if not msg.is_meta: # Insert before first non-meta message
insert_pos = j
break
else:
# If all messages are meta, insert at end
insert_pos = len(track)
track.insert(insert_pos, Message('program_change', program=program, time=0))
# Usage after loading MIDI with mido:
# set_track_instrument(mid.tracks[2], 33) # Set track 2 to Electric Bassfrom music21 import stream, note, chord, tempo
score = stream.Score()
# Create parts - don't worry about instrument assignment yet
synth_lead = stream.Part()
synth_pad = stream.Part()
bass = stream.Part()
# Add your notes/chords using .insert() with explicit timing
# CRITICAL: Always use .insert(offset, note) not .append(note)
offset = 0.0
synth_lead.insert(offset, note.Note('E5', quarterLength=1.0))
offset += 1.0
synth_lead.insert(offset, note.Note('G5', quarterLength=1.0))
# ... compose your music with .insert()
score.append(synth_lead)
score.append(synth_pad)
score.append(bass)
# Export to MIDI
midi_path = # define a output path
score.write('midi', fp=midi_path)from mido import MidiFile, Message
mid = MidiFile(midi_path)
# CRITICAL: DO NOT assume track numbers! Inspect the MIDI file first.
# Print track structure to see what tracks exist
print(f"Total tracks: {len(mid.tracks)}")
for i, track in enumerate(mid.tracks):
note_count = sum(1 for msg in track if msg.type == 'note_on' and msg.velocity > 0)
print(f"Track {i}: {note_count} notes")
# Helper function to set instruments
def set_track_instrument(track, program):
"""Insert a program_change message at the beginning of a MIDI track."""
insert_pos = 0
for j, msg in enumerate(track):
if not msg.is_meta:
insert_pos = j
break
else:
insert_pos = len(track)
track.insert(insert_pos, Message('program_change', program=program, time=0))
# Based on inspection, assign instruments to the correct tracks
# Example: if [drums, bass, guitar] were appended and inspection shows tracks 1, 2, 3 have notes:
set_track_instrument(mid.tracks[1], 80) # First part - Square Lead
set_track_instrument(mid.tracks[2], 88) # Second part - Pad
set_track_instrument(mid.tracks[3], 38) # Third part - Bass
mid.save(midi_path)# If track is drums, set ALL messages to channel 9
for i, track in enumerate(mid.tracks):
if i == 1: # This is the drum track
for msg in track:
if hasattr(msg, 'channel'):
msg.channel = 9 # Channel 10 in 1-indexedfrom midi2audio import FluidSynth
from pydub import AudioSegment
fs = FluidSynth('/usr/share/sounds/sf2/FluidR3_GM.sf2')
wav_path = # define a path here
fs.midi_to_audio(midi_path, wav_path)
audio = AudioSegment.from_wav(wav_path)
mp3_path = # define a path here
audio.export(mp3_path, format='mp3', bitrate='192k')# Standard Progressions (Roman numerals)
"pop": ["I", "V", "vi", "IV"] # C-G-Am-F (Journey, Adele)
"epic": ["i", "VI", "III", "VII"] # Am-F-C-G (Epic trailer music)
"sad": ["i", "VI", "iv", "V"] # Am-F-Dm-E (Melancholic)
"jazz": ["ii", "V", "I", "vi"] # Dm-G-C-Am (Jazz standard)
"classical": ["I", "IV", "V", "I"] # C-F-G-C (Classical cadence)
"blues": ["I", "I", "I", "I", "IV", "IV", "I", "I", "V", "IV", "I", "I"] # 12-bar blues
"house": ["i", "VI", "III", "VII"] # Minor house progression
"reggae": ["I", "V", "vi", "IV"] # Offbeat rhythm style
"country": ["I", "IV", "V", "I"] # Simple and direct
"rock": ["I", "bVII", "IV", "I"] # Power chord style
"r&b": ["I", "V", "vi", "iii", "IV", "I", "IV", "V"] # Complex R&B
# Genre-Specific Characteristics
STYLES = {
"house": {
"bpm": 120-128,
"time_signature": "4/4",
"drum_pattern": "4-on-floor kick, offbeat hats",
"bass": "Synth bass with groove",
"common_instruments": [38, 80, 88, 4] # Synth bass, lead, pad, e-piano
},
"jazz": {
"bpm": 100-180,
"time_signature": "4/4 or 3/4",
"chords": "Extended (7th, 9th, 11th, 13th)",
"common_instruments": [0, 32, 64, 56, 73] # Piano, bass, sax, trumpet, drums
},
"orchestral": {
"bpm": 60-140,
"sections": ["strings", "woodwinds", "brass", "percussion"],
"common_instruments": [40, 41, 42, 56, 73, 47] # Violin, viola, cello, trumpet, flute, timpani
},
"rock": {
"bpm": 100-140,
"time_signature": "4/4",
"guitars": "Distorted (30) or clean (27)",
"common_instruments": [30, 33, 0, 128] # Distortion guitar, bass, piano, drums
},
"ambient": {
"bpm": 60-90,
"characteristics": "Long sustained notes, atmospheric pads",
"common_instruments": [88, 89, 90, 91, 52] # Various pads, choir
},
"trap": {
"bpm": 130-170,
"drums": "Tight snare rolls, 808 bass kicks",
"hi_hats": "Fast hi-hat patterns (1/16 or 1/32 notes)",
"common_instruments": [38, 128] # Synth bass, drums
}
}from music21 import instrument
# Strings
instrument.Violin()
instrument.Viola()
instrument.Violoncello() # Note: NOT Cello()
instrument.Contrabass()
instrument.Harp()
# Piano
instrument.Piano()
instrument.Harpsichord()
# Brass
instrument.Trumpet()
instrument.Trombone()
instrument.Tuba()
instrument.Horn() # French horn
# Woodwinds
instrument.Flute()
instrument.Clarinet()
instrument.Oboe()
instrument.Bassoon()
instrument.SopranoSaxophone()
instrument.AltoSaxophone()
instrument.TenorSaxophone() # Most common for jazz
instrument.BaritoneSaxophone()
# Other
instrument.AcousticGuitar()
instrument.ElectricGuitar()
instrument.Bass()
instrument.Timpani()
# CRITICAL: music21 has LIMITED support for electronic instruments and drums
# For synths, drums, and electronic sounds, the following steps must be taken:
# 1. Create a Part without an instrument (or use a placeholder like Piano())
# 2. Use mido library to INSERT program_change messages after export
# 3. Set drums to MIDI channel 10 (channel 9 in 0-indexed) or they won't sound like drums
#
# Common mistakes:
# - instrument.Cello() doesn't exist - use Violoncello()
# - instrument.FrenchHorn() doesn't exist - use Horn()
# - Setting part.partName doesn't change the sound - MIDI program must be set with mido
# - Drums on channel 0 will play as pitched notes, not drum soundsmidofrom mido import MidiFile, Message
mid = MidiFile(midi_path)
# Define helper function
def set_track_instrument(track, program):
"""Insert a program_change message at the beginning of a MIDI track."""
insert_pos = 0
for j, msg in enumerate(track):
if not msg.is_meta:
insert_pos = j
break
else:
insert_pos = len(track)
track.insert(insert_pos, Message('program_change', program=program, time=0))
# Insert program_change messages
for i, track in enumerate(mid.tracks):
if i == 1: # Your track (tracks start at 1, not 0)
set_track_instrument(track, 38) # Synth Bass 1
# For drums: Set channel to 9 (channel 10 in 1-indexed)
for i, track in enumerate(mid.tracks):
if i == 1: # Drum track
for msg in track:
if hasattr(msg, 'channel'):
msg.channel = 9
mid.save(midi_path).append().insert(offset, note).insert().append()score.append(part)# RIGHT: Use .insert() for notes, .append() for parts
drum_part = stream.Part()
bass_part = stream.Part()
offset = 0.0
for beat in range(16):
# Kick and hi-hat on same beat (layered)
drum_part.insert(offset, note.Note(36, quarterLength=0.5)) # Kick
drum_part.insert(offset, note.Note(42, quarterLength=0.5)) # Hi-hat
# Bass note
bass_part.insert(offset, note.Note('A2', quarterLength=0.5))
offset += 0.5 # Advance time
# Add parts to score (this .append() is fine)
score.append(drum_part)
score.append(bass_part)bar_length = 1.5 # 6/8 time signature
offset = 0.0
for bar in range(8):
# Only fills first 1.0 quarter lengths, leaving 0.5 silent!
guitar_part.insert(offset, note.Note('D3', quarterLength=0.5))
guitar_part.insert(offset + 0.5, chord.Chord(['D3', 'F#3', 'A3'], quarterLength=0.5))
# Missing: offset + 1.0 to offset + 1.5
offset += bar_length # Advances to next bar, but gap remains
# Result: Guitar plays for 10 seconds, then silence for remaining durationbar_length = 1.5 # 6/8 time signature
offset = 0.0
for bar in range(8):
# Fill the ENTIRE bar with notes
guitar_part.insert(offset, note.Note('D3', quarterLength=0.5)) # 0.0 to 0.5
guitar_part.insert(offset + 0.5, chord.Chord(['D3', 'F#3', 'A3'], quarterLength=0.5)) # 0.5 to 1.0
guitar_part.insert(offset + 1.0, note.Note('D3', quarterLength=0.5)) # 1.0 to 1.5 ✓ Complete!
offset += bar_length
# Result: Guitar plays continuously throughout the entire pieceoffset += bar_lengthoffset + bar_lengthbar_length = 1.5offset + 1.0quarterLength=0.5offset + 1.5bar_length = 2.0offset + 1.5quarterLength=0.5offset + 2.0import random
n = note.Note('C5', quarterLength=1.0 + random.uniform(-0.05, 0.05))
n.volume.velocity = 80 + random.randint(-5, 5)audio.compress_dynamic_range()if i == 3part.append(note).insert().append()track.insert(pos, Message('program_change', ...))msg.program = XVioloncello()tempo.MetronomeMark()from mido import MidiFile
def set_track_velocity(track, velocity):
"""Set velocity for all note_on messages in a track."""
for msg in track:
if msg.type == 'note_on' and msg.velocity > 0:
msg.velocity = velocity
mid = MidiFile(midi_path)
for i, track in enumerate(mid.tracks):
if i == 1: # Drums
set_track_velocity(track, 75)
elif i == 2: # Bass
set_track_velocity(track, 80)
elif i == 3: # Lead instrument (sax, guitar, trumpet)
set_track_velocity(track, 95)
elif i == 4: # Background (organ, pads)
set_track_velocity(track, 55)
mid.save(midi_path)