Hi everybody,
I am not sure this is the best page for my question, but since it is related to a module I want to create...
I am looking for an algorithm to identify "left hand chords" on MIDI input for a module I am writing. The basic idea is quite simple : when a chord is found on the MIDI input, the module has to find the key note and the kind of chord.
For example, if the module receives C-E-G notes, it provides "C Major" on its outputs (I have an output giving the key number from 1 to 12) and dedicated outputs for Major, Minor, Seventh, etc...
I have found some algortihms on the web (like PyChoReLib or Carol Krumhansl algorithm) but they look like incredibly complex for this task. Such work is done on MIDI keyboards since a long, long time and I really doubt that machines made in the 70's were able to run such complex algorithms.
My first idea was to find "MIDI distances" between notes and identify the chords based on this, but I am facing the classical "major vs. minor" issues (C Major being also A Minor...). One of the biggest issue is to deal with all possible inversions.
Does anybody have an idea of what could be the algorithm hidding behind this ?
Thanks
Benoit
MIDI chord recognition
-
sm_jamieson
- Member
- Posts: 551
- Contact:
I think you would be surprised how much code is in those old keyboards. But I also expect they are
quite easy confuse.
All the complexity in those web algorithms is required to get accurate results.
Take rootless voicings - one voicing can be several chords, so you then get into harmonic analysis to choose
the chord, etc.
But as a basic, you would start with the chord basics and add extensions, etc.
You need to think how you transcribe a chord in your head, and write code to do that !
So, C-E-G, C major or Am7 ?
If there is a identifiable bass note, that is usually the chord root (but careful of chords with 3rd in the bass).
Else use the lowest note in the chord. But you probably also want to look for a major triad ...
Come to think about it, probably easier to use the code off the web !
Simon.
quite easy confuse.
All the complexity in those web algorithms is required to get accurate results.
Take rootless voicings - one voicing can be several chords, so you then get into harmonic analysis to choose
the chord, etc.
But as a basic, you would start with the chord basics and add extensions, etc.
You need to think how you transcribe a chord in your head, and write code to do that !
So, C-E-G, C major or Am7 ?
If there is a identifiable bass note, that is usually the chord root (but careful of chords with 3rd in the bass).
Else use the lowest note in the chord. But you probably also want to look for a major triad ...
Come to think about it, probably easier to use the code off the web !
Simon.
-
sm_jamieson
- Member
- Posts: 551
- Contact:
Well after having a quick look at PyChoReLib it seems to be quite simple. It does not really use an algorithm to "recognize" chords at all. It uses a database of intervals and a root node offset to recognize chords. The initialisation routine loads 77 types of chord voicings in the key of C, but these will define all keys since its stored as an interval.
Of course there is an algorithm to match the input to the database !
Here is a comment from the code explaining it a bit:
Method to register a new chord type, by showing an example of such a chord.
First: the chord is canonicalised, i.e.
- duplicate notes are removed
- notes are rearranged to minimize the intervals between them
Second: - chords are stored in a database as an interval pattern, making the representation independent of the chord's root note
- also store the offset of the root note in the canonicalised representation, needed for unparsing from interval pattern to chord name
e.g. a chord ['c','g','c','eb'] --- duplicate notes removed ---> ['c','g','eb']
--- rearrange to minimize intervals ---> ['c','eb','g']
--- use as key an interval pattern ---> [4, 3] (interval here is nr of half steps between 2 adjacent notes)
--- store chordname and offset of root note ---> Database entry with key ([4,3]) is (ChordName,0)
Simon.
Of course there is an algorithm to match the input to the database !
Here is a comment from the code explaining it a bit:
Method to register a new chord type, by showing an example of such a chord.
First: the chord is canonicalised, i.e.
- duplicate notes are removed
- notes are rearranged to minimize the intervals between them
Second: - chords are stored in a database as an interval pattern, making the representation independent of the chord's root note
- also store the offset of the root note in the canonicalised representation, needed for unparsing from interval pattern to chord name
e.g. a chord ['c','g','c','eb'] --- duplicate notes removed ---> ['c','g','eb']
--- rearrange to minimize intervals ---> ['c','eb','g']
--- use as key an interval pattern ---> [4, 3] (interval here is nr of half steps between 2 adjacent notes)
--- store chordname and offset of root note ---> Database entry with key ([4,3]) is (ChordName,0)
Simon.
-
imodularsynth
- Member
- Posts: 36
- Contact:
Hello Simon,
thanks for the time spent to analyse PsyChoReLib (I did not yet open the source code)
From what you describe, this library seems quite near of what I had in mind and what I already started to code. As I said in my first message, my main concern was about the number of entries to scan. There are little details on which my code differs (for example, I have added channel recognition, keyboard split - so you can use the "left hand" and "right hand" on the same MIDI keyboard to get chords and play melody)
There is also a kind of timer in my code, because I found that you need to wait for some chords to be sure to identify them (for example, you may get C-E-G which is identified as C Major then a few milliseconds later the B note, which turns the chord to a C Major Seventh)
So apparently, the trick from PsyChoReLib is to avoid a full database scan, they seem to use a special algorithm to speed it up (and I saw in a release note that their last algorithm was much faster)
Based on what you say, I will take a deeper look to this library. Their scan algorithm may inspire me...
Benoit
thanks for the time spent to analyse PsyChoReLib (I did not yet open the source code)
From what you describe, this library seems quite near of what I had in mind and what I already started to code. As I said in my first message, my main concern was about the number of entries to scan. There are little details on which my code differs (for example, I have added channel recognition, keyboard split - so you can use the "left hand" and "right hand" on the same MIDI keyboard to get chords and play melody)
There is also a kind of timer in my code, because I found that you need to wait for some chords to be sure to identify them (for example, you may get C-E-G which is identified as C Major then a few milliseconds later the B note, which turns the chord to a C Major Seventh)
So apparently, the trick from PsyChoReLib is to avoid a full database scan, they seem to use a special algorithm to speed it up (and I saw in a release note that their last algorithm was much faster)
Based on what you say, I will take a deeper look to this library. Their scan algorithm may inspire me...
Benoit
Who is online
Users browsing this forum: No registered users and 9 guests
