{"version":3,"sources":["jsdelivr-header.js","/npm/@tonaljs/scale@4.13.4/index.ts"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,8iBCNA,cAAA,GAAA,SAAA,cAAA,CAAA,QAAA,IAAA,cAAA,QAAA,IAAA,QAAA,OAAA,IAAA,OAAA,SAAA,IAAA,SAAA,IAAA,IAAA,IAAA,UAAA,IAAA,UAAA,MAAA,IAAA,MAAA,QAAA,IAAA,QAAA,QAAA,IAAA,QAAA,MAAA,IAAA,MAAA,YAAA,IAAA,YAAA,WAAA,IAAA,WAAA,MAAA,IAAA,MAAA,SAAA,IAAA,WAAA,OAAA,QAAA,aAAA,eAKA,IAAA,kBAAkC,QAAA,uBAClC,kBAAsC,QAAA,uBACtC,YAAsD,QAAA,iBACtD,aAMO,QAAA,kBACP,sBAAoD,QAAA,2BACpD,kBAA+B,QAAA,uBAC/B,kBAMO,QAAA,uBAWD,QAAiB,CACrB,OAAO,EACP,KAAM,GACN,KAAM,GACN,MAAO,KACP,OAAQ,IACR,OAAQ,GACR,WAAY,GACZ,QAAS,GACT,MAAO,GACP,UAAW,IAmBN,SAAS,SAAS,GACvB,GAAoB,iBAAT,EACT,MAAO,CAAC,GAAI,IAEd,MAAM,EAAI,EAAK,QAAQ,KACjB,GAAA,EAAQ,kBAAA,MAAK,EAAK,UAAU,EAAG,IACrC,GAAI,EAAM,MAAO,CACf,MAAM,GAAA,EAAI,kBAAA,MAAK,GACf,OAAO,EAAE,MAAQ,CAAC,GAAI,EAAK,eAAiB,CAAC,EAAE,KAAM,GACvD,CAEA,MAAM,EAAO,EAAK,UAAU,EAAM,KAAK,OAAS,GAAG,cACnD,MAAO,CAAC,EAAM,KAAM,EAAK,OAAS,EAAO,GAC3C,CAMO,IAAM,MAAQ,kBAAA,MAKd,SAAS,IAAI,GAClB,MAAM,EAAS,MAAM,QAAQ,GAAO,EAAM,SAAS,GAC7C,GAAA,EAAQ,kBAAA,MAAK,EAAO,IAAI,KACxB,GAAA,EAAK,kBAAA,KAAa,EAAO,IAC/B,GAAI,EAAG,MACL,OAAO,QAGT,MAAM,EAAO,EAAG,KACV,EAAkB,EACpB,EAAG,UAAU,KAAK,IAAA,EAAM,sBAAA,WAAU,EAAO,KACzC,GAEE,EAAO,EAAQ,EAAQ,IAAM,EAAO,EAE1C,MAAO,IAAK,EAAI,OAAM,OAAM,QAAO,QACrC,CAMO,IAAM,MAAQ,IAEd,SAAS,OACd,EACA,EAAuD,CAAC,GAExD,MAAM,GAAA,EAAc,aAAA,QAAO,GACrB,GAAA,EAAQ,kBAAA,MAAK,EAAQ,OAAS,EAAM,IAAM,IAC1C,EAAc,EAAM,OAC1B,QAAoB,IAAhB,EACF,MAAO,GAGT,MAAM,EAAe,EAAY,MAAM,IACvC,EAAa,GAAe,IAC5B,MAAM,GAAA,EAAc,kBAAA,QAAO,EAAa,GAAc,KAAK,IACrD,GAAA,EAAQ,kBAAA,OAAM,MAAM,GAAc,EAAU,SAAW,IAEvD,EAAoB,GAI1B,OAHI,GACF,EAAQ,KAAK,EAAM,KAAO,IAAM,EAAM,MAElB,UAAlB,EAAQ,OAIZ,SAAS,GAAa,SAAS,IAC7B,EAAQ,KAAK,EAAM,KAAO,IAAM,EAAS,IAJlC,CAQX,CAYO,SAAS,YAAY,GAC1B,MAAM,EAAI,IAAI,GACR,GAAA,EAAU,aAAA,YAAW,EAAE,QAC7B,SAAO,kBAAA,OACJ,QAAQ,GAAU,EAAQ,EAAM,UAChC,KAAK,GAAU,EAAM,QAAQ,IAClC,CAWO,SAAS,SAAS,GACvB,MAAM,KAAS,aAAA,UAAS,GAAQ,EAAO,IAAI,GAAM,OAC3C,GAAA,EAAa,aAAA,cAAa,GAChC,SAAO,kBAAA,OACJ,QAAQ,GAAU,EAAW,EAAM,UACnC,KAAK,GAAU,EAAM,MAC1B,CAaO,SAAS,QAAQ,GACtB,MAAM,GAAA,EAAW,aAAA,YAAW,IAAI,GAAM,QACtC,SAAO,kBAAA,OACJ,QAAQ,GAAU,EAAS,EAAM,UACjC,KAAK,GAAU,EAAM,MAC1B,CAaO,SAAS,WAAW,GACzB,MAAM,EAAkB,EAAM,KAAK,IAAA,EAAM,kBAAA,MAAK,GAAG,KAAI,QAAQ,GAAM,IAC7D,EAAQ,EAAM,GACd,KAAQ,YAAA,iBAAgB,GAC9B,SAAO,kBAAA,QAAO,EAAM,QAAQ,GAAQ,EACtC,CAiBO,SAAS,UAAU,GACxB,MAAM,EAAI,IAAI,GACd,GAAI,EAAE,MACJ,MAAO,GAGT,MAAM,EAAS,EAAE,MAAQ,EAAE,MAAQ,EAAE,UACrC,SAAO,aAAA,OAAM,EAAE,QACZ,KAAI,CAAC,EAAgB,KACpB,MAAM,EAAW,IAAI,GAAQ,KAC7B,OAAO,EAAW,CAAC,EAAO,GAAI,GAAY,CAAC,GAAI,GAAE,IAElD,QAAQ,GAAM,EAAE,IACrB,CAEA,SAAS,cAAc,GACrB,MAAM,EAAQ,MAAM,QAAQ,GAAS,WAAW,GAAS,IAAI,GAAO,MAC9D,EAAU,EAAM,KAAK,IAAA,EAAS,kBAAA,MAAK,GAAM,SAE/C,OAAQ,IACN,MAAM,EACkB,iBAAf,GAAe,EAClB,kBAAA,OAAA,EAAK,YAAA,UAAS,KAAW,EACzB,kBAAA,MAAK,GACL,EAAS,EAAS,OAExB,QAAe,IAAX,EAAsB,OAC1B,MAAM,EAAS,EAAS,GAClB,EAAW,EAAQ,QAAQ,GACjC,OAAiB,IAAb,GACJ,EAAO,YAAA,YAAW,EAAS,KAAM,EAAM,SADvC,CACgD,CAEpD,CAEO,SAAS,QAAQ,GACtB,MAAM,EAAU,cAAc,GAC9B,MAAO,CAAC,EAAkB,KACxB,MAAM,GAAA,EAAO,kBAAA,MAAK,GAAU,OACtB,GAAA,EAAK,kBAAA,MAAK,GAAQ,OACxB,YAAa,IAAT,QAA6B,IAAP,EAAyB,IAEnD,EAAO,kBAAA,OAAK,EAAM,GACf,IAAI,GACJ,QAAQ,GAAM,GAAC,CAEtB,CASO,SAAS,QAAQ,GACtB,MAAM,UAAE,EAAA,MAAW,GAAU,IAAI,GAC3B,KAAY,sBAAA,0BAAyB,EAAW,GACtD,OAAQ,GACN,EAAS,EAAU,EAAS,EAAI,EAAS,EAAI,GAAU,EAC3D,CAKO,SAAS,MAAM,GACpB,MAAM,UAAE,EAAA,MAAW,GAAU,IAAI,GACjC,SAAO,sBAAA,0BAAyB,EAAW,EAC7C,CAGA,IAAO,cAAQ,CACb,gBACA,cACA,kBACA,QACA,oBACA,YACA,gBACA,gBACA,wBACA,sBACA,YACA,kBAGA,MA5MmB","file":"/npm/@tonaljs/scale@4.13.4/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@tonaljs/scale@4.13.4/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/**\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 { enharmonic, fromMidi, sortedUniqNames } from \"@tonaljs/note\";\nimport {\n  chroma,\n  isChroma,\n  isSubsetOf,\n  isSupersetOf,\n  modes,\n} from \"@tonaljs/pcset\";\nimport { tonicIntervalsTransposer, transpose } from \"@tonaljs/pitch-distance\";\nimport { note, NoteName } from \"@tonaljs/pitch-note\";\nimport {\n  all,\n  get as getScaleType,\n  ScaleType,\n  names as scaleTypeNames,\n  all as scaleTypes,\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 returns 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 mixolydian\") // => [\"C\", \"mixolydian\"]\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.toLowerCase()] : [n.name, \"\"];\n  }\n\n  const type = name.substring(tonic.name.length + 1).toLowerCase();\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\n/**\n * @deprecated\n * @use Scale.get\n */\nexport const scale = 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\n/** @deprecated */\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"]}