Chapter 2: Specific Usage

 

2.1 Dynamic number of in- and outputs at runtime

Sometimes there is an object, which can do more than one thing, or on more than one rate (controlrate, audiorate, or a combination), where it would be useless to build the same object more than once. Here you see all the states of the '*'-object as an example. It would be redundant to support a list of all different shapes. (Note that the '+' and the '*' have some extra appearances, unlike other math objects.)

In CPS you can change the inputs and outputs of objects by selecting the object, and then pressing PAGE_UP or PAGE_DOWN. If this is supported by an object, it is always mentioned in the helptext of the objects. Almost all objects in CPS are pluriformal, because they work on both controlrate and audiorate, and often also at ‘sampleprecision’ (see chapter three).

All 'Operators' are pluriformal, and as well as all ‘Math’ objects. These objects have also an appearence where there are only inputs and no outputs. That appearence is also shown in the pictures of all ‘*’’s. You can use them to work with tables.

For the programmer of a plugin, a dynamic number of in- and outputs is very easy to implement; it is the same as increasing or decreasing a variable.

 

2.2 Build-in facilities to prevent bugs

The most important weapon against bugs in CPS is the runtime error handling. If you put an illegal argument into an object, it gets green, you hear a beep, and an errormessage explaining the error appears in the 'System Messages' window. Of course, this is nice, but more important is that your patch doesn't start doing something that it shouldn’t do (like crashing). For example, if you make the feedback parameter of the 'comblpf' object bigger than one (or any feedback parameter), then the signal goes to an infinite big value (it keeps increasing), and finally no sound would be heared at all. So, there is a check on that parameter. Instead of accepting the invalid argument and forcing the user to restart the audio, CPS gives a message explaining what is wrong, shows where it happened and the patch just goes on because the parameter was just not accepted.

This error handling is also used when a loop in the patch is detected. In the picture you see that if you change the value in the left thing, the signal would go into the right numberField and then into the left again; it would never stop. Again, CPS gives you the error and shows where it went wrong.

CPS allows a feedback loop depth of one (at controlrate). It means that if a value has come out of an object, it is allowed that a value is inserted in that object again, but not more than once. For example, you can let a number come out of a timer, and set the timing interval with the same trigger that the timer gave, as demonstrated here. This patch counts up to 20 with an interval of 500 milliseconds. If the number fromout the ‘count’ equals 20, then a –1 is put into the timer, which means that it has to stop.

All error messages (including all plugin errors) appear through this runtime error handling.

The following items are all things that are not implemented in CPS to prevent bugs. These are all more advanced topics.

 

 

Something that is not implemented, is a policy for priorities for the order of processing. If you look at the pictures here above, you see that the two patches do the same thing: delay an (audio) signal with a half second (see ‘sampleprecision’ in chapter three for more information), and add it to the current input. But, in what order is the input distributed to the add-object and the delay? This is called ambiguous. Some programs use the graphical position on screen to decide which objects to process first, but in practise this often means that a big patch doesn't work and you can't find the bug.

CPS has a special object for this situation, called 'order'. It defines the order of processing, as well at controlrate as at audiorate. It does nothing more than just passing the arguments; because outputs always come out from left to right (or from top to bottom), you can use it to define the ‘order’. Always use the ‘order’ object in case you distribute a signal to several objects which all give output. Fortunately, you will use ‘order’ very rarely, you won’t need it very often.

 

This problem only occurs when calculating at controlrate. Why can't it happen at audiorate? Because audio is continuous; it goes on all the time, so you do not have to an object a trigger to evaluate it’s output. Audio objects always give output. You can see the audio version at the right.

Something that was also not introduced in CPS, is the use of different signals. Things that go through the wires on the screen, are always from the type 'float', or: floating point. This means, that numbers can always be fractial (4.5, 6.22 are possible, and not forced to 5 or 6). But, parameters are often only usefull when they are integral (non-fractial numbers) just like MIDI note numbers; however, introducing integer signals would mean a lot of unnecessary conversions from non-fractial to fractial while the patch is running, and saving integer value's in fractial notation (4 as 4.00) is not a problem at all.

Another thing that is not introduced, is packing several value's into one value; this can be used for putting several value's into one object. This is not supported in CPS (except in the midiMessage object).

 

2.3 Tables

A table is an 'array' of numbers. You can use a table for several purposes within CPS. Tables can for example be used for 'table lookup', for temporal storage, or to store midi notenumbers in. There is no distinction between a table that contains an audio file, or one that is used to lookup value's at controlrate. You can read and write in tables at audiorate and at controlrate.

A table can be filled with numbers by using one of the 'wavetable generators', which are standard in MPEG-4 Structured Audio. The term 'generator' directly refers to the C-sound background of MPEG-4 Structured Audio (and before Csound).

When you doubleclick on a 'table' object, a simple editor appears. In the texline under the visual representation, you can type a line of text and press enter, after which the table is constructed.

There is a helptext under the button 'Generators', where it is explained how to fill the commandline under the graphical representation. That helptext is also included in this manual in appendix B. You can drag in the numberfields above the graphic representation, just like with the 'real' numberFields.

Let's see how tables are integrated in CPS. CPS does not have 'hidden wiring'. So, there is not a connection between two objects if you don't see them on screen. That is also the reason why you do not have more than one object representing the same hardware device. Although there is no 'hidden wiring' in CPS, there is one special case of a wire, that is a wire between a 'table' object an an other object. Those wires represent a (static) connection between the objects, instead of a signal path, which all other connections represent.

You can not use normal objects to work with tables, unless they work explicitly with tables as mentioned in the helptext. As we know, Operators and Math objects have a special appearance where they only have inputs, which is used for tables. If an object is in this format, it has has an extra input, which is for giving the object a 'trigger' to do it's task on the given table(s). In the picture, this is the third input.

When saving as an .saol file, operators on tables are written as a 'while' statement. (N.B. Saving and loading as .saol is not yet supported in CPS 1).

 

2.4 Overview of the MIDI protocol

A MIDI message is always one, two or three bytes long (except system exclusive messages, which are put into tables in CPS - read the 'midiMessage' helptext about these). The first byte is called the ‘status byte’, the second and third one are the 'data bytes'. A byte consists of eight bits (0 or 1). The first part of the first midi byte (the 'status byte') tells us what kind of message it is. The last four bits of the status byte can also be part of the 'kind of message', but can also tell us on which channel the midi event happened. The second byte and the third byte are optional, and may not appear depending on the function of the status byte.

The status byte is recognised at it's first bit; it is always one. This also means that the status byte is always a number between 128 and 255. The data bytes always have their first bit zero, so their range is from 0 to 127.

In the next table you can see what which number means. The hexadecimal notations are not shown here because you can’t see this notation in CPS either. Note that channels are numbered from 0 to 15.

 

Meaning

Status byte

Data byte 1

Data byte 2

Channel info:

     

Note off

128 + channel

Which key

Release velocity

Note on

144 + channel

Which key

Attack Velocity

Poly pressure

160 + channel

Which key

pressure

Control change

176 + channel

Which controller

value

Program change

192 + channel

Patch number

Bank number

Channel aftertouch

208 + channel

Pressure

-

Pitch bend

224 + channel

LSB pitch bend

MSB pitch bend

System Common Info:

 

System Exclusive

240

ID manufacturer

..................

Midi Time Code (MTC)

241

-

-

Song Position Pointer

242

LSB position

MSB position

Song Select

243

song number

-

Tune request

246

-

-

End of System Exclusive

247

-

-

System Realtime Info:

Time clock

248

-

-

Start

250

-

-

Continue

251

-

-

Stop

252

-

-

Active Sensing

254

-

-

System Reset

255

-

-

Some examples: 144-x-y means note x on x with velocity y at channel zero, 145-x-y means note x on with velocity y at channel one, etc. Often the channels are numbered from 1-16 on hardware, then you have to substract one to go to the wire/CPS numbering.

Nowadays, note off is seldomely used, but instead a note on with velocity zero (for example, releasing note 60 on channel 1 is 144-60-0). The active sensing (254) and the clock (248) are both filtered out by CPS; you will not see them back anywhere.

There is more to tell about the 'control change' (176/191-x-x); a lot of the controller numbers (first status byte) are standard. They are listed in the next table. Controller numbers 32 to 64 are the fine tuning for the controllers 0 to 31. Controller 64 to 83 are actually ment to be switches (so only have meaning when the 2nd data byte is 0 or 127, ‘on’ or ‘off’).

Meaning

1st data byte

Bank Select

0

Modulation wheel

1

Breath controller

2

Foot controller

4

Portamento time

5

Data entry

6 (used in combination)

Volume

7

Panning

10

Expression

11

Sustain pedal

64 (followed by zero or 127)

Portamento on/off

65 (followed by zero or 127)

Filter resonance

71

Envelope Release

72

Envelope Attack

73

Filter Cut-off

74

Effect Reverb

91

Effect Chorus

93

All notes off

123

Omni mode off

124 (followed by zero)

Omni mode off

125 (followed by zero)

Mono on

126 (followed by number of channels)

Poly on

127 (followed by zero)

So, to set the reverb parameter on channel one to '60' (the scale is still 0-127), then you would send 176-91-60. To do this on the second channel, send 177-91-60.

Implementers of MIDI are free to assign controlchanges to value's they like, although most listed here are standard. For example, the listed envelope release and attack controller numbers are not standard, but are recently seen in a few new synthesizers. Of course, you are also free to use them as you want.

There are also several special control changes, which are called RPN's (Registered Parameter Numbers) or NPRN's (Non-Registered Parameter Numbers). RPN's and NRPN's first say which parameter is ment in two seperate controlchanges, and then the data is sended through controlchange nr. 6. So, we always have to send three midiMessages to send the first value. Of course, after that we don't have to show which parameter is ment, and only sending a controlchange nr. 6 is enough.
PRN's use this sequence (for channel zero): 176-101-x 176-100-y 176-6-a1 176-6-a2 176-6-a3 to send the values 'a1' 'a2' and 'a3' after each other (there might be some time in between of course) for parameter number (128*x)+y. NRPN's do the same, but not with '101' and '100', but with '99' and '98'. It seems to be common to 'close' both RPN's and NRPN's with the following sequence (for channel zero): 176-101-127 176-100-127 ; however, it is not prescribed so it is often ignored.
There are a few registered parameter numbers; these are included in the 'Macro's' - 'MidiOut' section of CPS. CPS also has two macro's which extract NRPN's and RPN's.

 

2.5 Optimising your patch

There are several things you can do to optimise your patch. The first you can do is leave out Display objects that continuously show graphical feedback. So if you have a lot of numberFields in your calculations to show results, it is faster to let them out. It takes time in two ways: the number must go through the graphical objects, and the value must go to the graphical interface (the second transport does not happen if the object is not visable, for example in an unopened subpatch).

People often think that using subpatches does slow down a patch. This is not true in CPS, as discussed in paragraph 1.6. So putting everything in one window does not mean that your patch is any faster.

If an object is not connected through wires at the input, it doesn't take any processing time. This is always true, since there are no hidden wires in CPS. Things that do take processing time, are oscillators. Oscillators are things that give output. Oscillators at controlrate are for example ‘midiIn’ and ‘timer’, and oscillators at audiorate are for example ‘sinus’, ‘oscil’, ‘audioIn’ and ‘upsamp’. So, you can save processing time by for example combining several sinus objects together, or by using a timer twice.

Avoiding the use of 'upsamp' is a good idea; sometimes you can do a calculation at controlrate and upsamp once then, instead of upsamping all variables and doing the calculation at audiorate, just like it is shown here. Both patches give the same result. Note that the use of the special ‘*’, which acts like a build-in upsamp.