-- Back --

Compositor plug-ins: reference



Click on a mark to obtain details on its position, comment and current evaluation


Click in a box and drag the mouse to set the position for a new mark. If you simply click once in the box, you can ask for a precise position by entering at the prompt a number or a KeyKit expression returning a number: if it is between 0 and 1, it will be interpreted as a relative position; if it is more than 1, it will be interpreted as an absolute time value expressed in clicks. This last option only works on evaluated boxes.


Click in a box and drag the mouse to select an interval, or just click once to select the whole box, then give a test on "N_" to define which notes in this interval will be affected a mark (the box must have been previously evaluated). A mark is always created at the starting time of the corresponding note.

For example, if you type this at the prompt:
N_.chan==2 "c2"
... a red mark will be created for each note from channel 2 in the selected area. See here for details about the comment format.

Another example:
1 "c7"
... will create a small green mark at each note starting time.


Pick and drag a mark.


Click in a box and drag the mouse to select an interval; all notes beginning there will be deleted. Optionaly, you can give an integer parameter defining which channels will be effected:


Click in a box and drag the mouse on one of the following buttons:

The six upper left buttons are different kinds of envelopes for the volume. If you select one of them, you can then click in a box and drag the mouse to select an interval: the envelope will be applied on this interval.

0 -> 1 and 0 -> 1 are fade in and fade out. The parameter x(0.5) is used to define the shape of the fade: it is the relative time value (0 to 1) within the interval for which the envelope value is 0.5: the lower it is, the faster the envelope increases or decreases. You can set this parameter with the x(0.5) button

a -> b and b -> a works the same, the values of the envelope being scaled to the interval a,b instead of 0,1; the parameters a and b can be set using the corresponding buttons. x(0.5) is now the relative time value for which the envelope value is 0.5*(a+b)

--a and -- b: here the envelope is flat, with value a or b.

When applying the envelope, you are asked for an optional channel parameter. Its format is the same as in the Prune plug-in:


Click in a box and drag the mouse horizontally to select an interval, vertically for a pitch offset value (-24 to 24, that is a four octaves range). All notes beginning in the selected interval will be transposed by the choosen amount.


Use this plug-in to apply any KeyKit function on a given interval. The first argument of the function must be a phrase: it will be the selected interval (with a channel parameter, like the Prune one)

Click in a box and drag the mouse horizontally to select an interval, then give the name of a KeyKit function and its arguments, replacing the first one by the channel parameter. For example:

transpose, -5, 30
... transpose all notes from channels different from 5 by 30

... reverse the selection (it will be played backward)

reverse 1
... reverse only the notes from channel 1


This plug-in uses Notepad, pop-up consoles or specific sub-menus to let you edit the different fields of the box you clicked in. It is a fast and powerful way to define a box behaviour.

Choose which fields to edit from the pop-up menu:

(Note that much more items may be available for specific types of box)


The "ref" field will appear as ["-->"] followed by its constituting fields:

For a (ph) box:

"ref" is divided into a field ["d"] (do not change it) and a field ["ph"]
You can put any valid KeyKit expression returning a phrase in the ["ph"] field, provided that you do not use double-quotes in it.

For a (C) box:

"ref" is divided into a field ["d"] (do not change it) and a field ["C"]
You can put any valid KeyKit expression returning a Csound score in the ["C"] field, provided again that you do not use double-quotes in it.

For a (£) box:

"ref" is divided into a field ["d"] (do not change it) and a field ["£"]
You can put any valid KeyKit expression returning a ligne in the ["£"] field, provided still and again that you do not use double-quotes in it.

For a (&) box:

"ref" is divided into a field ["nb"] (plus maybe a ["nb2"] one), a field ["ph"] and a field ["sco"]

In ["nb"] you can set the index of the source box (in ["nb2"] the index for the optional second source)

In ["ph"] you can put any valid KeyKit expression returning a phrase, using the keywords "_ph_", "_ph2_", "_sco_" and "_sco2_" to represent the phrase(s) and score(s) from the source(s)

In ["sco"] you can put any valid KeyKit expression returning a score, using the same keywords.


(more here later ...)

delay/scale functions

... lets you replace the default functions used when delaying and scaling a box content (phrase and score) to obey links and time stamps. You can also define a way to amplify scores by setting the value of the field "scoamp"

The submenu allows you to copy/paste these settings from one box to another.

The format is the following: Examples:

The default functions are hold by the following parameters:
CompoFDPH    # "delay"
CompoFDSC    # "DelayScore"
CompoFSCPH   # "scaleng"
CompoFSCSC   # "ScaleScore"
CompoScoAmp  # "Id"


... here you can directly edit the tags string of the box. If you want it to be part of the $ set, remember that the "$" symbol must come first.

The submenu allows you to copy/paste the tags string from one box to another.

phrase display

(more here later ...)

toggles: mute, freeze, autofreeze

This is straightforward. A few reminders:

(all fields)

The whole internal representation of the box you clicked in is editable here. You should better know what you're doing, then...


This plug-in interfaces with the program Scala in order to allow microtonal or alternate tuning of phrases. Because of the way it works, it will only be useful if GeoMaestro is associated with a soft synthesizer such as TiMidity++ (see here for more about that) and if its interfacing with Csound is performed.
(I may adapt it sometime so that it handles a pure MIDI mix, but this is a much more complicated approach than the one described here. At the moment, you're left with the Scala() function if you want to do this your own way)


All related code lies in lib/scala_utils.k. You will need to go there and set the value of the global variables SCALADIR, SCALATEMP, SCALABAT (see here for details) and SCALASYNTH (the index of the soft synthesizer you want to use: this is required as explained below)


You must target a (ph), (£) or (&) box, whose MIDI content will be tuned by Scala. This box should not contain program/bank change messages: instead, they should be contained by a separate box.

Scala performs the tuning of MIDI data with pitch bend messages. In order to avoid messages overlapping, it splits the input MIDI into several ouput channels. So tuning multi-channel phrases is not straightforward: it has to be done in several steps. This is exactly what the CallScala plug-in do.


Here with have a program change box to bank 53, patch 0 on channel 1 and another one for bank 20, patch 58 on channel 2 (in my system, these are respectively a mandolin and a piano). Then comes a short phrase box using these two channels.

So evaluating box 1 returns the phrase in box 3 associated with the instruments described in box 1 and 2. So far, so good.

Now let's say we want to tune the phrase in box 3. With the "plug-in" mouse mode and "CallScala" selected in the plug-ins menu, we click on box 3.

Note: At this stage, if the target box has not been evaluated, CallScal will propose to stop. This is because the plug-in needs to know in advance how many channels are required. If you proceed with an non evaluated target, it will be assumed that all 16 channels are necessary, which will clutter your composition with a lot of useless boxes (not recommended !)

A pop-up window appears and ask for a scale name. The choice here is among the thousands (!) of different scales available with Scala (the *.scl files in folder /Scales). You can either directly give the file name (without extension), or type "*" and get a browser window to pick the file.

Next, another pop-up window asks for the index of the box containing the patches. In our example, it is box 1, which when evaluated contains both the program change messages and the notes.

Then a third pop-up window asks for a string of maximum 5 characters which will be used as root for building temporary MIDI file names. You can skip this step by simply pressing RETURN if CallScala is used only once in the composition, otherwise you need to give different roots in order to avoid confusion when the structure will be evaluated.

Next, a third pop-up window asks for the index of the box containing the patches. In our example, it is box 1, which when evaluated contains both the program change messages and the notes.

Now CallScala can go on: it will split the target box in several boxes, one per channel, and edit their reference field so that a call to the function Scala() is performed. For each of these boxes it creates an associated patch box and an associated synth box. All this is linked in the right way so that no extra setting is necessary.

In our example, this is what we get:

Now we can evaluate box 1 or directly box 4 (since the patch messages in 1 and 2 are overridden by the ones in boxes 5 and 8). This will create two temporary MIDI files (from synth boxes 4 and 7).

Next we click [Audio] and the mix is performed: we get the tuned phrase as an audio file.

The function Scala()

This is the low-level function used by CallScala to interface with Scala. You can use it to write your own tuning functions.

In order to use Scala(), you must define the following global variabes in InitScala() (all code lives in lib/scala_utils.k):
SCALADIR	# the path for the Scala directory, ending with a Dirseparator
SCALATEMP	# the full name for a temporary *.cmd file in the /cmd folder
SCALABAT	# the full name for a batch file calling Scala 
			#   in directory SCALADIR and executing SCALATEMP
Example: my own settings are:
SCALADIR = "C:\\Scala\\"	
SCALABAT = "C:\\Scala\\GM.bat"
... where GM.bat is a two-line batch file:
	cd C:\Scala
	Scala cmd\TEMP.cmd


Scala(ph, scaln {, fwname})

ph: phrase
scaln: string 	# ex: "avicenna" (for scale file "Scales/avicenna.scl")
fwname: string	# (optional) full name of a *.wav file
... will return an array containing the tuned counterpart for each channel of phrase ph, according to the scale scaln. If fwname is present, an audio file will be rendered under this name by TiMidity.

The result is an array, not a single phrase, because in most of the cases one input channel will give birth to several output channels in order to manage notes overlapping (see Scala documentation for details). As a consequence, it is very often impossible to tune a multi-channel phrase and keep the result in a single output phrase.

If you really want to have one single resulting phrase, merge all fields of the output like this:
tuned = Scala(ph, "avicenna")
ph = ''
for (c in tuned)
	tuned[c].chan = c
	ph |= tuned[c]


Click and drag from one box (1) to another (2): providing that both boxes have been evaluated, this will create a time stamp from box 2 to box 1, so that they are now bound to be synchronized, box 2 being the reference when scaling.

The time stamps is issued from an existing mark in box 2 if it is possible, otherwise a new mark is created.


This plug-in is intended to be used in time line mode on a scaled box.

It allows you to grab a box and move it, so that the horizontal shift in position is interpreted as a temporal offset, very much like moving a box in a regular time line display. Here is how it works:

Say we drag box 2 to the position outlined at the bottom of the above picture. The plug-in inserts a silent box tailored to represent the horizontal offset, box 4:

This box is not evaluated nor scaled, so we need to click on [EVAL] (assuming box 1 is the current box), then on [SCA], in order to get the scaled display:

The intermediary box is named after the box we moved; it will be updated if we move it again, and will disappear if the eventual offset gets back to 0.

Note that boxes can be moved in both directions. Here we give a negative offset to box 3:

(as you can see, the plug-in makes use of a link offset on box 5)


Echo boxes can be used to perform arbitrary operations on the musical data returned by an evaluated box: see here for an overview of echo boxes.

This plug-in moves a given box out of its place in the composition and replaces it with its echo, allowing a choice of pre-defined transformations to be applied on the source.

Here is the eventual set-up:

... box 6 now replaces box 4. box 5 (a black hole) is used to get rid of the musical data from box 4, while keeping it linked to the overal structure, as you can see in this example:



The pop-up menu allows you to either simply create a plain echo, or to transpose the source phrase, change its channel, repeat it or else convert it into a Csound score (in this case you have access to all the mappings registered in the Array Parameters tool through a sub-menu). More operations can be added here by hacking the plug-in code, located in lib/lib_cplugs.k


Similar to RepWithEcho, with an extra stage: the targetted box becomes the children of a (#) box.

The pop-up menu makes it possible to apply Csound filters to the "audio" field of the (&) box. This feature is not documented yet.


(more here later ...)


(more here later ...)


This plug-in is simply a hook for grabbing the "edit" menu of the group tool.

Most of the available transformations can thus be applied to a (ph) or (&) box. Some of them won't work and issue an error message instead, though.


Clicking a (ph) box replaces it with a group tool (T) box displaying the corresponding phrase. Once your modifications are done, you may revert to a plain (ph) box by hitting the [ph] button.


(more here later ...)

-- Back --