-- Back --


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.

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

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) 


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:
... 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:


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 "!"

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:

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
B ! C
...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
... 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 = 
... 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 INCLUDEs 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:
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(5 TIMES AA3)


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)
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.


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:
~APoint =POINT
The main interest of this feature is the fact that you can access relative positions around the pointer with the following statements: so that for example:
... is equivalent to
D3 ! B3 ! CC3 ! CC2

another example:
... this is the same as:
D3 ! DD3 ! E3 ! EE3 ! F3
(in this example the pointer is eventually set to "F3")

more sophisticated:
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)
I hope this demonstrates clearly enough how complex gestures can be defined and used.

-- Back --