Chapter 1: General Usage

 

1.1 Introduction

First of all, what is CPS?

CPS is a realtime programming environment for audio, MIDI and other media & I/O.

Patches are build by placing objects and making wires between them. Areas of interest are sound design, algorithmic composition, DSP, electronic/computer music and education.

Build-in objects allow low-level access to audio and MIDI. CPS has a lot of objects to process audio and MIDI (and other signals), include audio and MIDI in- and output, fourier analyse, filters, noise generators, envelopes, delay lines, table generators, and much more. Most audio objects are MPEG-4 Structured Audio compatible (see chapter 4).

CPS is not only a realtime toolkit; it is also a friendly graphical user environment. CPS has a subpatch architecture (of unlimited depth), with which you can put parts of you patch within one object. CPS has full Undo/Redo, and all objects have tooltips (including subpatches) and online help.

CPS is ideal for (DSP-) programmers. It is _extremely_ easy to build a plugin for CPS. The only knowledge needed is basic ANSI C/C++. You can directly start making a platform-independent plugin which for example works with streaming audio and reacts on MIDI too. You can use any build-in CPS object (including the MPEG-4 Structured Audio ones), in your new plugin if you need it.

You can easily build a graphical interface for your plugin in the platform-independent language 'Java'. You can directly communicate with your C++ - plugin fromout the graphical interface. If needed, you can also save as many data within your plugin as you want, or even define your own classes for storage.

Besides the plugin architecture, CPS can also be used standAlone inside a C++ or Java program, or inside MacroMedia Director.

 

 

1.2 Online help

Let’s get started and see how to get online help. The first things that you should need to know are in the general helptext, which appears when you press F1 after starting up CPS:

Welcome to CPS! CPS is a realtime programming environment.

You define your functionalities by placing objects and making wires between them.

To make a new object, click in an empty place with the popup mousebutton or click & wait, and then choose from the menu. To create a new object by typing it's name, doubleclick in a empty place and type the name; you can also type a number there (which becomes a numberField). To make cornered wires, simply drag onto a wire and a new corner is created; doubleclick on a corner to delete it.

For help about a certain object, select that object only and press 'F1'. Use this frequently to learn working with CPS. If an object has any special options, you can see them by doubleclicking on the object.

To drag Display-objects around, first hold down the shift key (= the 'Display' key). To edit options of Display-objects, hold the shiftkey and doubleclick on the object. To turn the audio on, press the spacebar; to stop the audio, press escape. To select more than one object, hold the CTRL key.

The sensitive area for wires of the Display objects is only outside the objects, for normal objects that is both inside as outside objects.

There are no rules that define in which sequence the signals flow; instead each object on itsself defines what is does. If you connect more than one wire from an object to another object, then the signals will go into the left inputs first. If an object outputs signals, they go out at the left outputs first too.

The 'blocks' on the screen are called 'objects' in CPS. You can add objects into your patch by holding down your mouse-button, or (on Windows) clicking the popup-button of your mouse, and choose in that menu which object you want to add. The position where you click with the popup-button, is the position where the new object appears on screen.
There's an other way to insert new objects into the screen, that is, doubleclicking in an empty space, and then typing the name of the object. If you need a numberField (you need it a lot normally!!), then you can also doubleclick in an empty space and type a number. It converts automaticly to a numberField.

As the initial helptext says, every object itsself has a helptext. In this helptext, it is often written down that the number of in- and outputs can be changed by selecting the object and then pressing PAGE_UP or PAGE_DOWN. You can read the helptexts of the objects in Appendix A.

There is more online help in the form of tooltips; if you place your mouse above an in- or output of an object, and don't move your mouse, a small line of text appears telling you the meaning of the in- or output.

All the four edges of the objects are used in CPS: the upper for the controlrate inputs, the lower for the controlrate output, the left for audio input, and the right for audio output. 'Controlrate' and 'audiorate' are explained in the next two paragraphs.

You can make a wire between objects by clicking in the 'sensitive area' (see the citated helptext above) of the source object, then hold the mousekey and drag to the input where you want it connected to. The connectors lighten up with a green color if you are in the sensitive area. The middle of an object is used to pick it up and move it around. You can also make wires backwards, that doesn't matter. If it fits, then the target object will look 'pushed', and then you can release the mouse button to acknoledge the wire. If you did not remember where you wanted to put the wire exactly, stop dragging with the mouse when the target button is 'pushed', and then the small line of text appears again, telling you what that in/output means.

You can delete objects and wires by selecting the objects or wires you want to delete, and pressing delete or backspace. Besides clicking objects and wires seperately, you can hold the controlkey to select more than one item. You can also select more items by dragging a rectangle on the screen.

Remember that you never have to start or stop the audio each time you change something; you can leave the audio running while you are making your patch. CPS is completely realtime.

 

1.3 Controlrate

If you have read section 1.2 carefully, you should be able to make a patch with a few wires between some objects. Now let's take a closer look to some things you need to know to build patches.

As we know, controlrate is everything that is defined by wires that go from top to bottom. MIDI is a controlrate signal. Controlrate signals are not continuous: MIDI signals do not happen all the time, but only when a midi messages is created.

Suppose you have created the patch showed here. You can change the numbers in the numberFields easily by pressing in the numberField, holding the mouse button, and start dragging up and down, as if it is a Fader.

It's clear that you want to evaluate the calculation now. Here you should ask yourself: whén do I want to evaluate the calculation? When the first argument has changed, or when the second argument has changed (or both)?

Of course, you do not want to say that in évery situation you want to evaluate the object when the first argument has changed, because then you would not be able to change the second argument and evaluate it (without introducing extra signals). That's why there is a third input, the 'evaluate' input. Only when you put a number into this output, the calculation is done. You can connect a numberField to it. If you drag on the numberField, then the signal also goes into the third input, which causes the object to be evaluated. You can see, that the result comes out the plus object now. Because the calculation is only done when you do something (put a signal in the object), this can be called 'event'-driven.

The controlrate part of CPS is completely event-driven. Objects only do their thing when they are asked to do so.

If you connect more than one wire from an object to the same object, just like here, then the signal always goes into the left inputs first. That is why an 'evaluate' input is always the most right input. Also, if an object gives more than one output, the left outputs get 'out' first.

We have seen how some objects work which need more than one argument. Here you see another example, an object with only one input. If you drag in the upper numberField, the answer comes out immediately. There can never be a misunderstanding of what you mean. But it is still 'event'-driven: you generate the event by changing something, then it starts calculating.






 

1.4 Audiorate

The signals that go from left to right, or: all audio objects, are called 'audiorate' (or: a-rate).

Digital audio is all about numbers, which are called ‘samples’. Normally 44100 samples are processed each second. The only difference between audiorate and controlrate, is that the audio works with 'buffers', each time a set of samples. You can set the size of the buffers in the 'Options' - 'Settings' menu.

Audiorate works with buffers, because it is faster to compute everything with a bunch of samples than call every object for each sample. Remember that, normally, there are 44100 samples going through the audio chain each second!. If we would use individual samples, then each sample would be put into each object, 44100 times a second. This means that, without optimalisation, we have to call each object in the audio chain 44100 times a second. If we work with a buffer of for example 512 samples, we only have to call each object about 86 times a second! That means less overhead in calling the objects and in data transfer time between the individual objects. The saving in CPU time is dramaticly, although the result is the same (there is a difference when you use k-rate objects though).

Often there is no change in the audio objects. If there is no change at all, then you can have a buffersize as big as a second (or even bigger), because a bigger buffersize is (in general) more efficiënt so that's perfect. But what if a change happens, for example an objects gets a controlrate signal (so that it's functionality is changed next time it processes buffers). Then it would take a second before you actually hear the change (an object can not process buffers and process controlrate signals at the same time). So the buffersize should be big but not so big that changes are heared after a very long time. For most purposes, 512 samples (the default buffersize) is allright (even too low).

The audio is represented by samples (or numbers) that lie (normally) between minus one and one. Silence is represented by zero. It is important to keep the numbers between minus one and one, although at each output (like audioOut or audioToDisk), the output is truncated between minus one and one. If we would not do this, and for example a number is greater than one, then the audio would 'flip' over to a negative number, and you would hear a terrible sound (distortion). In some sequencers when exporting the audio, and in old DAT-recorders you still hear this problem; if you put in/out a signal that is too loud, it sounds terrible. It is also prescribed by MPEG-4 Structured Audio to limit the output between minus one and one at the end.

But, sometimes you want to make a feedback connection, as you can see here. It is not impossible to do this when working with buffers, unless you accept a delay as big as the buffersize. Because you are always calculating (for example) 512 numbers at the time, the audio only comes back into the ‘+’-object after 512 samples! This is the delay of 512 samples, and you did not mean to introduce a delay here; you just wanted to add the output to the next input.

In all digital audio programs, this 'small feedback loop' problem is an issue. There are several solutions: make incredibly small buffersizes, or work with individual samples anyway. CPS supports both options (although CPS is not 100% optimised for working with individual samples only). You can set the buffersize in the 'Settings' menu as low as 5 samples (or less, if you dare). But be aware: the lower the buffersize, the greater the overhead of the system. In CPS, you can also work with individual samples; this is described in chapter three, and called 'sampleprecision'.

There is an other reason why we work with buffers. That is, we do not have to update every controlrate signal for each sample. An example of this is envelopes: for example, if you use the output of 'kline', then it normally sounds allright, although kline outputs only one new value each buffer. You will see an other example of updating value's less often, in chapter three.

Some last (advanced) notes about audiorate. First of all, if an object has more than one audio input (like 'agaussrand'), but not all inputs are filled by a signal, and you want to use it's output, then CPS gives a buffer with zero's (silence!) to the object at the not-filled inputs. On the other hand, if there are several wires connected to the same audio input, then CPS adds these inputs (these buffers) before it gives the buffer to the object.

 

1.5 Display Objects

In this paragraph, the Display objects are shortly discussed, because their usage sometimes differs from normal objects.

We already know, from paragraph 1.1, that to select and drag Display-objects as you would do with other objects (grab-and-drag), you must hold down the shift key. It simply disables all Display objects. If multiple objects are selected, you are in the dragging mode. Click somewhere not in an object (without having the CTRL key pressed) to deselect everything, and then you can use the Display objects normally again.

We also know from paragraph 1.1 that the 'sensitive area' (for connecting wires) is outside the display objects, rather than inside (as with normal objects). So if you want to make wire from for example a numberField to a '+', then you press right under (or right above) the numberField to start with the wire, and then start dragging to the destination object.

For more information about specific options of the Display objects (for example, you can make most Display objects bigger), see the appropriate helptexts.

Let's have a closer look to the options which Display objects can have. Make a new numberField, hold the shift key and doubleclick on the numberField. As we know, doubleclicking on an object shows it's specific options, so now we see which options this numberField has. With the numberField, the 'drag-range' means how much the current value is changed when we drag in the numberField. The fader also has this option, here 'drag-range' is more literaly; it means how big the range of the fader is.

More interesting is the 'Fire at startup (i-rate)' option. 'i-rate' is an MPEG-4 Structured Audio (and a C-sound) term. The manual of MPEG-4 Structured Audio says about i-rate:

" -> Initialisation rate: The rate type of variables, expressions, and statements that are set once at instrument instantiation and then do not change."

So, if this option is on, then the value is fired at the patch loadtime (a CPS patch is an MPEG-4 Structured Audio instrument). Anything that is activated by this value (expressions and statements) are also part of the i-rate. This option is by default vinked 'on', because you normally put Display-objects into your patch to adjust value's until they are good. Be carefull though, because you might also use Display-objects in the middle of a calculation to see what value goes through the wires; you should turn the 'Fire at startup' option off there.

If you put a number through a Display object, it will not change. But, if you let a number go through the ‘constant’ object, it will change into the number of the constant. In some circumstances, this can be helpfull, for example for resetting something to an initial state.

Something which you might need to know when you are an advanced user of CPS, is that Display objects which have the i-rate option vinked on (by default), will also throw out their value after copying or inserting, for example when you paste a subpatch, or when you load a subpatch from file. In practice you do not notice this, because it's very logical.
Another advanced thing to know is, that i-rates in subpatches are being 'fired' FIRST, then the i-rates in higher levels. This is done, so that the subpatch is ready before arguments are given to it. This completely makes sense with the practice: normally you give a subpatch it's arguments, but it's internal calculations must be done before these arguments can be used correctly.

 

 

 

 

1.6 Subpatches

The file that you are creating on screen is called a 'patch'. It is actually a quite analog term, referring to the time that it was really a patch of wires between (analog) objects. In MPEG-4 Structured Audio terms, it is an ‘instrument’ you are creating.

You can pack a set of objects and wires between them, into one object. This single object then looks just like any other object in CPS. It is called a subpatch. You can save a subpatch to disk (it has the same file format as a 'normal' patch), and insert it into an other patch. It is also possible to insert a subpatch into a subpatch into…etc. There is no limit on the depth of subpatches.

 

It is strongly recommend to use subpatches where it is needed. The helptext of the ‘SubPatch’ object says:

You can use subpatches for increasing the readability of your patch, seperating of concern, simplifying teamwork, or for increasing the re-useability of your patch.

 

The biggest advantage of the subpatches architecture in CPS, is that is does not take any extra processing time. So even if you have created subpatches that are for example 8 times inserted into each other (8 levels 'deep'), the calculations still go as fast as if you created everything into the one view. Of course, to you as a user, it is not more than obvious that CPS is efficiënt at certain places, but it is important to mention here because it is the most heared excuse not to use subpatches.

 

You create or insert subpatches by selecting the appropiate title in the Insert menu. If you make a new subpatch, select it and press F1, you can read the helptext of the subpatch. If you hold the shift key and doubleclick on the subpatch, then you can give it a name. If you doubleclick on it, you get the view of the subpatch. The title of the subpatch always tells you where the subpatch is located (for example: "these_sounds.cps::cheapverb").

If you now make the new window a bit smaller, so that you can also see the parent window, we can exactly see what happens if we add inputs and outputs to our new (sub)patch. You can select four items for inputs and outputs: APatchIn, APatchOut, KPatchIn, and KPatchOut. They stand for: this thing is on A or K (audio or control) rate, and it creates an In/Out- put on the output of this Patch.

The rest is simple; you can use the input and output objects just as if they were normal objects. If you need more than one in- or output, select the existing in- or output, and press PAGE_UP or PAGE_DOWN. In the picture you can see that the KpatchIn object now has 4 control outputs, and the parent window also gets four control inputs.

 

You can also give each input and output a name. Doubleclick on the representative in- or output of the subpatch (for eample APatchIn), and fill in the descriptions. If you close the window (which can always be done by pressing 'escape' too), the names are stored.

If you save subpatches in a ‘macros’ subfolder of CPS, the subpatch will appear under the ‘Macro’s’ header in the ‘Insert’ menu. This menu is refreshed each time you do File-New.

In CPS it is also possible to use a set of subpatches, which are refreshed when you load in your patch. For example, if you have a subpatch called 'recalulate', and you vink the option 'Try to reload this subpatch from file at startup' on, then when the main patch is being reloaded, CPS tries to load a file called 'recalculate.cps' and replace the subpatch with that file.

A small variation on subpatches, is the 'Save as Group' functionality. If you select some objects and save it as a group, you will create a .cpg file, which is nothing more than a traditional patch (just like .cps) with these objects inside them. You can even rename the file as .cps and reverse, without making the file invalid. But, if you insert the group file into the patch (Patch - Insert Group), you will see that it does not load the file as a single subpatch in the patch, but as these object 'extracted' on the screen. A good example of this is one of the fader macro's (Macro's - Display - Amplitude to Fader).

It's good to know that the 'Undo' is remembered (during editing) for each subpatch. That means, if you delete a subpatch, and then select 'Undo', that the original subpatch itsself comes back, but the Undo history of the editing inside the subpatch itsself is gone (if any).