Creating spatial scenes

As presented in the title, the notion of algorithmic spatialisation is made explicit by the creation of different scenes using predefined functions, macros, processes, and actors available in the Antescofo language.

Cloud_of_points Scene

The initial process used for this demonstration is a simple 2D trajectory called ::rectilinear() which will be the basis of a scene called Cloud_of_points. It will trigger, when called, a random spatial position for each chosen sound source at once.

First, in order to achieve fixed positions in space, the vector coordinates of the line has to be null:

@proc_def rectilinear($source=1, $iniT=-1, $targeT=1, $a=0, $b=0, $alpha=0, $beta=0,$count, $speed){}

In order to produce random positions, a user-defined function generator is first implemented thanks to @random a native function of the Antescofo language :

@fun_def @rand_range($min, $max)
{
    @rand($max-$min)+$min 
}

Then implemented in the rectilinear process to control the coordinates of the line :

::rectilinear(source=1, iniT=-1, targeT=1, count=1, speed=1, alpha=0, beta=0, a=@rand_range(-1, 1), b=@rand_range(-1, 1))

Each time this process will be triggered, a random position will be applied to audio source 1 and around the listener in a maximum distance of 1 meter.

In order to produce multiple random positions of a unique source, in a certain amount of time or duration, the previous process can be imbeded in a loop construction. A loop function is afforded in the program language

loop random_points 1 { 
    ::rectilinear()
} during[4#]

This process will trigger random postions during 4 beats, related to the BPM declared at the beginning of the score. To have a better control over the duration and choose to which audio source the process is applied, this loop can also be embedded in another process to declare additional variable parameters :

@proc_def ::random_points_relative($src,$sync,$dur)
{
  loop random_points_rel $sync
  {
    ::rectilinear($src, a=@rand_range(-1, 1), b=@rand_range(-1, 1), alpha=0, beta=0, speed=$sync)
  } during[$dur#]

::random_points_relative(3, 6, 4) 

Launching this process will apply 4 random positions to source 3, with an interval of 6 beat between each position. The sync variable will link the periodicity of the loop to the overall scene in order to avoid unnecessary jumps of the source. And a during clause is used to stop the loop. Declaring the same process and setting the during clause of the loop in milliseconds - during[dur ms] - is useful for the spatialisation of an audio file, synchronised to its duration.

Accordingly, a cloud of points, with multiple sources, can be achieved by either creating a group body, that allows to gather common actions and tie them to a declared tempo :

group cloud_of_points @tempo=60
{
  ::random_points_relative(1, 1, 8)
  ::random_points_relative(2, 1, 8)
  ::random_points_relative(3, 1, 8)
  ::random_points_relative(4, 1, 8)
}
Trajectory Score Libray - Cloud of Points Scene

Figure 1 shows a capture of one state of the Cloud of Points Scene.

Or a macro definition that will allow to parameterize fragments of code by a variable name like in the following scene.

The Square Scene

This time a macro definition is used to program a square scene with controlled speed of the audio source’s movement, at each side of the square, during the trajectory. The default line process is used. The coordinates of the line and those of the vector are hard coded. The only parameter that is tweaked through the macro is the duration or speed of the movement of the source. This same duration is set for the delay between each trajectory or action of the process.

Trajectory Score Libray - Square Scene

Figure 2 shows a Square Scene.

@macro_def @square($dur1,$dur2,$dur3,$dur4)
{
    ::rectilinear(a=-1, b=1, alpha=1, beta=0, $dur1)
    $dur1 
    ::rectilinear(a=1, b=1, alpha=0, beta=-1, $dur2)
    $dur2
    ::rectilinear(a=1, b=-1, alpha=-1, beta=0,$dur3)
    $dur3
    ::rectilinear(a=-1, b=-1, alpha=0, beta=1,$dur4) 
}

Once this macro is declared, a simple call @square with the four duration parameters : @square_01(4, 1, 1, 1/4) will trigger the prepared scene. Actually, the macro definition can be stored in an external antescofo file and loaded at start time, just like the file containing the trajectory processes. This method will provide a more readable score with clear and distinct lines of code.

Spatialisation per note basis I

In the following demonstration, the previous square scene, with controlled duration of the movement of the sound source, is used for the spatialisation of a musical instrument per note basis and the synchronisation of these notes with the movement in a vey simple manner.

Let us say we have four successive quarter notes and would like the sound of each note to cross exactly, in the same duration as the note, each side of the square, surrounding the listener. The score will be then written this way :

Trajectory Score Libray - Antescofo Score

Figure 3 shows a symbolic representation converted into an Antescofo score

Where the square scene is declared right after the first note, with the trajectory duration parameter set to the same durations of the notes.

Trajectory Score Libray - Antescof2Bach

Figure 4 shows an implementation of a bachroll receiving the score from the antescofo object.

In this Antescofo or electronic score, a tempo of 60 is declared at the beginning through the BPM instance. Then two files are called, at load through the @insert function. The first file @iniT.asco.txt contains Max and Antescofo initiation commands and some user-defined functions. The second one loads the parametric mathematical functions, that are compiled at load, and the different trajectory processes that the user may use in his electronic composition. These two files are loaded when the message start is sent to the antescofo object. Then a first event is declared with the NOTE specification, which is a container of one pitch specified with the midi A#4, its duration of 1 beat - related to the. BPM above - that is a quarter note in this case. A label may be used in order to follow the score on the Max interface, which is very handy during rehearsals.

Trajectory Score Libray - Interface

Figure 5 shows the Trajectory Score Library Max interface with the printed label of the first event in the loaded score.

The square scene will be triggered as soon as the A#4 event is either played or detected by the listening machine. If ever we apply another rhythmic pattern, let’s say a triplet followed by a dotted half note, and would like to synchronise the same spatialisation scene with this musical phrase, we simply apply those rhythmic divisions to the duration parameters of the macro :

NOTE A#4 1/3 launch_square
@square(1/3, 1/3, 1/3, 3)
NOTE G5 1/3 
NOTE D#5 1/3
NOTE E5 3

Trajectory Score Libray - antescofo2bach update

Figure 6 shows an implementation of the bachroll. Object updated with the score from the antescofo object

Besides, changing the tempo of the score through the BPM instance do not request to rewrite all the durations through the score. Antescofo does the translation . It is the case for complex subdivisions or nested rhythmic patterns.

The dot notation

The reference of an instance of a process can be used to assign a variable local to a process from the outside. And then address a specific parameter of a process with the dot notation, that will transform its state after the first run :

$linear_var := ::rectilinear(src=1, count=2, speed=4) 
4
$linear_var.$speed := 16

This example will trigger a line mouvement of the audio source number 1, a trajectory that will last four beat. Once the target position achieved the source will go through the same trajectory but this time four times slower.