UNPKG

@tonaljs/scale

Version:

Musical scales and its relations

202 lines (201 loc) 6.77 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all2) => { for (var name in all2) __defProp(target, name, { get: all2[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // index.ts var index_exports = {}; __export(index_exports, { default: () => index_default, degrees: () => degrees, detect: () => detect, extended: () => extended, get: () => get, modeNames: () => modeNames, names: () => names, rangeOf: () => rangeOf, reduced: () => reduced, scale: () => scale, scaleChords: () => scaleChords, scaleNotes: () => scaleNotes, steps: () => steps, tokenize: () => tokenize }); module.exports = __toCommonJS(index_exports); var import_chord_type = require("@tonaljs/chord-type"); var import_collection = require("@tonaljs/collection"); var import_note = require("@tonaljs/note"); var import_pcset = require("@tonaljs/pcset"); var import_pitch_distance = require("@tonaljs/pitch-distance"); var import_pitch_note = require("@tonaljs/pitch-note"); var import_scale_type = require("@tonaljs/scale-type"); var NoScale = { empty: true, name: "", type: "", tonic: null, setNum: NaN, chroma: "", normalized: "", aliases: [], notes: [], intervals: [] }; function tokenize(name) { if (typeof name !== "string") { return ["", ""]; } const i = name.indexOf(" "); const tonic = (0, import_pitch_note.note)(name.substring(0, i)); if (tonic.empty) { const n = (0, import_pitch_note.note)(name); return n.empty ? ["", name.toLowerCase()] : [n.name, ""]; } const type = name.substring(tonic.name.length + 1).toLowerCase(); return [tonic.name, type.length ? type : ""]; } var names = import_scale_type.names; function get(src) { const tokens = Array.isArray(src) ? src : tokenize(src); const tonic = (0, import_pitch_note.note)(tokens[0]).name; const st = (0, import_scale_type.get)(tokens[1]); if (st.empty) { return NoScale; } const type = st.name; const notes = tonic ? st.intervals.map((i) => (0, import_pitch_distance.transpose)(tonic, i)) : []; const name = tonic ? tonic + " " + type : type; return { ...st, name, type, tonic, notes }; } var scale = get; function detect(notes, options = {}) { const notesChroma = (0, import_pcset.chroma)(notes); const tonic = (0, import_pitch_note.note)(options.tonic ?? notes[0] ?? ""); const tonicChroma = tonic.chroma; if (tonicChroma === void 0) { return []; } const pitchClasses = notesChroma.split(""); pitchClasses[tonicChroma] = "1"; const scaleChroma = (0, import_collection.rotate)(tonicChroma, pitchClasses).join(""); const match = (0, import_scale_type.all)().find((scaleType) => scaleType.chroma === scaleChroma); const results = []; if (match) { results.push(tonic.name + " " + match.name); } if (options.match === "exact") { return results; } extended(scaleChroma).forEach((scaleName) => { results.push(tonic.name + " " + scaleName); }); return results; } function scaleChords(name) { const s = get(name); const inScale = (0, import_pcset.isSubsetOf)(s.chroma); return (0, import_chord_type.all)().filter((chord) => inScale(chord.chroma)).map((chord) => chord.aliases[0]); } function extended(name) { const chroma2 = (0, import_pcset.isChroma)(name) ? name : get(name).chroma; const isSuperset = (0, import_pcset.isSupersetOf)(chroma2); return (0, import_scale_type.all)().filter((scale2) => isSuperset(scale2.chroma)).map((scale2) => scale2.name); } function reduced(name) { const isSubset = (0, import_pcset.isSubsetOf)(get(name).chroma); return (0, import_scale_type.all)().filter((scale2) => isSubset(scale2.chroma)).map((scale2) => scale2.name); } function scaleNotes(notes) { const pcset = notes.map((n) => (0, import_pitch_note.note)(n).pc).filter((x) => x); const tonic = pcset[0]; const scale2 = (0, import_note.sortedUniqNames)(pcset); return (0, import_collection.rotate)(scale2.indexOf(tonic), scale2); } function modeNames(name) { const s = get(name); if (s.empty) { return []; } const tonics = s.tonic ? s.notes : s.intervals; return (0, import_pcset.modes)(s.chroma).map((chroma2, i) => { const modeName = get(chroma2).name; return modeName ? [tonics[i], modeName] : ["", ""]; }).filter((x) => x[0]); } function getNoteNameOf(scale2) { const names2 = Array.isArray(scale2) ? scaleNotes(scale2) : get(scale2).notes; const chromas = names2.map((name) => (0, import_pitch_note.note)(name).chroma); return (noteOrMidi) => { const currNote = typeof noteOrMidi === "number" ? (0, import_pitch_note.note)((0, import_note.fromMidi)(noteOrMidi)) : (0, import_pitch_note.note)(noteOrMidi); const height = currNote.height; if (height === void 0) return void 0; const chroma2 = height % 12; const position = chromas.indexOf(chroma2); if (position === -1) return void 0; return (0, import_note.enharmonic)(currNote.name, names2[position]); }; } function rangeOf(scale2) { const getName = getNoteNameOf(scale2); return (fromNote, toNote) => { const from = (0, import_pitch_note.note)(fromNote).height; const to = (0, import_pitch_note.note)(toNote).height; if (from === void 0 || to === void 0) return []; return (0, import_collection.range)(from, to).map(getName).filter((x) => x); }; } function degrees(scaleName) { const { intervals, tonic } = get(scaleName); const transpose2 = (0, import_pitch_distance.tonicIntervalsTransposer)(intervals, tonic); return (degree) => degree ? transpose2(degree > 0 ? degree - 1 : degree) : ""; } function steps(scaleName) { const { intervals, tonic } = get(scaleName); return (0, import_pitch_distance.tonicIntervalsTransposer)(intervals, tonic); } var index_default = { degrees, detect, extended, get, modeNames, names, rangeOf, reduced, scaleChords, scaleNotes, steps, tokenize, // deprecated scale }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { degrees, detect, extended, get, modeNames, names, rangeOf, reduced, scale, scaleChords, scaleNotes, steps, tokenize }); //# sourceMappingURL=index.js.map