@tonaljs/note
Version:
Parse and manipulate music notes in scientific notation
1 lines • 10.6 kB
Source Map (JSON)
{"version":3,"sources":["../index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { freqToMidi, midiToNoteName } from \"@tonaljs/midi\";\nimport { Pitch } from \"@tonaljs/pitch\";\nimport { distance as _dist, transpose as _tr } from \"@tonaljs/pitch-distance\";\nimport { IntervalName } from \"@tonaljs/pitch-interval\";\nimport {\n Note,\n NoteLiteral,\n NoteName,\n note as props,\n} from \"@tonaljs/pitch-note\";\n\nexport type { NoteType } from \"@tonaljs/pitch-note\";\n\nconst NAMES = [\"C\", \"D\", \"E\", \"F\", \"G\", \"A\", \"B\"];\n\nconst toName = (n: Note) => n.name;\nconst onlyNotes = (array: any[]) =>\n array.map(props).filter((n) => !n.empty) as Note[];\n\n/**\n * Return the natural note names without octave\n * @function\n * @example\n * Note.names(); // => [\"C\", \"D\", \"E\", \"F\", \"G\", \"A\", \"B\"]\n */\nexport function names(array?: any[]): string[] {\n if (array === undefined) {\n return NAMES.slice();\n } else if (!Array.isArray(array)) {\n return [];\n } else {\n return onlyNotes(array).map(toName);\n }\n}\n\n/**\n * Get a note from a note name\n *\n * @function\n * @example\n * Note.get('Bb4') // => { name: \"Bb4\", midi: 70, chroma: 10, ... }\n */\nexport const get = props;\n\n/**\n * Get the note name\n * @function\n */\nexport const name = (note: NoteLiteral) => get(note).name;\n\n/**\n * Get the note pitch class name\n * @function\n */\nexport const pitchClass = (note: NoteLiteral) => get(note).pc;\n\n/**\n * Get the note accidentals\n * @function\n */\nexport const accidentals = (note: NoteLiteral) => get(note).acc;\n\n/**\n * Get the note octave\n * @function\n */\nexport const octave = (note: NoteLiteral) => get(note).oct;\n\n/**\n * Get the note midi\n * @function\n */\nexport const midi = (note: NoteLiteral) => get(note).midi;\n\n/**\n * Get the note midi\n * @function\n */\nexport const freq = (note: NoteLiteral) => get(note).freq;\n\n/**\n * Get the note chroma\n * @function\n */\nexport const chroma = (note: NoteLiteral) => get(note).chroma;\n\n/**\n * Given a midi number, returns a note name. Uses flats for altered notes.\n *\n * @function\n * @param {number} midi - the midi note number\n * @return {string} the note name\n * @example\n * Note.fromMidi(61) // => \"Db4\"\n * Note.fromMidi(61.7) // => \"D4\"\n */\nexport function fromMidi(midi: number) {\n return midiToNoteName(midi);\n}\n\n/**\n * Given a midi number, returns a note name. Uses flats for altered notes.\n */\nexport function fromFreq(freq: number) {\n return midiToNoteName(freqToMidi(freq));\n}\n/**\n * Given a midi number, returns a note name. Uses flats for altered notes.\n */\nexport function fromFreqSharps(freq: number) {\n return midiToNoteName(freqToMidi(freq), { sharps: true });\n}\n\n/**\n * Given a midi number, returns a note name. Uses flats for altered notes.\n *\n * @function\n * @param {number} midi - the midi note number\n * @return {string} the note name\n * @example\n * Note.fromMidiSharps(61) // => \"C#4\"\n */\n\nexport function fromMidiSharps(midi: number) {\n return midiToNoteName(midi, { sharps: true });\n}\n\nexport const distance = _dist;\n\n/**\n * Transpose a note by an interval\n */\nexport const transpose = _tr;\nexport const tr = _tr;\n\n/**\n * Transpose by an interval.\n * @function\n * @param {string} interval\n * @return {function} a function that transposes by the given interval\n * @example\n * [\"C\", \"D\", \"E\"].map(Note.transposeBy(\"5P\"));\n * // => [\"G\", \"A\", \"B\"]\n */\nexport const transposeBy = (interval: IntervalName) => (note: NoteName) =>\n transpose(note, interval);\nexport const trBy = transposeBy;\n\n/**\n * Transpose from a note\n * @function\n * @param {string} note\n * @return {function} a function that transposes the the note by an interval\n * [\"1P\", \"3M\", \"5P\"].map(Note.transposeFrom(\"C\"));\n * // => [\"C\", \"E\", \"G\"]\n */\nexport const transposeFrom = (note: NoteName) => (interval: IntervalName) =>\n transpose(note, interval);\nexport const trFrom = transposeFrom;\n\n/**\n * Transpose a note by a number of perfect fifths.\n *\n * @function\n * @param {string} note - the note name\n * @param {number} fifths - the number of fifths\n * @return {string} the transposed note name\n *\n * @example\n * import { transposeFifths } from \"@tonaljs/note\"\n * transposeFifths(\"G4\", 1) // => \"D\"\n * [0, 1, 2, 3, 4].map(fifths => transposeFifths(\"C\", fifths)) // => [\"C\", \"G\", \"D\", \"A\", \"E\"]\n */\nexport function transposeFifths(noteName: NoteName, fifths: number): NoteName {\n return transpose(noteName, [fifths, 0]);\n}\nexport const trFifths = transposeFifths;\n\n// TODO: documentation\nexport function transposeOctaves(\n noteName: NoteName,\n octaves: number,\n): NoteName {\n return transpose(noteName, [0, octaves]);\n}\n\nexport type NoteComparator = (a: Note, b: Note) => number;\n\nexport const ascending: NoteComparator = (a, b) => a.height - b.height;\nexport const descending: NoteComparator = (a, b) => b.height - a.height;\n\nexport function sortedNames(\n notes: any[],\n comparator?: NoteComparator,\n): string[] {\n comparator = comparator || ascending;\n return onlyNotes(notes).sort(comparator).map(toName);\n}\n\nexport function sortedUniqNames(notes: any[]): string[] {\n return sortedNames(notes, ascending).filter(\n (n, i, a) => i === 0 || n !== a[i - 1],\n );\n}\n\n/**\n * Simplify a note\n *\n * @function\n * @param {string} note - the note to be simplified\n * - sameAccType: default true. Use same kind of accidentals that source\n * @return {string} the simplified note or '' if not valid note\n * @example\n * simplify(\"C##\") // => \"D\"\n * simplify(\"C###\") // => \"D#\"\n * simplify(\"C###\")\n * simplify(\"B#4\") // => \"C5\"\n */\nexport const simplify = (noteName: NoteName | Pitch): string => {\n const note = get(noteName);\n if (note.empty) {\n return \"\";\n }\n return midiToNoteName(note.midi || note.chroma, {\n sharps: note.alt > 0,\n pitchClass: note.midi === null,\n });\n};\n/**\n * Get enharmonic of a note\n *\n * @function\n * @param {string} note\n * @param [string] - [optional] Destination pitch class\n * @return {string} the enharmonic note name or '' if not valid note\n * @example\n * Note.enharmonic(\"Db\") // => \"C#\"\n * Note.enharmonic(\"C\") // => \"C\"\n * Note.enharmonic(\"F2\",\"E#\") // => \"E#2\"\n * Note.enharmonic(\"C##b\"); // => \"\"\n */\nexport function enharmonic(noteName: string, destName?: string) {\n const src = get(noteName);\n if (src.empty) {\n return \"\";\n }\n\n // destination: use given or generate one\n const dest = get(\n destName ||\n midiToNoteName(src.midi || src.chroma, {\n sharps: src.alt < 0,\n pitchClass: true,\n }),\n );\n\n // ensure destination is valid\n if (dest.empty || dest.chroma !== src.chroma) {\n return \"\";\n }\n\n // if src has no octave, no need to calculate anything else\n if (src.oct === undefined) {\n return dest.pc;\n }\n\n // detect any octave overflow\n const srcChroma = src.chroma - src.alt;\n const destChroma = dest.chroma - dest.alt;\n const destOctOffset =\n srcChroma > 11 || destChroma < 0\n ? -1\n : srcChroma < 0 || destChroma > 11\n ? +1\n : 0;\n // calculate the new octave\n const destOct = src.oct + destOctOffset;\n return dest.pc + destOct;\n}\n\n/** @deprecated */\nexport default {\n names,\n get,\n name,\n pitchClass,\n accidentals,\n octave,\n midi,\n ascending,\n descending,\n distance,\n sortedNames,\n sortedUniqNames,\n fromMidi,\n fromMidiSharps,\n freq,\n fromFreq,\n fromFreqSharps,\n chroma,\n transpose,\n tr,\n transposeBy,\n trBy,\n transposeFrom,\n trFrom,\n transposeFifths,\n transposeOctaves,\n trFifths,\n simplify,\n enharmonic,\n};\n"],"mappings":"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","names":["midi","freq"]}