@tonaljs/pcset
Version:
Functions to work with midi numbers
165 lines • 3.93 kB
JavaScript
// index.ts
import { compact, range, rotate } from "@tonaljs/collection";
import { transpose } from "@tonaljs/pitch-distance";
import { interval } from "@tonaljs/pitch-interval";
import { note } from "@tonaljs/pitch-note";
var EmptyPcset = {
empty: true,
name: "",
setNum: 0,
chroma: "000000000000",
normalized: "000000000000",
intervals: []
};
var setNumToChroma = (num2) => Number(num2).toString(2).padStart(12, "0");
var chromaToNumber = (chroma2) => parseInt(chroma2, 2);
var REGEX = /^[01]{12}$/;
function isChroma(set) {
return REGEX.test(set);
}
var isPcsetNum = (set) => typeof set === "number" && set >= 0 && set <= 4095;
var isPcset = (set) => set && isChroma(set.chroma);
var cache = { [EmptyPcset.chroma]: EmptyPcset };
function get(src) {
const chroma2 = isChroma(src) ? src : isPcsetNum(src) ? setNumToChroma(src) : Array.isArray(src) ? listToChroma(src) : isPcset(src) ? src.chroma : EmptyPcset.chroma;
return cache[chroma2] = cache[chroma2] || chromaToPcset(chroma2);
}
var pcset = get;
var chroma = (set) => get(set).chroma;
var intervals = (set) => get(set).intervals;
var num = (set) => get(set).setNum;
var IVLS = [
"1P",
"2m",
"2M",
"3m",
"3M",
"4P",
"5d",
"5P",
"6m",
"6M",
"7m",
"7M"
];
function chromaToIntervals(chroma2) {
const intervals2 = [];
for (let i = 0; i < 12; i++) {
if (chroma2.charAt(i) === "1") intervals2.push(IVLS[i]);
}
return intervals2;
}
function notes(set) {
return get(set).intervals.map((ivl) => transpose("C", ivl));
}
function chromas() {
return range(2048, 4095).map(setNumToChroma);
}
function modes(set, normalize = true) {
const pcs = get(set);
const binary = pcs.chroma.split("");
return compact(
binary.map((_, i) => {
const r = rotate(i, binary);
return normalize && r[0] === "0" ? null : r.join("");
})
);
}
function isEqual(s1, s2) {
return get(s1).setNum === get(s2).setNum;
}
function isSubsetOf(set) {
const s = get(set).setNum;
return (notes2) => {
const o = get(notes2).setNum;
return s && s !== o && (o & s) === o;
};
}
function isSupersetOf(set) {
const s = get(set).setNum;
return (notes2) => {
const o = get(notes2).setNum;
return s && s !== o && (o | s) === o;
};
}
function isNoteIncludedIn(set) {
const s = get(set);
return (noteName) => {
const n = note(noteName);
return s && !n.empty && s.chroma.charAt(n.chroma) === "1";
};
}
var includes = isNoteIncludedIn;
function filter(set) {
const isIncluded = isNoteIncludedIn(set);
return (notes2) => {
return notes2.filter(isIncluded);
};
}
var pcset_default = {
get,
chroma,
num,
intervals,
chromas,
isSupersetOf,
isSubsetOf,
isNoteIncludedIn,
isEqual,
filter,
modes,
notes,
// deprecated
pcset
};
function chromaRotations(chroma2) {
const binary = chroma2.split("");
return binary.map((_, i) => rotate(i, binary).join(""));
}
function chromaToPcset(chroma2) {
const setNum = chromaToNumber(chroma2);
const normalizedNum = chromaRotations(chroma2).map(chromaToNumber).filter((n) => n >= 2048).sort()[0];
const normalized = setNumToChroma(normalizedNum);
const intervals2 = chromaToIntervals(chroma2);
return {
empty: false,
name: "",
setNum,
chroma: chroma2,
normalized,
intervals: intervals2
};
}
function listToChroma(set) {
if (set.length === 0) {
return EmptyPcset.chroma;
}
let pitch;
const binary = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (let i = 0; i < set.length; i++) {
pitch = note(set[i]);
if (pitch.empty) pitch = interval(set[i]);
if (!pitch.empty) binary[pitch.chroma] = 1;
}
return binary.join("");
}
export {
EmptyPcset,
chroma,
chromas,
pcset_default as default,
filter,
get,
includes,
intervals,
isChroma,
isEqual,
isNoteIncludedIn,
isSubsetOf,
isSupersetOf,
modes,
notes,
num,
pcset
};
//# sourceMappingURL=index.mjs.map