- Let's move right into the mathematical functions. They are really very straight forward, and by now should be easy to follow assuming you have made it this far without frothing at the mouth and falling into a coma. Remember that these math statements are functions and as such, the "operation" comes first followed by the variables to be operated on. If it helps make sense of the syntax, in your mind just move the operator from in front of the function to in between the variables and they will seem more familiar. This will also help keep straight the order of operation in subtraction, division and in relational functions.
- (+ variableA variableB)
- This is simple enough. We add the value of variableB to variableA and send the result to whatever function contains this function. In short, there is no "target" or destination implied by just this function alone. You will use it within another larger function, most likely with an "equal" assignment sending the result to a third variable. For example, we might do something like
**(= Note.Vel (+ hammer baseline))**- in order to set the velocity of a note equal to the sum of two variables. As you might guess, one or both of these variables could also be constants or other functions such as
**(= Note.Dur (+ (+ offset pastdur) (- Event.Time lasttime)))**- Here a note duration is set equal to the sum of an offset amount and a stored duration plus the difference between the event's starting time and another stored time. Notice the way the functions stack. If you were to replace any of the "nested" functions with values, the order of the larger function's parts and math operations would stay the same. Remember, CAL doesn't care if you use variables, constants or nested functions as arguments. It's all the same to CAL. The placement of the "+" keywords and brackets never changes. You just stack them when the functions take on nested functions.
- (- variableA variableB)
- Take a close look at this function. With the addition function above, the order of the variables didn't matter. Addition gives the same result adding 2+3 and 3+2 due to addition being "commutative". This is not the case for subtraction. This statement reads in English "Subtract from variableA the value in variableB", or simply, "variableA minus variableB". Don't get the order mixed up or you'll have all kinds of problems. Otherwise, the rules for using "-" are the same as for using "+".
- (* variableA variableB)
- This is multiplication. Here the order doesn't matter. Just make sure you don't overrun the range limits of your variables. The rules for using this function are as described above.
- (/ variableA variableB)
- Division also has a specific order of the variables. This statement reads in English "divide variableA by variableB." Keep in mind that CAL does not see fractions and does not round off. The results of division in CAL is the integer value only. You must use the "modulo" function below to obtain the remainder of the division. Otherwise, the rules mentioned above apply.
- (% variableA variableB)
- Because CAL doesn't use fraction and doesn't round off division, we use the "modulo" function to obtain the fractional part of a division. The result of (% A B) is the integer number left over after subtracting B from A over and over (which is the act of division) until there is a remainder that is less than B and thus there can be no further subtraction without sending the result negative. This remainder is the fraction of A left over from the division. For example, if 23 were divided by 4, the answer would be 5 and the remainder would be 3. Thus, in CAL, the function (/ 23 4) would result in an answer of 5 and (% 23 4) would result in an answer of 3. Here is how you would use this function to round of division. Note the following formula for obtaining an average.
**(= average (/ sum count)) (if (>= (% sum count) (/ count 2)) (++ average))**- First the average is found by dividing the sum of numbers by the total of numbers that were summed. Assume we have added 45 numbers together and the total was 22845. Therefore, "sum" is 22845 and "count" is 45. We divide the two to get the average and the answer is 507.67. Because CAL doesn't see fractions and will not round, the answer for the first function above will be the integer 507. However, for accuracy, we would want to round off this number to 508. The second function does that by taking the remainder of the division of 22845 by 45, which is 30, and seeing if this remainder is greater than or equal to half of count, or half of 45. If it is, then we increment "average" and get 508 instead of 507. If you look at a CAL program supplied with Cakewalk called THINCTRL.CAL, which is a program that thins out controller events by deleting every Nth event, you will see the modulo function used to locate that Nth event by counting and dividing, and whenever it sees a remainder of 0, an event is deleted. Everything said about using and setting up the other math functions applies to the modulo function as well.
- (random minvalue maxvalue)
- Although this is sort of an assignment function, I place it here because it, like the rest of these math functions, has no implied destination for the result and must therefore be a nested function of a larger function. What this guy does is come up with a pseudo-random number that can be any number starting with "minvalue" up to "maxvalue". The reason it is called a "pseudo-random" number is that if you did nothing but call this function and your computer executed the exact same number of machine cycles between each number's output, the results would eventually form a repeating pattern and as such would be predictable and not truly random. In practice, however, the results are random enough for anything one might want to use the function for. Mostly, it is used to generate random notes or timing offsets for making computer generated music or "humanizing" (fluctuating slightly) the starting times of notes that have been hand-entered or quantized.