Search code examples
pythonmusic21music-notation

Is there a way to constrain music21's chord detection to non-slash chords?


I'm working on a script that takes as input a sequence of MIDI notes and outputs a chord symbol for use in Impro-Visor, an open-source jazz improvisation helper. In order to take advantage of Impro-Visor's large vocabulary of chords I've been trying to add to music21's chord vocabulary--music21 itself will handle the MIDI pitches and the interpretation of most common chords--using the harmony.addNewChordSymbol method, but the system doesn't offer the new chords in its chord detection. For example, if I try this chord from the Harmony module's docs:

>>>harmony.addNewChordSymbol('BethChord', '1,3,-6,#9', ['MH', 'beth'])
>>>c = chord.Chord(['C3','D#3','E3','A-3'])
>>>print(harmony.chordSymbolFromChord(c))
'A-+/CaddD#'

Whereas I would hope in this case to get: 'Cbeth'

Music21 consistently suggests slash chords like the above rather than whatever chord I've tried to add to the vocabulary, presumably because the chord type to the left of the slash--'+', in this case--comes earlier in the OrderedDict in harmony.py. Is there any way to make the chord-detection prefer a custom chord type over these slash chords (which I don't have any way of handling)?


Solution

  • I found that just telling music21 you meant for "C" to be the root does the trick. (Otherwise, it will try to stack in thirds and treat "Ab" as the root.) Call .root() like this:

    >>> harmony.addNewChordSymbol('BethChord', '1,3,-6,#9', ['MH', 'beth'])
    >>> c = chord.Chord(['C3','D#3','E3','A-3'])
    >>> c.root(c.bass())
    >>> harmony.chordSymbolFromChord(c)
    <music21.harmony.ChordSymbol CMH>