Index
Strasheela
Init
GUtils
LUtils
MUtils
Score
SMapping
SDistro
Out
Strasheela
FD_edited
Midi
The functor defines the core for a music score data structure of Strasheela.

Certain classes in the hierarchy are marked as [abstract class]. These classes should not be instantiated. Other classes are marked as [semi abstract class]. These classes are generic data types which may be instantiated. However, the user is encouraged to define more specific subclasses of these. Classes marked as [concrete class] may be freely instantiated, of course the user may define subclasses of them too.

Syntactic conventions:
If a method returns a value, the return value is the first argument.

Simple methods to access class attributes and for type checking are only documented here in a generic way.

{New <Class> init(<Arguments>)} is the constructor method for the class Class with certain initial arguments. In practice, New is hardly used and MakeScore is applied instead.
{O is<Class>(?B)} is a type checking method. Is the object O an instance of class Class (respectively of a subclass of Class) or not? B is bound to a boolean.
{O get<AttributeOrFeature>(X)} is an access method which binds X to the logic variable bound to AttributeOrFeature of object O. Special getter methods are defined for parameters and parameter values. {O get<ParameterName>(X)} returns the parameter value of ParameterName, {O get<ParameterName>Parameter(X)} (i.e. with a 'Parameter' after the actual parameter name) returns the parameter data object itself, and {O get<ParameterName>Unit(X)} returns the parameter data object unit.
{O set<AttributeOrFeature>(X)} is a writer method which binds the AttributeOrFeature of object O destructively to a fresh logic variable and initializes it with X.

Functor

Import

Export

Define

[class info]

[abstract class] The most general data type for score data is a ScoreObject.

The feature label binds an atom naming the class. The attribute info can be used for arbitrary user information.

class ScoreObject from NonType Reflection
   feat !ScoreObjectType label end

[class info]

[abstract class] An auxiliary top level class of the score data type hierarchy to inherit all typ-checking methods to all subclasses.

class NonType end

[class info]

[abstract class] Defines reflection capabilities for objects. Please note: this class uses undocumented Oz features, which are possibly not intended for end users ;-)

class Reflection end

[class info]

[semi abstract class] Musical parameters are the basic magnitudes in a music representation; examples are the parameters duration, amplitude and pitch, which add information to a note. A parameter is represented by an own class (i.e. not just as a feature/attribute of a score item, as in most other composition environments) to allow the expression of additional information on the parameter besides the actual parameter value. For instance, a single numeric value for a pitch is ambitious, it could express a frequency, a MIDI-keynumber, MIDI-cents, a scale degree etc. Therefore, a parameter allows to specify the unit of measurement explicitly.
The parameter attributes value and 'unit' specify the parameter setting and the unit of measurement. The attribute item points to the score item the parameter belongs to.
PS: The attribute 'unit' is mainly used for output.

class Parameter from ScoreObject
   feat label end

[class info]

class TimeParameter from Parameter
   feat label end

[class info]

[concrete class]

class TimePoint from TimeParameter
   feat label end

[class info]

[concrete class]

class TimeInterval from TimeParameter
   feat label end

[class info]

[concrete class]

class Amplitude from Parameter
   feat label end

[class info]

[concrete class]

class Pitch from Parameter
   feat label end

[class info]

Free parameter values are by default turned into FD ints during the score initialisation (with InitScore). In contrast, parameters which inherit from this mixin are left untouched (i.e. if their value is a free variable, it remains free during initialisation). This can be useful, for example, if parameter values are potentially non-integers (e.g., floats).

NOTE: uninitialised parameters will cause problems for the score distribution -- better exclude them from the distribution.

class LeaveUninitialisedParameterMixin
   feat !LeaveUninitialisedParameterMixinType end

fun{IsLeaveUninitialisedParameter X}
Returns true if X inherits from LeaveUninitialisedParameterMixin (or is an instance of LeaveUninitialisedParameterMixin), and false otherwise.


[class info]

[abstract class] An item is a generalization of score containers and elements. An item can be contained in one or more containers, the feature containers points to them.

class Item from ScoreObject SMapping.mappingMixin
   feat label end

[class info]

[abstract class] A container contains one or more score items. A container is a generalization of a score aspect and a score modifier. The attribute items points to the items contained in a container. Because containers themself are items as well, a container can contain other containers to form a score hierarchy of containers and elements. However, a container must not contain itself.

class Container from Item
   feat label end

[class info]

[semi abstract class] A Modifier contains one or more items and modifies them [their meaning? / modifies them when the score is output?] in some way. Conventional examples for modifiers in common music notation are the repetition sign, staccato sign, trill sign etc., which modify the music they belong to. Subclasses of Modifier can define all these signs of common music notation. The attribute items points to the music the modifier belong to.

However, even the modification itself the modifier applies to music (i.e. the meaning of the modifier) can be expressed directly in an instance of the class Modifier. The actual modification is defined as a unary function. When the score is output, the function will be called with the value bound to the attribute items. That way, arbitrary modifications can be defined. Examples include modifications of contained temporal attributes or other parameters by envelopes: ritardando, crescendo etc.

The attribute modifier binds the modification function.

!! NB: currently, the score output functions (see ./Output.oz) ignore the Modifier which is therefore without effect!

class Modifier from Container
   feat label end

[class info]

[semi abstract class] An aspect contains one or more score items to group them and to provide additional information to its items. For instance, a sequential groups items and imposes them in a sequential order in time.

class Aspect from Container
   feat label end

[class info]

[abstract class] A TemporalAspect is an aspect which contains timing related attributes and understands timing related methods. A TemporalAspect is a generalisation of a Sequential and a Simultaneous, which both impose timing information to the items they contain.
For a documentation of the time related attributes/parameters see doc of TimeMixin.

class TemporalAspect from Aspect TimeMixin
   feat label end

[class info]

[abstract class] The TimeMixin adds several timing attributes and methods to its subclasses.

The attributes startTime and endTime are absolute TimePoints. The attribute offsetTime is a relative TimeInterval to the startTime of the TemporalAspect an Item is contained in. The attribute duration is the TimeInterval difference of startTime and endTime.

The TimeUnit specifies what the numeric values for the TimeMixin attributes actually mean. The TimeUnit either specifies an absolute value (e.g. seconds) or a relative value (e.g. beats). The meaning of beat depends on the output definition, for instance, for the Lilypond output a beat is a quarter note. Currently, possible values are 'seconds' (or 'secs'), 'milliseconds' (or 'msecs'), 'beats', or beats(N), where N means number of ticks (i.e. the integer range) within a beat. For example, if the TimeUnit = beats(4) and a beat corresponds to a quarter note, then a note of duration 1 corresponds to a sixteenth note. beats is equivalent with beats(1). The meaning of a beat for sound output can be specified by the tempo (see Init.setBeatDuration, Init.setTempo etc.)
NB: to avoid confusion, the time units of all temporal items in the score are unified when a Strasheela score is initialised.
NB: A negative offsetTime value is not possible if the offsetTime is a FD integer (which presently is the only option). For the other temporal parameters, a negative value does not make sense anyway.

class TimeMixin
   feat label end

[class info]

[concrete class] A Sequential expresses that the items contained in it follow each other in a sequential manner in time. Usually, the parameter endTime of a proceeding item equals the parameter startTime of the following item. However, setting the parameter offsetTime of an item to a value greater zero causes a gap (i.e. a pause) before the item and a negative offsetTime causes an overlap with the proceeding item.
For a documentation of the time unit see doc of TimeMixin.
NB: A negative offsetTime value is not possible if the offsetTime is a FD integer (which presently is the only option).

class Sequential from TemporalAspect
   feat label end

[class info]

[concrete class] A Simultaneous expresses that the items contained in it start at the same time. However, setting the parameter offsetTime of an item to a value greater zero causes this item to delay its startTime the amount of offsetTime.
For a documentation of the time unit see doc of TimeMixin.

class Simultaneous from TemporalAspect
   feat label end

[class info]

[abstract class] An element is a score item which does not contain items. For instance, a note and a pause (rest) are both elements.

class Element from Item
   feat label end

[class info]

[semi abstract class] An AbstractElement is an element without timing information. For instance, an instrument definition for a sound synthesis language such as Csound could be represented by an instance of a subclass of AbstractElement.

class AbstractElement from Element
   feat label end

[class info]

[abstract class] A TemporalElement is an element with timing information. For instance, any action of a performer is a TemporalElement -- whether the action is heard or not. An unheard action can a change of the instrument (as muting it) is a TemporalElement, a heard action the performance of a note.

class TemporalElement from Element TimeMixin
   feat label end

[class info]

[concrete class] A pause (a better name would be rest!) is a score element to produce silence of a given duration. It can, e.g., be used within a sequential to produce an offset between two items in the sequential. However, in such situation a pause (rest) could be replaced by the use of the parameter offsetTime of the item after the pause. Nevertheless, a pause in an explicite representation.
For a documentation of the time unit see doc of TimeMixin.

class Pause from TemporalElement
   feat label end

[class info]

[semi abstract class or concrete class?] An event is a score element which produces sound when the score is played. An event is a very general representation for something producing sound. For instance, a note played on a piano (with a specific pitch, loudness etc.), a hand clapping (no pitch, but maybe a specific loudness), or an arbitrary sound synthesis language event (possibly with dozends of parameters) are all representable be an event.

To provide such generality, an event has the attribute parameters which points to a collection [better term?] of all parameters of the event. The parameters themself contain information about their purpose (e.g. parameters are of a certain class as pitch, or amplitude). However, as a convenience, certain parameters are additionally referenced by an extra feature (e.g. all timing related parameters have their own feature, as startTime, offsetTime, endTime or duration). Subclasses of the event class may define additional features. Nevertheless, all parameters can be accessed via the parameters feature

An event always has the timing parameters startTime, duration, endTime, and offsetTime. However, additional parameters can be specified optionally (e.g. by the feature addParameters of the init method).
For a documentation of the time unit see doc of TimeMixin.

class Event from TemporalElement
   feat label end

[class info]

[concrete class] A note is an score event with explicit attributes for the parameter pitch.
A note inherits various timing parameters from the event class. The full set of non-optional note parameters (i.e. parameters which are not only bound to the attribute parameters, but which have extra attributes) is startTime, duration, endTime, offsetTime}, and pitch. Additional parameters can be specified optionally (e.g. by the feature addParameters of the init method).

class Note2 from Event
   feat label end

[class info]

[concrete class] Extends class Note2 by parameter amplitude. These two classes exist because an amplitude is usually needed if a sound synthesis format is output but may not be needed if only a music notation format is output.
NOTE: unlike most other arguments, the amplitude argument defaults to a determined number.

class Note from Note2
   feat label end

fun{IsScoreObject X}
Returns a boolean whether X is an Object with the class/superclass ScoreObject.


fun{IsTemporalItem X}
Returns a boolean whether X is an item which inherits from TimeMixin (i.e. X is either a TemporalElement or a TemporalAspect).

fun{IsTemporalContainer X}
Returns a boolean whether X is a container which inherits from TimeMixin. This is an alias type check whether X is a TemporalAspect.

proc{MakeScore ScoreSpec Constructors X}
MakeScore returns an object-oriented hierarchic score representation according to a record-based score representation in ScoreSpec. In general, MakeScore transforms (possibly nested) class init records into (nested) class instances with bi-directional links (e.g. links from the container to the contained item and vice-versa). The label of each init record specifies its class, e.g.,
{Score.makeScore note(startTime:0) unit}}

The argument Constructors allows to specify additional or alternative classes or arbitrary unary constructor functions. Constructors is a record with either the label unit or add, where the label unit means overwrite all defaults and add allows you to add classes/constructures to the defaults. Features of Constructors correspond to the labels of score object specifications in ScoreSpec. For example, the following expression returns an instance of the class MyNote.
{Score.makeScore note(startTime:0) unit(note:MyNote)}}

A nested score hierarchy is expressed by specifying further init record lists at the feature items or containers, e.g.,
{Score.makeScore seq(items:[note note] startTime:0) unit}}
As a shorthand notation, the feature 1 can be used instead of items, e.g.,
{Score.makeScore seq([note note] startTime:0) unit}}

Score objects can be marked with an id. Score graphs can be formulated by referring to the same score object with the same id multiple times
{Score.makeScore sim(items:[note(containers:[aspect(id:1 info:test)]
duration:1)
note(containers:[aspect(id:1)]
duration:2)])
unit}


To express a more complex graph, ScoreSpec can also be a list of nested init records with shared ids, e.g.,
{Score.makeScore [aspect(id:1 info:bla)
aspect(items:[note(info:x containers:[aspect(id:1)])
note(info:y)])]
unit}


However, references using ids must not be recursive (e.g. within the declaration of a container with an id must be not references to that id).

A recommended alternative to formulate score graphs is to use multiple MakeScore2 calls which are combined (using bilinkItems or bilinkContainers) and only then fully initialised using InitScore).

Internally, MakeScore uses the init method of each class and all arguments the respective init method understands are supported by MakeScore. However, MakeScore performs also additional initialisation. This initialisation includes establishing inter-class instance relations correctly, closing the score hierarchy (which binds the tails of all slots items, containers and parameters for all items to nil), initialising all parameter values to FD variables, imposing timing constraints on all time mixings, and unifying all time units.

An already instatiated score object (created with Score.makeScore2, i.e. with an unclosed hierarchy) can be specified at any place an score object record (label representing object class and features init method arguments) is possible.

It is strongly recommended to use MakeScore to create a score instead of using the init method of the score classes directly, because MakeScore encapulates all necessary low-level details of the score representation.


proc{MakeScore2 ScoreSpec Constructors X}
MakeScore2 is a variant of MakeScore with the same arguments and the same functionality. However, the implicit initialisation of MakeScore2 is unfinished, such that the returned score hierarchy can still be extended (use the method bilinkItems or bilinkContainers to combine multiple score hierarchy parts created with MakeScore2). After the extention of the score, the score must be fully initialised (using InitScore). See strasheela/testing/ScoreCore-test.oz for an example.


proc{CopyScore MyScore MyCopy}
CopyScore returns a deep copy of MyScore. The resulting MyCopy has the same score topology and its objects are created from the same classes as MyScore. However, undetermined variables in MyScore are replaced by fresh variables with the same domain.
NB: CopyScore internally uses toInitRecord. Therefore, all present restrictions of toInitRecord apply: getInitInfo must be defined correctly for all classes and only tree-form score topologies are supported.
!!! NB: if the output of toInitRecord contains stateful data, then this data is not copied but used as is (i.e. such stateful data is shared between the copies).


fun{CopyScore2 MyScore}
Like CopyScore, but MyScore is not fully initialised (cf. MakeScore2 vs. MakeScore).


proc{InitScore X}
InitScore is an auxilary procedure to finish the initialisation of score hierarchies created by MakeScore2 and combined by the method bilinkItems or bilinkContainers. Using InitScore directly on the result of MakeScore2 is the same as generating a score by MakeScore.


proc{TransformScore MyScore Args TransformedScore}
TransformScore returns a transformed copy of MyScore.

The following optional arguments are supports via Args.
'clauses': a list of pairs TestI#FunI. TestI is a Boolean function or method, and FunI is a unary function expecting a score object and returning either a textual score object specification (a record), or a score object (which must not be fully initialised). For each object for which some TestI returns true, the corresponding FunI will be used for creating a score object which will replace the original object.
'constructors': the contructors used for creating the transformed score from a textual score (cf. MakeScore). Default are the classes of MyScore: {MyScore getInitClasses($)}, plus the default constructors.

Note that TransformScore does not support recursive transformations. For example, if you change the content of a container during a transformation, this new content will not be recursively processed (but you could explicitly call TransformScore again with the resulting score).

NB: CopyScore internally uses toInitRecord. Therefore, all present restrictions of toInitRecord apply: getInitInfo must be defined correctly for all classes and only tree-form score topologies are supported.


fun{TransformScore2 MyScore Args}
Like TransformScore, but the resulting score is not fully initialised (cf. MakeScore2 vs. MakeScore).


fun{MakeConstructor Constructor Defaults}
Returns a score item constructor function with interface {F Args} which creates essentially the same item as Constructor (unary function or class), but uses the default arguments Defaults (record of init arguments). Defaults and Args can be nested records, in which case nested default specs are not overwritten if Args specifies same higher-level arg (i.e. Default and Arg are combined with GUtils.recursiveAdjoin instead of just Adjoin). The item returned by the constructor is not fully initialised.
In addition, the resulting constructor function supports convenience notations for certain values. The following notations are supported (both as default arguments and as actual arguments).
fn # MyFun: the actual value is returned by the function MyFun (remember that handing undetermined variables to constructors is only possible if the constructor call is wrapped in the script or some other procedure; otherwise the search blocks).
fd # DomSpec: DomSpec is the specification expected by FD.int.

Example
{Score.makeConstructor Score.note
unit(pitch: fd#(60#72)
duration: fn#fun {$} {FD.int 1#10} end)}


proc{MakeItems Args Elements}
Extended script which returns a list of 'n' score items (e.g., notes), where many parameters can be still undetermined, and the objects are not fully initialised.

Args:
'n': number of items
'constructor': creator class or function for items
'handle': argument to access the resulting list of items (convenient when MakeItems is used in a nested data structure, cf. ScoreObject init method arg handle)
'rule': constraint (unary proc) applied to list of all items

In addition, all item arguments expected by 'constructors' are supported. If not specially marked, these arguments are shared by all parameters.

For specifying individual arguments for the elements, the following special cases are supported. These cases are notated as a pair Label # ArgValue. The following labels are supported.
fd#Spec: each parameter value has the given domain specification Spec. Example:
unit(pitch: fd#(60#72))
each#Xs: Xs is a list of length 'n' and specifies argument values for the individual elements. Example for specifying individual note pitches:
unit(pitch: each#[60 62 64])
fenv#MyFenv: MyFenv is a Fenv. Argument values for the individual elements are obtained by sampling the Fenv (method toList), and converting the results to integers.


Default Args:
unit(n: 1
constructor: Score.note)

NB: constructor must not expect any of the args expected by MakeItems (n, constructor, handle, rule), as these are affected by MakeItems. This fact limits the recursive use of MakeItems (where the constructor is created by MakeItems).



fun{MakeItems_iargs Args}
Same as Score.makeItems, but all Score.makeItems arguments are wrapped in arg iargs for compatibility with DefSubscript.
Note: arg processing (each-args etc) only supported for iargs, but not rarg, and also not for iargs.n. The reason is that only a single value of these args is needed for items creation (e.g., only one iargs.n is needed).


proc{MakeContainer Args MyMotif}
Extended script which returns a container with items, not fully initialised and where many parameters can be still undetermined. The contained elements are created with Score.makeItems.

Args:
'constructor': the container constructor (class or function)
'iargs': arguments for the creation of container items, a record of args in the format expected by Score.makeItems
Any other container argument is supported as well.

Default Args:
unit(iargs:unit
constructor: Sequential)


fun{MakeSim Args}
Extended script which returns a simultaneous container with items, not fully initialised and where many parameters can be still undetermined. Specialisation of MakeContainer where the constructor is Simultaneous. See MakeContainer for further information.


fun{MakeSeq Args}
Extended script which returns a sequential container with items, not fully initialised and where many parameters can be still undetermined. Specialisation of MakeContainer where the constructor is Sequential. See MakeContainer for further information.


fun{DefSubscript DefArgs Body}
Extended script creator for reusable (and hierarchical) sub-CSP definition: returns an extended script (a procedure with the interface {Script Args ?MyScore}) which specialises a "super" extended script. The super-script returns either an item (typically a container with items) or a list of items; possible super-scripts are, e.g., Score.makeItems_iargs, MakeContainer or any user-defined extended script, possibly also created with DefSubscript. The resulting score object(s) are not fully initialised, and can thus be integrated withing a higher-level container.

DefArgs is a record of optional arguments for declaring the super-script and the default arguments of the resulting script.

DefArgs:
'super': the super-script: a procedure with the interface {Script Args ?MyScore} where Args must support the argument 'iargs', and can support any other argument as well. 'iargs' is a record of args in the format expected by Score.makeItems.
'mixins': a list of mixins defined with DefMixinSubscript.
'defaults': record of default top-level argument values for resulting script.
'idefaults': record of default argument values for args feature 'iargs' of resulting script (idefaults = itemsDefaults).
'rdefaults': record of default argument values for args feature 'rargs' of resulting script (rdefaults = rulesDefaults).

Default DefArgs:
unit(super:MakeContainer
mixins: nil
defaults: unit
idefaults: unit
rdefaults: unit)

Body is a procedure with the interface {Body MyScore Args}, where MyScore is the item(s) created by the super-script, and Args is the record of the arguments specified for the resulting script. Body can also be nil (e.g. for combining a super script and a mixin without adding any further constraints). The features of Args are both the arguments supported by the resulting extended script, and the Args expected by body.

Args always has the features 'iargs' and 'rargs'.
'iargs': a record of arguments given to contained items in the format expected by Score.makeItems (iargs = itemsArgs)
'rargs': record of arguments for constraints (rargs = rulesArgs)

The variable Args of the body only contains the following arguments when they where specified with the extended script application.
'super': same as for DefArgs
'mixins': same as for DefArgs
In addition, Args can contain any init argument expected by the MyScore's top-level ("super" CSP creates a container).

More specifically, Args contains the arguments provided when calling the resulting script plus the default values of omitted arguments specified with 'defaults', 'idefaults' and 'rdefaults' for this specific script. Default arguments specified for any super-script are absent from Args, if you need the defaults of the super-script in Body, declare them again for this script.


Example:
Motif definition: creates CSP with sequential container of notes (MakeContainer is super CSP), default are 3 notes (idefaults.n is 3, i.e., the default value for iargs.n is 3). Note pitches are constrained with Pattern.continuous, the direction of this pattern is controlled with the argument rargs.direction, default is '<:'.
MakeRun
= {DefSubscript unit(super:MakeContainer
rdefaults: unit(direction: '<:')
idefaults: unit(n:3))
proc {$ MyScore Args} % body
{Pattern.continuous {MyScore mapItems($ getPitch)}
Args.rargs.direction}
end}
Motif application (MyScore is not fully initialised, see MakeContainer)
MyScore
= {MakeRun
unit(iargs:unit(%% number of notes (overwrites default 3)
n: 2
all notes of same duration 2 (see Score.makeItems for other format options)
duration:2)
decreasing pitches (overwrites default '<:')
rargs:unit(direction:'>:')
argument to top-level container
startTime:0)}

For testing purposes, you can call these definitions outside any top-level script and look at the result with the following lines
{Score.init MyScore}

then do
{Browse {MyScore toInitRecord($)}}



fun{DefMixinSubscript DefArgs Body}
[Complements DefSubscript]: defines further arguments and applies further constraints to a script defined by DefSubscript.

Args:
'super' (default GUtils.unarySkip): an optional super-mixin.
'rdefaults': same as for DefSubscript.

'idefaults' and 'defaults' are ignored: Note that defining default values for score object initialisation arguments is not supported for mixin scripts (defined values are ignored by the score object initialisation).

Body: same as for DefSubscript.

Example:
Motif definition where the pitch structure is defined with DefSubscript, and the rythmic structure by a mixin subscipt.
MakeDottedRhythm
= {DefMixinSubscript unit(rdefaults: unit(shortDur: 1))
proc {$ MyScore Args} % mixin body
Durs = {MyScore mapItems($ getDuration)}
Durs length must be at least 2
[Dur1 Dur2] = {List.take Durs 2}
in
Dur1 =: Dur2 * 3
Dur2 = Args.rargs.shortDur
{Pattern.cycle Durs 2}
end}
MakeContinuousNotes
= {DefSubscript unit(super:MakeContainer
rdefaults: unit(direction: '<:')
idefaults: unit(n:3))
proc {$ MyScore Args} % subscript body
{Pattern.continuous {MyScore mapItems($ getPitch)}
Args.rargs.direction}
end}
MakeMyMotif
= {DefSubscript unit(super: MakeContinuousNotes
mixins: [MakeDottedRhythm])
nil}
Motif application (MyScore is not fully initialised, see MakeContainer)
MyScore
= {MakeMyMotif
unit(iargs:unit(%% number of notes (overwrites default 3)
n: 4)
decreasing pitches (overwrites default '<:')
rargs:unit(direction:'>:'
shortDur: 2)
argument to top-level container
startTime:0)}

For testing purposes, you can call these definitions outside any top-level script and look at the result with the following lines
{Score.init MyScore}

then do
{Browse {MyScore toInitRecord($)}}


fun{ItemslistToContainerSubscript Subscript ContainerLabel}
Expects a subscript which returns a list of items, and returns a variant of this subscript which wraps a container around this items list. The subscript arguments iargs and rargs are handed to the Subscript (usually created with Score.defSubscript), all other subscript arguments are given to the container. ContainerLabel is a label such as seq or sim.
Purpose of this function: simplifies creation (& avoids code doubling) of two variants of a subscript, e.g., one returning plain list of notes (defined with DefSubscript), and one wrapping these notes in a container (defined with ItemslistToContainerSubscript from existing script).


fun{MakeClass Super FeatT Args}
MakeClass returns a subclass of the (score object) class Super. FeatT is a tuple with the additional subclass features, the label of FeatT defines the value at the feature 'label' of the new class. Args supports optional arguments, the defaults are:
unit(initRecord:init
init:proc {$ Self Args} skip end)
Args.initRecord specifies additional arguments for the init method of the class and optionally their default value. For instance, init(x:1 y) defines the two additional arguments x and y and the default value 1 for x.
Args.init defines a binary procedure which is called at the end of the initialisation of a class instance. The two arguments Self and Args are the initialised object and the record of initialisation arguments (i.e. for each Args feature either the specified default or the value handed the the init method).

NB: MakeClass allows only to define additional features (i.e. no attributes) [NB: this behaviour is inconsistent with other class definitions in Strasheela. Nonetheless, that way feature accessors are defined implicitly].

NB: Classes generated by MakeClass will not be documented automatically by ozh.

Example: define a note subclass with an additional parameter foo (init method arg foo defaults to 0):
{MakeClass Score.note
newNote(foo fooParameter)
unit(initRecord:newNote(foo:0)
init:proc {$ Self Args}
Self.fooParameter = {New Score.parameter init(value:Args.foo info:foo)}
Self.foo = {Self.fooParameter getValue($)}
{Self bilinkParameters([Self.fooParameter])}
end)}


proc{Apply_Heuristic H_Constraint Params Weight}
Applies a heuristic constraint (H_Constraint) to a list of parameter objects (Params) with a cetain weight Weight.

Heuristic constraints restrict the result of a CSP (as strict constraints do), but the expressed constraint is only used as a guidance during the search process that can be violated if it contradicts some strict constraint. More specifically, heuristic constraints are used to quasi sort the domain values of variables before deciding which domain value to try out first (dynamic value ordering).

Heuristic constraints are functions that expect n integers (*not* FD variables; FD int domain values) and return an integer. The result indicates how well the constraint is met by the input integers: the larger the number the better. A heuristic constraint is used to judge the quality of individual domain values. In a heuristic search (i.e. heuristic value ordering) the domain value with the highest quality according to all its applied heuristic constraints is selected.
The returned qualities should cover the interval [0, 100], so that the importance of all heuristic constraints is considered equally. Nevertheless, larger or even negative results are possible as well.
The weight of a constraint is a factor (int) that is applied to its returned quality and thus affects its importance.

The application of heuristic constraints is strait forward and very similar to the application of strict constraints except for a formal difference. Strict constraints are applied directly to parameter values (i.e. variables). For example, The constraint C is applied to the pitch parameter value of the note N with the following code.
{C {N getPitch($)}}
Instead, heuristic constraints are applied to the score object parameters using Score.apply_H. The heuristic constraint HC is applied to the pitch parameter of the note N with the following code.
{Score.apply_H HC {N getPitchParameter($)} 1}
More generally, parameter objects are accessed with methods like getFooParameter, where Foo is the name of the parameter.

NOTE: When heuristic constraints have been applied, the value ordering of the solver (distribution feature 'value') must be set to 'heuristic'.

NOTE: Heuristic only used if all but last variables involved are already bound. So, for heuristics with more than 2 variables involved there could additionally be "partial heuristics" that define related heuristics for less variables.

For an example, see strasheela/examples/Heuristic-Constraints.oz.


proc{AtTimeR X Time B}
[0/1 Constraint] Returns 0/1-integer whether Time (FD int) is between the start and end time of X (an temporal item), including its start but note the end time.


proc{AtTimeR2 X Time B}
[0/1 Constraint] Same as AtTimeR, but the time frame of X takes also the potential rest introduced by its offset time into account.


fun{InTimeframe X Start End}
[Deterministic function] Returns boolean whether (some part of) the item X is in the time frame specified by Start and End (ints).
This relation defines a conjunction of the following Allen's Interval Algebra relations: overlaps, starts, during, finishes and equal; only meets and before/after are excluded.


fun{InTimeframeOffset X Start End Offset}
[Deterministic function] Varian of InTimeframe where the offset time Offset (an int) is taken into account. It returns true if the item X would be in the time frame specified by Start and End, if these times would be moved by this offset time.


fun{InTimeframeR X Start End}
[0/1 Constraint] Returns 0/1-integer whether (some part of) the item X is in the time frame specified by Start and End (FD ints).
This relation defines a conjunction of the following Allen's Interval Algebra relations: overlaps, starts, during, finishes and equal; only meets and before/after are excluded.


fun{InTimeframeOffsetR X Start End Offset}
[0/1 Constraint] Varian of InTimeframeR where the offset time Offset (FD int) is taken into account. It returns true (1) if the item X would be in the time frame specified by Start and End, if these times would be moved by this offset time.


proc{GetItemsInTimeframe Xs Start End Args Result}
[Deterministic function] Returns list of score items in Xs (a list of items) in the time frame specified by Start and End (FD ints) -- see doc of InTimeframe -- and fulfilling the optional Boolean function or method test.
The implementation uses LUtils.cFilter and the reified constraint InTimeframeR. Items are returned as soon as the score contains enough information for all score objects in the score to tell whether or not they are simultaneous to self (i.e. rhythmic structure of the whole score must not necessarily be fully determined).

Args:
test (unary Boolean function or method): Only items for which this test returns true are collected. This function must be a deterministic function/method which does not block (e.g., checks on score object types or their position in the score topology are OK) and which is used for pre-filtering score objects.
cTest (unary Boolean function or method): Only items for which this test returns true are collected. The argument cTest is applied within the concurrent filtering of LUtils.cFilter, together with InTimeframeR. Computationally very expensive tests and in particular tests which can block are better handed to cTest.


proc{GetItemsInTimeframeOffset Xs Start End Offset Args Result}
[Deterministic function] Generalised version of GetItemsInTimeframe where the offset time Offset (FD int) is taken into account. See the doc of InTimeframeOffsetR for the meaning of the Offset.


End