{"version":3,"sources":["../index.ts"],"sourcesContent":["import { transpose, transposeFifths } from \"@tonaljs/note\";\nimport { accToAlt, altToAcc, note } from \"@tonaljs/pitch-note\";\nimport { get as roman } from \"@tonaljs/roman-numeral\";\n\nconst Empty: readonly string[] = Object.freeze([] as string[]);\n\nexport interface Key {\n  readonly type: \"major\" | \"minor\";\n  readonly tonic: string;\n  readonly alteration: number;\n  readonly keySignature: string;\n}\n\nconst NoKey: Key = {\n  type: \"major\",\n  tonic: \"\",\n  alteration: 0,\n  keySignature: \"\",\n};\n\nexport interface KeyScale {\n  readonly tonic: string;\n  readonly grades: readonly string[];\n  readonly intervals: readonly string[];\n  readonly scale: readonly string[];\n  readonly triads: readonly string[];\n  readonly chords: readonly string[];\n  readonly chordsHarmonicFunction: readonly string[];\n  readonly chordScales: readonly string[];\n  readonly secondaryDominants: readonly string[];\n  readonly secondaryDominantSupertonics: readonly string[];\n  readonly substituteDominants: readonly string[];\n  readonly substituteDominantSupertonics: readonly string[];\n\n  // @deprecated use secondaryDominantsSupertonic\n  readonly secondaryDominantsMinorRelative: readonly string[];\n  // @deprecated use substituteDominantSupertonics\n  readonly substituteDominantsMinorRelative: readonly string[];\n}\n\nconst NoKeyScale: KeyScale = {\n  tonic: \"\",\n  grades: Empty,\n  intervals: Empty,\n  scale: Empty,\n  triads: Empty,\n  chords: Empty,\n  chordsHarmonicFunction: Empty,\n  chordScales: Empty,\n  secondaryDominants: Empty,\n  secondaryDominantSupertonics: Empty,\n  substituteDominantsMinorRelative: Empty,\n  substituteDominants: Empty,\n  substituteDominantSupertonics: Empty,\n  secondaryDominantsMinorRelative: Empty,\n};\n\nexport interface MajorKey extends Key, KeyScale {\n  readonly type: \"major\";\n  readonly minorRelative: string;\n  readonly scale: readonly string[];\n  readonly substituteDominants: readonly string[];\n  readonly secondaryDominantSupertonics: readonly string[];\n  // @deprecated use secondaryDominantsSupertonic\n  readonly substituteDominantsMinorRelative: readonly string[];\n}\n\nconst NoMajorKey: MajorKey = {\n  ...NoKey,\n  ...NoKeyScale,\n  type: \"major\",\n  minorRelative: \"\",\n  scale: Empty,\n  substituteDominants: Empty,\n  secondaryDominantSupertonics: Empty,\n  substituteDominantsMinorRelative: Empty,\n};\n\nexport interface MinorKey extends Key {\n  readonly type: \"minor\";\n  readonly relativeMajor: string;\n  readonly natural: KeyScale;\n  readonly harmonic: KeyScale;\n  readonly melodic: KeyScale;\n}\n\nconst NoMinorKey: MinorKey = {\n  ...NoKey,\n  type: \"minor\",\n  relativeMajor: \"\",\n  natural: NoKeyScale,\n  harmonic: NoKeyScale,\n  melodic: NoKeyScale,\n};\n\nexport type KeyChord = {\n  name: string;\n  roles: string[];\n};\n\nconst mapScaleToType = (scale: string[], list: string[], sep = \"\") =>\n  list.map((type, i) => `${scale[i]}${sep}${type}`);\n\nfunction keyScale(\n  grades: string[],\n  triads: string[],\n  chordTypes: string[],\n  harmonicFunctions: string[],\n  chordScales: string[],\n) {\n  return (tonic: string): KeyScale => {\n    const intervals = grades.map((gr) => roman(gr).interval || \"\");\n    const scale = intervals.map((interval) => transpose(tonic, interval));\n    const chords = mapScaleToType(scale, chordTypes);\n    const secondaryDominants = scale\n      .map((note) => transpose(note, \"5P\"))\n      .map((note) =>\n        // A secondary dominant is a V chord which:\n        // 1. is not diatonic to the key,\n        // 2. it must have a diatonic root.\n        scale.includes(note) && !chords.includes(note + \"7\") ? note + \"7\" : \"\",\n      );\n\n    const secondaryDominantSupertonics = supertonics(\n      secondaryDominants,\n      triads,\n    );\n    const substituteDominants = secondaryDominants.map((chord) => {\n      if (!chord) return \"\";\n      const domRoot = chord.slice(0, -1);\n      const subRoot = transpose(domRoot, \"5d\");\n      return subRoot + \"7\";\n    });\n    const substituteDominantSupertonics = supertonics(\n      substituteDominants,\n      triads,\n    );\n\n    return {\n      tonic,\n      grades,\n      intervals,\n      scale,\n      triads: mapScaleToType(scale, triads),\n      chords,\n      chordsHarmonicFunction: harmonicFunctions.slice(),\n      chordScales: mapScaleToType(scale, chordScales, \" \"),\n      secondaryDominants,\n      secondaryDominantSupertonics,\n      substituteDominants,\n      substituteDominantSupertonics,\n\n      // @deprecated use secondaryDominantsSupertonic\n      secondaryDominantsMinorRelative: secondaryDominantSupertonics,\n      // @deprecated use secondaryDominantsSupertonic\n      substituteDominantsMinorRelative: substituteDominantSupertonics,\n    };\n  };\n}\n\nconst supertonics = (dominants: string[], targetTriads: string[]) => {\n  return dominants.map((chord, index) => {\n    if (!chord) return \"\";\n    const domRoot = chord.slice(0, -1);\n    const minorRoot = transpose(domRoot, \"5P\");\n    const target = targetTriads[index];\n    const isMinor = target.endsWith(\"m\");\n    return isMinor ? minorRoot + \"m7\" : minorRoot + \"m7b5\";\n  });\n};\n\nconst distInFifths = (from: string, to: string) => {\n  const f = note(from);\n  const t = note(to);\n  return f.empty || t.empty ? 0 : t.coord[0] - f.coord[0];\n};\n\nconst MajorScale = keyScale(\n  \"I II III IV V VI VII\".split(\" \"),\n  \" m m   m dim\".split(\" \"),\n  \"maj7 m7 m7 maj7 7 m7 m7b5\".split(\" \"),\n  \"T SD T SD D T D\".split(\" \"),\n  \"major,dorian,phrygian,lydian,mixolydian,minor,locrian\".split(\",\"),\n);\nconst NaturalScale = keyScale(\n  \"I II bIII IV V bVI bVII\".split(\" \"),\n  \"m dim  m m  \".split(\" \"),\n  \"m7 m7b5 maj7 m7 m7 maj7 7\".split(\" \"),\n  \"T SD T SD D SD SD\".split(\" \"),\n  \"minor,locrian,major,dorian,phrygian,lydian,mixolydian\".split(\",\"),\n);\nconst HarmonicScale = keyScale(\n  \"I II bIII IV V bVI VII\".split(\" \"),\n  \"m dim aug m   dim\".split(\" \"),\n  \"mMaj7 m7b5 +maj7 m7 7 maj7 o7\".split(\" \"),\n  \"T SD T SD D SD D\".split(\" \"),\n  \"harmonic minor,locrian 6,major augmented,lydian diminished,phrygian dominant,lydian #9,ultralocrian\".split(\n    \",\",\n  ),\n);\nconst MelodicScale = keyScale(\n  \"I II bIII IV V VI VII\".split(\" \"),\n  \"m m aug   dim dim\".split(\" \"),\n  \"m6 m7 +maj7 7 7 m7b5 m7b5\".split(\" \"),\n  \"T SD T SD D  \".split(\" \"),\n  \"melodic minor,dorian b2,lydian augmented,lydian dominant,mixolydian b6,locrian #2,altered\".split(\n    \",\",\n  ),\n);\n\n/**\n * Get a major key properties in a given tonic\n * @param tonic\n */\nexport function majorKey(tonic: string): MajorKey {\n  const pc = note(tonic).pc;\n  if (!pc) return NoMajorKey;\n\n  const keyScale = MajorScale(pc);\n  const alteration = distInFifths(\"C\", pc);\n\n  return {\n    ...keyScale,\n    type: \"major\",\n    minorRelative: transpose(pc, \"-3m\"),\n    alteration,\n    keySignature: altToAcc(alteration),\n  };\n}\n\n/**\n * Get a list of available chords for a given major key\n * @param tonic\n * @returns array of { name: string, roles: string[] }\n */\nexport function majorKeyChords(tonic: string): KeyChord[] {\n  const key = majorKey(tonic);\n  const chords: KeyChord[] = [];\n  keyChordsOf(key, chords);\n  return chords;\n}\n\n/**\n * Get a list of available chords for a given major key\n * @param tonic\n * @returns array of { name: string, roles: string[] }\n */\nexport function minorKeyChords(tonic: string): KeyChord[] {\n  const key = minorKey(tonic);\n  const chords: KeyChord[] = [];\n  keyChordsOf(key.natural, chords);\n  keyChordsOf(key.harmonic, chords);\n  keyChordsOf(key.melodic, chords);\n  return chords;\n}\n\nfunction keyChordsOf(key: KeyScale, chords: KeyChord[]) {\n  const updateChord = (name: string, newRole: string) => {\n    if (!name) return;\n    let keyChord = chords.find((chord) => chord.name === name);\n    if (!keyChord) {\n      keyChord = { name, roles: [] };\n      chords.push(keyChord);\n    }\n    if (newRole && !keyChord.roles.includes(newRole)) {\n      keyChord.roles.push(newRole);\n    }\n  };\n\n  key.chords.forEach((chordName, index) =>\n    updateChord(chordName, key.chordsHarmonicFunction[index]),\n  );\n  key.secondaryDominants.forEach((chordName, index) =>\n    updateChord(chordName, `V/${key.grades[index]}`),\n  );\n  key.secondaryDominantSupertonics.forEach((chordName, index) =>\n    updateChord(chordName, `ii/${key.grades[index]}`),\n  );\n  key.substituteDominants.forEach((chordName, index) =>\n    updateChord(chordName, `subV/${key.grades[index]}`),\n  );\n  key.substituteDominantSupertonics.forEach((chordName, index) =>\n    updateChord(chordName, `subii/${key.grades[index]}`),\n  );\n}\n\n/**\n * Get minor key properties in a given tonic\n * @param tonic\n */\nexport function minorKey(tnc: string): MinorKey {\n  const pc = note(tnc).pc;\n  if (!pc) return NoMinorKey;\n\n  const alteration = distInFifths(\"C\", pc) - 3;\n  return {\n    type: \"minor\",\n    tonic: pc,\n    relativeMajor: transpose(pc, \"3m\"),\n    alteration,\n    keySignature: altToAcc(alteration),\n    natural: NaturalScale(pc),\n    harmonic: HarmonicScale(pc),\n    melodic: MelodicScale(pc),\n  };\n}\n\n/**\n * Given a key signature, returns the tonic of the major key\n * @param signature\n * @example\n * majorTonicFromKeySignature('###') // => 'A'\n */\nexport function majorTonicFromKeySignature(\n  sig: string | number,\n): string | null {\n  if (typeof sig === \"number\") {\n    return transposeFifths(\"C\", sig);\n  } else if (typeof sig === \"string\" && /^b+|#+$/.test(sig)) {\n    return transposeFifths(\"C\", accToAlt(sig));\n  }\n  return null;\n}\n\n/** @deprecated */\nexport default { majorKey, majorTonicFromKeySignature, minorKey };\n"],"mappings":";AAAA,SAAS,WAAW,uBAAuB;AAC3C,SAAS,UAAU,UAAU,YAAY;AACzC,SAAS,OAAO,aAAa;AAE7B,IAAM,QAA2B,OAAO,OAAO,CAAC,CAAa;AAS7D,IAAM,QAAa;AAAA,EACjB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,cAAc;AAChB;AAsBA,IAAM,aAAuB;AAAA,EAC3B,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,wBAAwB;AAAA,EACxB,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,8BAA8B;AAAA,EAC9B,kCAAkC;AAAA,EAClC,qBAAqB;AAAA,EACrB,+BAA+B;AAAA,EAC/B,iCAAiC;AACnC;AAYA,IAAM,aAAuB;AAAA,EAC3B,GAAG;AAAA,EACH,GAAG;AAAA,EACH,MAAM;AAAA,EACN,eAAe;AAAA,EACf,OAAO;AAAA,EACP,qBAAqB;AAAA,EACrB,8BAA8B;AAAA,EAC9B,kCAAkC;AACpC;AAUA,IAAM,aAAuB;AAAA,EAC3B,GAAG;AAAA,EACH,MAAM;AAAA,EACN,eAAe;AAAA,EACf,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AACX;AAOA,IAAM,iBAAiB,CAAC,OAAiB,MAAgB,MAAM,OAC7D,KAAK,IAAI,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,EAAE;AAElD,SAAS,SACP,QACA,QACA,YACA,mBACA,aACA;AACA,SAAO,CAAC,UAA4B;AAClC,UAAM,YAAY,OAAO,IAAI,CAAC,OAAO,MAAM,EAAE,EAAE,YAAY,EAAE;AAC7D,UAAM,QAAQ,UAAU,IAAI,CAAC,aAAa,UAAU,OAAO,QAAQ,CAAC;AACpE,UAAM,SAAS,eAAe,OAAO,UAAU;AAC/C,UAAM,qBAAqB,MACxB,IAAI,CAACA,UAAS,UAAUA,OAAM,IAAI,CAAC,EACnC;AAAA,MAAI,CAACA;AAAA;AAAA;AAAA;AAAA,QAIJ,MAAM,SAASA,KAAI,KAAK,CAAC,OAAO,SAASA,QAAO,GAAG,IAAIA,QAAO,MAAM;AAAA;AAAA,IACtE;AAEF,UAAM,+BAA+B;AAAA,MACnC;AAAA,MACA;AAAA,IACF;AACA,UAAM,sBAAsB,mBAAmB,IAAI,CAAC,UAAU;AAC5D,UAAI,CAAC,MAAO,QAAO;AACnB,YAAM,UAAU,MAAM,MAAM,GAAG,EAAE;AACjC,YAAM,UAAU,UAAU,SAAS,IAAI;AACvC,aAAO,UAAU;AAAA,IACnB,CAAC;AACD,UAAM,gCAAgC;AAAA,MACpC;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,eAAe,OAAO,MAAM;AAAA,MACpC;AAAA,MACA,wBAAwB,kBAAkB,MAAM;AAAA,MAChD,aAAa,eAAe,OAAO,aAAa,GAAG;AAAA,MACnD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA,iCAAiC;AAAA;AAAA,MAEjC,kCAAkC;AAAA,IACpC;AAAA,EACF;AACF;AAEA,IAAM,cAAc,CAAC,WAAqB,iBAA2B;AACnE,SAAO,UAAU,IAAI,CAAC,OAAO,UAAU;AACrC,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,UAAU,MAAM,MAAM,GAAG,EAAE;AACjC,UAAM,YAAY,UAAU,SAAS,IAAI;AACzC,UAAM,SAAS,aAAa,KAAK;AACjC,UAAM,UAAU,OAAO,SAAS,GAAG;AACnC,WAAO,UAAU,YAAY,OAAO,YAAY;AAAA,EAClD,CAAC;AACH;AAEA,IAAM,eAAe,CAAC,MAAc,OAAe;AACjD,QAAM,IAAI,KAAK,IAAI;AACnB,QAAM,IAAI,KAAK,EAAE;AACjB,SAAO,EAAE,SAAS,EAAE,QAAQ,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC;AACxD;AAEA,IAAM,aAAa;AAAA,EACjB,uBAAuB,MAAM,GAAG;AAAA,EAChC,eAAe,MAAM,GAAG;AAAA,EACxB,4BAA4B,MAAM,GAAG;AAAA,EACrC,kBAAkB,MAAM,GAAG;AAAA,EAC3B,wDAAwD,MAAM,GAAG;AACnE;AACA,IAAM,eAAe;AAAA,EACnB,0BAA0B,MAAM,GAAG;AAAA,EACnC,eAAe,MAAM,GAAG;AAAA,EACxB,4BAA4B,MAAM,GAAG;AAAA,EACrC,oBAAoB,MAAM,GAAG;AAAA,EAC7B,wDAAwD,MAAM,GAAG;AACnE;AACA,IAAM,gBAAgB;AAAA,EACpB,yBAAyB,MAAM,GAAG;AAAA,EAClC,oBAAoB,MAAM,GAAG;AAAA,EAC7B,gCAAgC,MAAM,GAAG;AAAA,EACzC,mBAAmB,MAAM,GAAG;AAAA,EAC5B,sGAAsG;AAAA,IACpG;AAAA,EACF;AACF;AACA,IAAM,eAAe;AAAA,EACnB,wBAAwB,MAAM,GAAG;AAAA,EACjC,oBAAoB,MAAM,GAAG;AAAA,EAC7B,4BAA4B,MAAM,GAAG;AAAA,EACrC,gBAAgB,MAAM,GAAG;AAAA,EACzB,4FAA4F;AAAA,IAC1F;AAAA,EACF;AACF;AAMO,SAAS,SAAS,OAAyB;AAChD,QAAM,KAAK,KAAK,KAAK,EAAE;AACvB,MAAI,CAAC,GAAI,QAAO;AAEhB,QAAMC,YAAW,WAAW,EAAE;AAC9B,QAAM,aAAa,aAAa,KAAK,EAAE;AAEvC,SAAO;AAAA,IACL,GAAGA;AAAA,IACH,MAAM;AAAA,IACN,eAAe,UAAU,IAAI,KAAK;AAAA,IAClC;AAAA,IACA,cAAc,SAAS,UAAU;AAAA,EACnC;AACF;AAOO,SAAS,eAAe,OAA2B;AACxD,QAAM,MAAM,SAAS,KAAK;AAC1B,QAAM,SAAqB,CAAC;AAC5B,cAAY,KAAK,MAAM;AACvB,SAAO;AACT;AAOO,SAAS,eAAe,OAA2B;AACxD,QAAM,MAAM,SAAS,KAAK;AAC1B,QAAM,SAAqB,CAAC;AAC5B,cAAY,IAAI,SAAS,MAAM;AAC/B,cAAY,IAAI,UAAU,MAAM;AAChC,cAAY,IAAI,SAAS,MAAM;AAC/B,SAAO;AACT;AAEA,SAAS,YAAY,KAAe,QAAoB;AACtD,QAAM,cAAc,CAAC,MAAc,YAAoB;AACrD,QAAI,CAAC,KAAM;AACX,QAAI,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,SAAS,IAAI;AACzD,QAAI,CAAC,UAAU;AACb,iBAAW,EAAE,MAAM,OAAO,CAAC,EAAE;AAC7B,aAAO,KAAK,QAAQ;AAAA,IACtB;AACA,QAAI,WAAW,CAAC,SAAS,MAAM,SAAS,OAAO,GAAG;AAChD,eAAS,MAAM,KAAK,OAAO;AAAA,IAC7B;AAAA,EACF;AAEA,MAAI,OAAO;AAAA,IAAQ,CAAC,WAAW,UAC7B,YAAY,WAAW,IAAI,uBAAuB,KAAK,CAAC;AAAA,EAC1D;AACA,MAAI,mBAAmB;AAAA,IAAQ,CAAC,WAAW,UACzC,YAAY,WAAW,KAAK,IAAI,OAAO,KAAK,CAAC,EAAE;AAAA,EACjD;AACA,MAAI,6BAA6B;AAAA,IAAQ,CAAC,WAAW,UACnD,YAAY,WAAW,MAAM,IAAI,OAAO,KAAK,CAAC,EAAE;AAAA,EAClD;AACA,MAAI,oBAAoB;AAAA,IAAQ,CAAC,WAAW,UAC1C,YAAY,WAAW,QAAQ,IAAI,OAAO,KAAK,CAAC,EAAE;AAAA,EACpD;AACA,MAAI,8BAA8B;AAAA,IAAQ,CAAC,WAAW,UACpD,YAAY,WAAW,SAAS,IAAI,OAAO,KAAK,CAAC,EAAE;AAAA,EACrD;AACF;AAMO,SAAS,SAAS,KAAuB;AAC9C,QAAM,KAAK,KAAK,GAAG,EAAE;AACrB,MAAI,CAAC,GAAI,QAAO;AAEhB,QAAM,aAAa,aAAa,KAAK,EAAE,IAAI;AAC3C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,eAAe,UAAU,IAAI,IAAI;AAAA,IACjC;AAAA,IACA,cAAc,SAAS,UAAU;AAAA,IACjC,SAAS,aAAa,EAAE;AAAA,IACxB,UAAU,cAAc,EAAE;AAAA,IAC1B,SAAS,aAAa,EAAE;AAAA,EAC1B;AACF;AAQO,SAAS,2BACd,KACe;AACf,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO,gBAAgB,KAAK,GAAG;AAAA,EACjC,WAAW,OAAO,QAAQ,YAAY,UAAU,KAAK,GAAG,GAAG;AACzD,WAAO,gBAAgB,KAAK,SAAS,GAAG,CAAC;AAAA,EAC3C;AACA,SAAO;AACT;AAGA,IAAO,gBAAQ,EAAE,UAAU,4BAA4B,SAAS;","names":["note","keyScale"]}