A chord cannot be rooted on the one degree whose fifth is a tritone - #53
Merged
Conversation
The progression tables are roman numerals wearing degree numbers: a row commented I-IV-vi-V is that in the genre's home mode and something else in the mode beside it. Lydian's degree 3 is the sharp 4, major's degree 6 is the leading tone, aeolian's degree 1 is the natural 2 — and on each of those the scale gives the triad no perfect fifth. VoicedTone then forces one, which is right for the shape a guitarist frets and, on that degree, buys the shape by importing a pitch from outside the scale. The chord arrives consonant, confident and in another key, and NearestSoundingTone snaps the tune onto it. So the changes go through Harmony.PlayableProgressions as they are drawn, which walks each root back two degrees until its fifth is perfect. That lands on the triad CONTAINING the original degree as a chord tone in every scale here — lydian's sharp 4 is II's third, dorian's natural 6 is the major IV's, phrygian's 5th is flat III's. A mode becomes a transformation of one progression table rather than a filter over it, which is why this is not a table per mode: 50 clean (mode, progression) pairings become 65. Two rows do not survive the move and are dropped: ska's I-flatVII-V-I under major, which collapses to I-V-V-I, and rock's i-iv-flatVII-i under dorian, which lands on the substitution of the row above it. Substituting at the draw rather than at the point of use is what lets the bass, the voice-leading plan and the tune's chord-tone snap read the same changes.
… phrases Melody.Draw gives the consequent one variation: its own AnswerOp. Drawn freely it can be the antecedent's, and over the same call that produces the same phrase but for its last note — so the four-phrase period collapses back to the two-phrase tune it was written to be bigger than. 13 of 480 drawn periods did exactly that. The operator is now drawn without replacement against the antecedent's, by zeroing a weight rather than by re-drawing, so it stays one draw and the tune's stream does not shift; a genre that weights a single operator keeps it. And at MinPhraseBars only Contrasting puts a second rhythm into a tune, so the other two shapes hand the most exposed voice in the mix one two-bar rhythm to sing four times. That lands hardest on pop and punk, whose four-chord single-bar cycle puts every phrase at the floor — the genres the period was written for. ShortShapeWeights leans a floor-length tune toward Contrasting without forbidding a parallel period, which is a real shape at two bars too. --stats over 100 songs x 6 genres, distinct phrase rhythms and contours within one tune: 1.25-1.42 -> 1.46-1.57 and 3.35-3.49 -> 3.64-3.73. A period holds at most two rhythms, so the first figure is reading the Contrasting rate almost directly. Not changed: a verse is already sparser than its chorus through `move`, and the engine test measures it over 60 tunes. One song where the verse has more notes is the draw, not the rule. Digests re-blessed; the change is meant to be audible.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found from
8nj8bjys:0— a pop song that sounds minor, spooky and out of key.The chord
--scorebar 14 against bar 13, in B lydian (B C# D# E# F# G# A#):A chord rooted on the tritone, containing C natural — a semitone above the tonic and in no
reading of the key — for one bar in every four, all song. The lead's out-of-key note is that same
C:
NearestSoundingTonecorrectly snaps the tune onto the chord that is actually sounding.Why
PopProgressionsrow{0, 3, 5, 4}is commentedI-IV-vi-V, which is true in major. Pop alsodraws lydian, where degree 3 is the ♯4 and its triad has no perfect fifth.
VoicedTonethenforces one — right for the shape a guitarist frets, and on that degree it imports a pitch from
outside the scale, so the chord comes out consonant, confident and in another key.
Every seven-note mode has exactly one such degree. It bites wherever a genre's progressions land
on it:
♭IIrows, which are phrygian vocabulary♭VIIrows, which are mixolydian vocabulary♭VIrow, which is an aeolian reading17 of 67 (genre, mode, progression) pairings.
The fix
Not a table per mode. Walk the root back two degrees until its fifth is perfect
(
Harmony.PlayableProgressions, applied at the draw inCompose.cs). That lands on the triadcontaining the original degree as a chord tone, in every scale this engine draws — lydian's ♯4
is II's third, dorian's ♮6 is the major IV's, phrygian's 5th is ♭III's, major's leading tone is V's.
That is not a coincidence to be tuned: a mode's characteristic note lives in a chord, and rooting a
chord on it is the mistake.
So a mode becomes a transformation of one progression table rather than a filter over it, and
variety goes up rather than down:
The seed above now draws
[0 1 5 4]—I-II-vi-V, a real lydian pop loop — and bar 14 soundsC# D# G#resolving toC# major, every note in the key.Two rows do not survive the move and are dropped: ska's
I-♭VII-V-Iunder major (collapses toI-V-V-I) and rock'si-iv-♭VII-iunder dorian (lands on the row above it). A row written as apedal keeps its repeats.
VoicedToneis untouched — with nothing ever rooted on the tritone degree it only ever seesdegrees where forcing the fifth is already correct, and it stays right for the power chord it was
written for.
Tests
Four new invariants in the harmony section, each with the vacuity check the file's style asks for:
later that breaks it needs looking at, not accepting)
572 checks passed, node suite green,web/_frameworkre-staged from this engine(
bundle-stamp checkclean). The render digests were unaffected — none of the 10 matrix seedsdraws one of the affected modes, which is worth knowing about that matrix rather than reassuring.
One judgement call left open
The written-table cap (no two genres share more than one progression) still holds and is still
asserted. But substitution can land two genres on the same realised changes — metal's
♭IIrowsread as rock's
♭VIIvamp under aeolian, because that is what those degrees are in aeolian. Sixsuch pairs. Arguably correct (they are genuinely the same aeolian vamp, separated by tempo, kit and
voicing) and arguably not, so the test prints the number rather than failing on it.
Not in this PR
8nj8bjys:0's other defect: the tune's consequent restates its antecedent verbatim, so the 8-barperiod is a 4-bar loop, and pop/punk get one 2-bar rhythm for the whole tune. Filed as PLAN.md
rank 38.
Second commit: the tune's period (was PLAN rank 38, now deleted)
Melody.Drawgives the consequent exactly one thing to vary — its ownAnswerOp— and drawing itfreely lets it be the antecedent's. Over the same call that is the same phrase but for its last
note, so the four-phrase period collapses to the two-phrase tune it was written to be bigger than.
13 of 480 drawn periods did that,
8nj8bjys:0's chorus among them.Two changes:
AnswerOpis drawn without replacement against the antecedent's, by zeroinga weight rather than by re-drawing — one draw either way, so the tune's stream does not shift. A
genre that weights a single operator keeps it (an answer it would never write is worse than an
answer heard twice).
Melody.ShortShapeWeights— atMinPhraseBarsonlyContrastingputs a second rhythm into atune, so
ParallelandVariedhand the most exposed voice in the mix one two-bar rhythm to singfour times. Worst for pop and punk, whose single-bar four-chord cycle puts every phrase at the
floor: the genres the period work was written for.
{2, 3, 5}instead of{4, 3, 3}there — alean, not a rule, since a parallel period is real at two bars too.
--stats, 100 songs × 6 genres, distinct phrase rhythms and contours within one tune:A period holds at most two rhythms, so the first figure reads the
Contrastingrate almostdirectly — half of tunes now, a quarter before.
New check: a parallel period never answers itself the same way twice. Verified non-vacuous — it
reports
13 of 480with the without-replacement draw removed.One thing from the original diagnosis was wrong and is not changed. I reported the chorus tune
as sparser than the verse and blamed a missing mechanism. The mechanism exists (
move, 1 for thechorus and 0.8 for the verse, leaning the length draw across the
LongFromsplit) and the enginesuite already asserts it over 60 tunes.
8nj8bjys:0is one draw going the other way, which is whata lean does.
docs/composition.mdnow says so, so the row does not get re-filed off one song.Digests re-blessed — this is meant to be audible.
573 checks passed, node suite green, bundlere-staged.