UNPKG

@tonaljs/voicing

Version:

Voicings and Voice Leading for Chords

69 lines 2.47 kB
// index.ts import Chord from "@tonaljs/chord"; import Interval from "@tonaljs/interval"; import Note from "@tonaljs/note"; import Range from "@tonaljs/range"; import VoiceLeading from "@tonaljs/voice-leading"; import VoicingDictionary from "@tonaljs/voicing-dictionary"; var defaultRange = ["C3", "C5"]; var defaultDictionary = VoicingDictionary.all; var defaultVoiceLeading = VoiceLeading.topNoteDiff; function get(chord, range = defaultRange, dictionary = defaultDictionary, voiceLeading = defaultVoiceLeading, lastVoicing) { const voicings = search(chord, range, dictionary); if (!lastVoicing || !lastVoicing.length) { return voicings[0]; } else { return voiceLeading(voicings, lastVoicing); } } function search(chord, range = defaultRange, dictionary = VoicingDictionary.triads) { const [tonic, symbol] = Chord.tokenize(chord); const sets = VoicingDictionary.lookup(symbol, dictionary); if (!sets) { return []; } const voicings = sets.map((intervals) => intervals.split(" ")); const notesInRange = Range.chromatic(range); return voicings.reduce((voiced, voicing) => { const relativeIntervals = voicing.map( (interval) => Interval.subtract(interval, voicing[0]) || "" ); const bottomPitchClass = Note.transpose(tonic, voicing[0]); const starts = notesInRange.filter((note) => Note.chroma(note) === Note.chroma(bottomPitchClass)).filter( (note) => (Note.midi( Note.transpose( note, relativeIntervals[relativeIntervals.length - 1] ) ) || 0) <= (Note.midi(range[1]) || 0) ).map((note) => Note.enharmonic(note, bottomPitchClass)); const notes = starts.map( (start) => relativeIntervals.map((interval) => Note.transpose(start, interval)) ); return voiced.concat(notes); }, []); } function sequence(chords, range = defaultRange, dictionary = defaultDictionary, voiceLeading = defaultVoiceLeading, lastVoicing) { const { voicings } = chords.reduce( ({ voicings: voicings2, lastVoicing: lastVoicing2 }, chord) => { const voicing = get(chord, range, dictionary, voiceLeading, lastVoicing2); lastVoicing2 = voicing; voicings2.push(voicing); return { voicings: voicings2, lastVoicing: lastVoicing2 }; }, { voicings: [], lastVoicing } ); return voicings; } var index_default = { get, search, sequence }; export { index_default as default, get, search, sequence }; //# sourceMappingURL=index.mjs.map