Skip to content

Harmony & Chord Progressions

This document explains the harmonic system in MIDI Sketch.

Note

This page uses music theory terminology. These concepts are handled automatically by the system, but understanding them allows for more precise parameter selection.

New to these terms?

Degree, cadence, secondary dominant, tritone substitution and the rest are taught from scratch — with playable examples — in the course chapters Chord Progressions and Harmony & Color.

New to music theory?

If chords and progressions are new to you, the Course builds them up from scratch with playable notation examples — start there, then come back to this reference.

Chord Progressions

MIDI Sketch includes 22 built-in chord progressions, covering common pop music patterns.

What is a Chord Progression?

A chord progression is the sequence of chords that forms the harmonic backbone of a song. It's what gives music its sense of movement and emotion. The same melody can feel completely different over different chord progressions.

Four-Chord Progressions (IDs 0-19)

Three of the built-in four-chord progressions Three rows, one per progression, each showing four degree chips joined left to right by arrows. Row one is FourChordPop, id 0, I to V to vi to IV, which is C, G, A minor, F in C major. Row two is Axis, id 2, vi to IV to I to V. Row three is Minor2, id 8, vi to IV to V to I. A closing caption notes that the table stores degree numbers rather than pitches, so a pattern transposes to any key unchanged. in C major id 0 · FourChordPop I V vi IV C - G - Am - F the plain four-chord loop, and the default id 2 · Axis vi IV I V Am - F - C - G opens on the relative minor, so it reads dark id 8 · Minor2 vi IV V I Am - F - G - C same four chords, rotated to end on V to I The table stores degree numbers, not pitches, so one pattern transposes to every key unchanged. Twenty four-chord and two five-chord patterns ship.

Pass the ID as chordProgressionId.

IDNameDegreesCharacter
0FourChordPopI-V-vi-IVThe plain four-chord loop, and the default
1Pop1I-vi-IV-VFifties turnaround; V hands back to the top
2Axisvi-IV-I-VOpens on the relative minor, so it reads dark
3Pop2IV-I-V-viStarts on the subdominant, ends on a deceptive V-vi
4ClassicI-IV-V-ITextbook I-IV-V closed by an authentic cadence
5Pop3I-IV-vi-VBright opening, dips to vi, leaves V hanging
6OudouIV-V-iii-viThe Royal Road, a J-pop staple
7Minor1vi-V-IV-VRocks between IV and V around a minor tonic; never settles
8Minor2vi-IV-V-IThe same four chords as Axis, rotated to end V-I
9Pop4I-V-iii-IVFourChordPop with iii in place of vi - lighter, less settled
10Pop5I-iii-IV-VSteps up the scale to a V that pushes back to I
11Rock1I-bVII-IV-IMixolydian bVII; rock and blues
12Rock2I-IV-bVII-IThe same bVII colour, approached through IV
13Extended4I-V-vi-iiiThe Pachelbel opening, stopped at iii
14Minor3vi-I-V-IVMinor opening, then three major chords descending
15AeolianPopvi-bVI-bVII-IBorrowed bVI and bVII rising into the tonic
16AnimeHighEnergy1vi-iii-IV-IMinor opening driving to a bright I
17JazzPopii-V-I-viThe ii-V-I turnaround, reopened on vi
18AnimeHighEnergy2vi-ii-V-IA full circle-of-fifths descent onto the tonic
19CityPopI-vi-ii-VA ii-V folded into a pop loop; city-pop groove
Understanding These Progressions
  • FourChordPop (I-V-vi-IV): The most common loop in modern pop. Familiar enough that almost any melody sits on it comfortably.
  • Axis (vi-IV-I-V): The same chord set starting on the minor, which colours the whole loop melancholic. Common in emotional ballads.
  • Minor2 (vi-IV-V-I): The V→I at the end is an authentic cadence, so a loop that begins in minor territory arrives somewhere bright.
  • Oudou (IV-V-iii-vi): The Royal Road progression. Starting away from the tonic and ending on vi keeps it perpetually unresolved.
  • Rock1 (I-bVII-IV-I): bVII is borrowed from the parallel minor and gives the Mixolydian, rock-and-blues flavour.
  • AeolianPop (vi-bVI-bVII-I): Two borrowed chords step upward into the tonic - the loudest modal-interchange move in the set.

Five-Chord Progressions (IDs 20-21)

IDNameDegreesCharacter
20Extended5I-V-vi-iii-IVPachelbel-derived, extended
21NeapolitanPopvi-iv-bII-V-IBorrowed iv and Neapolitan bII into an authentic cadence

Full Progression List

All 22 progressions are listed above: twenty four-chord patterns and two five-chord patterns. Between them they cover:

  • Diatonic pop loops, bright and dark
  • Modal-interchange colour (bVI, bVII, iv, bII)
  • Rock patterns built on bVII
  • Jazz-leaning ii-V turnarounds

Degree System

What are Chord Degrees?

Chord degrees (I, ii, iii, IV, V, vi, vii) indicate the position of a chord within a key. Uppercase = major chord, lowercase = minor chord. For example, in C major: I = C major, ii = D minor, V = G major.

Chord degrees are plain integers rather than a named enum type, so a progression is simply an array of degree numbers:

ValueDegreeRoleExample in C major
0ITonicC
1iiSupertonicDm
2iiiMediantEm
3IVSubdominantF
4VDominantG
5viSubmediantAm
6vii°Leading toneBdim
8bVIBorrowed from the parallel minorAb
10bVIIBorrowed from the parallel minorBb
11bIIIBorrowed from the parallel minorEb
12ivBorrowed minor subdominantFm
13bIINeapolitanDb
14#IVdimChromatic passing chordF#dim

Values 7 and 9 are unused. bII is the Neapolitan; iv gives the minor plagal cadence iv-I. These degrees are not decorative: AeolianPop (15) emits bVI and bVII, and NeapolitanPop (21) emits iv and bII, so anything parsing degree output has to handle values above 6.

Chord Quality

Major vs Minor

  • Major chords sound bright, happy, and stable (C, F, G)
  • Minor chords sound darker, sadder, and more emotional (Dm, Em, Am)
  • Diminished chords sound tense and unstable (rarely used in pop)

Quality follows from the degree alone - the key and the mode are never consulted, and there is no augmented quality:

How a degree number becomes a chord quality On the left, getChordQuality takes a single degree number; the key and the mode are never passed in. Three panels on the right show the result. Major covers I, IV and V plus the borrowed bIII, bVI, bVII and bII. Minor covers ii, iii and vi plus the borrowed iv. Diminished covers vii and the borrowed raised-fourth diminished chord. Only three qualities exist; there is no augmented triad. diatonic borrowed from the parallel minor getChordQuality One argument: the degree number. The key and the mode are never consulted, so quality is fixed by the degree alone. Only three qualities exist — the engine has no augmented triad. major triad I · 0 IV · 3 V · 4 bIII · 11 bVI · 8 bVII · 10 bII · 13 minor triad ii · 1 iii · 2 vi · 5 iv · 12 diminished triad vii · 6 #IV° · 14 Of the borrowed degrees, only bVI, bVII, iv and bII appear in the shipped progression table — through Rock1, Rock2, AeolianPop and NeapolitanPop.
cpp
ChordQuality getChordQuality(int8_t degree) {
    // 6 = vii, 14 = #IVdim
    if (degree == 6 || degree == 14) return ChordQuality::Diminished;
    // 1 = ii, 2 = iii, 5 = vi, 12 = borrowed iv
    if (degree == 1 || degree == 2 || degree == 5 || degree == 12) return ChordQuality::Minor;
    // I, IV, V and the borrowed bVI, bVII, bIII, bII
    return ChordQuality::Major;
}

The borrowed iv is minor - that minor third is the whole reason it is borrowed - while bVI, bVII, bIII and bII are all major triads.

Chord Extensions

Extensions add color to basic triads:

When to Use Extensions

  • Sus chords: Create tension before resolution. Great for anticipation moments.
  • 7th chords: Add sophistication and jazz flavor. Common in city pop and R&B.
  • 9th chords: Rich, complex sound. Use sparingly for maximum impact.

Higher extension probabilities work well for city pop, jazz, and R&B styles. Keep them low for simple pop and rock.

Extension Types

TypeNotes AddedExample (C)
TriadRoot, 3rd, 5thC-E-G
Sus2Root, 2nd, 5thC-D-G
Sus4Root, 4th, 5thC-F-G
7th+ 7thC-E-G-B/Bb
add9+ 9th (no 7th)C-E-G-D
9th+ 7th + 9thC-E-G-B-D (maj9) / C-E-G-Bb-D (dom9) / C-Eb-G-Bb-D (min9)

Extension Application Rules

The three extension tests, in the order they run Three lanes, each with a condition, a probability roll and a result. The sus test looks at the bar position — the first or next-to-last bar of a section — and skips minor chords; it yields Sus4 seventy percent of the time and Sus2 otherwise. The seventh test applies in B and Chorus sections or on V, where the threshold is doubled. The ninth test applies to any chord in a Chorus, or to V inside a B section. The first test that passes returns; if none does, the chord stays a plain triad. A caveat notes that Chorus chords are rewritten beforehand. the three tests run in this order — the first one that passes wins, and a chord never gets two extensions 1 · sus the first bar of the section, or the next-to-last bar — and not a minor chord roll < susProb one roll per chord Sus4 — 70% of the time Sus2 — the other 30% 2 · 7th the section is B or Chorus, or the chord is V roll < 7thProb V doubles the threshold V → Dom7 · minor → Min7 everything else → Maj7 3 · 9th the section is Chorus — any chord — or the chord is V inside a B section roll < 9thProb a roll of its own V → Dom9 · I → Maj9 · ii or vi → Min9 iii → Min7 · anything else → Add9 no test matched — the chord stays a plain triad and with all three flags off, none of this runs at all reharmonizeForSection settles Chorus chords first, so this table applies elsewhere Only one extension is ever applied: the first test that passes returns, and the tests below it are never reached.

The three families are tested in order - sus, then 7th, then 9th - and the first test that passes returns, so a chord never carries two extensions. Each family rolls its own die, so raising one probability does not starve the others.

  • Sus is a bar-position rule: the first or the next-to-last bar of a section, and never on a minor chord. Sus4 is chosen 70 % of the time, Sus2 the rest.
  • 7th applies in B and Chorus sections, or on V anywhere; on V the probability is doubled.
  • 9th applies to any chord in a Chorus, or to V inside a B section. iii falls back to Min7, because its diatonic 9th would be a flat 9th above the root.

Chorus chords are decided beforehand

Whenever 7ths are enabled, a chorus is reharmonised before these tests run: V becomes Dom7, minor chords Min7, I becomes Maj7 and everything else gets add9. The rules above then only govern what happens outside a chorus, or inside one with 7ths disabled. The same pass may substitute ii for IV in an A section, unless that IV resolves to V or I or ii is already an adjacent chord.

Configuration

cpp
struct ChordExtensionParams {
    bool enable_sus = false;
    bool enable_7th = false;
    bool enable_9th = false;
    bool tritone_sub = false;              // Tritone substitution (V7 -> bII7)
    float sus_probability = 0.2f;          // 0.0-1.0 (20% chance)
    float seventh_probability = 0.15f;     // 0.0-1.0 (15% chance)
    float ninth_probability = 0.25f;       // 0.0-1.0 (25% chance)
    float tritone_sub_probability = 0.5f;  // 0.0-1.0 (50% chance when enabled)
};

In the JS SongConfig, these map to chordExtSus / chordExt7th / chordExt9th / chordExtTritoneSub and chordExtSusProb / chordExt7thProb / chordExt9thProb / chordExtTritoneSubProb (all probabilities 0.0-1.0).

Mood-Dependent Probability Auto-Adjustment

When chordExtProbExplicit=false (default), the mood automatically adjusts chord extension probabilities to match the style. Set chordExtProbExplicit=true to manually control all extension probabilities.

Voice Leading

What is Voice Leading?

Voice leading is how individual notes move from one chord to the next. Good voice leading creates smooth, connected chord transitions. Poor voice leading sounds choppy and disconnected. MIDI Sketch automatically applies optimized voice leading to all generated chord progressions.

Principles

  1. Minimize movement: Each voice moves by smallest interval
  2. Common tones: Retain shared notes between chords
  3. Parallel fifths/octaves: penalised, not forbidden. The penalty is mood-scaled - heavy for ballad and dramatic moods, light for dance and idol moods where parallel motion is idiomatic.
  4. Smooth bass: Stepwise or small leaps preferred

Algorithm

cpp
VoicedChord selectVoicing(const VoicedChord& prev, const Chord& next, Mood mood) {
    auto candidates = generateVoicings(next);

    // Higher is better. Common tones dominate; distance is weighted so the
    // bass and soprano count double. Parallel 5ths/octaves cost a mood-
    // dependent penalty rather than being forbidden outright.
    int score = typeBonus(candidate)
              + countCommonTones(prev, candidate) * 100
              + (hasParallelFifthsOrOctaves(prev, candidate) ? parallelPenalty(mood) : 0)
              - weightedVoicingDistance(prev, candidate)
              + repetitionPenalty(candidate, prev);

    // Ties are broken randomly, so repeated bars do not lock into one voicing.
    return pickRandomlyAmongBest(candidates, score);
}

There is no per-voice leap term. weightedVoicingDistance is a per-voice sum in which the bass and the soprano count double and the inner voices count once. A common tone is worth 100, which outweighs several semitones of movement, so retaining shared notes is the strongest single force. A voicing repeated three or more times in a row costs 50 per extra repeat.

Voicing Types

The three voicing types laid out on a pitch axis A shared horizontal pitch axis running from C3 to C5, with three rows below it. Close position places C4, E4, G4 and B4 inside a single octave. Open position, the drop-2 form, moves the voice below the top down an octave, giving G3, C4, E4 and B4. Rootless drops the root entirely and plays E3, G3, B3 and D4, leaving the root to the bass. A closing note lists the conditions the engine requires before it picks a rootless voicing. C3 C4 C5 Close all inside one octave C4 E4 G4 B4 all four notes inside one octave — compact, direct, the pop default Open · Drop2 the second voice drops G3 C4 E4 B4 the voice below the top drops an octave; wide and airy Rootless the root is left out E3 G3 B3 D4 no root — the bass has it, and the low register stays clear Close and Open cover most bars. Rootless also needs the bass to sound the root on beat 1, a B, Chorus or Bridge section, a CityPop, Nostalgic, Dramatic or ModernPop mood, and one more roll to pass — and ballads never use it at all.
Voicing Explained
  • Close Position: All notes within one octave. Sounds compact and direct. Common in pop.
  • Open Position: Notes spread across multiple octaves. Sounds spacious and full. Great for ballads.
  • Rootless: Omits the root note (bass plays it). Creates clarity and avoids muddiness. Common arranging technique.

Bass-Chord Coordination

The chord track uses bass analysis to avoid doubling:

cpp
struct BassAnalysis {
    bool hasRootOnBeat1;   // Root on downbeat
    bool hasRootOnBeat3;   // Root on beat 3
    bool hasFifth;         // Fifth present
    Tick accentTicks[];    // Strong beat positions
};

// A bass root makes rootless voicing *eligible*; it is then gated by mood
// and section, and chosen probabilistically (20-30% in B/Chorus/Bridge).
if (bassAnalysis.hasRootOnBeat1 && moodSupportsRootless(mood) && rollProbability(sectionRate)) {
    voicing = generateRootlessVoicing(chord);
}

Rootless voicing is reserved for the jazz-leaning moods (CityPop, Nostalgic, Dramatic, ModernPop) and only in B, Chorus and Bridge. Verses, intros, outros and ballads always keep the root.

Secondary Dominants

Secondary dominants are dominant chords (V7) that resolve to diatonic chords other than the tonic. They create stronger harmonic pull and add harmonic variety.

What are Secondary Dominants?

Instead of going directly from IV to V, inserting V/V (a dominant chord that resolves to V) creates a stronger sense of motion. For example, in C major: F → D7 → G is more compelling than F → G because D7 (V/V) "wants to" resolve to G.

Common Secondary Dominants

SymbolResolves ToExample in C
V/VV (dominant)D7 → G
V/vivi (relative minor)E7 → Am
V/iiii (supertonic)A7 → Dm
V/IVIV (subdominant)C7 → F

Automatic Insertion

MIDI Sketch inserts secondary dominants under two rules:

  • Entering a chorus (deterministic): when the first chord of a Chorus is ii, IV, V or vi, its dominant is placed in the last half-bar of the preceding section.
  • Within a section (probabilistic): the per-bar chance is the section's tension times 0.25. Only Chorus (0.75), Pre-chorus B (0.65), Bridge (0.60) and MixBreak (0.55) clear the 0.5 tension threshold; verses, intros and outros never receive one.

Two limits keep the density pop-appropriate: at least two bars between insertions, and at most bars / 8 per section (one per eight bars). Only ii, IV, V and vi are valid targets; the inserted chord is always a dominant 7th.

cpp
// Example: V/V insertion before V
// Original: IV → V → I
// Enhanced: IV → V/V → V → I

Tritone Substitution

Tritone substitution replaces a V7 chord with a bII7 chord (a dominant 7th built a tritone away). This creates chromatic bass motion and adds harmonic sophistication.

Configuration

Tritone substitution is available via:

  • SongConfig (JS): chordExtTritoneSub (enable, default false) and chordExtTritoneSubProb (probability 0.0-1.0, default 0.5)
  • AccompanimentConfig (JS): chordExtTritoneSub (enable) and chordExtTritoneSubProb (probability 0.0-1.0, default 0.5)
  • C++ SongConfig: chord_extension.tritone_sub and chord_extension.tritone_sub_probability (0.0-1.0)

Mood-Dependent Chord Extension Probabilities

When chordExtProbExplicit=false, the mood automatically adjusts chord extension probabilities to match the style:

Mood7th Prob9th ProbSus ProbNotes
CityPop40%25%-Jazz-influenced voicings
RnBNeoSoul50%35%-Rich extended harmonies
Ballad/Sentimental30%-25%Expressive sus resolutions
Nostalgic/Chill25%--Gentle extensions
Lofi40%30%-Warm, lo-fi character

Explicit vs Automatic

Set chordExtProbExplicit=true to manually control all extension probabilities, or leave it false to let the mood system choose appropriate values automatically.

ChordEvent in EventData

The EventData JSON output includes a chords array with per-section chord information, including secondary-dominant annotations, so external tools can visualise and analyse the harmonic structure.

Key Modulation

Why Modulate?

Key modulation (changing the key mid-song) is a powerful technique to add excitement and emotional lift. A modulation up by 1-2 semitones in the final chorus creates a feeling of "taking it to the next level" - a classic technique used in countless hit songs.

Modulation Parameters

ParameterRangeDescription
modulationTiming0-4When to modulate (0=disabled)
modulationSemitones1-4Amount to modulate (required when timing is not 0)

WARNING

When modulationTiming is non-zero, modulationSemitones must be set to 1-4. The vocal high range is automatically adjusted to prevent the final sections from exceeding the vocal range after transposition.

Modulation Points

The amount always comes from modulationSemitones (1-4; the C++ default when unset is 2) and never varies by song structure. The position is chosen by modulationTiming:

modulationTimingPosition
1 LastChorusStart of the final chorus (most common)
2 AfterBridgeFirst chorus that follows a bridge; falls back to the final chorus
3 EachChorusFalls back to a single final-chorus lift and emits a warning
4 RandomA randomly selected chorus (seed-determined)

The DirectChorus and ShortForm structures never modulate - they have no meaningful modulation point.

Implementation

cpp
struct Modulation {
    Tick tick;           // When to modulate
    int8_t semitones;    // How much (1-4 semitones)
};

// Applied during MIDI output
void MidiWriter::writeTrack(MidiTrack& track, Modulation mod) {
    for (auto& note : track.notes) {
        if (note.tick >= mod.tick) {
            note.pitch += mod.semitones;
        }
    }
}

Chord Tone Analysis

Used for melody generation to determine note consonance:

cpp
bool isChordTone(uint8_t pitch, Chord chord) {
    uint8_t pitchClass = pitch % 12;

    // Check against chord pitch classes
    for (auto& chordPitch : chord.pitchClasses()) {
        if (pitchClass == chordPitch) return true;
    }
    return false;
}

uint8_t nearestChordTone(uint8_t pitch, Chord chord) {
    // Find closest chord tone by semitone distance
    int minDist = 12;
    uint8_t nearest = pitch;

    for (auto& target : chord.pitches()) {
        int dist = abs(pitch - target);
        if (dist < minDist) {
            minDist = dist;
            nearest = target;
        }
    }
    return nearest;
}

Tension Notes

What are Tension Notes?

Tension notes are notes that don't belong to the current chord but are used intentionally to create musical interest. They create a sense of "wanting to resolve" - like a musical question waiting for an answer. Used skillfully, they make melodies more expressive and emotionally compelling.

Tension availability is decided per chord degree, not globally - a tension that would clash with the chord's third or produce a b9 is excluded:

DegreeAvailable tensions
I9th, 13th (11th excluded: #4 against the major 3rd)
ii9th, 11th, 13th
iii11th, b13th (9th excluded: it would be a b9)
IV9th, #11th, 13th
V9th, 13th (11th only over sus4)
vi9th, 11th (13th excluded: it would be a b13)
vii°11th only
TensionInterval above the rootTypical resolution
9thMajor 2ndDown to the root
11thPerfect 4thDown to the 3rd
#11Aug 4thUp to the 5th
13thMajor 6thDown to the 5th
b13Minor 6thDown to the 5th

Usage by Vocal Attitude

AttitudePitch poolMusical effect
CleanChord tones onlySafe, consonant, easy to sing
ExpressiveChord tones plus the 7th, 9th and 11th above the root, kept inside the key. Added only on longer notes - notes shorter than an eighth fall back to chord tones, and tensionUsage sets how long a note must beColourful, emotional, expressive
RawAll seven diatonic scale tones, chord tone or notEdgy, unpredictable, intense

Note duration, not beat position

Tension is gated by how long a note is, not by where it falls in the bar. A short note is always pushed back onto a chord tone regardless of attitude, because a passing dissonance that is over quickly is safe while a sustained one is not.

Where beat position matters

Beat position governs a different pass. MelodicEmbellisher classifies beats 1 and 3 as Strong, beats 2 and 4 as Medium, off-beat eighths as Weak, and sixteenth subdivisions as VeryWeak. Passing and neighbour tones require a non-Strong position; appoggiaturas and suspensions are accented Strong-beat figures that resolve by step.

Choosing Vocal Attitude

  • Clean: Best for simple pop, children's songs, and when singability is important
  • Expressive: Best for ballads, R&B, city pop - adds emotional depth
  • Raw: Best for rock, alternative, experimental - creates tension and edge

Harmony-Melody Integration

The vocal generation system uses harmony information to shape melody candidates.

HarmonyContext

The HarmonyContext system tracks generated tracks and filters many unsafe pitch candidates:

How a proposed melody pitch is checked against the sounding harmony The melody writer proposes a pitch and a duration. HarmonyContext answers with two parts: a chord tracker that knows which chord sounds at that tick, and a collision detector that knows which notes are already sounding. The seven registered pitched roles are vocal, bass, chord, motif, aux, arpeggio and guitar; the candidate's own role is excluded, and drums and SE are excluded. Generation uses actual semitone distances: minor 2nds at 1 or 13, major 2nds at 2, major 7ths at 11, 23 or 35, and tritones at 6, 18 or 30. A sounding-chord major 2nd, a registered root major seventh on normalized I/IV (degree 0/3) in a Maj7/Maj9 chord, and a tritone in V, vii or a secondary dominant are context exceptions. Brief melodic 1- and 2-semitone overlaps may pass only outside sustained chord/guitar roles, with at most 120 or 240 ticks respectively (halved on beats 1 and 3), when at least one pitch is C4 or above. A bass below C3 blocks a major seventh at 11 semitones; the registered I/IV root–M7 exception applies only at 23 semitones or wider. The analyzer has a base cutoff above 24 semitones, then applies a low-bass override. One boolean comes back as a candidate filter, not a guarantee of a clean final mix. MelodyDesigner proposes a pitch and a duration HarmonyContext ChordProgressionTracker which chord is sounding at this tick TrackCollisionDetector which notes are already sounding there Seven pitched roles; own role excluded Drums and SE are excluded what counts as a clash m2: 1 or 13 semitones blocked* M2: 2 semitones blocked* M7: 11 / 23 / 35 blocked* tritone: 6 / 18 / 30 context* m7: 10; M9: 14; >=36 base: fine one boolean comes back — a filter, with no ranking or final guarantee * Brief melodic m2/M2 may pass: 1 ≤120 ticks, 2 ≤240 (half on beats 1/3); at least one pitch C4+. V/vii/secondary tritones are context-owned; low bass (< C3) blocks M7 at 11, and registered M7 only passes at ≥23. Analyzer >24 is a base cutoff with a low-bass override.

Why HarmonyContext Matters

Without HarmonyContext, melodies might clash with accompaniment. For example, if the bass plays E and the melody plays F simultaneously, the result is a harsh minor 2nd dissonance. HarmonyContext checks active notes before suggesting melody pitches and filters many such clashes; later passes and intentional figures still depend on musical context.

What Counts as a Collision

HarmonyContext answers a single yes-or-no question. It asks TrackCollisionDetector whether a proposed pitch clashes with anything already sounding and gets back one boolean, with no ranking. The seven registered pitched roles are vocal, bass, chord, motif, aux, arpeggio and guitar; a candidate's own role is excluded, and drums and SE do not participate in pitch collision detection. Generation compares actual semitone distances, so the same pitch-class interval can have different results at different spacings.

IntervalGenerator rule
Minor 2nd1 or 13 semitones: dissonant; brief melodic 1-semitone overlaps may pass
Major 2nd2 semitones: dissonant; 14 (major 9th) is not, and two tones of the sounding chord are accepted
Major 7th11, 23 or 35 semitones: dissonant; a registered root–M7 pair on normalized I/IV (degree 0/3) in a Maj7/Maj9 chord is an exception
Tritone6, 18 or 30 semitones: dissonant unless the chord is V, vii° or an active secondary dominant
Other intervalsMinor 7ths, major 9ths and distances of 36 semitones or more pass the base rule

Brief melodic 1- and 2-semitone overlaps are tolerated only outside sustained chord/guitar roles, when at least one pitch is at or above C4: the overlap limits are 120 ticks for 1 semitone and 240 ticks for 2 semitones, halved on beats 1 and 3. A major 7th involving a bass below C3 remains blocked at 11 semitones; a registered root–M7 pair on normalized I/IV (degree 0/3) in Maj7/Maj9 is exempt only at a spacing of at least 23 semitones. The post-generation analyzer uses a base cutoff above 24 semitones, then applies its own low-bass and registered-extension handling, so it can omit a collision that generation still rejects, such as a 35-semitone major 7th or a 30-semitone tritone. The boolean is a candidate filter and does not guarantee a dissonance-free final mix.

The graded Mild and Severe levels belong to a different module: the read-only PianoRollSafety API described below, which reports severity for display rather than gating generation.

Chord-Aware Melody Generation

Melody writing is a single pass, not a generate-evaluate-refine cycle. generateSection lays out a phrase plan, chooses each pitch note by note against the chord sounding at that tick, adds embellishments, and finally snaps an illegal note in the downbeat window onto a chord tone. A licensed accented dissonance that resolves down by step can remain. generateSectionWithEvaluation wraps that pass, running it up to a hundred times per section and choosing between the results.

Where chord knowledge enters melody writing On the left, one candidate melody is written in four steps: a phrase plan, then a pitch chosen note by note with a chord tone scoring sixteen points, a root or fifth four more and a scale tone twelve, then embellishment, then a downbeat constraint that snaps an illegal note onto a chord tone while retaining a licensed accented dissonance that resolves down by step. That whole pass runs up to a hundred times per section. On the right, each candidate is scored, the weaker half is dropped, and one of the survivors is picked by a weighted roll. one candidate — written up to 100 times per section 1 · phrase plan where phrases begin and end 2 · pitch per note chord tone +16, root or 5th +4, scale tone +12 3 · embellish passing and neighbour tones 4 · downbeat check Keep legal accents; snap other notes choosing between them score each candidate style 0.4 + culling 0.4 + bias 0.2 drop the weaker half weighted random pick among the survivors Only beats 1 and 3 are measured for chord-tone fit — the score is the share of those notes landing on a chord tone. There is no separate refinement pass: the downbeat snap and the candidate cull are where harmony is enforced.

Note scoring: while a candidate is being written, a chord tone is worth 16 points, a root or fifth 4 more on top of that, and a scale tone 12. A non-scale tone earns nothing from harmony and survives only if the melodic and rhythmic terms carry it.

Downbeat rule: beats 1 and 3 are the only positions measured for chord-tone fit. In the downbeat window, classifyVocalTone leaves chord tones and licensed accented dissonances such as descending appoggiaturas or suspensions in place; only illegal pitches are snapped to a chord tone. This grounds the harmony while leaving room for directed melodic tension.

VocalStyleProfile and Harmony

Each VocalStyleProfile configures how the melody interacts with harmony:

ProfileChord Tone PreferenceTension UsageApproach
StandardHigh on strong beatsOccasional 9thSafe, singable
IdolVery highMinimalCatchy, simple
CityPopMediumFrequent 9th, 13thSophisticated
VocaloidLowAggressiveSurprising
BalladHighExpressive appoggiaturasEmotional

Style-Harmony Matching

For best results, match your chord extensions to your vocal style:

  • Idol/Standard: Keep extensions low (sus, occasional 7th)
  • CityPop/Jazz: Use high extension probabilities (7th, 9th)
  • Vocaloid: Extensions don't matter much (melody is freer)

Melody Evaluation: Harmony Component

Harmony enters the melody score as a single ratio. calcChordToneRatio looks only at notes starting on beat 1 or beat 3, checks each against the chord sounding at that tick, and returns the share that are chord tones. There is no graded reward or penalty per note, and weak-beat notes are not counted at all - a phrase with no strong-beat notes scores a neutral 0.5.

The finer weighting happens earlier, while the notes are being written rather than when the finished candidate is judged: that is the 16 / 4 / 12 point scale described above. Harmony therefore shapes the melody twice, once as a bias during writing and once as a blunt ratio during selection.

Hook System and Harmony

The hook system (used in Chorus sections) respects harmony while creating memorable patterns:

Hook SkeletonMelodic shape
RepeatHolds one pitch
AscendingThree consecutive scale steps upward
AscendDropArpeggiates up through the triad, then steps back down one degree
LeapReturnLeaps up a fifth to a chord tone, then falls to the second degree above the anchor

Skeleton offsets are scale degrees relative to the phrase anchor, so the same shape adapts to whatever chord is sounding. The engine ships twenty-five skeletons; these four are the most common.

Hook + Chord Sync

Hooks are most effective when they align with chord changes. The hookIntensity parameter controls how strongly hooks emphasize chord tones vs. create melodic interest through tensions.

Piano Roll Safety API

For external tools such as piano roll editors, the JavaScript PianoRollSafety API exposes display-only safety, reason flags, and collision details for each MIDI pitch. After a sketch has been generated:

javascript
const info = sketch.getPianoRollSafetyAt(0)
const safety = info.safety[60]
const reasons = info.reason[60]

The colors describe this display API's own safety levels: green is safe, yellow is a warning, and red is dissonant or out of range. Its severity policy is separate from the HarmonyContext generator filter and does not inherit that filter's chord exceptions.


Practical Guide

StyleProgressionExtensionsAttitude
Simple PopFourChordPop (0)Low (10-20%)Clean
Emotional BalladAxis (2)Medium (30%)Expressive
J-PopOudou (6)Medium (30%)Expressive
City PopCityPop (19)High (50%+)Expressive
RockRock1 (11)Low (10%)Raw

Quick Start Recommendations

For Beginners

Start with these safe defaults:

  • Progression: FourChordPop (ID 0) - works with almost anything
  • Extensions: Keep all probabilities under 30%
  • Attitude: Clean - easiest melodies to work with
  • Modulation: None or LastChorus +1 semitone

Once you're comfortable, experiment with more complex progressions and higher extension probabilities.