write-jazz-album

star 2

Generate jazz albums (bebop, swing, cool jazz, Latin jazz, modal jazz, blues, stride, boogie-woogie). Uses CoupledHMMHarmonizer with manual MixingDesk/MasteringDesk pipeline. WalkingBass, PianoComp, SaxSolo, StridePiano, Montuno, BluesLick, BoogieWoogie generators.

bivex By bivex schedule Updated 6/5/2026

name: write-jazz-album description: Generate jazz albums (bebop, swing, cool jazz, Latin jazz, modal jazz, blues, stride, boogie-woogie). Uses CoupledHMMHarmonizer with manual MixingDesk/MasteringDesk pipeline. WalkingBass, PianoComp, SaxSolo, StridePiano, Montuno, BluesLick, BoogieWoogie generators.

Write Jazz Album

Use this skill for bebop, swing, cool jazz, hard bop, Latin jazz, modal jazz, blues, stride piano, and boogie-woogie albums. Uses CoupledHMMHarmonizer for harmony and manual mixing with MixingDesk + MasteringDesk.

1. When to Use

  • Traditional / swing / big band jazz
  • Bebop / hard bop / cool jazz
  • Modal jazz (Kind of Blue style)
  • Latin jazz / Afro-Cuban jazz
  • Blues / jazz-blues crossover
  • Stride piano / boogie-woogie
  • Jazz ballads and slow standards

2. Required Imports

import random
import sys
import warnings
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent))

from melodica import types
from melodica.theory import Quality
from melodica.types import NoteInfo, Scale, Mode, ChordLabel, Quality, KeyLabel, MusicTimeline
from melodica.generators import GeneratorParams
from melodica.generators.melody import MelodyGenerator
from melodica.generators.solo_melody import SoloMelodyGenerator
from melodica.generators.walking_bass import WalkingBassGenerator
from melodica.generators.piano_comp import PianoCompGenerator
from melodica.generators.sax_solo import SaxSoloGenerator
from melodica.generators.swing import SwingGenerator
from melodica.generators.stride_piano import StridePianoGenerator
from melodica.generators.montuno import MontunoGenerator
from melodica.generators.blues_lick import BluesLickGenerator
from melodica.generators.boogie_woogie import BoogieWoogieGenerator
from melodica.generators.arpeggiator import ArpeggiatorGenerator
from melodica.generators.ambient import AmbientPadGenerator
from melodica.generators.drum_kit_pattern import DrumKitPatternGenerator
from melodica.generators.ghost_notes import GhostNotesGenerator
from melodica.generators.bass import BassGenerator
from melodica.harmonize.coupled_hmm import CoupledHMMHarmonizer
from melodica.composer.transformers import spiceup
from melodica.shorts_mixing import MixingDesk
from melodica.shorts_mastering import MasteringDesk

3. Jazz Scales & Modes

# Bebop / Hard Bop
Bb_BEBOP_DOM = Scale(root=10, mode=Mode.BEBOP_DOMINANT)
F_BEBOP_DOM  = Scale(root=5,  mode=Mode.BEBOP_DOMINANT)
C_BEBOP_DOM  = Scale(root=0,  mode=Mode.BEBOP_DOMINANT)

# Modal Jazz
D_DORIAN   = Scale(root=2, mode=Mode.DORIAN)     # So What
C_DORIAN   = Scale(root=0, mode=Mode.DORIAN)
G_DORIAN   = Scale(root=7, mode=Mode.DORIAN)

# Standard Jazz
Bb_MAJOR   = Scale(root=10, mode=Mode.MAJOR)      # Bright swing
F_MAJOR    = Scale(root=5,  mode=Mode.MAJOR)       # Classic
Eb_MAJOR   = Scale(root=3,  mode=Mode.MAJOR)       # Bluesy
C_MAJOR    = Scale(root=0,  mode=Mode.MAJOR)

# Minor / Blues
D_MINOR    = Scale(root=2, mode=Mode.NATURAL_MINOR) # Ballad
G_MINOR    = Scale(root=7, mode=Mode.NATURAL_MINOR)
C_MINOR    = Scale(root=0, mode=Mode.NATURAL_MINOR)
F_BLUES    = Scale(root=5, mode=Mode.BLUES)
Bb_BLUES   = Scale(root=10, mode=Mode.BLUES)

# Latin Jazz
A_DORIAN   = Scale(root=9,  mode=Mode.DORIAN)      # Latin feel
G_MIXOLYD  = Scale(root=7,  mode=Mode.MIXOLYDIAN)   # Montuno

4. Harmony: CoupledHMMHarmonizer

def make_chords(key: Scale, dur: float, bars_per_chord: float = 4.0) -> list[ChordLabel]:
    total_bars = int(dur / bars_per_chord)
    harmonizer = CoupledHMMHarmonizer(
        beam_width=14,
        chord_change="half",     # "half" = half-note resolution (jazz standard)
    )
    # Build a sparse melody contour for harmonization
    contour = []
    degrees = key.degrees()
    for bar in range(total_bars):
        deg = degrees[bar % len(degrees)]
        contour.append(NoteInfo(
            pitch=60 + int(deg),
            start=bar * bars_per_chord,
            duration=bars_per_chord - 0.1,
            velocity=60,
        ))
    chords = harmonizer.harmonize(contour, key, dur)
    return chords

5. GM MIDI Programs

PIANO       = 0    # Acoustic Grand Piano
EPIANO      = 4    # Electric Piano 1 (Rhodes)
ORGAN       = 16   # Drawbar Organ
JAZZ_GUITAR = 26   # Jazz Guitar (archtop)
ACOUSTIC_BASS = 32 # Acoustic Bass (walking)
FRETLESS    = 35   # Fretless Bass
TRUMPET     = 56
TROMBONE    = 57
SOPRANO_SAX = 64
ALTO_SAX    = 65
TENOR_SAX   = 66
BARI_SAX    = 67
CLARINET    = 71
FLUTE       = 73
VIBRAPHONE  = 11
DRUMS       = 0    # Drums use program 0 (channel assigned sequentially)

6. Register Separation

Critical for clean jazz mixes — keep generators in their own frequency bands:

Role Range Pitches
Bass 24–38 Bass guitar, acoustic bass
Low Comp 36–48 Left-hand piano, stride
Comp 48–67 Piano voicings, guitar chords
Melody 54–84 Sax, trumpet, flute lead
Sparkle 72–88 Upper piano, vibraphone, flute top

7. Core Generators

Walking Bass

bass = WalkingBassGenerator(
    GeneratorParams(density=0.70, key_range_low=24, key_range_high=40),
    style="walking",              # "walking", "two_feel", "half_time"
    use_passing_tones=True,
    use_approach_notes=True,
    target_notes_weight=0.3,
).render(chords, key, dur)

Piano Comping

comp = PianoCompGenerator(
    GeneratorParams(density=0.45, key_range_low=48, key_range_high=67),
    voicing_style="rootless",     # "rootless", "shell", "spread", "locked_hands"
    rhythm_style="syncopated",    # "syncopated", "charleston", "stride_rhythm", "four_beat"
    fill_probability=0.15,
    fill_density=0.4,
).render(chords, key, dur)

Saxophone Solo

sax = SaxSoloGenerator(
    GeneratorParams(density=0.55, key_range_low=54, key_range_high=84),
    style="bebop",                # "bebop", "cool", "hard_bop", "smooth"
    use_chromatic_passages=True,
    quote_probability=0.08,
    vibrato_depth=0.5,
).render(chords, key, dur)

Swing Ride / Feel

swing = SwingGenerator(
    GeneratorParams(density=0.40, key_range_low=48, key_range_high=84),
    swing_ratio=0.67,             # Jazz triplet swing (0.67 ≈ 2:1)
).render(chords, key, dur)

Stride Piano

stride = StridePianoGenerator(
    GeneratorParams(density=0.55, key_range_low=28, key_range_high=88),
    style="harlem_stride",        # "harlem_stride", "fats_waller", "james_p_johnson"
).render(chords, key, dur)

Montuno (Latin Jazz)

montuno = MontunoGenerator(
    GeneratorParams(density=0.50, key_range_low=60, key_range_high=84),
    clave_type="son_23",          # "rumba_23", "rumba_32", "son_23", "son_32", "none"
    octave_doubling=False,        # Keep False to avoid register masking
    syncopation_level=0.6,
).render(chords, key, dur)

Blues Licks

blues = BluesLickGenerator(
    GeneratorParams(density=0.50, key_range_low=48, key_range_high=72),
    lick_complexity=0.6,          # 0.0-1.0
    bend_probability=0.15,
).render(chords, key, dur)

Boogie-Woogie

boogie = BoogieWoogieGenerator(
    GeneratorParams(density=0.65, key_range_low=36, key_range_high=72),
    pattern="eight_to_bar",       # "eight_to_bar", "sixteen_beat", "triple_treble"
).render(chords, key, dur)

Jazz Drums

drums = DrumKitPatternGenerator(
    GeneratorParams(density=0.08),
    style="jazz",                 # Ride cymbal (51) + snare (38) + kick (36)
    groove_swing=0.67,           # Match jazz swing ratio
    fill_frequency=0.15,
    auto_fills=True,
).render(chords, key, dur)

Brush Ghost Notes

ghosts = GhostNotesGenerator(
    GeneratorParams(density=0.03),
    pattern="jazz",               # Built-in jazz brush pattern
    target="snare",
    ghost_velocity=30,
    ghost_density=0.4,
).render(chords, key, dur)

8. Mixing & Mastering

def _mix(raw, bpm):
    desk = MixingDesk(niche_cfg={})
    desk.track_gains.update({
        "Bass":    0.85,
        "Comp":    0.80,
        "Melody":  0.88,
        "Guitar":  0.78,
        "Drums":   0.72,
        "Ghosts":  0.55,
        "Strings": 0.68,
        "Pad":     0.55,
        "Stride":  0.82,
        "Montuno": 0.78,
    })
    mixed = desk.apply_mixing(raw, [], int(bpm))
    m = MasteringDesk(target_lufs=-18.0)   # Jazz sits at -18 LUFS (louder than ambient -20)
    return m.apply_mastering(mixed)

9. Track Function Pattern

def _track(title: str, key: Scale, bpm: float, dur: float, builder, instruments: dict):
    chords = make_chords(key, dur)
    raw = builder(chords, key, dur)
    mixed = _mix(raw, bpm)
    out = album_dir / f"{title}.mid"
    export_multitrack_midi(mixed, instruments, int(bpm), str(out), key_label=key.name)

def main():
    global album_dir
    album_dir = Path("output/album_name")
    album_dir.mkdir(exist_ok=True, parents=True)

    _track("01_Sunny Side", Scale(root=10, mode=Mode.BEBOP_DOMINANT), 138, 64.0,
            build_sunny_side, {"Bass": ACOUSTIC_BASS, "Comp": PIANO, ...})

10. Subgenre Guide

Subgenre BPM Density Feel
Ballad 55–75 0.25–0.40 Rubato, sparse
Cool Jazz 80–110 0.35–0.50 Laid-back, legato
Bebop 140–200 0.55–0.75 Fast, dense lines
Hard Bop 120–145 0.45–0.65 Gospel-blues infused
Swing / Big Band 120–160 0.45–0.60 Driving, ensemble
Modal Jazz 90–130 0.30–0.50 Open, spacious
Latin Jazz 100–135 0.45–0.65 Syncopated, clave
Stride Piano 120–160 0.50–0.65 Virtuosic, rhythmic
Boogie-Woogie 130–170 0.55–0.70 Driving 8ths
Jazz-Blues 100–135 0.40–0.60 12-bar, swinging

11. Key Instrument Combinations

Style Lead Comp Bass Drums
Bebop SaxSolo (66) PianoComp (0) WalkingBass (32) DrumKit jazz (0)
Cool Jazz MelodyGenerator on Flute (73) PianoComp rootless (0) WalkingBass two_feel (32) DrumKit jazz (0)
Latin Jazz Trumpet (56) Montuno (0) WalkingBass (32) DrumKit jazz (0) + Ghosts
Stride StridePiano (0) WalkingBass (32) DrumKit jazz (0)
Blues BluesLick (0) + Sax (66) PianoComp shell (0) WalkingBass (32) DrumKit jazz (0)
Ballad SaxSolo cool (66) PianoComp spread (0) WalkingBass half_time (35) Ghosts jazz only
Boogie-Woogie BoogieWoogie (0) BassGenerator walking (32) DrumKit jazz (0)
Organ Trio MelodyGenerator (16) PianoComp locked_hands (16) WalkingBass (32) DrumKit jazz (0)

12. Common Pitfalls

Issue Fix
Mode.HARMONIC_MINOR not found Use Mode.HARM_MINOR
Montuno clave_type error Valid: rumba_23, rumba_32, son_23, son_32, none
note_range_low on GeneratorParams Use key_range_low / key_range_high on GeneratorParams; note_range_low/note_range_high only on MelodyGenerator
Bass and comp overlap Keep bass ≤38, comp ≥48 — see register table
Montuno octave_doubling pushes too high Set octave_doubling=False
Drums not audible Add both DrumKitPattern (ride+snare+kick) AND GhostNotes (brushes)
Swing feel missing Set groove_swing=0.67 on drums, swing_ratio=0.67 on SwingGenerator
CoupledHMMHarmonizer not found Import from melodica.harmonize.coupled_hmm
WalkingBass too busy Lower density to 0.55, or use style="two_feel"
Jazz too quiet after mastering Target -18 LUFS, not -20 (ambient is quieter)

13. Running

python scripts/albums/jazz/album_name.py
Install via CLI
npx skills add https://github.com/bivex/Melodica --skill write-jazz-album
Repository Details
star Stars 2
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator