Files
pocket-chords/app/app/lib/transpose.ts

35 lines
1.1 KiB
TypeScript

import type { Song } from "./types";
const NOTES_SHARP = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
const NOTES_FLAT = ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"];
function transposeChord(chord: string, semitones: number): string {
const match = chord.match(/^([A-G][#b]?)(.*)/);
if (!match) return chord;
const [, root, descriptor] = match;
const idx = NOTES_SHARP.indexOf(root) !== -1
? NOTES_SHARP.indexOf(root)
: NOTES_FLAT.indexOf(root);
if (idx === -1) return chord;
const newIdx = ((idx + semitones) % 12 + 12) % 12;
const notes = semitones >= 0 ? NOTES_SHARP : NOTES_FLAT;
return notes[newIdx] + descriptor;
}
export function transposeSong(song: Song, semitones: number): Song {
if (semitones === 0) return song;
return {
...song,
sections: song.sections.map((section) => ({
...section,
lines: section.lines.map((line) => ({
...line,
chords: line.chords.map((cp) => ({
...cp,
chord: transposeChord(cp.chord, semitones),
})),
})),
})),
};
}