Functor
HCP ("/Users/torsten/oz/music/Strasheela/strasheela/trunk/strasheela/contributions/anders/Segments/source/HomophonicChordProgression.oz")
Import
- FD
- FS
- GUtils at "x-ozlib://anders/strasheela/source/GeneralUtils.ozf"
- LUtils at "x-ozlib://anders/strasheela/source/ListUtils.ozf"
- Score at "x-ozlib://anders/strasheela/source/ScoreCore.ozf"
- Pattern at "x-ozlib://anders/strasheela/Pattern/Pattern.ozf"
- HS at "x-ozlib://anders/strasheela/HarmonisedScore/HarmonisedScore.ozf"
- Segs at "../Segments.ozf"
Export
Define
proc{HomophonicChordProgression Args MyScore}
Top-level script or subscript for creating homophonic chord progressions. The individual voices are created with Segs.makeCounterpoint_Seq, the underlying chords (and optionally scales) are given as arguments.
The number of chords determines the number of notes per voice, the start time of each chord equals the start times of the sim notes (so the resulting score is truely homophonic), and the sim notes must sound all pitch classes of the chord (i.e. arg voiceNo must be high enough, see below). By default, no voice crossing is permitted, the highest voice is the first and so forth. For inversion chords, the bass plays the bass pitch class of the chord (the soprano pitch class is ignored). The upper voices are at maximum an octave apart of each other by default.
Args:
'chords' (default {HS.score.makeChords unit}): non-nil list of chords. Remember that neither score objects nor variables can be in the top-level space, so the chords (and scales) to HomophonicChordProgression must be created inside a script.
'scales' (default nil): list of scales.
'restrictMelodicIntervals' (default as follow)
unit(bassIntervals: unit('=<:': 3#2
'=:': [2#1])
upperVoiceIntervals: unit('=<:': 3#2
'=:': nil)
step: 8#7
minPercent:50
maxPercent:100)
If non-false, then the melodic intervals are constrained as specified by the "sub arguments". The melodic intervals allowed for the bass are given by the arg 'bassIntervals', where the feature '=<:' specifies a ratio for an interval up to which all intervals are permitted and the feature '=:' specifies a list of ratios that are additionally permitted.
For example, the default setting constrains all bass intervals to up to a fifth at maximum and additionally the octave is allowed. The melodic intervals for the upper voices are specified the same way with the argument 'upperVoiceIntervals'.
The remaining arguments of the settings control the required number of steps between upper voices. The maximum interval considered a step is given as a ratio to the argument 'step'. The args 'minPercent'/'maxPercent' specify the percentage boudary of the number of steps in the upper voices.
If 'restrictMelodicIntervals' is set to false, then all these constraints are disabled.
'commonPitchesHeldOver' (default false): if true, the notes of the harmonic band stay in the same voice and octave. [this constraint can be problematic]
'noParallels' (default true): if true, no parallel perfect consonances are permitted.
'playAllChordTones' (default true): if true, all chord tones are played.
'noVoiceCrossing' (possible settings: false, true or strict. default true): if true, no voice crossings are permitted. If strict, not even unisons are permitted (tone doublication in octaves is still fine).
'maxUpperVoiceDistance' (default {HS.db.getPitchesPerOctave}): maximum interval between upper voices (interval to bass can be larger). Disabled if false.
'sliceRule' (default false): unary constraint applied to the list MyChord | Notes at each "time slice" (i.e., for each chord and the notes sim to this chord). Notes are the notes in descending order (i.e. Bass last). Disabled if false.
'sopranoRule' (default false): unary constraint applied to the list of soprano notes, i.e. the notes of the first voice. NB: the first voice is only guaranteed to be the highest voice if 'noVoiceCrossing' is true. Disabled if false.
'bassRule' (default false): unary constraint applied to the list of bass notes, i.e. the notes of the last voice. NB: the last voice is only guaranteed to be the lowest voice if 'noVoiceCrossing' is true. Disabled if false.
'makeTopLevel' (a function with the interface {$ Voices End Args}, returning a container): By default, HomophonicChordProgression returns a fully initialised score object with the following topology (chords and scales are optional).
sim([seq(note+)+
seq(chord+)
seq(scale+)])
This score topology can be overwritting with the argument 'makeTopLevel', which expects a function with the following arguments: Voices is a list of sequential containers containing notes that represent the individual voices; End (an FD int) is the end time that is shared by all voices (can be used to constrain, e.g., the end time of the chord sequence); and Args is the record of arguments expected by HomophonicChordProgression. For example, if you do not want HomophonicChordProgression to return a fully initialised score object and if chords/scales should be left out, then you can set the argument makeTopLevel to the following function.
fun {$ Voices End Args}
{Score.make2 sim(Voices)
unit}
end
The following second example of a makeTopLevel function changes the score topology such that the default Strasheela Lilypond export will export the first 2 voices in the first staff and the rest in the second staff.
fun {$ Voices End Args}
UpperStaffVoices LowerStaffVoices
in
attach first 2 voices to UpperStaffVoices and rest to LowerStaffVoices
{List.takeDrop Voices 2 UpperStaffVoices LowerStaffVoices}
{Score.make
sim([%% surrounding seq for default Lily output
(which can be customised with Out.toLilypond arg 'hasImplicitStaff')
seq([sim(UpperStaffVoices)])
seq(%% Set to bass clef.
Invisible grace note necessary to put clef at the very beginning
info:lily("\\clef bass \\grace s")
[sim(LowerStaffVoices)])
seq(info:lily("\\set Staff.instrumentName = \"Anal.\"")
Args.chords
endTime: End)
uncomment if scale should be included
seq(Args.scales
endTime: End)
]
startTime: 0)
unit}
end
'voiceArgs' (default unit): arbitrary arguments given to the constructure Score.makeItems, which creates the list of all voices.
Further Args.iargs, Args.rargs: as for Segs.makeCounterpoint_Seq
Args.iargs.n overwritten (is length of chords)
Further Args: for top-level sim.
End