Trip-hop / downtempo music generation pipeline β from config to complete, playable tracks. Inspired by Portishead, Massive Attack, and Vegyn's Headache project.
Input: mood preset + config
Output: finished .wav / .mp3 you can play immediately
# 1. Install dependencies
uv sync
# 2. Generate a track (defaults: melancholic, ~78 BPM, ~3 min)
uv run python generate_track.py
# 3. Find your track in ./output/Note: MP3 export requires ffmpeg to be installed on your system (
brew install ffmpegon macOS).
# Basic
uv run python generate_track.py
# Full control
uv run python generate_track.py \
--mood paranoid \
--bpm 85 \
--length 120 \
--seed 42 \
--vocal-engine gtts \
--output ./my_tracks
# Instrumental only (no vocals)
uv run python generate_track.py --vocal-engine silent
# Supply your own spoken-word text
uv run python generate_track.py --text "Beneath the surface. We oscillate. The architecture of silence."| Flag | Default | Description |
|---|---|---|
--mood, -m |
melancholic |
Mood preset: melancholic, paranoid, ethereal |
--bpm, -b |
from preset | Tempo (70β90 BPM typical) |
--length, -l |
from arrangement | Target track length in seconds |
--seed, -s |
random | Seed for reproducible output |
--vocal-engine, -v |
gtts |
TTS engine: gtts, pyttsx3, silent |
--text, -t |
generated | Custom text for vocals |
--output, -o |
./output |
Output directory |
ββββββββββββββββ βββββββββββββββββ ββββββββββββββββββ
β 1. LYRICS βββββΆβ 2. VOCALS βββββΆβ β
β (generator) β β (TTS engine) β β β
ββββββββββββββββ βββββββββββββββββ β β
β 4. ARRANGER β
ββββββββββββββββ βββββββββββββββββ β (structure) β
β 3. SYNTH βββββΆβ Drums βββββΆβ β
β (engines) β β Bass β β β
β β β Pads β βββββββββ¬βββββββββ
β β β Textures β β
ββββββββββββββββ βββββββββββββββββ βΌ
ββββββββββββββββββ βββββββββββ
β 5. MIXER βββββΆβ .wav β
β (effects + β β .mp3 β
β master bus) β β stems/ β
ββββββββββββββββββ βββββββββββ
Template-based spoken-word poetry with curated word banks per mood. Produces introspective, abstract text matching the trip-hop aesthetic.
Converts lyrics to audio via text-to-speech:
- gTTS β Google TTS (free, needs internet, natural-sounding)
- pyttsx3 β Offline system TTS (more robotic = on-brand)
- silent β Instrumental-only mode
All sounds generated from scratch via numpy β no samples required:
- Drums: Kick (pitch-swept sine + transient), snare (tone + noise), hi-hat (metallic partials + HP noise), clap (layered noise bursts)
- Bass: Sub-bass sine + harmonics, warm/deep/distorted characters
- Pads: Detuned super-saw-style oscillators with LFO modulation
- Textures: Vinyl crackle, tape hiss, ambient washes
Programmatic track structure with sections:
- Intro β Verse 1 β Break β Verse 2 β Bridge β Outro
- Per-section drum/bass/pad activation
- Swing and velocity humanisation
- Per-stem effects (vocal reverb/delay, snare reverb, etc.)
- Stereo panning and widening
- Master bus compression, saturation, EQ
- Export: WAV + MP3 + instrumental version + individual stems
Each run produces:
output/
βββ hollow_shadow_20260207_143022.wav # Full track with vocals
βββ hollow_shadow_20260207_143022.mp3 # MP3 version
βββ hollow_shadow_20260207_143022_instrumental.wav # No vocals
βββ hollow_shadow_20260207_143022_lyrics.txt # Generated lyrics
βββ hollow_shadow_20260207_143022_stems/ # Individual stems
βββ stem_kick.wav
βββ stem_snare.wav
βββ stem_hihat.wav
βββ stem_bass.wav
βββ stem_pads.wav
βββ stem_textures.wav
βββ stem_vocals.wav
Slow, heavy, dark β Portishead / Dummy-era vibes. 75 BPM, Am, sparse drums, warm bass, wide pads.
Tense, claustrophobic β Massive Attack / Mezzanine. 85 BPM, Am, standard drums, distorted bass, crisp hats.
Dreamy, floating β Cocteau Twins meet Air. 70 BPM, Dm, sparse/lo-fi drums, deep bass, lush pads.
mood-machine/
βββ generate_track.py # CLI entry point
βββ pyproject.toml # Project config & dependencies (uv)
βββ config/
β βββ moods/
β βββ melancholic.yaml
β βββ paranoid.yaml
β βββ ethereal.yaml
βββ mood_machine/
β βββ __init__.py
β βββ config.py # Configuration management
β βββ pipeline.py # Main orchestrator
β βββ lyrics/
β β βββ generator.py # Poetry/lyrics generation
β βββ vocals/
β β βββ engine.py # TTS wrappers
β βββ synth/
β β βββ core.py # Oscillators, envelopes, utilities
β β βββ drums.py # Drum synthesis
β β βββ bass.py # Bass synthesis
β β βββ pads.py # Pad/chord synthesis
β β βββ textures.py # Vinyl crackle, hiss, ambience
β βββ sequencer/
β β βββ patterns.py # Drum/bass patterns, chord progressions
β β βββ arranger.py # Full track arrangement
β βββ mixing/
β βββ effects.py # Reverb, delay, compression, EQ
β βββ mixer.py # Stereo mixdown engine
βββ output/ # Generated tracks
βββ samples/ # (reserved for future sample packs)
| Package | Purpose |
|---|---|
| numpy | All audio synthesis and DSP |
| scipy | Filters, convolution reverb |
| pydub | Audio format conversion and export |
| gTTS | Google Text-to-Speech (free) |
| pyttsx3 | Offline system TTS (fallback) |
| PyYAML | Config file parsing |
| pedalboard | High-quality effects (optional, falls back to scipy) |
- ffmpeg β Required for MP3 export and gTTS audio processing
# macOS brew install ffmpeg # Ubuntu/Debian sudo apt install ffmpeg
Add a YAML file to config/moods/:
mood: dystopian
bpm: 82
key: Cm
synth:
pad_filter_cutoff: 1000
bass_character: distorted
drum_tone: lo-fi
drums:
pattern_style: standard
swing: 0.55
progression:
- { root: C, type: minor7, bars: 2 }
- { root: Ab, type: major7, bars: 2 }
- { root: Eb, type: major, bars: 2 }
- { root: Bb, type: dom7, bars: 2 }Then: uv run python generate_track.py --mood dystopian
Implement the VocalEngine interface in mood_machine/vocals/engine.py:
class ElevenLabsTTS(VocalEngine):
def synthesise(self, text: str) -> np.ndarray:
# Call ElevenLabs API, return numpy array
...- Reproducibility: Use
--seed 42to get the same track every time - Quick iteration: Use
uv run python generate_track.py --vocal-engine silent --length 30for fast test renders - Stem mixing: Import stems into a DAW for manual mixing/mastering
- Custom lyrics: Use
--textwith your own spoken-word poetry
MIT