{"version":3,"sources":["../index.ts"],"sourcesContent":["import Chord from \"@tonaljs/chord\";\nimport Interval from \"@tonaljs/interval\";\nimport Note from \"@tonaljs/note\";\nimport Range from \"@tonaljs/range\";\nimport VoiceLeading from \"@tonaljs/voice-leading\";\nimport VoicingDictionary from \"@tonaljs/voicing-dictionary\";\n\nconst defaultRange = [\"C3\", \"C5\"];\nconst defaultDictionary = VoicingDictionary.all;\nconst defaultVoiceLeading = VoiceLeading.topNoteDiff;\n\nexport function get(\n  chord: string,\n  range: string[] = defaultRange,\n  dictionary = defaultDictionary,\n  voiceLeading = defaultVoiceLeading,\n  lastVoicing?: string[],\n) {\n  const voicings = search(chord, range, dictionary);\n  if (!lastVoicing || !lastVoicing.length) {\n    // notes = voicings[Math.ceil(voicings.length / 2)]; // pick middle voicing..\n    return voicings[0]; // pick lowest voicing..\n  } else {\n    // calculates the distance between the last note and the given voicings top note\n    // sort voicings with differ\n    return voiceLeading(voicings, lastVoicing);\n  }\n}\n\nexport function search(\n  chord: string,\n  range = defaultRange,\n  dictionary = VoicingDictionary.triads,\n): string[][] {\n  const [tonic, symbol] = Chord.tokenize(chord);\n  const sets = VoicingDictionary.lookup(symbol, dictionary);\n  // find equivalent symbol that is used as a key in dictionary:\n  if (!sets) {\n    return [];\n  }\n  // resolve array of interval arrays for the wanted symbol\n  const voicings = sets.map((intervals) => intervals.split(\" \"));\n  const notesInRange = Range.chromatic(range); // gives array of notes inside range\n  return voicings.reduce((voiced: string[][], voicing: string[]) => {\n    // transpose intervals relative to first interval (e.g. 3m 5P > 1P 3M)\n    const relativeIntervals = voicing.map(\n      (interval) => Interval.subtract(interval, voicing[0]) || \"\",\n    );\n    // get enharmonic correct pitch class the bottom note\n    const bottomPitchClass = Note.transpose(tonic, voicing[0]);\n    // get all possible start notes for voicing\n    const starts = notesInRange\n      // only get the start notes:\n      .filter((note) => Note.chroma(note) === Note.chroma(bottomPitchClass))\n      // filter out start notes that will overshoot the top end of the range\n      .filter(\n        (note) =>\n          (Note.midi(\n            Note.transpose(\n              note,\n              relativeIntervals[relativeIntervals.length - 1],\n            ),\n          ) || 0) <= (Note.midi(range[1]) || 0),\n      )\n      // replace Range.chromatic notes with the correct enharmonic equivalents\n      .map((note) => Note.enharmonic(note, bottomPitchClass));\n    // render one voicing for each start note\n    const notes = starts.map((start) =>\n      relativeIntervals.map((interval) => Note.transpose(start, interval)),\n    );\n    return voiced.concat(notes);\n  }, []);\n}\n\nexport function sequence(\n  chords: string[],\n  range = defaultRange,\n  dictionary = defaultDictionary,\n  voiceLeading = defaultVoiceLeading,\n  lastVoicing?: string[],\n) {\n  const { voicings } = chords.reduce<{\n    voicings: string[][];\n    lastVoicing: string[] | undefined;\n  }>(\n    ({ voicings, lastVoicing }, chord) => {\n      const voicing = get(chord, range, dictionary, voiceLeading, lastVoicing);\n      lastVoicing = voicing;\n      voicings.push(voicing);\n      return { voicings, lastVoicing };\n    },\n    { voicings: [], lastVoicing },\n  );\n  return voicings;\n}\n\n/** @deprecated */\nexport default {\n  get,\n  search,\n  sequence,\n};\n"],"mappings":";AAAA,OAAO,WAAW;AAClB,OAAO,cAAc;AACrB,OAAO,UAAU;AACjB,OAAO,WAAW;AAClB,OAAO,kBAAkB;AACzB,OAAO,uBAAuB;AAE9B,IAAM,eAAe,CAAC,MAAM,IAAI;AAChC,IAAM,oBAAoB,kBAAkB;AAC5C,IAAM,sBAAsB,aAAa;AAElC,SAAS,IACd,OACA,QAAkB,cAClB,aAAa,mBACb,eAAe,qBACf,aACA;AACA,QAAM,WAAW,OAAO,OAAO,OAAO,UAAU;AAChD,MAAI,CAAC,eAAe,CAAC,YAAY,QAAQ;AAEvC,WAAO,SAAS,CAAC;AAAA,EACnB,OAAO;AAGL,WAAO,aAAa,UAAU,WAAW;AAAA,EAC3C;AACF;AAEO,SAAS,OACd,OACA,QAAQ,cACR,aAAa,kBAAkB,QACnB;AACZ,QAAM,CAAC,OAAO,MAAM,IAAI,MAAM,SAAS,KAAK;AAC5C,QAAM,OAAO,kBAAkB,OAAO,QAAQ,UAAU;AAExD,MAAI,CAAC,MAAM;AACT,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAW,KAAK,IAAI,CAAC,cAAc,UAAU,MAAM,GAAG,CAAC;AAC7D,QAAM,eAAe,MAAM,UAAU,KAAK;AAC1C,SAAO,SAAS,OAAO,CAAC,QAAoB,YAAsB;AAEhE,UAAM,oBAAoB,QAAQ;AAAA,MAChC,CAAC,aAAa,SAAS,SAAS,UAAU,QAAQ,CAAC,CAAC,KAAK;AAAA,IAC3D;AAEA,UAAM,mBAAmB,KAAK,UAAU,OAAO,QAAQ,CAAC,CAAC;AAEzD,UAAM,SAAS,aAEZ,OAAO,CAAC,SAAS,KAAK,OAAO,IAAI,MAAM,KAAK,OAAO,gBAAgB,CAAC,EAEpE;AAAA,MACC,CAAC,UACE,KAAK;AAAA,QACJ,KAAK;AAAA,UACH;AAAA,UACA,kBAAkB,kBAAkB,SAAS,CAAC;AAAA,QAChD;AAAA,MACF,KAAK,OAAO,KAAK,KAAK,MAAM,CAAC,CAAC,KAAK;AAAA,IACvC,EAEC,IAAI,CAAC,SAAS,KAAK,WAAW,MAAM,gBAAgB,CAAC;AAExD,UAAM,QAAQ,OAAO;AAAA,MAAI,CAAC,UACxB,kBAAkB,IAAI,CAAC,aAAa,KAAK,UAAU,OAAO,QAAQ,CAAC;AAAA,IACrE;AACA,WAAO,OAAO,OAAO,KAAK;AAAA,EAC5B,GAAG,CAAC,CAAC;AACP;AAEO,SAAS,SACd,QACA,QAAQ,cACR,aAAa,mBACb,eAAe,qBACf,aACA;AACA,QAAM,EAAE,SAAS,IAAI,OAAO;AAAA,IAI1B,CAAC,EAAE,UAAAA,WAAU,aAAAC,aAAY,GAAG,UAAU;AACpC,YAAM,UAAU,IAAI,OAAO,OAAO,YAAY,cAAcA,YAAW;AACvE,MAAAA,eAAc;AACd,MAAAD,UAAS,KAAK,OAAO;AACrB,aAAO,EAAE,UAAAA,WAAU,aAAAC,aAAY;AAAA,IACjC;AAAA,IACA,EAAE,UAAU,CAAC,GAAG,YAAY;AAAA,EAC9B;AACA,SAAO;AACT;AAGA,IAAO,gBAAQ;AAAA,EACb;AAAA,EACA;AAAA,EACA;AACF;","names":["voicings","lastVoicing"]}