martijnversluis / ChordSheetJS

A JavaScript library for parsing and formatting chords and chord sheets
https://github.com/users/martijnversluis/projects/4
GNU General Public License v2.0
318 stars 50 forks source link

How to detect the current key? #1066

Closed gpr19 closed 5 months ago

gpr19 commented 11 months ago

Is there any way to detect which key a song is in?

martijnversluis commented 11 months ago

Hey @gpr19. Thanks for reaching out.

Unless the current key is set in the song (either in chordpro or programmatically), there is no way to get the song key.

You could probably implement something to guess the song key, but it is not a current or planned feature.

edwinzap commented 9 months ago

Few years ago I wrote my own chordpro library in which I implemented a basic key guesser system. I plan to join the development of this library since it looks great now.

There are techniques like checking the first and last chord of the song, taking the most use chord,...

I will try to implement that in the future (when I have more time).

martijnversluis commented 9 months ago

Wow, sounds great @edwinzap! Looking forward to your contributions, and thanks for reaching out! 👍

gpr19 commented 6 months ago

With the help of chatGPT I managed to create a function that works temporarily for me.

function:

function determineKey(chords) {
    // Create an object to count the frequency of each note
    const frequencyChords = {};

    // Iterate over the note array and count the frequency of each note
    chords.forEach(chord => {
        if (frequencyChords[chord]) {
          frequencyChords[chord]++;
        } else {
          frequencyChords[chord] = 1;
        }
    });

    // Find the note with the highest frequency
    let key = '';
    let maxFrequency = 0;
    Object.keys(frequencyChords).forEach(chord => {
        if (frequencyChords[chord] > maxFrequency) {
            key = chord;
            maxFrequency = frequencyChords[chord];
        }
    });

    return key;
}

Use:

const song = new ChordSheetJS.ChordProParser().parse(chordSheet)
let chords = []
let key
if (!song.key){
    song.mapItems((item) => {
      if (item instanceof ChordLyricsPair) {
        if (item.chords) {
          chords.push(item.chords)
        }
      }
    })
    key = determineKey(chords)
}