Working with ChordRecognizer


#1

Hey,

I’m trying to make use of ChordRecognizer / FindChordName. I have some samples that contain full orchestra chords (major, minor, diminished and dom7). I’d like to detect if the currently played chord is a major or minor chord (or none of them).

I’ve seen that the algorithm seems to always consider the lowest note to be the root note so the recognition only works if the chords are played in root position. In real life that’s not very helpful for me because I use every voicing in all inversions. So I first tried to extend the ChordRecognizer with RemoveChordInterval and AddChordInterval but this can’t use the root note issue.

My next idea was to extract the root note from the ChordName string (result of FindChordName) and extract the first character of the string. Here I don’t know if this is already possible in GPScript because I couldn’t find a function like copy (Pascal) or substr(ing) (JavaScript) that can extract a part of the string. (And accessing a string like an array and writing ChordName[0] or ChordName[1] doesn’t work as well - I suppose that David doesn’t like this approach ;-)) So I was not able to extract the first character or check if the second character is a “#”.

If I could manage that, my approach were to figure out if the found chord type is a “Min 6th”, then take the root note, convert it into an integer and subtract 4 to get my “real” root note. And the same thing for “Major 2nd” and -5. By the way: Recognizing “C F A” results in “C major 2nd” which in fact has to be “F major 2nd”.

I’ve written some different chord detections in JavaScript which work pretty well in my own projects ( http://player.leadsheeteditor.com/Chords ) and also detect very advanced chords with many tensions, but in this case I just need to find out if the played chord is a major or a minor chord and then get the right root note to send the correct note to KONTAKT.

Thanks for any suggestions or help!

Lukas


#2

That ChordRecognizer was something I threw in to do some testing and it’s certainly not complete. I’m open to suggestions to improving the algorithms. It’s never been clear to me how to deal with root note though…for example, if you play C E A, is that a C6th chord or an inverted Am? So I just used the bottom and assumed that was the root. Again suggestions for improvement are welcome.

Also, I can easily add more string functions if needed — strings were just never really high on the list because I didn’t really expect people to do string processing in what’s supposed to be a real-time environment. Give me a list of what string functions you would like.


#3

Thanks for the answer David.

>> for example, if you play C E A, is that a C6th chord or an inverted Am?
Yes. Some people call it C6 if the fifths is included (C E G A), the first inversion of Am7 (A C E G). But I think more basic chord types should always be prefered. So a minor triad is more basic than a major chord with some extensions (C6, Cmaj7, C7, Cadd9, Csus4 etc.)

It’s the same for Csus2 and Gsus4… or Bm7b5 and Dm6: Same notes but different root note.

For further improvements I could imagine one more bool parameter for FindChordName that decides if the lowest note should be considered to be the root note or if it should return a chord symbol with inversions (Am/C) (in my cases I would always use the second option). And if some don’t want to see the bass note (“Am” instead of “Am/C”), they can use StringContains(ChordName, “/”) and StringBefore :slight_smile:

String functions:

  • Copy/Substring(source : String, index : Integer, count : Integer)
  • LastIndexOfSubstring (like IndexOfSubstring, but returns the last occurance)
  • StringBefore(source : String, substring : String) -> StringBefore(“C major 7”, " ") should return “C”
  • StringAfter(source : String, substring : String)
  • StringContains or similar (source : String, substring : String) -> returns if source contains substr. That would be only for convenience because we can do this with IndexOfSubstring and -1

#4

But “G C E” returning “G major 2nd” is a bug, right? (there’s no easy chord symbol that would describe these notes from a root of G -> it would be Gsus4add13omit5 or something but this makes no sense. I would prefer if it simply returned “C/G” or “C/E” for “E G C” because that’s what would be found on a leadsheet or song book)


#5

Yes, I can only agree with jazzundso. This would make the most sense and would be very cool. I’d like to make a script that adds the root (one or two octaves lower) to a chord, played with one hand. The root, not the lowest note. I’m also aware of the problem that it can’t always be “right”, but would be very satisfied with the logic of jazzundso “more basic chord types should always be prefered”, and the “on bass notation” C/G…


#6

I forgot all about those chord definitions. It is possible to remove them and replace them with your own definitions but I should fix those blatantly wrong ones. Thanks for reminding me


#7

Yes, I’d love to add my own definitions.


#8

There are two functions, AddChordInterval and RemoveChordInterval that you can use to do this.

That whole thing probably needs some improvement, it’s very simple right now. You pass in an array of intervals, always starting at 0 (which is probably unneccessary!) Suggestions to enhance this are welcome

E.g.

RemoveChordInterval(cr, [0,4,7])   // Removes the definition of a major chord
AddChordInterval(cr, [0,4,7], "Major") // Adds it back in again

#9

Hi,
Is there any chance of a simple example of how to use the chord recognizer please…(as I have a feeling I am over thinking it)

Ta
Barry


#10

Nobody?


#11

Are you not talking to us ?


#12

This is a user forum.
The developers sure read - when they have time.


#13

Fair enough - except I originally asked on Oct 25 and its now 3rd Nov. Yet there has been other voluminous feedback to lots of other questions asked since mine (including coding ones). I personally would have thought that when LeeHarvey answered with ‘Nobody’ 3 days ago then someone could have just said that they would respond when they had time. Its no big deal - I’ll figure it out - I just thought there had to be a simple obvious solution that I was missing.