This Strasheela contribution defines means to constrain formal relations in music. The constribution adds generic means to define motif domains and to impose constraints on motifs.
The general Motif data structure MotifMixin (which is used later in this functor to extend Score.simultaneous and Score.sequential) defines two parameters: 'motifIdentity' and 'motifVariation' (parameter values are FD integers). The parameter value 'motifIdentity' decides for a specific motif out of an user-defined motif database, a list of records with user-defined motif features (a 'motifIdentity' value N denotes the Nth value in the motif database). For example, a possible motif database entry defines absolute note durations and the pitch contour of the motif (the contour defines the sequence of directions of intervals, see Pattern.contour and Pattern.direction for details).
motif(durations:[2 2 2 8] pitchContour:[1 1 0] comment:beethovensFifth)
The parameter value 'motifVariation' decides for a specific binary procedure out of a user-defined procedure database, a list of binary procedures (a 'motifVariation' value N denotes the Nth value in the procedure database). The procedure represented by 'motifVariation' constrains the motif score instance in a user defined way -- usually dependent on the motif database entry represented by 'motifIdentity'. Procedure arguments are a motif instance and an 0/1-integer. The 0/1-integer denotes whether or not the motif score instance fulfills the constraint imposed by the procedure (see Mozart/Oz doc for details on 0/1-constraints and reified constraints). For instance, one possible 'motifVariation' procedure may apply a motif database entry in the above-mentioned format by constraining the motif note durations and pitchContour according to the durations and pitchContour specified in the database entry represented by 'motifIdentity'. However, another 'motifVariation' procedure may constraints the motif pitches to follow the inverse of the pitchContour defined by the database entry.
The domain of motifs thus depends on three user-controlled dimensions: (a) the set of entries in the motif database, (b) the set of 'motifVariation' procedures, and (c) the ambiguity implicit in the motif definition (e.g. constraining only the pitch contour allows many motif variants with the same 'motifIdentity' and 'motifVariation'). Each of theses dimensions can be freely constrained. For instance, in a succession of several motifs the 'motifIdentity' and 'motifVariation' may be constrained to follow some pattern and the pitches of the motif notes constrained to follows some motif contour may be further constrained to follow some harmonic progression.
However, the formalisation of motific relations proposed here is even more general. Entries in the motif database may be undetermined in the definition of the constraint satisfaction problem (CSP). For instance, the user may constrain a set of motif score instances to be the same motif (e.g. all motif indices are equal), but the actual shape of the motif is undetermined in the CSP and may depend, e.g., on contrapunctual motif combinations (e.g. the shape of a fugue subject and counter-subject may only be found during search).
Furthermore, the number of notes in a score motif instance may be constrained by the decision, e.g., for a certain 'motifIdentity'. This is archived by some 'trick': notes of duration 0 can be considered non-existent. All entries in the motif database and all motifs in the score instance may actually have the same number of notes. However, in some motif database entries the duration of some notes is set to 0 which effectively reduces the note number of these motifs. The note number of any motif in the score instance may be virtually reduced by constraining certain note durations to 0.
However, for efficiency reasons a CSP involving the note duration 0 as an option should eliminate symmetries (for details see www.mozart-oz.org/documentation/fdt/node53.html). Notes with duration 0 must only occur at a certain position in motif (e.g. the motif end). If the duration of a note equals 0 the pitch of the note is arbitrary and should be determined as well to reduce the size of the search space (e.g. (duration = 0) -> (pitch = 0)).
See the contribution ConstrainTimingTree for further details.
To model free, non-motific sections between motific sections, a specific 'motifVariation' procedure may be defined which does not apply any constraints on the motif score instance (or constrains only the number of notes by setting note durations to 0). In the CSP, a decision for this 'motifVariation' means a decision for a non-motific section. To eliminate symmetries, the 'motifVariation' procedure should also determine the 'motifIdentity'.
The data structure defined in this Strasheela contribution may also serve to define higher-level formal relations (e.g. variated repetitions of motif sequences). Instead of a motif containing notes, a 'higher-level motif' containes motifs. A 'Higher-level motif' constrains the contained submotif in the same way a motif constraints contained notes by deciding for the parameters 'motifIdentity' and 'motifVariation' and thus deciding for an entry in the motif database and an entry in the database of procedures. For example, the user may want to constrain the sequence of motifs contained in a 'higher-level motif' by applying a pattern constraint on submotif indices, or a pattern constraint on the sequence of the maximum pitches of each motif.
To control for which level a specific entry in either database is used (e.g. only for motifs of notes or only for 'higher-level motifs'), the user may reduce the domain of 'motifIdentity' and 'motifVariation' according to their motif instance level.
Of course, arbitrary parameters can be constrained in a motif. For instance, to model pauses before or between motif notes, the note offsetTimes may be constrained.
Note that there also exists another motif model in Strasheela. See contributions/anders/PrototypeMotif for details. The two motif models are also compared there.
Functor
Import
- FD
- Combinator
- 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"
Export
Define
[concrete class] a data abstraction which encapsulates the two databases in the two attributes motifDescriptionDB and motifVariationDB. An instance of this class is required by MotifMixin, initMotifMixin
.
A motif database is a list of arbitrary values. Example:
[motif(pitchContour:[1 1 0] comment:beethovensFifth)
motif(pitchContour:[2 0 1] comment:test)]
The format of all motif entries should be uniform. The motif database is used by the procedures defined in the motif constraints database.
NB: In case the motif database gets determined only during search, it is important that all variables have only local scope in the constraint script and consequently the database instance as well is local in the constraint script.
The motif constraint database is a list of binary procedures. The first motifVariation argument is always the constrained motif and the second argument is a 0/1-integer which states whether the constraint is applied or not (arbitrary constraints can be turned into reified constraints with the help of Combinator.'reify').
class Database
feat !DatabaseType
- init(motifDescriptionDB:MDs motifVariationDB:MVs)
- getMotifDescriptionDB(X)
- getMotifVariationDB(X)
end
fun{IsDatabase X}
class MotifMixin
feat !MotifType
- initMotifMixin(database:DB motifIdentity:MI motifVariation:MV)
- getMotifIdentity(X)
- getMotifIdentityParameter(X)
- getMotifVariation(X)
- getMotifVariationParameter(X)
- getDB(X)
- getMotifDescriptionDB(X)
- getMotifVariationDB(X)
end
class Sequential from Score.sequential MotifMixin
feat label
- init(...)
- getInitInfo($ ...)
end
class Simultaneous from Score.simultaneous MotifMixin
feat simMotif
- init(...)
- getInitInfo($ ...)
end
fun{IsMotif X}
fun{IsInMotif X Test}
Is X contained in a motif (directly or indirectly) and Test is true? Test is a boolean binary function fun {$ X MyMotif} end.
fun{MakeVariation Decl}
MakeVariation simplifies the definition of a motif variation procedure, while at the same time also somewhat restricting the description format given to the MotifDescriptionDB. MakeVariation expects a declarations and returns a variation procedure (expecting a motif instance and a 0/1-variable). Decl is a record, where each record feature is also a feature in the MotifDescriptionDB. Each record field value is an accessor function or method expecting a motif instance and returning a list of FD integers which corresponds with this feature (this returned list is unified with the database list at the corresponding feature).
The required motif description format (given to the MotifDescriptionDB) is as follows. Each motif description is a record with descriptive record features (e.g. durations, pitches, pitchContour). The values at these features are lists of FD integers. Entries in the MotifDescriptionDB must be uniform: they have the same features, and lists at the same MotifDescriptionDB feature have the same length.
Exception: MotifDescriptionDB entries may omit features altogether (i.e. entries can effectively differ in the set of features), but in case a feature is present then its value must be a list with same length as in other entries at this feature.
Exception: Decl can omit features, i.e. different variation functions can constrain different sets of features.
See Motif/testing/Motif-test.oz for usage examples.
NB: there can be undetermined FD ints in the solution in case motif specs in MotifDescriptionDB may differ in their set of features.
End