Skip to content

Instantly share code, notes, and snippets.

@5t111111
Last active May 31, 2021 12:56
Show Gist options
  • Save 5t111111/698c87f8ee518f4db737bd00502695f1 to your computer and use it in GitHub Desktop.
Save 5t111111/698c87f8ee518f4db737bd00502695f1 to your computer and use it in GitHub Desktop.
Get music key (scale) from notes used in it

Usage

  1. Install Deno
  2. Run
deno run https://gist.githubusercontent.com/5t111111/698c87f8ee518f4db737bd00502695f1/raw/get-music-key-from-notes.ts C E F

The above will output:

{ candidates: [ "C", "F", "Dm", "Am" ] }
/*
* Get music key (scale) from notes used
*
* Usage:
*
* deno run https://gist.githubusercontent.com/5t111111/698c87f8ee518f4db737bd00502695f1/raw/get-music-key-from-notes.ts C E F
*
* The above example shows you `{ candidates: [ "C", "F", "Dm", "Am" ] }`
*/
const notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
const majorIntervals = [0, 2, 2, 1, 2, 2, 2];
const majorIntervalsFromRoot = majorIntervals.map((interval, idx) =>
majorIntervals.slice(0, idx + 1).reduce<number>((acc, curr) => acc + curr, 0)
);
const minorIntervals = [0, 2, 1, 2, 2, 1, 2];
const minorIntervalsFromRoot = minorIntervals.map((interval, idx) =>
minorIntervals.slice(0, idx + 1).reduce<number>((acc, curr) => acc + curr, 0)
);
const getNotesOfScale = (intervals: number[], root: string) =>
intervals.reduce<string[]>((acc, curr) => {
const index = notes.findIndex((elem) => elem === root) + curr;
const noteIndex = index >= 12 ? index - 12 : index;
acc.push(notes[noteIndex]);
return acc;
}, []);
const majorScales = notes
.map((note) => {
const notesOfScale = getNotesOfScale(majorIntervalsFromRoot, note);
return {
[note]: notesOfScale,
};
})
.reduce((acc, curr) => Object.assign(acc, curr), {});
const minorScales = notes
.map((note) => {
const notesOfScale = getNotesOfScale(minorIntervalsFromRoot, note);
return {
[`${note}m`]: notesOfScale,
};
})
.reduce((acc, curr) => Object.assign(acc, curr), {});
const scales = Object.assign(majorScales, minorScales);
// console.log(scales);
const notesToFind: string[] = Array.from(
new Set(Deno.args.filter((arg) => notes.includes(arg)))
);
let candidates: string[] = [];
for (const scaleKey in scales) {
if (notesToFind.every((curr) => scales[scaleKey].includes(curr))) {
candidates.push(scaleKey);
}
}
console.log({ candidates });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment