monome / norns

norns is many sound instruments.
http://monome.org
GNU General Public License v3.0
633 stars 147 forks source link

Return correct 7th chords from musicutil.generate_chord_scale_degree #1688

Closed Dewb closed 1 year ago

Dewb commented 1 year ago

Summary:

The musicutil function generate_chord_scale_degree produces incorrect results when you ask for 7th chords, and returns intervals outside the scale. This PR fixes the issue and returns the correct chords, but it makes some breaking changes to the Roman-notation parsing function generate_chord_roman in the process.

Longer explanation:

Yesterday @dstroud mentioned on Discord that he thought some of the 7th chords in the SCALE_CHORD_DEGREES table ought to be half-diminished instead of diminished. I started looking into the issue and found several other problems with the 7th chord sections of this table.

When I added generate_chord_scale_degree to musicutil, the 7th chords feature was kind of an afterthought; I relied on the chord parsing function present in the WesternMusicElements library that musicutil is largely adapted from. Its Roman notation parsing was comprehensive for triads but was incomplete for 7ths, limited to major, minor, diminished, and augmented 7ths, so it wasn't suitable for building a scale degree system without modification of the original algorithm.

In order to generate the correct chords, generate_chord_roman also needs to support half-diminished 7ths (e.g. "viø7"), minor major 7ths ("i♮7"), augmented major 7ths ("III+M7"), and dominant 7ths ("V7"). This necessitates some new notation for the first three ("ø", "♮", "M") and a breaking interpretation of existing notation for the last one.

The current behavior treats all augmented chords as augmented minor, and all capital-letter 7ths as major (rather than major or dominant depending on context, as a lot of notation styles do.) The new behavior allows upper/lowercase to determine major or minor for augmented chords as it does for other chord forms, and assumes that uppercase 7th chords with no aug/dim symbols are dominant unless a "M" suffix is added to specify major. The "M" suffix on an augmented 7th chord now signifies that it's "Augmented Major 7" instead of a regular "Augmented 7" chord. (Both are major triads, but the 7th is raised an additional half-step in the former.)

The new notation is relatively uncontroversial. The natural sign already exists in the default font, but half-diminished needs the O-with-slash glyph to be added.

The breaking changes are a little more concerning. Initial consensus of Discord stakeholders seems to be that since the existing results are not musically correct, breaking it is not an issue.

Another possible solution strategy would be to keep roman chord parsing as is, but make it more contextually aware, so that III7 could return either a major or dominant chord depending on the scale requested. However, it does seem friendlier to users who aren't deeply versed in western music theory, and also friendlier to UI programmers, to have the Roman chord labels be explicit and deterministic.

Dewb commented 1 year ago

The change to 04B_03__.TTF adds U+00D8 and U+00F8, the uppercase and lowercase O-slash glyphs. I think it is 70% smaller because I used PixelForge instead of FontForge this time around, and it replaced empty glyphs with blank characters rather than boxes. This is probably not desirable so I'll re-apply the changes with FontForge.

Dewb commented 1 year ago

In a side discussion with @dstroud we came to the conclusion that it made sense to require an M to disambiguate Augmented Major 7 from Augmented 7th, like the M to disambiguate Major 7 from Dominant 7. In addition to being consistent it also eliminates one of the two breaking changes to generate_chord_roman (requests for chords like "III+" will continue to return Augmented 7 like they did before.) Updated the PR description a bit to reflect this.

Also reprocessed the font glyph additions with FontForge instead of PixelForge to restore the missing box-glyphs for unused characters, and re-ran the internal offline script to update the chord tables inside SCALES (since CHORDS was modified to add the Augmented Major 7 chord.)

tehn commented 1 year ago

thank you for putting the time in on this!