-
Notifications
You must be signed in to change notification settings - Fork 219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Voicing Package #223
Comments
Example usage for voicing multiple chords: function sequence(chords, range?, dictionary?, voiceLeading?, lastVoicing?) {
return chords.reduce(
({ voicings, lastVoicing }, chord) => {
lastVoicing = Voicing.get(chord, range, dictionary, topNoteDiff, lastVoicing);
voicings.push(lastVoicing);
return { voicings, lastVoicing };
},
{ voicings: [], lastVoicing }
).voicings;
}
const voicings = sequence(['C', 'F', 'G'], ['F3', 'A4'], triads, VoiceLeading.topNoteDiff);
/* [
[ 'C4', 'E4', 'G4' ], // root position
[ 'A3', 'C4', 'F4' ], // first inversion (F4 closest to G4)
[ 'B3', 'D4', 'G4' ] // first inversion (G4 closest to F4)
] */ Maybe, sequence could also be a part of Voicing itself... |
Hi @felixroos I am stoked with your contribution ;-) I did a quick read, but I think I'll need some time to digest and understand this well. Anyway, some questions/thoughts arose in this first read:
|
From my understanding, lefthand voicings are piano voicings that can be played with one hand, which is mostly the left one as the right is commonly used to play a melody above. But you can also play them with the right hand and use the left for a bassline. Also, they rarely contain the root note, as the root is often played by a bass instrument (or the left hand if the right hand plays the "lefthand" voicing). Sometimes they are also called rootless voicings, but I think the term "rootless" is a little more open, where lefthand are mostly a relatively small set of voicings that are first taught to jazz piano beginners.
Yeah, that was exactly my intention here. But this is a rather complicated topic.. Generally, a chord has a sort of hierarchy of note importance. As a rule of thumb the 3 and 7 are essential, while the rest is optional. Also, you can play as many or as little notes as you like. Plus, there are many "rules" to be aware of, like lower interval limits.. After a LOT of experimentation with the topic, I found that using a "combinatorial search" with flexible rules is a pretty good solution to generate any voicing.
Yes, it's kind of inconsistent. I found it difficult to name the "search" method, as it starts with Voicing.* but the result contains mutiple VoicingS...
That could be done. On the other hand, I think there are not that many voice-leading algorithms out there. Also, I think the aim for voicing-dictionary should'nt be completeness, as this is just impossible... |
closing this, as #224 exists |
As mentioned here, it would be cool if tonal could handle voicings. I am stoked that you offered me to contribute :)
I have written about most of my ideas here:
For the start, I would just concentrate on generating voicings from dictionaries, as it is way simpler and I am mostly done implementing it.
UPDATE: further changes in #224
I'll make a rough proposal by writing a pseudo doc + some test for methods that could be available:
VoicingDictionary
Maps a chord symbol to a set of voicings (interval string). The Voicings package could provide a set of common voicings. Could this also be a seperate package?!
Maybe this could also be in array format.
Voicing.search
This method returns all possible voicings of the given chord, as defined in the dictionary, inside the given range:
changes:
Voicing.get
This method returns the best voicing for chord after the optional lastVoicing, using voiceLeading. Internally calls Voicing.search to generate the available voicings.
changes:
VoiceLeading
A function that decides which of a set of voicings is picked as a follow up to lastVoicing.
The lib could include some common voice leading strategies:
changes:
VoicingDictionary.lookup
Get possible interval sets for given chord in given dictionary:
Note that it works, even if the chord symbol "M7" is just an alias of the "^7" symbol used in the dictionary.
changes:
Optional: Voicing.analyze
Returns some useful info on the given voicing:
Optional: Voicing.analyzeTransition
Returns some useful info on the given voice transition
Could also use intervals instead of semitones (but semitones are easier to compare)
Optional: Voicing.searchSets
Renders all sets of notes that represent any of the interval sets inside the given range, relative to the root:
changes:
Note.enharmonicEquivalent
For my implementation of Voicing.get to work, I would also need a helper function that returns enharmonic equivalents. As this is a rather general purpose method, I would propose this as part of Note:
edit: this feature is now covered by Note.enharmonic
That's it for a start. What do you think? UPDATE: Of course, I am open to suggestions of any sort!
UPDATE: changed some method names + param orderings (see changes under each section)
The text was updated successfully, but these errors were encountered: