UNPKG

@tonaljs/pitch-note

Version:

Parse intervals in shorthand notation

98 lines 2.51 kB
// index.ts import { coordinates, isNamedPitch, isPitch, pitch } from "@tonaljs/pitch"; var fillStr = (s, n) => Array(Math.abs(n) + 1).join(s); var NoNote = Object.freeze({ empty: true, name: "", letter: "", acc: "", pc: "", step: NaN, alt: NaN, chroma: NaN, height: NaN, coord: [], midi: null, freq: null }); var cache = /* @__PURE__ */ new Map(); var stepToLetter = (step) => "CDEFGAB".charAt(step); var altToAcc = (alt) => alt < 0 ? fillStr("b", -alt) : fillStr("#", alt); var accToAlt = (acc) => acc[0] === "b" ? -acc.length : acc.length; function note(src) { const stringSrc = JSON.stringify(src); const cached = cache.get(stringSrc); if (cached) { return cached; } const value = typeof src === "string" ? parse(src) : isPitch(src) ? note(pitchName(src)) : isNamedPitch(src) ? note(src.name) : NoNote; cache.set(stringSrc, value); return value; } var REGEX = /^([a-gA-G]?)(#{1,}|b{1,}|x{1,}|)(-?\d*)\s*(.*)$/; function tokenizeNote(str) { const m = REGEX.exec(str); return m ? [m[1].toUpperCase(), m[2].replace(/x/g, "##"), m[3], m[4]] : ["", "", "", ""]; } function coordToNote(noteCoord) { return note(pitch(noteCoord)); } var mod = (n, m) => (n % m + m) % m; var SEMI = [0, 2, 4, 5, 7, 9, 11]; function parse(noteName) { const tokens = tokenizeNote(noteName); if (tokens[0] === "" || tokens[3] !== "") { return NoNote; } const letter = tokens[0]; const acc = tokens[1]; const octStr = tokens[2]; const step = (letter.charCodeAt(0) + 3) % 7; const alt = accToAlt(acc); const oct = octStr.length ? +octStr : void 0; const coord = coordinates({ step, alt, oct }); const name = letter + acc + octStr; const pc = letter + acc; const chroma = (SEMI[step] + alt + 120) % 12; const height = oct === void 0 ? mod(SEMI[step] + alt, 12) - 12 * 99 : SEMI[step] + alt + 12 * (oct + 1); const midi = height >= 0 && height <= 127 ? height : null; const freq = oct === void 0 ? null : Math.pow(2, (height - 69) / 12) * 440; return { empty: false, acc, alt, chroma, coord, freq, height, letter, midi, name, oct, pc, step }; } function pitchName(props) { const { step, alt, oct } = props; const letter = stepToLetter(step); if (!letter) { return ""; } const pc = letter + altToAcc(alt); return oct || oct === 0 ? pc + oct : pc; } export { accToAlt, altToAcc, coordToNote, note, stepToLetter, tokenizeNote }; //# sourceMappingURL=index.mjs.map