Actions Specifications¶
Actions are commands and computations performed by Antescofo at a certain point in time. Often, theses actions are messages sent to a MAX/PD object to trigger other activities. Other actions correspond to internal computations. Actions can be also used to specify the temporal organization of subsequent actions.
Actions can be categorized as instantaneous or durative:
-
an instantaneous action takes no time to be performed (see the Synchrony hypothesis);
-
a durative action is an action that takes times to be performed.
However, another relevant categorization is atomic or compound:
-
An atomic action performs an elementary computation or a simple message passing that cannot be decomposed.
-
A compound action groups other ‘‘child actions’’ allowing for polyphony (i.e. actions that are interleaved in time or that are are performed in parallel), loops (i.e. actions that are iterated and repeated in time), conditional actions, etc.
An atomic action is always instantaneous. Usually, a compound action takes time to be performed. Howevever, some compound actions may be instantaneous (for example, a conditional action that involves only one atomic action without delay.
Action Sequence¶
Actions always appear in sequences called groups. A group organizes the performance of its actions in time. Some groups are explicit when they are introduced with the Group construction (the fundamental compound action). Or they can be implicit:
-
as the sequence of actions that appears after a musical event,
-
as the children of other compound actions: Loop, Whenever, etc.,
-
as the body of a process,
-
as an @abort clause of a compound action,
-
as an @init clause, a @whenever clause or as the body of a method in an object.
An action within a sequence of actions:
-
Starts with an optional delay
-
is linked with the previous action through a continuation operator. They are currently three continuation operators:
-
(nothing, the two actions appears in sequence in the text) which specifies that the action that follows starts with the begining of the previous one;
-
==>
which triggers the next action with the end of the previous one; -
and
+=>
which launches the next action at the end of the previous one including its children.
-
In addition, actions have optional attributes that are specified differently depending on whether the action is atomic or compound.
A sequence of actions may also defines variables and temporal variables anywhere in the sequence. These definitions are not actions and takes no time in the computations.
A Glimpse of Syntax¶
Actions Sequence¶
Sequence of actions appear after a musical event or as the body of a compound action. They are made explicit with the notion of Group which is used to specify additional properties of the sequence (e.g. synchronization attributes).
The @local, @global and @tempovar keywords introduce variables
declaration. The local variables are local to the sequence of actions
where the declaration appears, and global variables can be accesssed
from anywhere. The keywords @local
and @global
are also attributes of an action,
see below.
Atomic Action¶
These actions are further described in chapter Atomic Actions. They are performed instantaneously.
Compound Action¶
These actions are further described in chapter Compound Actions. They act as temporal containers organizing the temporal relationships of other actions that are called child's of the container.
Action Attributes¶
Each action has some optional attributes which appear as a comma separated list:
Group G @att₁, @att₂ := value { }
atomic_action @att₁, @att₂ := value
compound_action @att₁, @att₂ := value { ... }
In this example, @att1
is an attribute limited to one keyword, and
@att2
is an attribute that requires a parameter. The parameter is given
after the optional :=
sign.
Some attributes can be used on any actions:
-
@local
and@global
attributes specify the behavior in the handling of missed events and in fastforward mode, see antescofo_is_in_rehearsal_mode. -
the @latency attribute alters the computation of delays to compensate latency.
-
synchronization attributes may alter all actions, incuding atomic ones. Most of them are useless on an atomic action, like the specification of a tempo. As a rule of thumb, the effect of synchronization attributes on an atomic action is achieved by putting this action as the sole action of a group with this attribute.
Other attributes are specific to some kind of actions. There are listed below and they are described in the section dedicated to this kind of action:
-
@abort and @exclusive are relevant only for compound actions,
-
@norec and @rec_if_alive are taken into account only on the abort atomic action,
-
@action and @grain are meaningful only for the Curve construct,
-
@immediate is relevant only for Whenever,
-
@staticscope is a qualifier for process definition,
-
@handling_int64, @handling_double and @handling_tab, are relevant only for oscsend declaration
The following diagrams gives the syntax of these attributes:
Attributes Meaningfull on All Actions
Curve Specific Attributes
@grain is a mandatory attributes but not @action.
Whenever Specific Attributes
Process Definition Specific Attributes
Abort Specific Attributes
Compound Actions Specific Attributes
Synchronization Specific Attributes
Labels¶
There is one additional attribute that can be specified for all actions:
a label. The label of a compound action usally follows the keyword
introducing the compound action. This is confusing for some compound
action like the if. However, the label can also be specified with the
@label
attribute:
action ... @label := a_label
action ... @label := "a label"
(this is the only way to give a label to an atomic action or to an
if
or a switch
).
Labels are used to refer to an action, for instance to terminate it. Like events, actions can be labeled with:
-
a simple identifier,
-
a string,
-
an integer.
There can be several labels for the same action. Unlike with event labels, the $-identifier associated to the label of an action cannot be used to refer to the relative position of this action in the score.
Delays¶
An optional specification of a delay can be given before any action A. This defines either
-
ordinary delays represent the time to wait between the previous event or action in the score and the start of the calculation of A;
-
date_delays start with a
§
and represents the time to wait between the origin of A and its computation. Date delays are internally rewritten in ordinary delays and are merely a convenience of writing.
In either case, delays can be expressed in beats (relatively of a tempo), seconds or milliseconds.
Ordinary delays¶
The countdown of the delay will start from either the beginning or the end of the previous action following the continuation operator that links the two actions. See section Continuation Operator for more information. If the action is triggered by an event, the timer countdown should start as soon as the event is recognized. For the rest of this section, we assume a default continuation: delays are counted from the start of the previous action.
Upon the expiration of the delay, we say that the action is fired (we use also the word triggered or launched). Thus, the following sequence
NOTE C2 2.0
d₁ action₁
d₂ action₂
NOTE D2 1.0
specifies that, in an ideal performance that adheres strictly to the
temporal constraint specified in the score, action₁
will be fired d₁
after the recognition of the C2
note, and action₂
will
be triggered d₂
after the firing of action₁
. That is to say,
action₂
is fired d₁ + d₂
after the recognition of C2
.
A delay can be any expression. This expression is evaluated when the
preceding event is launched. That is, expression d₂
is evaluated in
the logical instant where action₁
is computed. If the result is not a
number, an error is signaled.
Zero Delay¶
The absence of a delay is equivalent to a zero delay. A zero-delayed action is launched synchronously with the preceding action or with the recognition of its associated event. Synchronous actions are performed in the same logical instant and last zero time, cf. paragraph Logical Instant.
Negative Delay¶
The delay to wait to launch an action can be negative for three reason:
-
the value of the delay is really negative,
-
there is a latency compensation mechanism at work, see @latency,
-
or the action is launched lately because it is triggered by a missed event, see Missed Event Errors Strategie.
In this case, the action is launched immediately in late mode: global actions are launched but not local actions and the time lag is propagated to the next one, until delays becomes positive again, in which case the continuation of the actions is processed in normal mode.
For instance, in
a₀
-1 a₁
4 a₂
a₁
will be launched late, that is, right after the launch of a₀
but
a_2
will be launched in normal mode after a delay of 3 (computed as
4 + (-1)) starting from a₀
.
Absolute and Relative Delay¶
A delay can be either absolute or relative. An absolute delay is expressed in seconds (or in milliseconds) and refers to wall clock time or physical time. The qualifier (s or ms, respectively) is used to denote an absolute delay:
a₀
1 s a₁
(2*$v) ms a₂
Action a₁
occurs one second after a₀
and a₂
occurs (2 * $v) milliseconds
after a₁
. If the qualifier (s or ms) is missing, the delay is expressed in
beat and it is relative to the tempo of the enclosing group.
Evaluation of a Delay¶
In the previous example, the delay for a₂
implies a computation whose
result may depend of the date of the computation (for instance, the
variable $v
may be updated somewhere else in
parallel). So, it is important to know when the computation of a delay
occurs: it takes place when the previous action is launched, since the
launching of this action is also the start of the delay. And the delay
of the first action in a group is computed when the group is launched.
A second remark is that, once computed, the delay itself is not reevaluated until its expiration. However, the delay can be expressed in the relative tempo or relatively to a computed tempo and its mapping into the physical time is reevaluated as needed - that is, when the tempo changes.
Delay vs. Expressions. The expression used in the specification of a delay, and more generally of a duration1, must evaluate to a numeric (integer or float). There no specific type of values corresponding to a delay.
This means that 1 s
is not a value. The s
or ms
qualifier appears in the specification of a delay, but is not part of
the expression defining the duration of the delay. A consequence is
that you cannot pass 1 s
as the value of an argument
(however, you can pass 1
).
Synchronization Strategies¶
Delays can be seen as temporal relationships between actions. There are several ways, called synchronization strategies, to implement these temporal relationships at runtime.
For instance, assuming that in the first example of this section
action₂
actually occurs after the occurrence of NOTE D
, one may
count a delay of d₁ + d₂ - 2.0 starting from NOTE D
after launching
action₂
. This approach will be for instance more tightly coupled with
the stream of musical events. Synchronization strategies are discussed
in chapter Synchronization Strategies.
Date delays¶
Date delays differ from ordinary delays by starting the waiting time not from the previous action, but from the origin of the sequence of actions.
The origin of an action is the event or action that is reached by going up the sequence of previous actions, staying in the same group of actions, until reaching an action without a predecessor.
Date delays are rewritten in ordinary delays and the previous consideration on ordinary delays also apply on date delays. They are merely a convenience. Imagine for instance a sequence of actions: the first one launches a sample, and the others one open or close some effects at predetermined date in the sample. It would be painful to express the datation of these actions relatively from one to the other. It is much simpler to express their datation from the launch of the sample, that is, from the first action. It can be done with date delays:
action₁
§ d₂ action₂
§ d₃ action₃
§ d₄ action₄
_which is equivalent to
and implemented as_
action₁
d₂ action₂
(d₃ - d₂) action₃
(d₄ - (d₃ - d₂)) action₄
The §
character is an abbreviation which avoids to make explicit the
computation of the date. This computation is done internally by
Antescofo and its transparent for the user. However, this translation
must be kept in mind: for instance, synchronization strategies apply to
the ordinary delays computed from the date delays.
Ordinary delays and date delays can be mixed:
action₁
§ d₂ action₂
d₃ action₃
§ d₄ action₄
_which is equivalent to
and implemented as_
action₁
d₂ action₂
d₃ action₃
(d₄ - (d₂ + d₃)) action₄
However, it is not possible to mix absolute and relative delay if there are date delays: the delays of the actions in the involved sequence must be all absolute or all relative:
d₁ s action₁ ; ERROR: there is an absolute ordinary delay
§ d₂ action₂ ; and a relative date delay in the same sequence
d₃ action₃ ; of actions
§ d₄ s action₄
Date delays are computed and can be negative: they are then handled as explained above. Some of these computations can be done statically (if all the delays involved are constant expressions). In this case, the detection of a negative delay will raise a warning:
action₁
3 action₂
§ 1 action₃ ; the equivalent ordinary delay is (1 - 3) = -2
However, all such negative delays cannot be statically detected.
When an Action is Performed¶
We write at the beginning of this chapter that actions are performed when arriving at some date. The specification of this date is always a delay starting from some internal or external event:
-
the occurrence of a musical event (detected by the listening machine)
-
the change of a musical parameter (i.e., the tempo)
-
the start or the end of another action
-
the reception of an OSC message
-
a logical event (see the whenever construction and the chapter Patterns) triggered by an internal update (via
:=
) or an external update (via the setvar message) -
the reception of a message from the host environment (Max, PD)
-
the loading of the score (cf. @eval_when_load)
-
the sampling of a Curve
-
the launch of a process (cf. Processes) or the creation of an object (cf. Objects)
In addition, for delays and for durative actions, the passing of time depends on a temporal scope which defines a tempo, a synchronization strategy and other temporal parameters. These notions are investigated in chapter Synchronization.