GeoMaestro
Batteur
L = Batteur(name, program, ...)
name, program: strings
This is a very complex projector, whose code is located in lib/proj_batteur.k ; check here for an example composition.
Basically, it is a set-up defining a 2-dimensional drum machine (or sequencer) driven by an external program file. Each instance of the projector has a name and must be initialized before the projector can be called.
Initialisation:
InitBatteur(name, C, period)
... defines a Batteur named name, centered in point C and whose period is period (in clicks)
When defined, a bunch of green reference lines will appear in the background of the graphic area, as you can see in the above picture. You can toggle this display on and off with the command
TogBatt(name)
Reference points can be displayed using the function BattRing():
BattRing(name) # displays all points (see above picture)
BattRing(name, ring) # displays all points in a given ring (ring = 1, 2 or 3)
Principle:
The first ring has a diameter of period; in the second and third rings, consecutive points are separated by a distance period. The purpose of this set-up is to be able to easily call Arc() projections of same length (the period, or beat), all of them looking at the first circle from different point of view.
First of all, let's see the names of the reference points:
(the points in the inner (first) ring range from A to P)
It is important to notice that these are dummy names, used for programming the Batteur. The actual names of these points start with the Batteur name (HH3 is really TotoHH3 in our example). So if you had already something called HH3 in KeyKit, don't worry as it will not be erased (TotoHH3 would).
The program is a file whose name (including its path) must be stored in the string variable program
For example, let's say
TestProg = DATA+"TestProg.txt"
... we can now edit the Batteur program in a text file named TestProg.txt, located in the GeoMaestro /data directory.
Let's edit this file, simply typing the 3 lines:
HH3
B2
K
... which are point names, as you can see in the above picture.
Now if we call Batteur:
BAT = "Toto" # giving the Batteur a name (upper-case required)
InitBatteur(BAT, Or, 1) # initialisation
BattRing(BAT) # asking to see all the points
Batteur(BAT, TestProg) # projection
... here are the performed projections:
(zooming)
You can see the three arcs corresponding to the three points in the program (note that, on the first ring, an arc is always a diameter).
The program may also be explicitely given as the second string argument:
Batteur(BAT, "HH3!B2!K")
... does the same as
Batteur(BAT, TestProg)
Program format:
(an example program is listed here)
In its simplest form, a program is just a list of point names. They can be on separated lines, or in the same line: in this case the names must be separated by a "!"
example:
HH3 ! B2 ! K
(note that you are not restricted to the set of points created when initializing the Batteur: any existing point may be used in the program)
Now there are some enhancements:
- empty lines are ignored, so are comment lines (starting with "# ")
- a dot (".") instead of a point name means a silence of duration one beat.
- if a number follows a point name or a dot, it sets an alternate length for the corresponding arc (or an alternate duration for a silence)
- if this number is negative, the arc will be drawn backward
- these numbers can be formulas; you can use the keyword "_d_" to represent the beat (or period)
- "-_d_" can be replaced by a simple "-"
- macros can be defined with statements
DEFINE
and INCLUDE
- we have a few special statements:
START
, STOP
, MARK
, TIMES
, FORK
and INSERT
(see below)
- also, a pointer can be moved around in order to define relative gestures through the statements
NEXT
, PREV
, UP
and DOWN
(see below)
- the generated MIDI phrase can be post-processed using the statement FILT
special statements, macros
You can mark your program with keywords starting with a "#" (on a single line) and use these marks to set alternate starting and ending points, with the START
and STOP
statements.
For example, the following program:
START #here
STOP #there
A2 ! B2 ! C2
HH3
#here
A
B ! C
#there
H2
...will play the same as the following one:
A ! B ! C
More interestingly, START
and STOP
can also be decided from the console: if BAT
is the name of the Batteur, you can define and use two string variables named BAT+"_START"
and BAT+"_STOP"
to replace the START
and STOP
statements. In our example BAT
is "Toto"
so this is done with the following commands:
Toto_START = "#here"
Toto_STOP = "#there"
The main interest of this feature is that different projectors can then play at the same time different parts of the same program
To reuse in several instances a whole pattern, use DEFINE
to give it a name, like this:
DEFINE pattern1 A ! B ! C
DEFINE pattern2 A2 ! B2 ! C2
pattern1
pattern2
pattern1
pattern2
... which is the same as:
A ! B ! C
A2 ! B2 ! C2
A ! B ! C
A2 ! B2 ! C2
These patterns are actually macro and accepts arguments:
DEFINE dothis(X,Y,Z,=) X = ! Y = ! Z =
dothis(AA3,H2,C,0.5*_d_)
... is the same as:
AA3 0.5*_d_ ! H2 0.5*_d_ ! C 0.5*_d_
If the macro call is not the first and only statement in the program line, it must be featured between {}
, as illustrated below:
{dothis(AA3,H2,C,0.5*_d_)} ! {dothis(A3,HH2,CC2,_d_)}
DEFINE example {dothis(A,B,C,_d_)}!E!F
All DEFINE
statements from an external file can be read with an INCLUDE
statement:
INCLUDE DATA++MyMacros.txt
...will load all definitions coded in the file MyMacros.txt located in the DATA directory (here the ++
syntax is used to express a system-independant filename; you may also use plain file names). Note that INCLUDE
statements in MyMacros.txt will be ignored: only DEFINE
statements are read.
The batteur always INCLUDE
s the file BatteursMacros.txt in the DATA directory, if it exists. All macros defined in this file will be available for all Batteur()
programs. Such a file is provided in the GeoMaestro distribution: it's a good idea to have a look at the macros it defines.
The macro expansion mechanism is very basic and relies only on text replacements, so check that you are not using meaningful names or keywords as macro names and arguments.
If trouble arises, set WriteBatteurLog
to 1. This will produce one or more LogBatteur...
files in the DATA directory where you will see how the parser did expand the macros.
Simple repeatitions can be performed with the keyword TIMES
:
3 TIMES A!B!C
5 TIMES {pattern1} ! {pattern2}
You can merge arbitrary projector calls in the program with the statements FORK
and INSERT
:
FORK Ecoute(~A,~H)
INSERT Ecoute(~A,~H,°duration)
FORK
will merge the projection (it is the only way to have things happen in parallel within the program), INSERT
will insert it in the sequence (like all other statements do)
The symbol ~
is replaced by the batteur name (so that ~A
stands for the batteur-relative point A), while the keywords °duration, °t0, °region
and °df
are replaced by the corresponding arguments in the Batteur()
call: this allows for automatic scaling of the program tempo, for example.
Here is how you would have a short batteur program play in parallel with the main one:
FORK Batteur("~","A!B!C!D",°duration)
And here is how you would define a macro to do this more simply:
DEFINE forkprog(prog) FORK Batteur("~","prog",°duration,°t0,°region,°df)
forkprog(A!B!C!D)
forkprog(5 TIMES AA3)
post-processing
The statement FILT
may be used to have the generated phrase processed further. It uses the keyword _ph_
within any valid KeyKit expression returning a phrase, for example:
FILT reverse(_ph_)
FILT legato(_ph_)
FILT _ph_|transpose(_ph_,12)
FILT
The processing is in action until it is replaced by another one. FILT
used by itelf, with no following expression, cancels the current processing if there is one.
Note that this only effects the ["ph"]
field in the ligne returned by Batteur
.
marks
At any point in your program you may insert the definition for a Compositor mark, with the statement MARK
:
MARK c2 |c (@)
(see here for the syntax of mark comments)
Marks are stored in the "m" field of the resulting ligne, which is read by the Compositor.
pointer and relative motions
At the beginning of the program a pointer is set to "A". Then it permanently refers to a point in the Batteur, which you can get through the statement =POINT
and set with POINT=
, like this:
POINT= CC3
~APoint =POINT
The main interest of this feature is the fact that you can access relative positions around the pointer with the following statements:
NEXT
refers to the next point in the corresponding ring
PREV
refers to the previous point in the corresponding ring
UP
refers to the corresponding point in the upper ring, if there is one
DOWN
refers to the corresponding point in the lower ring, if there is one
so that for example:
POINT= CC3
NEXT ! PREV ! UP ! DOWN
... is equivalent to
D3 ! B3 ! CC3 ! CC2
another example:
POINT= CC3
5 TIMES NEXT ! POINT= NEXT
... this is the same as:
D3 ! DD3 ! E3 ! EE3 ! F3
(in this example the pointer is eventually set to "F3")
more sophisticated:
POINT= CC3
5 TIMES POINT= NEXT
~Tmp =POINT
INSERT CercleRythm(~CC3,~Tmp,10)
... here the first three lines are used to define a temporary point (whose name is the batteur name + "Tmp
") which is then used as second argument for the CercleRythm()
call.
As a last example, here is how the whole thing could be wrapped into a macro accepting for arguments the starting point, the number of points to be skipped in order to get the temporary point (we can also choose the direction: NEXT
or PREV
), and the number of CercleRythm()
segments:
DEFINE yo($$,%,DIR,nseg) POINT= $$ ! % TIMES POINT= DIR ! ~Tmp =POINT ! INSERT CercleRythm(~$$,~Tmp,nseg)
yo(CC3,5,NEXT,10)
yo(A2,2,PREV,15)
I hope this demonstrates clearly enough how complex gestures can be defined and used.
-- Back --