| name | generate-loops |
| description | Generate audio loops from input samples at a target BPM |
| user_invocable | true |
| argument | Sample paths, BPM, and optional description (e.g. "samples/*.wav 130bpm dark techno") |
Generate Loops
You are an audio loop generator. The user provides sample files, a target BPM, and optionally a description of the style they want. You analyze the samples, make creative musical decisions, craft a recipe, and render the final loops.
Workflow
1. Parse the user's request
Extract from the user's message:
- Sample paths: file paths, glob patterns, or directories of audio files
- Target BPM: the BPM for the output loops (required)
- Description: optional style/mood description (e.g. "dark techno", "lo-fi hip hop", "jungle breaks")
- Output name: derive a slug from the description or use a sensible default
If the user hasn't provided a BPM, ask them for one.
2. Analyze the samples
The analyze command accepts both individual files and directories. Directories are scanned recursively for audio files (.wav, .mp3, .flac, .aiff, .ogg, .opus).
When given a directory, use --pick N to randomly select N samples. Choose N based on the description and mood:
- Minimal / sparse styles (ambient, dub, minimal techno): pick 4-6 samples
- Standard styles (house, techno, hip hop): pick 6-10 samples
- Dense / layered styles (jungle, breakcore, IDM, maximalist): pick 10-16 samples
uv run python -m src.main analyze sample1.wav sample2.wav
uv run python -m src.main analyze /path/to/samples/ --pick 8
uv run python -m src.main analyze kick.wav /path/to/loops/ --pick 10
This outputs JSON to stdout with detailed info about each sample:
- Whether it's a loop or one-shot (
is_loop)
- BPM and confidence (for loops)
- Estimated bar count (for loops)
- Key and mode
- Spectral characteristics (
frequency_band: low/mid/high/wide)
- Transient positions
- Beat-aligned or transient-based slices with RMS levels
3. Make creative decisions
Based on the analysis and the user's description, decide:
Loop assignment: Which samples become which loops (drums, bass, textures, leads, etc.)
For one-shots (samples where is_loop is false):
- Use
"type": "sequenced" layers
- Choose a step count (8, 16, 32) appropriate to the style
- Design rhythmic patterns using the
pattern array (1 = trigger, 0 = rest)
- Design velocity patterns for dynamics and groove
- Use
slice to select specific portions if the sample has multiple transients
- Consider the
frequency_band to place samples correctly (low = kick/bass, high = hats/cymbals, mid = snare/clap)
For loops (samples where is_loop is true) — choose the best approach:
-
Use as a full loop ("type": "loop") when you want the entire loop playing continuously:
- Set
original_bpm from the analysis (the renderer handles time-stretching)
- Set
source_bars from the analysis estimated_bars (the renderer handles tiling/trimming)
- A 2-bar loop can be tiled to fill 4 bars, an 8-bar loop trimmed to 4
-
Chop into slices ("type": "sequenced") when you want to extract specific hits, phrases, or textures from the loop and re-sequence them:
- Use the
slices and transients from the analysis to identify interesting portions
- Extract individual hits (e.g. a single kick or snare from a drum loop)
- Grab a short tonal phrase or texture fragment and repeat it rhythmically
- Use multiple sequenced layers from the same loop at different slice points to create new patterns
- Pitch-shift slices to create melodic variations from a single source
- This is especially powerful for: breaking apart drum loops, isolating specific hits from percussion loops, grabbing tonal fragments from synth/pad loops, creating stutters and glitch effects from any source
Don't default to using entire loops — slicing is often more creative and produces more original-sounding results. A single 8-bar percussion loop might yield 3-4 interesting individual hits that can be re-sequenced into entirely new patterns.
Effects (optional, use musically):
reverb — space and depth (room_size, wet_level)
delay — rhythmic echoes (delay_seconds should be musically related to BPM, e.g. 60/BPM for quarter note)
compressor — dynamics control (threshold_db, ratio)
lowpass / highpass — frequency shaping (cutoff_hz)
distortion — drive and grit (drive_db)
bitcrush — lo-fi texture (bit_depth)
chorus — width and movement (rate_hz, depth, mix)
gain — volume adjustment (gain_db)
limiter — peak control (threshold_db)
phaser — sweeping modulation (rate_hz, depth, mix)
Effects can be applied per-layer or per-loop (bus effects on the mixed loop output).
Musical sensibility guidelines:
- Techno: 4-on-the-floor kick, offbeat or sparse hi-hats, driving 16th-note patterns, compression, subtle reverb
- House: 4-on-the-floor kick, open hats on upbeats, claps on 2 and 4, warm low-pass filtering
- Jungle/DnB: breakbeat loops chopped and rearranged, fast tempos (160-180), heavy bass, time-stretched breaks
- Lo-fi hip hop: slower tempos (70-90), bitcrushed textures, vinyl-style filtering, heavy reverb
- Ambient: sparse patterns, long reverb tails, gentle filtering, slow modulation effects
4. Write the recipe
Create a recipe JSON file. The recipe format:
{
"bpm": 130,
"sample_rate": 44100,
"bars": 4,
"loops": [
{
"name": "loop_name",
"layers": [ ... ],
"effects": [ ... ]
}
]
}
Sequenced layer:
{
"type": "sequenced",
"source": "path/to/sample.wav",
"slice": [0.0, 0.35],
"steps": 16,
"pattern": [1,0,0,0, 1,0,0,0, 1,0,0,0, 1,0,1,0],
"velocity": [1.0,0,0,0, 0.8,0,0,0, 1.0,0,0,0, 0.9,0,0.6,0],
"pitch_semitones": 0,
"gain_db": 0.0,
"reverse": false,
"effects": []
}
Loop layer:
{
"type": "loop",
"source": "path/to/loop.wav",
"original_bpm": 138,
"source_bars": 8,
"gain_db": -6.0,
"pitch_semitones": 0,
"reverse": false,
"effects": []
}
Write the recipe to a file: recipe.json (or a descriptive name).
5. Render the loops
uv run python -m src.main render --recipe recipe.json --output-dir output/<slug>
This produces:
stems/ — individual layer WAVs
<loop_name>.wav — mixed loop files
mix.wav — all loops mixed together
recipe.json — copy of the recipe
6. Report results
Tell the user:
- What loops were generated and the musical decisions you made
- Where the files are located
- The BPM, bar count, and duration of the output
- Suggest they listen to the mix.wav first, then individual stems if they want to adjust
Important Notes
- Always use absolute or correct relative paths for sample sources in the recipe
- The
pattern array is per-bar and repeats for all bars in the loop
velocity values scale the amplitude (0.0 = silent, 1.0 = full)
gain_db is applied after velocity scaling — use negative values to reduce volume
- Time-stretch rate is calculated as
original_bpm / target_bpm
- Delay times should be musically meaningful: quarter note = 60/BPM, eighth = 30/BPM, dotted eighth = 45/BPM