Skip to content

Latest commit

Β 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎡 Psygen β€” Automated Psytrance Music Generator

Psygen is a fully automated, headless psytrance music generation pipeline written in Python. It produces complete, playable .wav or .mp3 tracks from code β€” no DAW, no external hardware, no manual intervention required.

Input:  python -m psygen --style fullon --kick techno --bass techno --length 240
Output: A full-on track with a techno low end β€” generated in seconds

Features

  • Data-driven style engine β€” every layer's pattern, synthesis, and effects come from editable YAML style files; ships with signature, fullon, and techno
  • Per-element style mixing β€” assign a different style to each layer (e.g. techno kick + full-on lead) to craft a unique signature sound
  • Selectable scale modes β€” minor, phrygian, phrygian-dominant, harmonic minor, and more
  • MIDI export β€” write a multi-track .mid alongside the audio to take stems into a DAW
  • Full pipeline β€” composition β†’ synthesis β†’ effects β†’ mixing β†’ mastering β†’ export
  • Band-limited synthesis β€” PolyBLEP sawtooth/square oscillators eliminate aliasing artifacts
  • Acid bass engine β€” chunked LadderFilter automation for classic filter-sweep sound
  • Studio-grade effects β€” powered by pedalboard (Spotify's JUCE-based DSP library)
  • Intelligent arrangement β€” style-defined section templates with per-section layer control
  • Sidechain pumping β€” kick-synced envelope modulation on bass and pads
  • Reproducible β€” seed any generation for deterministic, byte-identical output
  • Fast β€” generates 4 minutes of audio in seconds (tens of Γ— real-time)

Quick Start

Prerequisites

  • Python 3.10+
  • uv (recommended) or pip

Installation

git clone https://github.com/leoneperdigao/psygen.git
cd psygen
uv venv && uv pip install -e ".[dev]"

Generate Your First Track

uv run python -m psygen --length 240

This produces output.wav β€” a 4-minute track in your signature style.

Usage

usage: psygen [-h] [--style STYLE] [--kick STYLE] [--bass STYLE] [--hihat STYLE]
              [--lead STYLE] [--pad STYLE] [--scale-mode SCALE_MODE] [--bpm BPM]
              [--length LENGTH] [--key KEY] [--intensity INTENSITY] [--seed SEED]
              [-o OUTPUT] [--midi PATH] [--list-styles]

🎡 Psygen β€” automated psytrance music generator

options:
  -h, --help            show this help message and exit
  --style STYLE         Base style name (default: signature). See --list-styles.
  --kick/--bass/--hihat/--lead/--pad STYLE
                        Override a single layer with another style's block.
  --scale-mode MODE     minor, phrygian, phrygian_dominant, harmonic_minor, major, …
  --bpm BPM             Tempo in BPM (default: the style's own tempo)
  --length LENGTH       Track length in seconds (default: 240 = 4 minutes)
  --key KEY             Musical key root, e.g. Cm, D#m, F#m (default: Cm)
  --intensity INTENSITY Energy / intensity 0.0–1.0 (default: 0.75)
  --seed SEED           Random seed for reproducible output (default: random)
  -o, --output OUTPUT   Output audio file path (.wav or .mp3) (default: output.wav)
  --midi PATH           Also write a multi-track MIDI render to PATH
  --list-styles         List available styles and exit

Examples

# Your signature style, 4 minutes
uv run python -m psygen --length 240 -o signature.wav

# A built-in style in a chosen key
uv run python -m psygen --style fullon --key F#m -o fullon.wav

# Per-element mixing: a full-on track with a techno low end
uv run python -m psygen --style fullon --kick techno --bass techno -o blend.wav

# Pick a scale mode and also export MIDI stems
uv run python -m psygen --style fullon --scale-mode phrygian_dominant --midi stems.mid

# Reproducible generation (same seed + style = byte-identical output)
uv run python -m psygen --style techno --seed 42

# List the available styles
uv run python -m psygen --list-styles

Styles

A style is a complete description of how a track should sound. It bundles global parameters (tempo, scale mode) with one block per layer β€” kick, bass, hi-hat, lead, pad β€” plus arrangement, mix, and master settings. Each block holds everything that defines that layer's character: its pattern density, its synthesis (oscillators, envelopes), and its effects.

Styles live as editable YAML files in psygen/styles/presets/:

Style Character
signature Your unique default β€” darker, driving, phrygian, aggressive acid bass
fullon Full-on / Goa β€” uplifting, fast, busy phrygian-dominant arps, lush pads
techno Slower, hypnotic, boomy kick, rumbling sustained bass, minimal melody

Per-element mixing

Because each layer's character lives in its own block, you can graft one style's layer onto another. Global tempo and key stay from the base --style; an overridden layer keeps its own sonic character but plays at the track's tempo:

# full-on everything, but a techno kick + bass underneath
uv run python -m psygen --style fullon --kick techno --bass techno

Authoring your own style

Copy a preset and tweak it β€” any field you omit falls back to the engine default, so a style file only needs the values you want to change:

# psygen/styles/presets/myvibe.yaml
name: myvibe
bpm: 142
scale_mode: phrygian
bass:
  octave_up_prob: 0.7     # more octave jumps
  ladder_resonance: 0.65  # more acid bite
pad:
  fx_reverb_wet: 0.5      # washier atmosphere

Then uv run python -m psygen --style myvibe. You can also keep styles outside the repo by pointing PSYGEN_STYLE_DIR at your own folder of *.yaml files (these override presets of the same name).

MIDI export

Pass --midi out.mid to also render the composition as a multi-track MIDI file β€” one track per layer, drums mapped to General-MIDI percussion, pitched layers on melodic channels β€” so you can re-voice the stems with your own instruments in any DAW.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  COMPOSITION                         β”‚
β”‚  Pattern generators: kick, bass, hihat, lead, pad    β”‚
β”‚  NoteEvent sequences with per-section variation      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚ NoteEvent lists
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β–Ό            β–Ό            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Kick Synth   β”‚ β”‚ Bass Synthβ”‚ β”‚ Lead Synthβ”‚  ← numpy/scipy
β”‚ (sine sweep  β”‚ β”‚ (PolyBLEPβ”‚ β”‚ (square + β”‚    direct waveform
β”‚  + sub + clk)β”‚ β”‚  saw Γ—2) β”‚ β”‚  saw)     β”‚    synthesis
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
       β”‚               β”‚            β”‚          float32 numpy arrays
       β–Ό               β–Ό            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Pedalboard:  β”‚ β”‚ Pedalbrd:β”‚ β”‚ Pedalbrd:β”‚   ← pedalboard
β”‚ HPF β†’ Comp β†’ β”‚ β”‚ Ladder β†’ β”‚ β”‚ LPF β†’    β”‚    effect chains
β”‚ LowShelf     β”‚ β”‚ Dist β†’   β”‚ β”‚ Delay β†’  β”‚
β”‚              β”‚ β”‚ Comp     β”‚ β”‚ Reverb   β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
       β”‚               β”‚            β”‚
       β–Ό               β–Ό            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              MIXER & ARRANGER                    β”‚
β”‚  Volume / Pan / Sidechain pump / Section layout  β”‚
β”‚  intro β†’ buildup β†’ main β†’ breakdown β†’ main      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              MASTER BUS                          β”‚
β”‚  HPF β†’ LowShelf β†’ HighShelf β†’ Comp β†’ Limiter    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
                       β–Ό
                 WAV / MP3 file

Project Structure

psygen/
β”œβ”€β”€ pyproject.toml                 # Package metadata & dependencies
β”œβ”€β”€ psygen/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ __main__.py                # python -m psygen entry point
β”‚   β”œβ”€β”€ cli.py                     # Argument parsing
β”‚   β”œβ”€β”€ config.py                  # TrackConfig dataclass
β”‚   β”œβ”€β”€ theory.py                  # Scales, keys, note/freq conversion
β”‚   β”œβ”€β”€ pipeline.py                # End-to-end orchestrator
β”‚   β”œβ”€β”€ composition/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   └── patterns.py            # Pattern generators for all instruments
β”‚   β”œβ”€β”€ synth/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ oscillators.py         # PolyBLEP saw/square, sine, noise
β”‚   β”‚   β”œβ”€β”€ envelopes.py           # ADSR, exponential decay, fades
β”‚   β”‚   └── instruments.py         # Instrument renderers (patterns β†’ audio)
β”‚   β”œβ”€β”€ effects/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   └── chains.py              # Per-track & master bus effect chains
β”‚   β”œβ”€β”€ mixer/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   └── mix.py                 # Stereo mixing, panning, sidechain, arrangement
β”‚   β”œβ”€β”€ styles/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ schema.py              # Style + per-layer dataclasses
β”‚   β”‚   β”œβ”€β”€ loader.py              # YAML β†’ Style; preset registry
β”‚   β”‚   β”œβ”€β”€ blend.py               # Per-element style resolution
β”‚   β”‚   └── presets/               # signature.yaml, fullon.yaml, techno.yaml
β”‚   └── export/
β”‚       β”œβ”€β”€ __init__.py
β”‚       └── midi.py                # Multi-track MIDI export via mido

How It Works

1. Composition (psygen/composition/)

Pattern generators create NoteEvent sequences for each instrument layer:

Layer Pattern Style Details
Kick 4/4 four-on-the-floor Optional ghost kicks based on variation
Bass Rolling 16th notes Root-centric acid patterns with passing tones
Hi-hats Offbeat 8ths Open hats on offbeats, closed hat fills
Lead 16th-note arpeggios Scale-based with up/down/random directions
Pad Sustained chords Chord progression changing every 2-4 bars

2. Synthesis (psygen/synth/)

All audio is generated directly from numpy arrays β€” no samples or soundfonts needed:

  • Oscillators β€” PolyBLEP-corrected sawtooth and square waves (alias-free), sine, white/filtered noise
  • Kick drum β€” Sine sweep (160β†’42 Hz) + sub sine (45 Hz) + noise click transient
  • Bass β€” Two detuned PolyBLEP saws with snappy ADSR
  • Lead β€” Square + saw mix with fast attack
  • Pads β€” Three detuned saws with slow attack for lush texture
  • Hi-hats β€” Bandpass-filtered noise with exponential decay

3. Effects (psygen/effects/)

Per-track processing via pedalboard (JUCE-based, studio-quality):

Track Chain
Kick Highpass (30 Hz) β†’ Compressor β†’ Gain β†’ Low Shelf
Bass LadderFilter (animated cutoff!) β†’ Distortion β†’ Compressor β†’ Highpass
Hi-hat Highpass (4 kHz) β†’ Compressor β†’ Gain β†’ Reverb
Lead Lowpass β†’ Delay (β…œ note) β†’ Reverb β†’ Compressor
Pad Lowpass β†’ Chorus β†’ Reverb (large room) β†’ Compressor

The bass chain processes audio in 256-sample chunks, updating the Moog-style LadderFilter cutoff between each chunk to create the classic acid filter sweep.

4. Mixing & Mastering (psygen/mixer/)

  • Stereo panning β€” constant-power pan law
  • Sidechain pump β€” kick-synced envelope multiplied into bass (depth 0.45) and pads (depth 0.35)
  • Arrangement β€” intro β†’ buildup β†’ main β†’ breakdown β†’ buildup β†’ main, with per-section layer muting and volume control
  • Fade in/out β€” 2-second linear fades
  • Master bus β€” Highpass β†’ Low Shelf β†’ High Shelf β†’ Compressor β†’ Limiter (βˆ’1 dBFS)

Supported Keys

Standard note names with sharps or flats: C, C#/Db, D, D#/Eb, E, F, F#/Gb, G, G#/Ab, A, A#/Bb, B

Append m for minor (default and recommended for psytrance): Cm, F#m, Bbm, etc.

The --key sets the root; the mode comes from the style (or --scale-mode). Available modes: minor, natural_minor, harmonic_minor, phrygian, phrygian_dominant, major, chromatic.

Dependencies

Package Role
numpy Waveform generation, array math
scipy Butterworth filters for noise shaping
pedalboard Studio-grade audio effects (JUCE-based)
mido MIDI export
PyYAML Loading editable style files

Future Improvements

  • MIDI file export alongside audio
  • Selectable scale modes (Phrygian, Phrygian dominant, …)
  • Data-driven styles with per-element mixing
  • Sample import (load one-shot kicks, percussion)
  • Multi-band compression on master bus
  • Per-section filter automation curves
  • Web UI for parameter tweaking
  • VST3/AU plugin loading via pedalboard
  • Batch generation mode

License

MIT

About

🧠🎡 Turn code into psychedelic trance. AI-assisted MIDI generation for producers who prefer Python to piano rolls.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages