A comprehensive, plugin-based MIDI drum track generation system
๐ Quick Start โข ๐ Documentation โข ๐ต Examples โข ๐ Plugins โข ๐ค Contributing
MIDI Drums Generator is a powerful Python system that creates professional-quality drum tracks in MIDI format. Built with a modular, plugin-based architecture, it supports multiple musical genres, drummer styles, and song structures with realistic humanization and variations.
๐ช Multi-Genre Support
- Metal: Heavy, Death, Power, Progressive, Doom, Thrash, Breakdown
- Rock: Classic, Blues, Alternative, Progressive, Punk, Hard, Pop
- Jazz: Swing, Bebop, Fusion, Latin, Ballad, Hard Bop, Contemporary
- Funk: Classic, P-Funk, Shuffle, New Orleans, Fusion, Minimal, Heavy
- Expandable: Plugin architecture for Electronic and more
๐ฅ Drummer Imitation
- 7 Famous Drummers: Bonham, Porcaro, Weckl, Chambers, Roeder, Dee, Hoglan
- Signature fills and playing techniques based on research
- Compatible across multiple genres with authentic styles
๐๏ธ Flexible Song Structure
- Configurable sections (verse, chorus, bridge, breakdown)
- Pattern variations and dynamic fills
- Custom song arrangements
๐๏ธ Professional Features
- Realistic velocity variations and humanization
- EZDrummer 3 compatible MIDI mapping
- Multiple complexity and dynamics levels
๐ง Multiple Interfaces
- Python API for integration
- Command-line interface for batch processing
- Direct module usage for custom applications
๐ค AI-Powered Generation (NEW!)
- Natural language pattern generation with Pydantic AI
- Intelligent composition with Langchain agents
- Provider-agnostic backend (Anthropic, OpenAI, Groq, Cohere)
- Environment-driven configuration for production use
The MIDI Drums Generator underwent comprehensive refactoring achieving extraordinary code reduction while maintaining 100% functional equivalence:
| Achievement | Metric |
|---|---|
| Total Code Reduction | 62% (2,898 lines eliminated) |
| Genre Plugins | 37% reduction (757 lines saved) |
| Drummer Plugins | 83% reduction (2,141 lines saved!) |
| Test Coverage | 39 comprehensive tests, 100% passing |
| Type Safety | Full type hints throughout |
The refactored architecture uses three foundational systems:
1. Configuration Constants - Type-safe constants eliminating magic numbers
from midi_drums.config import VELOCITY, TIMING, DEFAULTS
builder.kick(0.0, VELOCITY.KICK_MEDIUM) # Self-documenting!2. Pattern Templates - 8 reusable templates for declarative composition
from midi_drums.patterns import TemplateComposer, DoubleBassPedal, BlastBeat
pattern = TemplateComposer("death_metal").add(DoubleBassPedal()).build()3. Drummer Modifications - 12 composable modifications for authentic techniques
from midi_drums.modifications import BehindBeatTiming, TripletVocabulary
pattern = behind_beat.apply(triplets.apply(pattern))โ Zero Code Duplication - Reusable templates and modifications โ Professional Quality - Full type hints, comprehensive testing โ Maintainable - Clear separation of concerns, easy to extend โ Tested - 100% functional equivalence validated โ Documented - See REFACTORING_PROGRESS.md for details
# Clone the repository
git clone https://github.com/yourusername/midi-drums.git
cd midi-drums
# Set up virtual environment
python -m venv .venv
source .venv/bin/activate # Linux/macOS
# or
.venv\Scripts\activate # Windows
# Install dependencies
pip install -r core_requirements.txtfrom midi_drums.api.python_api import DrumGeneratorAPI
# Initialize the generator
api = DrumGeneratorAPI()
# Create a death metal song
song = api.create_song("metal", "death", tempo=180)
api.save_as_midi(song, "death_metal_track.mid")
# Create a jazz swing pattern with Dave Weckl style
jazz_song = api.create_song("jazz", "swing", tempo=120, drummer="weckl")
api.save_as_midi(jazz_song, "jazz_swing_weckl.mid")
print("๐ต Generated: death_metal_track.mid & jazz_swing_weckl.mid")# Generate songs across different genres
python -m midi_drums generate --genre metal --style heavy --tempo 155 --output metal_song.mid
python -m midi_drums generate --genre rock --style classic --tempo 140 --output rock_song.mid
python -m midi_drums generate --genre jazz --style swing --tempo 120 --output jazz_song.mid
python -m midi_drums generate --genre funk --style classic --tempo 110 --output funk_song.mid
# Generate patterns with drummer styles
python -m midi_drums pattern --genre rock --section verse --drummer bonham --output bonham_verse.mid
# List available options
python -m midi_drums list genres
python -m midi_drums list drummersGenerate drum patterns from natural language using AI! The system supports multiple AI providers with environment-driven configuration.
# Install AI dependencies
pip install -r ai_requirements.txt
# Configure your preferred AI provider
export AI_PROVIDER="anthropic" # or openai, groq, cohere
export ANTHROPIC_API_KEY="your-api-key"
export AI_MODEL="claude-sonnet-4-20250514" # optional, has smart defaultsfrom midi_drums.ai import DrumGeneratorAI
# Initialize AI generator (uses environment variables)
ai = DrumGeneratorAI()
# Generate from natural language descriptions
pattern, response = await ai.generate_pattern_from_text(
"aggressive metal breakdown with double bass and blast beats",
section="breakdown",
tempo=180,
bars=4
)
# AI analyzes and infers characteristics
print(f"Genre: {response.characteristics.genre}")
print(f"Style: {response.characteristics.style}")
print(f"Intensity: {response.characteristics.intensity}")
print(f"Double bass: {response.characteristics.use_double_bass}")
# Export to MIDI
ai.export_pattern(pattern, "ai_breakdown.mid", tempo=180)# Use Langchain agent for multi-step reasoning
result = ai.compose_with_agent(
"Create a progressive metal song with verse and chorus patterns, "
"then apply the Bonham drummer style to make it more dynamic"
)
print(result['output']) # Agent's creative responsefrom midi_drums.ai import AIBackendConfig, AIProvider
# Switch providers programmatically
openai_config = AIBackendConfig(
provider=AIProvider.OPENAI,
model="gpt-4o",
api_key="sk-...",
temperature=0.7
)
ai_openai = DrumGeneratorAI(backend_config=openai_config)
# Or use Groq for fast, cost-effective generation
groq_config = AIBackendConfig(
provider=AIProvider.GROQ,
model="llama-3.3-70b-versatile",
api_key="gsk-..."
)
ai_groq = DrumGeneratorAI(backend_config=groq_config)| Provider | Models | Best For |
|---|---|---|
| Anthropic | Claude Sonnet 4 | High-quality, nuanced generation |
| OpenAI | GPT-4o, GPT-4 Turbo | Versatile, well-tested |
| Groq | Llama 3.3 70B | Fast inference, cost-effective |
| Cohere | Command R+ | Enterprise use cases |
Environment Variables:
AI_PROVIDER- Provider selection (default: anthropic)AI_MODEL- Model identifier (provider-specific defaults)ANTHROPIC_API_KEY,OPENAI_API_KEY,GROQ_API_KEY,COHERE_API_KEYAI_TEMPERATURE- Generation temperature (0.0-2.0, default: 0.7)AI_MAX_TOKENS- Maximum output tokens (default: 4096)
See claudedocs/AI_BACKEND_MIGRATION.md for complete documentation.
The system follows a layered, plugin-based architecture:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ API Layer โ
โ CLI โ Python API โ Direct Usage โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Application Layer โ
โ DrumGenerator โ Pattern Manager โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Plugin System โ
โ Genre Plugins โ Drummer Plugins โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Core Models โ
โ Pattern โ Song โ Beat โ Kit โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Processing Engines โ
โ MIDI Engine โ Humanization โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- Heavy: Classic heavy metal (Sabbath, Iron Maiden style)
- Death: Blast beats, double bass, intense patterns
- Power: Anthemic, driving patterns with melodic elements
- Progressive: Complex time signatures and syncopation
- Thrash: Fast, aggressive patterns with precision
- Doom: Slow, heavy, powerful patterns
- Breakdown: Syncopated patterns for breakdown sections
- Classic: 70s classic rock (Led Zeppelin, Deep Purple)
- Blues: Blues rock with shuffles and triplets
- Alternative: 90s alternative rock syncopation
- Progressive: Complex progressive rock patterns
- Punk: Fast, aggressive punk rock
- Hard: Hard rock with heavy emphasis
- Pop: Pop rock with clean patterns
- Swing: Traditional swing with ride patterns
- Bebop: Fast, complex bebop rhythms
- Fusion: Jazz fusion with electric energy
- Latin: Latin jazz with clave patterns
- Ballad: Soft, brushed ballad patterns
- Hard Bop: Aggressive hard bop rhythms
- Contemporary: Modern contemporary jazz
- Classic: James Brown "the one" emphasis
- P-Funk: Parliament-Funkadelic grooves
- Shuffle: Bernard Purdie shuffle patterns
- New Orleans: Second line funk patterns
- Fusion: Jazz-funk fusion styles
- Minimal: Stripped-down pocket grooves
- Heavy: Heavy funk with rock influence
- John Bonham: Triplet vocabulary, behind-the-beat timing
- Jeff Porcaro: Half-time shuffle, studio precision
- Dave Weckl: Linear playing, fusion mastery
- Dennis Chambers: Funk mastery, incredible chops
- Jason Roeder: Atmospheric sludge, minimal creativity
- Mikkey Dee: Speed/precision, versatile power
- Gene Hoglan: Mechanical precision, blast beats
- Electronic: House, Techno, Drum'n'Bass, Dubstep
- World: Latin, Reggae, Afrobeat
- More Drummers: Neil Peart, Buddy Rich, Stewart Copeland
from midi_drums.api.python_api import DrumGeneratorAPI
api = DrumGeneratorAPI()
# Multi-genre songs with custom parameters
metal_song = api.create_song("metal", "progressive", tempo=140, complexity=0.9)
rock_song = api.create_song("rock", "classic", tempo=130, drummer="bonham")
jazz_song = api.create_song("jazz", "swing", tempo=120, drummer="weckl")
funk_song = api.create_song("funk", "classic", tempo=110, drummer="chambers")
# Batch generation across genres
specs = [
{'genre': 'metal', 'style': 'death', 'tempo': 180},
{'genre': 'rock', 'style': 'blues', 'tempo': 95, 'drummer': 'porcaro'},
{'genre': 'jazz', 'style': 'fusion', 'tempo': 135, 'drummer': 'weckl'},
{'genre': 'funk', 'style': 'pfunk', 'tempo': 105, 'drummer': 'chambers'}
]
files = api.batch_generate(specs, "output/")
# Individual patterns with drummer styles
verse = api.generate_pattern("rock", "verse", "classic")
bonham_verse = api.apply_drummer_style(verse, "bonham")
jazz_swing = api.generate_pattern("jazz", "verse", "swing")
funk_breakdown = api.generate_pattern("funk", "breakdown", "heavy")from midi_drums import DrumGenerator
generator = DrumGenerator()
# Custom song structure
song = generator.create_song(
genre="metal",
style="heavy",
tempo=155,
structure=[
("intro", 4), ("verse", 8), ("chorus", 8),
("verse", 8), ("chorus", 8), ("bridge", 4),
("chorus", 8), ("outro", 4)
],
complexity=0.7,
humanization=0.3
)
generator.export_midi(song, "custom_song.mid")# Generate songs across all genres
python -m midi_drums generate --genre metal --style death --tempo 180 --complexity 0.8 --output death.mid
python -m midi_drums generate --genre rock --style classic --tempo 140 --drummer bonham --output rock_bonham.mid
python -m midi_drums generate --genre jazz --style swing --tempo 120 --drummer weckl --output jazz_weckl.mid
python -m midi_drums generate --genre funk --style classic --tempo 110 --drummer chambers --output funk_chambers.mid
# Generate patterns with drummer styles
python -m midi_drums pattern --genre rock --section verse --style blues --drummer porcaro --output porcaro_verse.mid
python -m midi_drums pattern --genre jazz --section bridge --style fusion --drummer weckl --output weckl_bridge.mid
# System information
python -m midi_drums info
python -m midi_drums list genres
python -m midi_drums list styles --genre jazz
python -m midi_drums list drummersThe plugin architecture makes it easy to extend the system with new genres and drummer styles. The refactored architecture provides reusable templates and modifications for rapid development.
Modern approach using pattern templates for declarative composition:
from midi_drums.plugins.base import GenrePlugin
from midi_drums.patterns import TemplateComposer, BasicGroove, DoubleBassPedal
from midi_drums.config import VELOCITY, TIMING
class MetalGenrePluginRefactored(GenrePlugin):
@property
def genre_name(self) -> str:
return "metal"
@property
def supported_styles(self) -> List[str]:
return ["heavy", "death", "power", "progressive", "thrash", "doom"]
def generate_pattern(self, section: str, parameters: GenerationParameters) -> Pattern:
if parameters.style == "death":
# Declarative composition - just 5 lines!
return (
TemplateComposer(f"death_metal_{section}")
.add(DoubleBassPedal(pattern="continuous", speed=16))
.add(BlastBeat(style="traditional", intensity=0.9))
.build(bars=2, complexity=parameters.complexity)
)
# ... other styles using templatesTraditional approach still available for custom patterns:
from midi_drums.plugins.base import GenrePlugin
from midi_drums.models.pattern import PatternBuilder
class RockGenrePlugin(GenrePlugin):
def generate_pattern(self, section: str, parameters: GenerationParameters) -> Pattern:
builder = PatternBuilder(f"rock_{parameters.style}_{section}")
if parameters.style == "classic":
builder.kick(0.0, 105).kick(2.0, 105)
builder.snare(1.0, 110).snare(3.0, 110)
for i in range(8):
builder.hihat(i * 0.5, 80)
return builder.build()Modern approach using composable modifications (reduced from ~380 to ~66 lines!):
from midi_drums.plugins.base import DrummerPlugin
from midi_drums.modifications import BehindBeatTiming, TripletVocabulary, HeavyAccents
class BonhamPluginRefactored(DrummerPlugin):
def __init__(self):
self.behind_beat = BehindBeatTiming(max_delay_ms=25.0)
self.triplets = TripletVocabulary(triplet_probability=0.4)
self.accents = HeavyAccents(accent_boost=15)
@property
def drummer_name(self) -> str:
return "bonham"
def apply_style(self, pattern: Pattern) -> Pattern:
# Composable modifications - authentic Bonham techniques!
styled_pattern = pattern.copy()
styled_pattern = self.behind_beat.apply(styled_pattern, intensity=0.7)
styled_pattern = self.triplets.apply(styled_pattern, intensity=0.8)
styled_pattern = self.accents.apply(styled_pattern, intensity=0.9)
return styled_patternAvailable Modifications: BehindBeatTiming, TripletVocabulary, GhostNoteLayer, LinearCoordination, HeavyAccents, ShuffleFeelApplication, FastChopsTriplets, PocketStretching, MinimalCreativity, SpeedPrecision, TwistedAccents, MechanicalPrecision
Available Templates: BasicGroove, DoubleBassPedal, BlastBeat, JazzRidePattern, FunkGhostNotes, CrashAccents, TomFill, TemplateComposer
# Install development dependencies
bin/py_update.sh # Linux/macOS
bin/py_update.bat # Windows
# Or using uv (recommended)
uv sync --all-groups # Syncs dev, ai, and core dependencies
# Run linting
bin/linting.sh # Linux/macOS
bin/linting.bat # WindowsThe project uses pytest with comprehensive test coverage:
# Run all tests
pytest
# Run specific test categories
pytest -m unit # Unit tests (no API key needed)
pytest -m integration # Integration tests
pytest -m ai # AI tests (requires API key)
# Run tests in parallel
pytest -n auto
# Run with coverage
pytest --cov=midi_drums --cov-report=html
# Skip AI tests if no API key
pytest -m "not requires_api"Test Organization:
tests/unit/- Unit tests for individual components (8 files)tests/integration/- End-to-end integration tests (6 files)tests/ai/- AI-powered generation tests (4 files)tests/conftest.py- Shared fixtures and configuration
Test Markers:
@pytest.mark.unit- Fast unit tests, no external dependencies@pytest.mark.integration- Integration tests@pytest.mark.ai- AI functionality tests@pytest.mark.requires_api- Tests requiring API keys (auto-skipped if unavailable)@pytest.mark.slow- Long-running tests
# Example test run output
============================= test session starts =============================
8 passed in 10.69s ==============================
โ
Backend abstraction tests
โ
Configuration validation
โ
Environment variable loading
โ
Provider fallback handlingmidi_drums/
โโโ __init__.py # Main exports
โโโ config/
โ โโโ constants.py # VELOCITY, TIMING, DEFAULTS (283 lines)
โโโ patterns/
โ โโโ templates.py # 8 reusable pattern templates (585 lines)
โโโ modifications/
โ โโโ drummer_mods.py # 12 drummer modifications (732 lines)
โโโ core/
โ โโโ engine.py # DrumGenerator - main engine
โโโ models/
โ โโโ pattern.py # Pattern, Beat, PatternBuilder
โ โโโ song.py # Song, Section, GenerationParameters
โ โโโ kit.py # DrumKit configurations
โโโ plugins/
โ โโโ base.py # Plugin system foundation
โ โโโ genres/
โ โ โโโ metal_refactored.py # 290 lines (was 373)
โ โ โโโ rock_refactored.py # 332 lines (was 513)
โ โ โโโ jazz_refactored.py # 337 lines (was 599)
โ โ โโโ funk_refactored.py # 330 lines (was 561)
โ โโโ drummers/
โ โโโ bonham_refactored.py # 66 lines (was 339)
โ โโโ porcaro_refactored.py # 63 lines (was 369)
โ โโโ weckl_refactored.py # 63 lines (was 383)
โ โโโ chambers_refactored.py # 70 lines (was 381)
โ โโโ roeder_refactored.py # 63 lines (was 371)
โ โโโ dee_refactored.py # 63 lines (was 360)
โ โโโ hoglan_refactored.py # 63 lines (was 389)
โโโ engines/
โ โโโ midi_engine.py # MIDI file generation
โโโ api/
โ โโโ python_api.py # High-level Python API
โ โโโ cli.py # Command-line interface
โโโ claudedocs/
โโโ REFACTORING_PROGRESS.md # Complete refactoring docs
# Test the system
python test_new_architecture.py
# Try the examples
python examples/basic_usage.py
# Compare with original implementation
python migrate_from_original.pyThe system generates professional MIDI files compatible with:
- EZDrummer 3 (primary target)
- Superior Drummer 3
- BFD3
- Any GM-compatible drum sampler
- DAWs (Logic Pro, Pro Tools, Cubase, Reaper, etc.)
- โ Standard GM drum mapping
- โ Realistic velocity variations (60-127)
- โ Humanized timing (configurable)
- โ Ghost notes and accents
- โ Dynamic fills and variations
- โ Multi-bar pattern support
This system evolved from a simple single-file generator (generate_metal_drum_track.py) into a comprehensive platform:
| Original | New Architecture |
|---|---|
| Single file | Modular plugin system |
| One metal style | 7+ metal styles, expandable |
| Fixed song structure | Configurable structures |
| Hardcoded patterns | Dynamic pattern generation |
| No API | Multiple interfaces |
| No variations | Humanization & variations |
The original script is preserved for compatibility, and migrate_from_original.py demonstrates equivalent functionality.
We welcome contributions! Here's how you can help:
- Create a new plugin in
midi_drums/plugins/genres/ - Implement the
GenrePlugininterface - Add comprehensive patterns for different sections and styles
- Include characteristic fills and variations
- Examples: Rock, Jazz, and Funk genres with 7 styles each
- Create a drummer plugin in
midi_drums/plugins/drummers/ - Implement the
DrummerPlugininterface - Add signature playing techniques and fills based on research
- Make it compatible with multiple genres
- Examples: 7 drummers already implemented with authentic styles
- Found a bug? Open an issue on GitHub
- Include MIDI output samples if possible
- Provide steps to reproduce
- New musical genres or styles
- Advanced humanization techniques
- Integration with specific DAWs or samplers
This project is licensed under the MIT License - see the LICENSE file for details.
- Original Inspiration: Single-file metal drum generator
- MIDI Generation: midiutil library
- Target Platform: EZDrummer 3 compatibility
- Architecture: Plugin-based design inspired by modern audio software
- Rock genre plugin with 7 styles
- Jazz genre plugin with 7 styles (swing, bebop, fusion, latin, etc.)
- Funk genre plugin with 7 styles
- 7 drummer plugins (Bonham, Porcaro, Weckl, Chambers, Roeder, Dee, Hoglan)
- Comprehensive testing and validation system
- Electronic genre plugin (House, Techno, Drum'n'Bass)
- More drummer plugins (Neil Peart, Buddy Rich, Stewart Copeland)
- Real-time audio synthesis
- AI-driven pattern variations
- Advanced humanization algorithms
- Groove template system
- REST API for web services
- DAW integration (VST/AU plugins)
- Pattern marketplace
- Visual pattern editor
- World music genres (Latin, Reggae, Afrobeat)
Made with โค๏ธ for drummers, producers, and music creators
โญ Star this project โข ๐ Report Bug โข ๐ก Request Feature