A chord voicing is an instance of a Chord that can be played or sung.
This package's recommended way of creating four-part Voicings is to use the Chord.voiceFourParts function along with VoicingMethods like the ones in this module:
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ basic ]
(Chord.majorSeventh PitchClass.c)In this example, we pass the following to voiceFourParts:
Ranges of the instruments involvedVoicingMethods to be usedThis uses the characteristics of the VoicingMethod to return a List of all possible Voicings.
From here, you may choose from this list based on some criteria:
myGeneratedVoicings
|> List.filter
(\voicing ->
containsPitchInVoiceOne Pitch.e5 voicing
&& (span voicing >= Interval.perfectOctave)
)
|> List.sortWith (centerOrder Pitch.g4)
|> List.headThis does the following:
Voicings which have E5 in the top voice, and have a span of at least an octave from bottom to top voiceVoicings which are centered around the pitch G4 are at the beginningThese sorting and filtering processes allow you to account for considerations like voice leading, or the harmonization of a melody. You'll find comparison functions in this module for doing that.
There are cases where you may want to create a specific voicing you have in mind:
Create a voicing from pitches and a chord:
voicing
{ voiceOne = Pitch.c5
, voiceTwo = Pitch.a4
, voiceThree = Pitch.g4
, voiceFour = Pitch.e4
}
(Chord.majorSix PitchClass.c)
== Ok Voicing ...If the pitches given do not match the chord, this function will return Err with the erroneous pitch classes:
voicing
{ voiceOne = Pitch.c5
, voiceTwo = Pitch.d4
, voiceThree = Pitch.g4
, voiceFour = Pitch.e4
}
(Chord.majorSix PitchClass.c)
== Err [ PitchClass.d ]Get the chord being voiced:
chord myVoicing == Chord.majorSixNine PitchClass.cGet the interval from the lowest to the highest pitch in the voicing:
span myVoicing == Interval.minorSeventhGet the midpoint between the highest and lowest voices in semitones:
center myVoicing
== Pitch.semitones Pitch.fSharp3Get the first (highest) pitch of the voicing:
voiceOne myVoicing == Pitch.d5Get the second pitch of the voicing:
voiceTwo myVoicing == Pitch.a4Get the third pitch of the voicing:
voiceThree myVoicing == Pitch.g4Get the fourth (lowest) pitch of the voicing:
voiceFour myVoicing == Pitch.e4Find out whether a voicing contains a specific pitch:
containsPitch Pitch.d5 myVoicing == TrueFind out whether a voicing has a specific pitch in the first voice:
containsPitchInVoiceOne Pitch.d5 myVoicing == TrueFind out whether a voicing has a specific pitch in the second voice:
containsPitchInVoiceTwo Pitch.a4 myVoicing == TrueFind out whether a voicing has a specific pitch in the third voice:
containsPitchInVoiceThree Pitch.g4 myVoicing == TrueFind out whether a voicing has a specific pitch in the fourth voice:
containsPitchInVoiceFour Pitch.e4 myVoicing == TrueGet all pitches in common between two voicings:
commonTones bFlatVoicing bDimVoicing
== [ Pitch.d4
, Pitch.f4
]Find out whether the first and fourth voices move in opposite directions (known as contrary motion).
Find out whether any two moving voices maintain a perfect fifth interval between them. Identifying parallel fifths and octaves is important in the study of counterpoint.
Find out whether any two moving voices maintain a perfect octave interval between them.
Given two voicings, find out how far in semitones all voices move.
Given two voicings, find out how far in semitones the first (top) voice moves.
Given two voicings, find out how far in semitones the second voice moves.
Given two voicings, find out how far in semitones the third voice moves.
Given two voicings, find out how far in semitones the fourth (bottom) voice moves.
A low interval limit is the lowest pitch at which the character of an interval cannot be heard clearly. I have heard this explained in terms of the harmonic series, but it seems to be taught as more of a guideline for arrangers than a physical absolute.
Sort by multiple ordering functions:
sortWeighted
[ ( totalSemitoneDistanceOrder previousVoicing, 10.0 )
, ( contraryMotionOrder previousVoicing, 5.0 )
, ( commonTonesOrder previousVoicing, 2.0 )
]
voicingListCombine multiple ordering functions:
orderWeighted
[ ( totalSemitoneDistanceOrder previousVoicing, 10.0 )
, ( contraryMotionOrder previousVoicing, 5.0 )
, ( commonTonesOrder previousVoicing, 2.0 )
]
|> List.orderWithCompare voicings by how far their centers are from a goal pitch:
myVoicingList
|> List.sortWith (centerOrder Pitch.g4)Useful for finding voicings that are centered around a particular pitch.
Compare voicings by how many pitches they have in common with a previous voicing:
myVoicingList
|> List.sortWith (commonTonesOrder previousVoicing)Compare voicings by whether they use contrary motion from a previous voicing:
myVoicingList
|> List.sortWith (contraryMotionOrder previousVoicing)"Contrary motion" here is in respect to the top and bottom voices.
Compare voicings by absolute difference in semitones from a previous voicing:
myVoicingList
|> List.sortWith (totalSemitoneDistanceOrder previousVoicing)Compare voicings by absolute difference in semitones in voice one:
myVoicingList
|> List.sortWith (semitoneDistanceVoiceOneOrder previousVoicing)Compare voicings by absolute difference in semitones in voice two:
myVoicingList
|> List.sortWith (semitoneDistanceVoiceTwoOrder previousVoicing)Compare voicings by absolute difference in semitones in voice three:
myVoicingList
|> List.sortWith (semitoneDistanceVoiceThreeOrder previousVoicing)Compare voicings by absolute difference in semitones in voice four:
myVoicingList
|> List.sortWith (semitoneDistanceVoiceFourOrder previousVoicing)The pitches contained in a voicing.
These are in order from highest (voiceOne) to lowest (voiceFour), the way you might read them on a staff.
Get all pitches contained in a voicing:
toPitches myVoicing
== { voiceOne = Pitch.d5
, voiceTwo = Pitch.a4
, voiceThree = Pitch.g4
, voiceFour = Pitch.e4
}Get all pitches contained in a voicing, as a List:
toPitchList myVoicing
== [ Pitch.d5
, Pitch.a4
, Pitch.g4
, Pitch.e4
]Get all pitches contained in a voicing, as a stringified list:
toPitchList myVoicing
== "D5, A4, G4, E4"Get all intervals between each pitch in a voicing:
toIntervals myVoicing
== { fourToOne = Interval.majorSixth
, fourToTwo = Interval.majorSecond
, fourToThree = Interval.majorThird
, threeToOne = Interval.perfectFifth
, threeToTwo = Interval.majorSecond
, twoToOne = Interval.perfectFourth
}Get all intervals between each pitch in a voicing as a List:
toIntervalList myVoicing
== [ Interval.majorSecond
, Interval.majorSecond
, Interval.majorThird
, Interval.perfectFourth
, Interval.perfectFifth
, Interval.majorSixth
]A basic textbook method for voicing a chord in root position:
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ basic ]
(Chord.majorSeventh PitchClass.c)
|> List.map toString
== [ "B4, G4, E4, C4"
, -- 2 others...
]These methods were adapted from Jazz Arranging Techniques by Gary Lindsay.
Notes:
Voice a chord using the "four-way close" method:
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ close ]
(Chord.majorSeventh PitchClass.c)
|> List.map toString
== [ "C4, B3, G3, E3"
, -- 39 others...
]This method voices all four notes "closely" within the span of an octave.
Voice a chord using the "four-way drop-2" method:
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ drop2 ]
(Chord.majorSeventh PitchClass.c)
|> List.map toString
== [ "C4, G3, E3, B2"
, -- 55 others...
]This method is the same as four-way close, but with the second pitch from the top dropped by an octave for a wider, semi-open sound.
Voice a chord using the "four-way drop-3" method:
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ drop3 ]
(Chord.majorSeventh PitchClass.c)
|> List.map toString
== [ "C4, G3, E3, B2"
, -- 55 others...
]Same as drop-2, but with the third pitch from the top dropped instead of the second.
Voice a chord using the "four-way drop-2-and-4" method:
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ drop2and4 ]
(Chord.majorSeventh PitchClass.c)
|> List.map toString
== [ "G4, C4, E3, B2"
, -- 55 others...
]A double drop voicing, with the second and fourth pitches from the top dropped for a wide, open sound.
Voice a chord using the "four-way spread" method:
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ spread ]
(Chord.majorSeventh PitchClass.c)
|> List.map toString
== [ "C4, B3, E3, G2"
, -- 22 others...
]Another open voicing method, with the root of the chord on the bottom for a dramatic effect.
Note: these classical methods were developed before jazz harmony, and so chord extensions and added tones will not be included.
Voice a chord in "root position":
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ rootPosition ]
(Chord.major PitchClass.c)
|> List.map toString
== [ "G4, E4, G3, C3"
, -- 30 others...
]A root position voicing is any voicing where the root is in the lowest voice.
Voice a chord in "first inversion":
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ firstInversion ]
(Chord.major PitchClass.c)
|> List.map toString
== [ "C6, C5, G4, E3"
, -- 32 others...
]A first inversion voicing is any voicing where the third of the chord is in the lowest voice.
Voice a chord in "second inversion":
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ secondInversion ]
(Chord.major PitchClass.c)
|> List.map toString
== [ "E4, G3, C3, G2"
, -- 32 others...
]A second inversion voicing is any voicing where the fifth of the chord is in the lowest voice.
Voice a chord in "third inversion":
Chord.voiceFourParts
{ voiceOne = Range.sopranoVoice
, voiceTwo = Range.altoVoice
, voiceThree = Range.tenorVoice
, voiceFour = Range.bassVoice
}
[ thirdInversion ]
(Chord.dominantSeventh PitchClass.c)
|> List.map toString
== [ "E4, C4, C3, B♭2"
, -- 32 others...
]A third inversion voicing is any voicing where the seventh of the chord is in the lowest voice.
Note: this will return an empty list when used with triad chord types like major and minor, because a seventh must be included.
Voicing methods are a deep and nuanced topic, that I hope to make approachable. I've modeled this API with three main concepts of chord voicing in mind:
Here are the steps in building a voicing method:
Since chords can vary, use some method of categorizing the factors of a chord into groups that you can guarantee are present. Examples of this type of categorization function are Chord.categorizeFactors and Chord.availableTensions.
Select factors using the with... functions in this section.
Use the placeSelectedFactors function, passing a SpacingLimits.
Example:
myCustomVoicingMethod : VoicingMethod
myCustomVoicingMethod =
custom
ChordType.categorizeFactors
(\factors ->
selectFactors
|> withFactorFrom
(List.filterMap identity
[ Just Interval.perfectUnison
, factors.sixthOrSeventh
]
)
|> withFactor factors.fifth
|> withFactor factors.third
|> withFactor Interval.perfectUnison
|> placeSelectedFactors spacingLimits
)
spacingLimits =
{ twoToOne =
Interval.range
Interval.augmentedUnison
Interval.perfectOctave
, threeToTwo =
Interval.range
Interval.augmentedUnison
Interval.perfectOctave
, fourToThree =
Interval.range
Interval.augmentedUnison
Interval.perfectOctave
}Begin a custom voicing method:
method Chord.categorizeFactors
(\categorized ->
...
)Begin selecting factors for a voicing method.
Select a chord factor for use in a voice.
Select a factor that has not yet been used.
Select a factor from a list of options.
Select a factor that has not yet been used, from a list of options.
Select two factors from a list of options.
Select two factors that have not yet been used, from a list of options.
Select three factors from a list of options.
Select two factors that have not yet been used, from a list of options.
Finish selecting factors for a voicing method and place them according to the spacing limits.
Combine multiple VoicingMethods together:
myComboVoicingMethod =
combineVoicingMethods [ voicingMethodOne, voicingMethodTwo, voicingMethodThree ]This is useful if you want to define multiple VoicingMethods that act as a group (e.g. inversions or similar methods that use different chord factors).