What's wrong
In Chord.TryParse (Semantics.Music/Chord.cs), only add9 is consumed as an added tone (ConsumeModifiers, Take(ref body, "add9")). ApplyExtensions then takes any bare 13, 11 or 9 left in the body, treats it as a stacked extension and forces seventh = SeventhType.Dominant. Nothing checks what remains of the body afterwards, so leftover text such as add is silently ignored and the parse succeeds.
Effects:
C69, the common unslashed spelling of the six-nine chord, gets its 9 read as a dominant ninth. The result gains a b7 and prints as C769.
Cadd11 loses the add, and 11 then implies a dominant 7th and a 9th.
Cadd13 behaves the same way.
#248 fixed only the slashed form C6/9, through TryRewriteSixNine, which requires a /.
Failure scenario
| Input |
ToString() |
Chord tones |
Correct tones |
Chord.Parse("C69") |
C769 |
[0,4,7,9,10,14] |
[0,4,7,9,14] (no b7) |
Chord.Parse("Cm69") |
Cm769 |
[0,3,7,9,10,14] |
no b7 |
Chord.Parse("Cadd11") |
C711 |
[0,4,7,10,14,17] |
[0,4,7,17] (C E G F) |
Chord.Parse("Cadd13") |
C713 |
[0,4,7,10,14,17,21] |
[0,4,7,21] |
These are wrong notes returned without any error, so callers voicing or analysing lead sheets get a different chord from the one written.
Suggested fix
- Treat
69 (a 6 immediately followed by a bare 9) the same way as 6/9, e.g. rewrite it to 6add9 before extension handling.
- Either support
add11/add13 (added tones that don't imply a seventh) or reject them.
- After all tokens are consumed, fail
TryParse if the body still holds unrecognised text such as add, instead of ignoring it.
What's wrong
In
Chord.TryParse(Semantics.Music/Chord.cs), onlyadd9is consumed as an added tone (ConsumeModifiers,Take(ref body, "add9")).ApplyExtensionsthen takes any bare13,11or9left in the body, treats it as a stacked extension and forcesseventh = SeventhType.Dominant. Nothing checks what remains of the body afterwards, so leftover text such asaddis silently ignored and the parse succeeds.Effects:
C69, the common unslashed spelling of the six-nine chord, gets its9read as a dominant ninth. The result gains a b7 and prints asC769.Cadd11loses theadd, and11then implies a dominant 7th and a 9th.Cadd13behaves the same way.#248 fixed only the slashed form
C6/9, throughTryRewriteSixNine, which requires a/.Failure scenario
ToString()Chord.Parse("C69")C769[0,4,7,9,10,14][0,4,7,9,14](no b7)Chord.Parse("Cm69")Cm769[0,3,7,9,10,14]Chord.Parse("Cadd11")C711[0,4,7,10,14,17][0,4,7,17](C E G F)Chord.Parse("Cadd13")C713[0,4,7,10,14,17,21][0,4,7,21]These are wrong notes returned without any error, so callers voicing or analysing lead sheets get a different chord from the one written.
Suggested fix
69(a6immediately followed by a bare9) the same way as6/9, e.g. rewrite it to6add9before extension handling.add11/add13(added tones that don't imply a seventh) or reject them.TryParseif the body still holds unrecognised text such asadd, instead of ignoring it.