I was wondering how would one create a javascript function for transposing music chords.
Since I don\'t expect everyone to be a musician here, I\'ll try to explain how i
All of these solutions are lacking the fact that after transposing a note, it needs to be converted to a sharp or flat depending on the key or chord.
So the API must be:
transpose(note, semitones, useSharps)
Here is my implementation. It also handles multiple # and b modifiers.
function transposeNote(note, semitones, useSharps) {
// parse root followed by modifiers (# and b)
const rx = /^([a-gA-G])([#b]*)$/;
const m = rx.exec(note);
if (!m) {
return null;
}
// convert note from 0 to 11 based off of A
let root;
switch (m[1].toUpperCase()) {
case "A":
root = 0;
break;
case "B":
root = 2;
break;
case "C":
root = 3;
break;
case "D":
root = 5;
break;
case "E":
root = 7;
break;
case "F":
root = 8;
break;
case "G":
root = 10;
break;
}
// modify root
let mods = m[2];
if (mods) {
for (var i = 0; i < mods.length; i++) {
if (mods.charAt(i) === "#") {
root++;
} else {
root--;
}
}
}
// transpose note
root = (root + semitones) % 12;
if (root < 0) {
root += 12
}
// convert back to a note
const sharps = [
"A",
"A#",
"B",
"C",
"C#",
"D",
"D#",
"E",
"F",
"F#",
"G",
"G#"
];
const flats = [
"A",
"Bb",
"B",
"C",
"Db",
"D",
"Eb",
"E",
"F",
"Gb",
"G",
"Ab"
];
const transposedNote = useSharps ? sharps[root] : flats[root];
return transposedNote;
}
function transposeChord(chord, semitones, useSharps) {
const rx = /^([a-gA-G][#b]*)\s*([^\/]*)(\/[a-gA-G][#b]*)?$/;
const m = rx.exec(chord);
if (!m) {
return null;
}
const root = transposeNote(m[1], semitones, useSharps);
const quality = m[2] || "";
let bass = m[3] || "";
if (bass.length > 0) {
bass = "/" + transposeNote(bass.substring(1), semitones, useSharps);
}
return root + quality + bass;
}
Use it like this
console.log(transposeChord("Cmin7/Eb", 3, false));