Skip to main content

write-blues-album

Generate blues tracks — major 12-bar dom7 blues (I7-IV7-V7) and minor blues (Im7-IVm7-V7), plus jazz-blues and blues ballads. Uses CoupledHMMHarmonizer with chord-tone-contour harmony and manual MixingDesk/MasteringDesk. CRITICAL profile rule: blues profile (dom7-only) for major blues, funk profile (dom7+min7) for minor blues. WalkingBass, PianoComp, BluesLick, SaxSolo, brushed drums.

Source facts

Repository
bivex/Melodica
Last source activity
July 3, 2026 at 03:58
Detected SKILL.md language
English
Stars
3
Forks
1

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
write-blues-album
description
Generate blues tracks — major 12-bar dom7 blues (I7-IV7-V7) and minor blues (Im7-IVm7-V7), plus jazz-blues and blues ballads. Uses CoupledHMMHarmonizer with chord-tone-contour harmony and manual MixingDesk/MasteringDesk. CRITICAL profile rule: blues profile (dom7-only) for major blues, funk profile (dom7+min7) for minor blues. WalkingBass, PianoComp, BluesLick, SaxSolo, brushed drums.
# Write Blues Album Use this skill for 12-bar blues — **major dom7 blues** (I7–IV7–V7) and **minor blues** (Im7–IVm7–V7) — plus jazz-blues and slow blues ballads. Uses **CoupledHMMHarmonizer** with **chord-tone-contour harmony** + **manual MixingDesk/MasteringDesk**. ## 1. The decisive choice: `blues` vs `funk` profile This is the single most important decision, and it is **structural, not a tuning knob**. The profile's `completion_bonus` determines which 7th qualities the harmonizer can retain: | Blues type | Form | Profile | `completion_bonus` | |---|---|---|---| | **Major blues** | I7 – IV7 – V7 (all dom7) | `blues` | `{8: 5.0}` — **dom7-only** | | **Minor blues** | Im7 – IVm7 – V7 (m7 + dom7) | `funk` | `{8: 5.0, 7: 4.0}` — **dom7+min7** | | Jazz-blues | ii-V-I / secondary doms | `jazz` | `5.0` — uniform 7th | - The **`blues` profile is dom7-only**. It structurally **cannot retain m7** — on a minor blues, Im7/IVm7 collapse to min triads or get substituted by bIII/bVI diatonics (Ebmaj/Abmaj) whose tones are subsets of the m7 contour. **Never use `blues` for minor blues.** - The **`funk` profile** rewards dom7 AND min7. It is the correct profile for minor blues. - **Chord-type codes: type 7 = min7, type 8 = dom7.** ## 2. Chord-tone contour technique (how to force the harmony) The harmonizer won't reliably emit 7ths from a plain scale-degree melody. Instead **spell each bar's target chord as its actual chord-tone arpeggio** in the contour. The completion_bonus then retains it, and the **pitch-class set disambiguates quality** — Cm7 `[0,3,7,10]` can only complete to m7, never dom7 `[0,4,7,10]`. ```python from melodica.harmonize.coupled_hmm import CoupledHMMHarmonizer from melodica.harmonize import harmonizer_profile from melodica.types import NoteInfo, Scale, Mode # MAJOR blues: dom7 arpeggios, in C. (pc = pitch class) FORM = ["I","I","I","I","IV","IV","I","I","V","IV","I","V"] DOM7 = {"I":[0,4,7,10], "IV":[5,9,0,3], "V":[7,11,2,5]} # C7 / F7 / G7 def make_chords(key, dur, bars_per_chord=4.0): total = int(dur / bars_per_chord) h = CoupledHMMHarmonizer(beam_width=14, chord_change="bars", config=harmonizer_profile("blues")) # <- "funk" for MINOR blues contour = [] for bar in range(total): for j, pc in enumerate(DOM7[FORM[bar % 12]]): contour.append(NoteInfo(pitch=48 + pc, # base MUST be a multiple of 12 start=bar*bars_per_chord + j, duration=1.0, velocity=60)) return h.harmonize(contour, key, dur) ``` **Minor blues** — swap profile to `"funk"` and the arpeggios to m7/dom7: ```python KEY = Scale(root=0, mode=Mode.NATURAL_MINOR) # C minor FORM = ["Im7","Im7","Im7","Im7","IVm7","IVm7","Im7","Im7","V7","IVm7","Im7","V7"] ARP = {"Im7":[0,3,7,10], "IVm7":[5,8,0,3], "V7":[7,11,2,5]} # Cm7 / Fm7 / G7 # config=harmonizer_profile("funk") ``` ## 3. Required imports + pipeline ```python import random, sys, warnings from pathlib import Path REPO = Path(__file__).resolve().parents[3]; sys.path.insert(0, str(REPO)) warnings.filterwarnings("ignore"); random.seed(13) from melodica.generators import GeneratorParams from melodica.generators.walking_bass import WalkingBassGenerator from melodica.generators.piano_comp import PianoCompGenerator from melodica.generators.blues_lick import BluesLickGenerator from melodica.generators.sax_solo import SaxSoloGenerator from melodica.generators.drum_kit_pattern import DrumKitPatternGenerator from melodica.generators.ghost_notes import GhostNotesGenerator from melodica.shorts_mixing import MixingDesk from melodica.shorts_mastering import MasteringDesk from melodica.midi import export_multitrack_midi def _mix(raw, bpm, gains): desk = MixingDesk(niche_cfg={}); desk.track_gains.update(gains) mixed = desk.apply_mixing(raw, [], int(bpm)) mastered, _cc = MasteringDesk(target_lufs=-18.0).apply_mastering(mixed) # returns a TUPLE return mastered # export_multitrack_midi(mixed, out_path, bpm=BPM, key=KEY, instruments={"Bass":32, ...}) ``` ## 4. GM programs `ACOUSTIC_BASS=32`, `PIANO=0`, `EPIANO=4` (Rhodes), `TENOR_SAX=66`, `JAZZ_GUITAR=26`, `DRUMS=0` (drums auto-assigned to channel 10). ## 5. Generators (verified kwargs) ```python bass = WalkingBassGenerator( GeneratorParams(density=0.65, key_range_low=28, key_range_high=40), approach_style="mixed", add_chromatic_passing=True, swing_eighth_ratio=0.67, ).render(chords, key, dur) comp = PianoCompGenerator( GeneratorParams(density=0.45, key_range_low=48, key_range_high=72), comp_style="jazz", voicing_type="shell", accent_pattern="2_4", chord_density=0.6, ).render(chords, key, dur) # voicing_type ∈ {shell, rootless, close} lead = BluesLickGenerator( GeneratorParams(density=0.40, key_range_low=48, key_range_high=72), lick_style="standard", rest_probability=0.45, bend_probability=0.15, ).render(chords, key, dur) sax = SaxSoloGenerator( GeneratorParams(density=0.40, key_range_low=54, key_range_high=84), style="cool", vibrato_depth=0.5, chromaticism=0.4, blues_notes=True, ).render(chords, key, dur) ghosts = GhostNotesGenerator( GeneratorParams(density=0.04), target="snare", pattern="jazz", ghost_velocity=30, ghost_density=0.4, ).render(chords, key, dur) # brushed snare ghost notes drums = DrumKitPatternGenerator( GeneratorParams(density=0.10), style="jazz", groove_swing=0.67, fill_frequency=0.12, auto_fills=True, ).render(chords, key, dur) # style ∈ {rock, jazz, latin, funk, hiphop} ``` ## 6. Subgenres | Subgenre | Key | BPM | Profile | Form | Example script | |---|---|---|---|---|---| | Major shuffle | C major | 120 | `blues` | I7-IV7-V7 dom7 | `scripts/albums/jazz/blues.py` | | Minor blues ballad | C minor | 62 | `funk` | Im7-IVm7-V7 | `scripts/albums/jazz/evening_blues.py` | | Jazz-blues | F/Bb major | 130 | `jazz` | ii-V-I + blues form | — | ## 7. Pitfalls | Issue | Fix | |---|---| | Minor blues Im7/IVm7 collapse to triads | Use `funk` profile, not `blues`. `blues` is dom7-only and cannot retain m7. | | Whole track transposed by a few semitones | Contour base `pitch=` must be a **multiple of 12** (48, 60). `50 + pc` shifts every pc by +2 (50 mod 12 = 2). | | V7 (G7) missing in major blues | The dom7 must be **spelled in the contour** (`{8:5}` fires only when the dom7 tones are present). A bare scale-degree melody won't trigger it. | | `MasteringDesk().apply_mastering()` crashes | It returns a **tuple** `(mastered, cc)` — unpack it. | | Drums silent | Use `DrumKitPatternGenerator` (ride/snare/kick) **AND** `GhostNotesGenerator` (brushes). | | Wrong generator kwargs | The kwargs above are verified against the current API. Older skill docs (`voicing_style`, `style="walking"`, `use_passing_tones`) are **stale and will raise ValueError** — use `voicing_type`, `approach_style`, `add_chromatic_passing`. |
View on GitHub