@tonaljs/pitch-note
Version:
Parse intervals in shorthand notation
98 lines • 2.51 kB
JavaScript
// 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