@tonaljs/scale 4.12.0 → 4.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -182,6 +182,7 @@ var scale_default = {
182
182
  scaleNotes,
183
183
  steps,
184
184
  tokenize,
185
+ // deprecated
185
186
  scale
186
187
  };
187
188
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"sourcesContent":["/**\n * References:\n * - https://www.researchgate.net/publication/327567188_An_Algorithm_for_Spelling_the_Pitches_of_Any_Musical_Scale\n * @module scale\n */\nimport { all as chordTypes } from \"@tonaljs/chord-type\";\nimport { range as nums, rotate } from \"@tonaljs/collection\";\nimport {\n deprecate,\n note,\n NoteName,\n tonicIntervalsTransposer,\n transpose,\n} from \"@tonaljs/core\";\nimport { enharmonic, fromMidi, sortedUniqNames } from \"@tonaljs/note\";\nimport {\n chroma,\n isChroma,\n isSubsetOf,\n isSupersetOf,\n modes,\n} from \"@tonaljs/pcset\";\nimport {\n all,\n all as scaleTypes,\n get as getScaleType,\n names as scaleTypeNames,\n ScaleType,\n} from \"@tonaljs/scale-type\";\n\ntype ScaleName = string;\ntype ScaleNameTokens = [string, string]; // [TONIC, SCALE TYPE]\n\nexport interface Scale extends ScaleType {\n tonic: string | null;\n type: string;\n notes: NoteName[];\n}\n\nconst NoScale: Scale = {\n empty: true,\n name: \"\",\n type: \"\",\n tonic: null,\n setNum: NaN,\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n/**\n * Given a string with a scale name and (optionally) a tonic, split\n * that components.\n *\n * It retuns an array with the form [ name, tonic ] where tonic can be a\n * note name or null and name can be any arbitrary string\n * (this function doesn\"t check if that scale name exists)\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array} an array [tonic, name]\n * @example\n * tokenize(\"C mixolydean\") // => [\"C\", \"mixolydean\"]\n * tokenize(\"anything is valid\") // => [\"\", \"anything is valid\"]\n * tokenize() // => [\"\", \"\"]\n */\nexport function tokenize(name: ScaleName): ScaleNameTokens {\n if (typeof name !== \"string\") {\n return [\"\", \"\"];\n }\n const i = name.indexOf(\" \");\n const tonic = note(name.substring(0, i));\n if (tonic.empty) {\n const n = note(name);\n return n.empty ? [\"\", name] : [n.name, \"\"];\n }\n\n const type = name.substring(tonic.name.length + 1);\n return [tonic.name, type.length ? type : \"\"];\n}\n\n/**\n * Get all scale names\n * @function\n */\nexport const names = scaleTypeNames;\n\n/**\n * Get a Scale from a scale name.\n */\nexport function get(src: ScaleName | ScaleNameTokens): Scale {\n const tokens = Array.isArray(src) ? src : tokenize(src);\n const tonic = note(tokens[0]).name;\n const st = getScaleType(tokens[1]);\n if (st.empty) {\n return NoScale;\n }\n\n const type = st.name;\n const notes: string[] = tonic\n ? st.intervals.map((i) => transpose(tonic, i))\n : [];\n\n const name = tonic ? tonic + \" \" + type : type;\n\n return { ...st, name, type, tonic, notes };\n}\n\nexport const scale = deprecate(\"Scale.scale\", \"Scale.get\", get);\n\nexport function detect(\n notes: string[],\n options: { tonic?: string; match?: \"exact\" | \"fit\" } = {}\n): string[] {\n const notesChroma = chroma(notes);\n const tonic = note(options.tonic ?? notes[0] ?? \"\");\n const tonicChroma = tonic.chroma;\n if (tonicChroma === undefined) {\n return [];\n }\n\n const pitchClasses = notesChroma.split(\"\");\n pitchClasses[tonicChroma] = \"1\";\n const scaleChroma = rotate(tonicChroma, pitchClasses).join(\"\");\n const match = all().find((scaleType) => scaleType.chroma === scaleChroma);\n\n const results: string[] = [];\n if (match) {\n results.push(tonic.name + \" \" + match.name);\n }\n if (options.match === \"exact\") {\n return results;\n }\n\n extended(scaleChroma).forEach((scaleName) => {\n results.push(tonic.name + \" \" + scaleName);\n });\n\n return results;\n}\n\n/**\n * Get all chords that fits a given scale\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array<string>} - the chord names\n *\n * @example\n * scaleChords(\"pentatonic\") // => [\"5\", \"64\", \"M\", \"M6\", \"Madd9\", \"Msus2\"]\n */\nexport function scaleChords(name: string): string[] {\n const s = get(name);\n const inScale = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => inScale(chord.chroma))\n .map((chord) => chord.aliases[0]);\n}\n/**\n * Get all scales names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n * @example\n * extended(\"major\") // => [\"bebop\", \"bebop dominant\", \"bebop major\", \"chromatic\", \"ichikosucho\"]\n */\nexport function extended(name: string): string[] {\n const chroma = isChroma(name) ? name : get(name).chroma;\n const isSuperset = isSupersetOf(chroma);\n return scaleTypes()\n .filter((scale) => isSuperset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Find all scales names that are a subset of the given one\n * (has less notes but all from the given scale)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n *\n * @example\n * reduced(\"major\") // => [\"ionian pentatonic\", \"major pentatonic\", \"ritusen\"]\n */\nexport function reduced(name: string): string[] {\n const isSubset = isSubsetOf(get(name).chroma);\n return scaleTypes()\n .filter((scale) => isSubset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Given an array of notes, return the scale: a pitch class set starting from\n * the first note of the array\n *\n * @function\n * @param {string[]} notes\n * @return {string[]} pitch classes with same tonic\n * @example\n * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => [\"C\"]\n * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => [\"D\", \"F#\", \"A\", \"C#\"]\n */\nexport function scaleNotes(notes: NoteName[]) {\n const pcset: string[] = notes.map((n) => note(n).pc).filter((x) => x);\n const tonic = pcset[0];\n const scale = sortedUniqNames(pcset);\n return rotate(scale.indexOf(tonic), scale);\n}\n\ntype ScaleMode = [string, string];\n/**\n * Find mode names of a scale\n *\n * @function\n * @param {string} name - scale name\n * @example\n * modeNames(\"C pentatonic\") // => [\n * [\"C\", \"major pentatonic\"],\n * [\"D\", \"egyptian\"],\n * [\"E\", \"malkos raga\"],\n * [\"G\", \"ritusen\"],\n * [\"A\", \"minor pentatonic\"]\n * ]\n */\nexport function modeNames(name: string): ScaleMode[] {\n const s = get(name);\n if (s.empty) {\n return [];\n }\n\n const tonics = s.tonic ? s.notes : s.intervals;\n return modes(s.chroma)\n .map((chroma: string, i: number): ScaleMode => {\n const modeName = get(chroma).name;\n return modeName ? [tonics[i], modeName] : [\"\", \"\"];\n })\n .filter((x) => x[0]);\n}\n\nfunction getNoteNameOf(scale: string | string[]) {\n const names = Array.isArray(scale) ? scaleNotes(scale) : get(scale).notes;\n const chromas = names.map((name) => note(name).chroma);\n\n return (noteOrMidi: string | number): string | undefined => {\n const currNote =\n typeof noteOrMidi === \"number\"\n ? note(fromMidi(noteOrMidi))\n : note(noteOrMidi);\n const height = currNote.height;\n\n if (height === undefined) return undefined;\n const chroma = height % 12;\n const position = chromas.indexOf(chroma);\n if (position === -1) return undefined;\n return enharmonic(currNote.name, names[position]);\n };\n}\n\nexport function rangeOf(scale: string | string[]) {\n const getName = getNoteNameOf(scale);\n return (fromNote: string, toNote: string) => {\n const from = note(fromNote).height;\n const to = note(toNote).height;\n if (from === undefined || to === undefined) return [];\n\n return nums(from, to)\n .map(getName)\n .filter((x) => x);\n };\n}\n\n/**\n * Returns a function to get a note name from the scale degree.\n *\n * @example\n * [1, 2, 3].map(Scale.degrees(\"C major\")) => [\"C\", \"D\", \"E\"]\n * [1, 2, 3].map(Scale.degrees(\"C4 major\")) => [\"C4\", \"D4\", \"E4\"]\n */\nexport function degrees(scaleName: string | ScaleNameTokens) {\n const { intervals, tonic } = get(scaleName);\n const transpose = tonicIntervalsTransposer(intervals, tonic);\n return (degree: number) =>\n degree ? transpose(degree > 0 ? degree - 1 : degree) : \"\";\n}\n\n/**\n * Sames as `degree` but with 0-based index\n */\nexport function steps(scaleName: string | ScaleNameTokens) {\n const { intervals, tonic } = get(scaleName);\n return tonicIntervalsTransposer(intervals, tonic);\n}\n\nexport default {\n degrees,\n detect,\n extended,\n get,\n modeNames,\n names,\n rangeOf,\n reduced,\n scaleChords,\n scaleNotes,\n steps,\n tokenize,\n\n // deprecated\n scale,\n};\n"],"mappings":"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","names":["scaleTypeNames","getScaleType","chordTypes","chroma","scaleTypes","scale","names","nums","transpose"]}
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["/**\n * References:\n * - https://www.researchgate.net/publication/327567188_An_Algorithm_for_Spelling_the_Pitches_of_Any_Musical_Scale\n * @module scale\n */\nimport { all as chordTypes } from \"@tonaljs/chord-type\";\nimport { range as nums, rotate } from \"@tonaljs/collection\";\nimport {\n deprecate,\n note,\n NoteName,\n tonicIntervalsTransposer,\n transpose,\n} from \"@tonaljs/core\";\nimport { enharmonic, fromMidi, sortedUniqNames } from \"@tonaljs/note\";\nimport {\n chroma,\n isChroma,\n isSubsetOf,\n isSupersetOf,\n modes,\n} from \"@tonaljs/pcset\";\nimport {\n all,\n all as scaleTypes,\n get as getScaleType,\n names as scaleTypeNames,\n ScaleType,\n} from \"@tonaljs/scale-type\";\n\ntype ScaleName = string;\ntype ScaleNameTokens = [string, string]; // [TONIC, SCALE TYPE]\n\nexport interface Scale extends ScaleType {\n tonic: string | null;\n type: string;\n notes: NoteName[];\n}\n\nconst NoScale: Scale = {\n empty: true,\n name: \"\",\n type: \"\",\n tonic: null,\n setNum: NaN,\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n/**\n * Given a string with a scale name and (optionally) a tonic, split\n * that components.\n *\n * It retuns an array with the form [ name, tonic ] where tonic can be a\n * note name or null and name can be any arbitrary string\n * (this function doesn\"t check if that scale name exists)\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array} an array [tonic, name]\n * @example\n * tokenize(\"C mixolydean\") // => [\"C\", \"mixolydean\"]\n * tokenize(\"anything is valid\") // => [\"\", \"anything is valid\"]\n * tokenize() // => [\"\", \"\"]\n */\nexport function tokenize(name: ScaleName): ScaleNameTokens {\n if (typeof name !== \"string\") {\n return [\"\", \"\"];\n }\n const i = name.indexOf(\" \");\n const tonic = note(name.substring(0, i));\n if (tonic.empty) {\n const n = note(name);\n return n.empty ? [\"\", name] : [n.name, \"\"];\n }\n\n const type = name.substring(tonic.name.length + 1);\n return [tonic.name, type.length ? type : \"\"];\n}\n\n/**\n * Get all scale names\n * @function\n */\nexport const names = scaleTypeNames;\n\n/**\n * Get a Scale from a scale name.\n */\nexport function get(src: ScaleName | ScaleNameTokens): Scale {\n const tokens = Array.isArray(src) ? src : tokenize(src);\n const tonic = note(tokens[0]).name;\n const st = getScaleType(tokens[1]);\n if (st.empty) {\n return NoScale;\n }\n\n const type = st.name;\n const notes: string[] = tonic\n ? st.intervals.map((i) => transpose(tonic, i))\n : [];\n\n const name = tonic ? tonic + \" \" + type : type;\n\n return { ...st, name, type, tonic, notes };\n}\n\nexport const scale = deprecate(\"Scale.scale\", \"Scale.get\", get);\n\nexport function detect(\n notes: string[],\n options: { tonic?: string; match?: \"exact\" | \"fit\" } = {}\n): string[] {\n const notesChroma = chroma(notes);\n const tonic = note(options.tonic ?? notes[0] ?? \"\");\n const tonicChroma = tonic.chroma;\n if (tonicChroma === undefined) {\n return [];\n }\n\n const pitchClasses = notesChroma.split(\"\");\n pitchClasses[tonicChroma] = \"1\";\n const scaleChroma = rotate(tonicChroma, pitchClasses).join(\"\");\n const match = all().find((scaleType) => scaleType.chroma === scaleChroma);\n\n const results: string[] = [];\n if (match) {\n results.push(tonic.name + \" \" + match.name);\n }\n if (options.match === \"exact\") {\n return results;\n }\n\n extended(scaleChroma).forEach((scaleName) => {\n results.push(tonic.name + \" \" + scaleName);\n });\n\n return results;\n}\n\n/**\n * Get all chords that fits a given scale\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array<string>} - the chord names\n *\n * @example\n * scaleChords(\"pentatonic\") // => [\"5\", \"64\", \"M\", \"M6\", \"Madd9\", \"Msus2\"]\n */\nexport function scaleChords(name: string): string[] {\n const s = get(name);\n const inScale = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => inScale(chord.chroma))\n .map((chord) => chord.aliases[0]);\n}\n/**\n * Get all scales names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n * @example\n * extended(\"major\") // => [\"bebop\", \"bebop dominant\", \"bebop major\", \"chromatic\", \"ichikosucho\"]\n */\nexport function extended(name: string): string[] {\n const chroma = isChroma(name) ? name : get(name).chroma;\n const isSuperset = isSupersetOf(chroma);\n return scaleTypes()\n .filter((scale) => isSuperset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Find all scales names that are a subset of the given one\n * (has less notes but all from the given scale)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n *\n * @example\n * reduced(\"major\") // => [\"ionian pentatonic\", \"major pentatonic\", \"ritusen\"]\n */\nexport function reduced(name: string): string[] {\n const isSubset = isSubsetOf(get(name).chroma);\n return scaleTypes()\n .filter((scale) => isSubset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Given an array of notes, return the scale: a pitch class set starting from\n * the first note of the array\n *\n * @function\n * @param {string[]} notes\n * @return {string[]} pitch classes with same tonic\n * @example\n * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => [\"C\"]\n * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => [\"D\", \"F#\", \"A\", \"C#\"]\n */\nexport function scaleNotes(notes: NoteName[]) {\n const pcset: string[] = notes.map((n) => note(n).pc).filter((x) => x);\n const tonic = pcset[0];\n const scale = sortedUniqNames(pcset);\n return rotate(scale.indexOf(tonic), scale);\n}\n\ntype ScaleMode = [string, string];\n/**\n * Find mode names of a scale\n *\n * @function\n * @param {string} name - scale name\n * @example\n * modeNames(\"C pentatonic\") // => [\n * [\"C\", \"major pentatonic\"],\n * [\"D\", \"egyptian\"],\n * [\"E\", \"malkos raga\"],\n * [\"G\", \"ritusen\"],\n * [\"A\", \"minor pentatonic\"]\n * ]\n */\nexport function modeNames(name: string): ScaleMode[] {\n const s = get(name);\n if (s.empty) {\n return [];\n }\n\n const tonics = s.tonic ? s.notes : s.intervals;\n return modes(s.chroma)\n .map((chroma: string, i: number): ScaleMode => {\n const modeName = get(chroma).name;\n return modeName ? [tonics[i], modeName] : [\"\", \"\"];\n })\n .filter((x) => x[0]);\n}\n\nfunction getNoteNameOf(scale: string | string[]) {\n const names = Array.isArray(scale) ? scaleNotes(scale) : get(scale).notes;\n const chromas = names.map((name) => note(name).chroma);\n\n return (noteOrMidi: string | number): string | undefined => {\n const currNote =\n typeof noteOrMidi === \"number\"\n ? note(fromMidi(noteOrMidi))\n : note(noteOrMidi);\n const height = currNote.height;\n\n if (height === undefined) return undefined;\n const chroma = height % 12;\n const position = chromas.indexOf(chroma);\n if (position === -1) return undefined;\n return enharmonic(currNote.name, names[position]);\n };\n}\n\nexport function rangeOf(scale: string | string[]) {\n const getName = getNoteNameOf(scale);\n return (fromNote: string, toNote: string) => {\n const from = note(fromNote).height;\n const to = note(toNote).height;\n if (from === undefined || to === undefined) return [];\n\n return nums(from, to)\n .map(getName)\n .filter((x) => x);\n };\n}\n\n/**\n * Returns a function to get a note name from the scale degree.\n *\n * @example\n * [1, 2, 3].map(Scale.degrees(\"C major\")) => [\"C\", \"D\", \"E\"]\n * [1, 2, 3].map(Scale.degrees(\"C4 major\")) => [\"C4\", \"D4\", \"E4\"]\n */\nexport function degrees(scaleName: string | ScaleNameTokens) {\n const { intervals, tonic } = get(scaleName);\n const transpose = tonicIntervalsTransposer(intervals, tonic);\n return (degree: number) =>\n degree ? transpose(degree > 0 ? degree - 1 : degree) : \"\";\n}\n\n/**\n * Sames as `degree` but with 0-based index\n */\nexport function steps(scaleName: string | ScaleNameTokens) {\n const { intervals, tonic } = get(scaleName);\n return tonicIntervalsTransposer(intervals, tonic);\n}\n\nexport default {\n degrees,\n detect,\n extended,\n get,\n modeNames,\n names,\n rangeOf,\n reduced,\n scaleChords,\n scaleNotes,\n steps,\n tokenize,\n\n // deprecated\n scale,\n};\n"],"mappings":"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","names":["scaleTypeNames","getScaleType","chordTypes","chroma","scaleTypes","scale","names","nums","transpose"]}
package/dist/index.mjs CHANGED
@@ -161,6 +161,7 @@ var scale_default = {
161
161
  scaleNotes,
162
162
  steps,
163
163
  tokenize,
164
+ // deprecated
164
165
  scale
165
166
  };
166
167
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"sourcesContent":["/**\n * References:\n * - https://www.researchgate.net/publication/327567188_An_Algorithm_for_Spelling_the_Pitches_of_Any_Musical_Scale\n * @module scale\n */\nimport { all as chordTypes } from \"@tonaljs/chord-type\";\nimport { range as nums, rotate } from \"@tonaljs/collection\";\nimport {\n deprecate,\n note,\n NoteName,\n tonicIntervalsTransposer,\n transpose,\n} from \"@tonaljs/core\";\nimport { enharmonic, fromMidi, sortedUniqNames } from \"@tonaljs/note\";\nimport {\n chroma,\n isChroma,\n isSubsetOf,\n isSupersetOf,\n modes,\n} from \"@tonaljs/pcset\";\nimport {\n all,\n all as scaleTypes,\n get as getScaleType,\n names as scaleTypeNames,\n ScaleType,\n} from \"@tonaljs/scale-type\";\n\ntype ScaleName = string;\ntype ScaleNameTokens = [string, string]; // [TONIC, SCALE TYPE]\n\nexport interface Scale extends ScaleType {\n tonic: string | null;\n type: string;\n notes: NoteName[];\n}\n\nconst NoScale: Scale = {\n empty: true,\n name: \"\",\n type: \"\",\n tonic: null,\n setNum: NaN,\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n/**\n * Given a string with a scale name and (optionally) a tonic, split\n * that components.\n *\n * It retuns an array with the form [ name, tonic ] where tonic can be a\n * note name or null and name can be any arbitrary string\n * (this function doesn\"t check if that scale name exists)\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array} an array [tonic, name]\n * @example\n * tokenize(\"C mixolydean\") // => [\"C\", \"mixolydean\"]\n * tokenize(\"anything is valid\") // => [\"\", \"anything is valid\"]\n * tokenize() // => [\"\", \"\"]\n */\nexport function tokenize(name: ScaleName): ScaleNameTokens {\n if (typeof name !== \"string\") {\n return [\"\", \"\"];\n }\n const i = name.indexOf(\" \");\n const tonic = note(name.substring(0, i));\n if (tonic.empty) {\n const n = note(name);\n return n.empty ? [\"\", name] : [n.name, \"\"];\n }\n\n const type = name.substring(tonic.name.length + 1);\n return [tonic.name, type.length ? type : \"\"];\n}\n\n/**\n * Get all scale names\n * @function\n */\nexport const names = scaleTypeNames;\n\n/**\n * Get a Scale from a scale name.\n */\nexport function get(src: ScaleName | ScaleNameTokens): Scale {\n const tokens = Array.isArray(src) ? src : tokenize(src);\n const tonic = note(tokens[0]).name;\n const st = getScaleType(tokens[1]);\n if (st.empty) {\n return NoScale;\n }\n\n const type = st.name;\n const notes: string[] = tonic\n ? st.intervals.map((i) => transpose(tonic, i))\n : [];\n\n const name = tonic ? tonic + \" \" + type : type;\n\n return { ...st, name, type, tonic, notes };\n}\n\nexport const scale = deprecate(\"Scale.scale\", \"Scale.get\", get);\n\nexport function detect(\n notes: string[],\n options: { tonic?: string; match?: \"exact\" | \"fit\" } = {}\n): string[] {\n const notesChroma = chroma(notes);\n const tonic = note(options.tonic ?? notes[0] ?? \"\");\n const tonicChroma = tonic.chroma;\n if (tonicChroma === undefined) {\n return [];\n }\n\n const pitchClasses = notesChroma.split(\"\");\n pitchClasses[tonicChroma] = \"1\";\n const scaleChroma = rotate(tonicChroma, pitchClasses).join(\"\");\n const match = all().find((scaleType) => scaleType.chroma === scaleChroma);\n\n const results: string[] = [];\n if (match) {\n results.push(tonic.name + \" \" + match.name);\n }\n if (options.match === \"exact\") {\n return results;\n }\n\n extended(scaleChroma).forEach((scaleName) => {\n results.push(tonic.name + \" \" + scaleName);\n });\n\n return results;\n}\n\n/**\n * Get all chords that fits a given scale\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array<string>} - the chord names\n *\n * @example\n * scaleChords(\"pentatonic\") // => [\"5\", \"64\", \"M\", \"M6\", \"Madd9\", \"Msus2\"]\n */\nexport function scaleChords(name: string): string[] {\n const s = get(name);\n const inScale = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => inScale(chord.chroma))\n .map((chord) => chord.aliases[0]);\n}\n/**\n * Get all scales names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n * @example\n * extended(\"major\") // => [\"bebop\", \"bebop dominant\", \"bebop major\", \"chromatic\", \"ichikosucho\"]\n */\nexport function extended(name: string): string[] {\n const chroma = isChroma(name) ? name : get(name).chroma;\n const isSuperset = isSupersetOf(chroma);\n return scaleTypes()\n .filter((scale) => isSuperset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Find all scales names that are a subset of the given one\n * (has less notes but all from the given scale)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n *\n * @example\n * reduced(\"major\") // => [\"ionian pentatonic\", \"major pentatonic\", \"ritusen\"]\n */\nexport function reduced(name: string): string[] {\n const isSubset = isSubsetOf(get(name).chroma);\n return scaleTypes()\n .filter((scale) => isSubset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Given an array of notes, return the scale: a pitch class set starting from\n * the first note of the array\n *\n * @function\n * @param {string[]} notes\n * @return {string[]} pitch classes with same tonic\n * @example\n * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => [\"C\"]\n * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => [\"D\", \"F#\", \"A\", \"C#\"]\n */\nexport function scaleNotes(notes: NoteName[]) {\n const pcset: string[] = notes.map((n) => note(n).pc).filter((x) => x);\n const tonic = pcset[0];\n const scale = sortedUniqNames(pcset);\n return rotate(scale.indexOf(tonic), scale);\n}\n\ntype ScaleMode = [string, string];\n/**\n * Find mode names of a scale\n *\n * @function\n * @param {string} name - scale name\n * @example\n * modeNames(\"C pentatonic\") // => [\n * [\"C\", \"major pentatonic\"],\n * [\"D\", \"egyptian\"],\n * [\"E\", \"malkos raga\"],\n * [\"G\", \"ritusen\"],\n * [\"A\", \"minor pentatonic\"]\n * ]\n */\nexport function modeNames(name: string): ScaleMode[] {\n const s = get(name);\n if (s.empty) {\n return [];\n }\n\n const tonics = s.tonic ? s.notes : s.intervals;\n return modes(s.chroma)\n .map((chroma: string, i: number): ScaleMode => {\n const modeName = get(chroma).name;\n return modeName ? [tonics[i], modeName] : [\"\", \"\"];\n })\n .filter((x) => x[0]);\n}\n\nfunction getNoteNameOf(scale: string | string[]) {\n const names = Array.isArray(scale) ? scaleNotes(scale) : get(scale).notes;\n const chromas = names.map((name) => note(name).chroma);\n\n return (noteOrMidi: string | number): string | undefined => {\n const currNote =\n typeof noteOrMidi === \"number\"\n ? note(fromMidi(noteOrMidi))\n : note(noteOrMidi);\n const height = currNote.height;\n\n if (height === undefined) return undefined;\n const chroma = height % 12;\n const position = chromas.indexOf(chroma);\n if (position === -1) return undefined;\n return enharmonic(currNote.name, names[position]);\n };\n}\n\nexport function rangeOf(scale: string | string[]) {\n const getName = getNoteNameOf(scale);\n return (fromNote: string, toNote: string) => {\n const from = note(fromNote).height;\n const to = note(toNote).height;\n if (from === undefined || to === undefined) return [];\n\n return nums(from, to)\n .map(getName)\n .filter((x) => x);\n };\n}\n\n/**\n * Returns a function to get a note name from the scale degree.\n *\n * @example\n * [1, 2, 3].map(Scale.degrees(\"C major\")) => [\"C\", \"D\", \"E\"]\n * [1, 2, 3].map(Scale.degrees(\"C4 major\")) => [\"C4\", \"D4\", \"E4\"]\n */\nexport function degrees(scaleName: string | ScaleNameTokens) {\n const { intervals, tonic } = get(scaleName);\n const transpose = tonicIntervalsTransposer(intervals, tonic);\n return (degree: number) =>\n degree ? transpose(degree > 0 ? degree - 1 : degree) : \"\";\n}\n\n/**\n * Sames as `degree` but with 0-based index\n */\nexport function steps(scaleName: string | ScaleNameTokens) {\n const { intervals, tonic } = get(scaleName);\n return tonicIntervalsTransposer(intervals, tonic);\n}\n\nexport default {\n degrees,\n detect,\n extended,\n get,\n modeNames,\n names,\n rangeOf,\n reduced,\n scaleChords,\n scaleNotes,\n steps,\n tokenize,\n\n // deprecated\n scale,\n};\n"],"mappings":"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","names":["chroma","scale","names","transpose"]}
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["/**\n * References:\n * - https://www.researchgate.net/publication/327567188_An_Algorithm_for_Spelling_the_Pitches_of_Any_Musical_Scale\n * @module scale\n */\nimport { all as chordTypes } from \"@tonaljs/chord-type\";\nimport { range as nums, rotate } from \"@tonaljs/collection\";\nimport {\n deprecate,\n note,\n NoteName,\n tonicIntervalsTransposer,\n transpose,\n} from \"@tonaljs/core\";\nimport { enharmonic, fromMidi, sortedUniqNames } from \"@tonaljs/note\";\nimport {\n chroma,\n isChroma,\n isSubsetOf,\n isSupersetOf,\n modes,\n} from \"@tonaljs/pcset\";\nimport {\n all,\n all as scaleTypes,\n get as getScaleType,\n names as scaleTypeNames,\n ScaleType,\n} from \"@tonaljs/scale-type\";\n\ntype ScaleName = string;\ntype ScaleNameTokens = [string, string]; // [TONIC, SCALE TYPE]\n\nexport interface Scale extends ScaleType {\n tonic: string | null;\n type: string;\n notes: NoteName[];\n}\n\nconst NoScale: Scale = {\n empty: true,\n name: \"\",\n type: \"\",\n tonic: null,\n setNum: NaN,\n chroma: \"\",\n normalized: \"\",\n aliases: [],\n notes: [],\n intervals: [],\n};\n\n/**\n * Given a string with a scale name and (optionally) a tonic, split\n * that components.\n *\n * It retuns an array with the form [ name, tonic ] where tonic can be a\n * note name or null and name can be any arbitrary string\n * (this function doesn\"t check if that scale name exists)\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array} an array [tonic, name]\n * @example\n * tokenize(\"C mixolydean\") // => [\"C\", \"mixolydean\"]\n * tokenize(\"anything is valid\") // => [\"\", \"anything is valid\"]\n * tokenize() // => [\"\", \"\"]\n */\nexport function tokenize(name: ScaleName): ScaleNameTokens {\n if (typeof name !== \"string\") {\n return [\"\", \"\"];\n }\n const i = name.indexOf(\" \");\n const tonic = note(name.substring(0, i));\n if (tonic.empty) {\n const n = note(name);\n return n.empty ? [\"\", name] : [n.name, \"\"];\n }\n\n const type = name.substring(tonic.name.length + 1);\n return [tonic.name, type.length ? type : \"\"];\n}\n\n/**\n * Get all scale names\n * @function\n */\nexport const names = scaleTypeNames;\n\n/**\n * Get a Scale from a scale name.\n */\nexport function get(src: ScaleName | ScaleNameTokens): Scale {\n const tokens = Array.isArray(src) ? src : tokenize(src);\n const tonic = note(tokens[0]).name;\n const st = getScaleType(tokens[1]);\n if (st.empty) {\n return NoScale;\n }\n\n const type = st.name;\n const notes: string[] = tonic\n ? st.intervals.map((i) => transpose(tonic, i))\n : [];\n\n const name = tonic ? tonic + \" \" + type : type;\n\n return { ...st, name, type, tonic, notes };\n}\n\nexport const scale = deprecate(\"Scale.scale\", \"Scale.get\", get);\n\nexport function detect(\n notes: string[],\n options: { tonic?: string; match?: \"exact\" | \"fit\" } = {}\n): string[] {\n const notesChroma = chroma(notes);\n const tonic = note(options.tonic ?? notes[0] ?? \"\");\n const tonicChroma = tonic.chroma;\n if (tonicChroma === undefined) {\n return [];\n }\n\n const pitchClasses = notesChroma.split(\"\");\n pitchClasses[tonicChroma] = \"1\";\n const scaleChroma = rotate(tonicChroma, pitchClasses).join(\"\");\n const match = all().find((scaleType) => scaleType.chroma === scaleChroma);\n\n const results: string[] = [];\n if (match) {\n results.push(tonic.name + \" \" + match.name);\n }\n if (options.match === \"exact\") {\n return results;\n }\n\n extended(scaleChroma).forEach((scaleName) => {\n results.push(tonic.name + \" \" + scaleName);\n });\n\n return results;\n}\n\n/**\n * Get all chords that fits a given scale\n *\n * @function\n * @param {string} name - the scale name\n * @return {Array<string>} - the chord names\n *\n * @example\n * scaleChords(\"pentatonic\") // => [\"5\", \"64\", \"M\", \"M6\", \"Madd9\", \"Msus2\"]\n */\nexport function scaleChords(name: string): string[] {\n const s = get(name);\n const inScale = isSubsetOf(s.chroma);\n return chordTypes()\n .filter((chord) => inScale(chord.chroma))\n .map((chord) => chord.aliases[0]);\n}\n/**\n * Get all scales names that are a superset of the given one\n * (has the same notes and at least one more)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n * @example\n * extended(\"major\") // => [\"bebop\", \"bebop dominant\", \"bebop major\", \"chromatic\", \"ichikosucho\"]\n */\nexport function extended(name: string): string[] {\n const chroma = isChroma(name) ? name : get(name).chroma;\n const isSuperset = isSupersetOf(chroma);\n return scaleTypes()\n .filter((scale) => isSuperset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Find all scales names that are a subset of the given one\n * (has less notes but all from the given scale)\n *\n * @function\n * @param {string} name\n * @return {Array} a list of scale names\n *\n * @example\n * reduced(\"major\") // => [\"ionian pentatonic\", \"major pentatonic\", \"ritusen\"]\n */\nexport function reduced(name: string): string[] {\n const isSubset = isSubsetOf(get(name).chroma);\n return scaleTypes()\n .filter((scale) => isSubset(scale.chroma))\n .map((scale) => scale.name);\n}\n\n/**\n * Given an array of notes, return the scale: a pitch class set starting from\n * the first note of the array\n *\n * @function\n * @param {string[]} notes\n * @return {string[]} pitch classes with same tonic\n * @example\n * scaleNotes(['C4', 'c3', 'C5', 'C4', 'c4']) // => [\"C\"]\n * scaleNotes(['D4', 'c#5', 'A5', 'F#6']) // => [\"D\", \"F#\", \"A\", \"C#\"]\n */\nexport function scaleNotes(notes: NoteName[]) {\n const pcset: string[] = notes.map((n) => note(n).pc).filter((x) => x);\n const tonic = pcset[0];\n const scale = sortedUniqNames(pcset);\n return rotate(scale.indexOf(tonic), scale);\n}\n\ntype ScaleMode = [string, string];\n/**\n * Find mode names of a scale\n *\n * @function\n * @param {string} name - scale name\n * @example\n * modeNames(\"C pentatonic\") // => [\n * [\"C\", \"major pentatonic\"],\n * [\"D\", \"egyptian\"],\n * [\"E\", \"malkos raga\"],\n * [\"G\", \"ritusen\"],\n * [\"A\", \"minor pentatonic\"]\n * ]\n */\nexport function modeNames(name: string): ScaleMode[] {\n const s = get(name);\n if (s.empty) {\n return [];\n }\n\n const tonics = s.tonic ? s.notes : s.intervals;\n return modes(s.chroma)\n .map((chroma: string, i: number): ScaleMode => {\n const modeName = get(chroma).name;\n return modeName ? [tonics[i], modeName] : [\"\", \"\"];\n })\n .filter((x) => x[0]);\n}\n\nfunction getNoteNameOf(scale: string | string[]) {\n const names = Array.isArray(scale) ? scaleNotes(scale) : get(scale).notes;\n const chromas = names.map((name) => note(name).chroma);\n\n return (noteOrMidi: string | number): string | undefined => {\n const currNote =\n typeof noteOrMidi === \"number\"\n ? note(fromMidi(noteOrMidi))\n : note(noteOrMidi);\n const height = currNote.height;\n\n if (height === undefined) return undefined;\n const chroma = height % 12;\n const position = chromas.indexOf(chroma);\n if (position === -1) return undefined;\n return enharmonic(currNote.name, names[position]);\n };\n}\n\nexport function rangeOf(scale: string | string[]) {\n const getName = getNoteNameOf(scale);\n return (fromNote: string, toNote: string) => {\n const from = note(fromNote).height;\n const to = note(toNote).height;\n if (from === undefined || to === undefined) return [];\n\n return nums(from, to)\n .map(getName)\n .filter((x) => x);\n };\n}\n\n/**\n * Returns a function to get a note name from the scale degree.\n *\n * @example\n * [1, 2, 3].map(Scale.degrees(\"C major\")) => [\"C\", \"D\", \"E\"]\n * [1, 2, 3].map(Scale.degrees(\"C4 major\")) => [\"C4\", \"D4\", \"E4\"]\n */\nexport function degrees(scaleName: string | ScaleNameTokens) {\n const { intervals, tonic } = get(scaleName);\n const transpose = tonicIntervalsTransposer(intervals, tonic);\n return (degree: number) =>\n degree ? transpose(degree > 0 ? degree - 1 : degree) : \"\";\n}\n\n/**\n * Sames as `degree` but with 0-based index\n */\nexport function steps(scaleName: string | ScaleNameTokens) {\n const { intervals, tonic } = get(scaleName);\n return tonicIntervalsTransposer(intervals, tonic);\n}\n\nexport default {\n degrees,\n detect,\n extended,\n get,\n modeNames,\n names,\n rangeOf,\n reduced,\n scaleChords,\n scaleNotes,\n steps,\n tokenize,\n\n // deprecated\n scale,\n};\n"],"mappings":"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","names":["chroma","scale","names","transpose"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonaljs/scale",
3
- "version": "4.12.0",
3
+ "version": "4.12.2",
4
4
  "description": "Musical scales and its relations",
5
5
  "keywords": [
6
6
  "scale",
@@ -16,12 +16,12 @@
16
16
  ],
17
17
  "types": "dist/index.d.ts",
18
18
  "dependencies": {
19
- "@tonaljs/chord-type": "^4.8.0",
19
+ "@tonaljs/chord-type": "^5.0.0",
20
20
  "@tonaljs/collection": "^4.8.0",
21
21
  "@tonaljs/core": "^4.10.0",
22
22
  "@tonaljs/note": "^4.10.0",
23
- "@tonaljs/pcset": "^4.8.1",
24
- "@tonaljs/scale-type": "^4.8.1"
23
+ "@tonaljs/pcset": "^4.8.2",
24
+ "@tonaljs/scale-type": "^4.8.2"
25
25
  },
26
26
  "author": "danigb@gmail.com",
27
27
  "license": "MIT",