@tonaljs/voicing
Version:
Voicings and Voice Leading for Chords
69 lines • 2.47 kB
JavaScript
// 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