SCDoc: Use proper static string constants instead of comparing string literals.
[supercollider.git] / HelpSource / Overviews / Operators.schelp
blob28fd27329385691c2ec2612a1fcacb7c7b40c051
1 title:: Operators
2 categories:: Language, Common methods
3 summary:: common unary and binary operators
4 related:: Reference/Adverbs
6 SuperCollider supports operator overloading. Operators can thus be applied to a variety of different objects; Numbers, Ugens, Collections, and so on. When operators are applied to ugens they result in link::Classes/BinaryOpUGen::s or link::Classes/UnaryOpUGen::s, through the methods of link::Classes/AbstractFunction::.
8 This is a list of some of the common unary and binary operators that are implemented by several classes.
9 See the specific classes for details and other operators.
11 You can see which classes implements a specific operator by clicking on the method name.
13 section:: Unary Operators
14 Unary operators may be written in two ways:
15 code::
16 a.operator
17 operator(a)
20 method:: neg
21 Inversion.
22 discussion::
23 code::
25         var a;
26         a = FSinOsc.ar(300);
27         [ a, a.neg ]
28 }.plot
31 method:: reciprocal
32 Reciprocal (1/x).
34 method:: abs
35 Absolute value.
37 method:: floor
38 Next lower integer.
39 discussion::
40 code::
42         var a;
43         a = Line.ar(-1, 1, 0.01);
44         [ a, a.floor ]
45 }.plot
48 method:: ceil
49 Next higher integer.
50 discussion::
51 code::
53         var a;
54         a = Line.ar(-1, 1, 0.01);
55         [ a, a.ceil ]
56 }.plot
59 method:: frac
60 Fractional part.
62 method:: sign
63 Sign function.
64 returns::
65 -1 when a < 0, +1 when a > 0, 0 when a is 0
67 method:: squared
68 Squared value.
69 returns::
70 code:: a*a ::
72 method:: cubed
73 Cubed value.
74 returns::
75 code:: a*a*a ::
77 method:: sqrt
78 Square root.
79 discussion::
80 The definition of square root is extended for signals so that sqrt(a) when a<0 returns
81 -sqrt(-a).
83 method:: exp
84 Exponential.
86 method:: midicps
87 Convert MIDI note number to cycles per second.
88 discussion::
89 code::
91         Saw.ar(Line.kr(24,108,10).midicps, 0.2)
92 }.play
95 method:: cpsmidi
96 Convert cycles per second to MIDI note.
98 method:: midiratio
99 Convert an interval in MIDI notes into a frequency ratio.
101 method:: ratiomidi
102 Convert a frequency ratio to an interval in MIDI notes.
104 method:: dbamp
105 Convert decibels to linear amplitude.
107 method:: ampdb
108 Convert linear amplitude to decibels.
110 method:: octcps
111 Convert decimal octaves to cycles per second.
113 method:: cpsoct
114 Convert cycles per second to decimal octaves.
116 method:: log
117 Natural logarithm.
118 discussion::
119 code::
121         var a, e;
122         e = exp(1);
123         a = Line.ar(e, 1/e, 0.01);
124         a.log
125 }.plot
128 method:: log2
129 Base 2 logarithm.
131 method:: log10
132 Base 10 logarithm.
134 method:: sin
135 Sine.
137 method:: cos
138 Cosine.
140 method:: tan
141 Tangent.
143 method:: asin
144 Arcsine.
146 method:: acos
147 Arccosine.
149 method:: atan
150 Arctangent.
152 method:: sinh
153 Hyperbolic sine.
155 method:: cosh
156 Hyperbolic cosine.
158 method:: tanh
159 Hyperbolic tangent.
161 method:: distort
162 Nonlinear distortion.
163 discussion::
164 code::
167         var a;
168         a = Line.ar(-4, 4, 0.01);
169         a.distort
170 }.plot
173 { FSinOsc.ar(500, 0.0, XLine.kr(0.1, 10, 10)).distort * 0.25 }.scope;
176 method:: softclip
177 Nonlinear distortion.
178 discussion::
179 Distortion with a perfectly linear region from -0.5 to +0.5
180 code::
183         var a;
184         a = Line.ar(-2, 2, 0.01);
185         a.softclip
186 }.plot
190 { FSinOsc.ar(500,0.0, XLine.kr(0.1, 10, 10)).softclip * 0.25 }.scope(2);
193 method:: isPositive
194 Test if signal is >= 0.
196 method:: isNegative
197 Test if signal is < 0.
199 method:: isStrictlyPositive
200 Test if signal is > 0.
202 section:: Binary Operators
203 Three different syntaxes can be used for binary operators consisting of letters:
204 code::
205 operator(a, b)
207 a operator: b
209 a.operator(b)
211 Operators consisting of symbols are written like this:
212 code::
213 a + b
216 subsection:: Arithmetics
218 method:: +
219 Addition.
221 method:: -
222 Subtraction.
224 method:: *
225 Multiplication.
227 method:: /
228 Division.
230 method:: %
231 Floating point modulo.
233 method:: **
234 Exponentiation. When used with UGens which produce a negative signal this function extends the usual definition of
235 exponentiation and returns neg(neg(a) ** b). This allows exponentiation of negative signal values by noninteger exponents. For the normal behaviour use pow (see below).
237 method:: pow
238 Exponentiation.
240 subsection:: Comparisions
242 method:: <
243 Less than.
245 method:: <=
246 Less than or equal.
248 method:: >
249 Greater than.
250 discussion::
251 With UGens, this can be useful for triggering purposes, among other things:
252 code::
253 { // trigger an envelope
254         var trig;
255         trig = SinOsc.ar(1) > 0;
256         Out.ar(0,
257                 EnvGen.kr(Env.perc, trig, doneAction: 0)
258                         * SinOsc.ar(440,0,0.1)
259         )
260 }.play(s);
262 ( // trigger a synth
263 SynthDef("help-EnvGen",{ arg out=0;
264         Out.ar(out,
265                 EnvGen.kr(Env.perc,1.0,doneAction: 2)
266                         * SinOsc.ar(440,0,0.1)
267         )
268 }).send(s);
270 // This synth has no output. It only checks amplitude of input and looks for a transition from < 0.2
271 // to > 0.2
273 SynthDef("help-> trig", {
274         SendTrig.kr(Amplitude.kr(SoundIn.ar(0)) > 0.2);
275 }).play(s);
277 // OSCFunc to trigger synth
278 OSCFunc({ "triggered".postln; Synth.new("help-EnvGen") },'/tr', s.addr);
282 method:: >=
283 Greater than or equal.
285 method:: ==
286 Equal.
288 method:: !=
289 Not equal.
291 subsection:: Other
293 method:: <!
294 Return first argument.
296 method:: min
297 Minimum.
298 discussion::
299 code::
300 { // distorts and envelopes z
301 var z;
302 z = FSinOsc.ar(500);
303 z min: FSinOsc.ar(0.1);
304 }.play;
307 method:: max
308 Maximum.
309 discussion::
310 code::
311 { // modulates and envelopes z
312 var z;
313 z = FSinOsc.ar(500);
314 z max: FSinOsc.ar(0.1);
315 }.play;
318 method:: round
319 Quantization by rounding. Rounds a to the nearest multiple of b.
321 method:: trunc
322 Quantization by truncation. Truncate a to a multiple of b.
324 method:: hypot
325 Hypotenuse. Returns the square root of the sum of the squares of a and b. Or equivalently, the distance from the origin
326 to the point (x, y).
327 discussion::
328 In this example, hypot is used to calculate a doppler shift pitch and amplitude based on distance.
329 code::
332         var x, y, distance, velocity, pitchRatio, amplitude;
333         // object travels 200 meters in 6 secs (=120kph) passing 10 meters
334         // from the listener
335         x = 10;
336         y = LFSaw.kr(1/6, 0, 100);
337         distance = hypot(x, y);
338         velocity = Slope.kr(distance);
339         pitchRatio = (344 - velocity) / 344;  // speed of sound is 344 meters/sec
340         amplitude = 10 / distance.squared;
341         FSinOsc.ar(1000 * pitchRatio, 0, amplitude)
342 }.play)
344 The next example uses the distance to modulate a delay line.
345 code::
348         var x, y, distance, velocity, pitchRatio, amplitude, motorSound;
349         // object travels 200 meters in 6 secs (=120kph) passing 10 meters
350         // from the listener
351         x = 10;
352         y = LFSaw.kr(1/6, 0, 100);
353         distance = hypot(x, y);
354         amplitude = 40 / distance.squared;
355         motorSound = RLPF.ar(FSinOsc.ar(200, 0, LFPulse.ar(31.3, 0, 0.4)), 400, 0.3);
356         DelayL.ar(motorSound, 110/344, distance/344, amplitude)
357 }.play)
360 method:: hypotApx
361 Hypotenuse approximation. Returns an approximation of the square root of the sum of the squares of x and y.
362 discussion::
363 The formula used is :
364 code::
365 abs(x) + abs(y) - ((sqrt(2) - 1) * min(abs(x), abs(y)))
367 hypotApx is used to implement Complex method magnitudeApx.
368 This should not be used for simulating a doppler shift because it is discontinuous. Use hypot.
370 See also link::#.hypot::, link::#.atan2::.
372 method:: atan2
373 Returns the arctangent of y/x.
374 discussion::
375 OK, now we can add a pan to the link::#.hypot:: doppler examples by using atan2 to find the azimuth,
376 or direction angle, of the sound source.
377 Assume speakers at +/- 45 degrees and clip the direction to between those.
378 code::
381         var x, y, distance, velocity, pitchRatio, amplitude, azimuth, panValue;
382         // object travels 200 meters in 6 secs (=120kph) passing 10 meters
383         // from the listener
384         x = 10;
385         y = LFSaw.kr(1/6, 0, 100);
386         distance = hypot(x, y);
387         velocity = Slope.kr(distance);
388         pitchRatio = (344 - velocity) / 344;  // speed of sound is 344 meters/sec
389         amplitude = 10 / distance.squared;
390         azimuth = atan2(y, x); // azimuth in radians
391         panValue = (azimuth / 0.5pi).clip2(1);
392         Pan2.ar(FSinOsc.ar(1000 * pitchRatio), panValue, amplitude)
393 }.play)
397         var x, y, distance, velocity, pitchRatio, amplitude, motorSound,
398                         azimuth, panValue;
399         // object travels 200 meters in 6 secs (=120kph) passing 10 meters
400         // from the listener
401         x = 10;
402         y = LFSaw.kr(1/6, 0, 100);
403         distance = hypot(x, y);
404         amplitude = 40 / distance.squared;
405         motorSound = RLPF.ar(FSinOsc.ar(200, 0, LFPulse.ar(31.3, 0, 0.4)), 400, 0.3);
406         azimuth = atan2(y, x); // azimuth in radians
407         panValue = (azimuth / 0.5pi).clip2(1); // make a value for Pan2 from azimuth
408         Pan2.ar(DelayL.ar(motorSound, 110/344, distance/344), panValue, amplitude)
409 }.play)
412 method:: ring1
413 Ring modulation plus first source.
414 discussion::
415 Return the value of  ((a*b) + a). This is more efficient than using
416 separate unit generators for the multiply and add.
418 See also link::#.*::, link::#.ring1::, link::#.ring2::, link::#.ring3::, link::#.ring4::.
419 code::
420 { (FSinOsc.ar(800) ring1: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
422 same as :
423 code::
426         var a, b;
427         a = FSinOsc.ar(800);
428         b = FSinOsc.ar(XLine.kr(200,500,5));
429         ((a * b) + a) * 0.125
430 }.play)
432 normal ring modulation:
433 code::
436         var a, b;
437         a = FSinOsc.ar(800);
438         b = FSinOsc.ar(XLine.kr(200,500,5));
439         (a * b) * 0.125
440 }.play)
443 method:: ring2
444 Ring modulation plus both sources.
445 discussion::
446 Return the value of  ((a*b) + a + b). This is more efficient than using
447 separate unit generators for the multiply and adds.
448 code::
449 { (FSinOsc.ar(800) ring2: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
451 same as :
452 code::
455         var a, b;
456         a = FSinOsc.ar(800);
457         b = FSinOsc.ar(XLine.kr(200,500,5));
458         ((a * b) + a + b) * 0.125
459 }.play)
462 method:: ring3
463 Ring modulation variant.
464 discussion::
465 Return the value of  (a*a *b). This is more efficient than using
466 separate unit generators for each multiply.
467 code::
468 { (FSinOsc.ar(800) ring3: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
470 same as :
471 code::
474         var a, b;
475         a = FSinOsc.ar(800);
476         b = FSinOsc.ar(XLine.kr(200,500,5));
477         (a * a * b) * 0.125;
478 }.play)
481 method:: ring4
482 Ring modulation variant.
483 discussion::
484 Return the value of  ((a*a *b) - (a*b*b)). This is more efficient than using
485 separate unit generators for each operation.
486 code::
487 { (FSinOsc.ar(800) ring4: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
489 same as :
490 code::
493         var a, b;
494         a = FSinOsc.ar(800);
495         b = FSinOsc.ar(XLine.kr(200,500,5));
496         ((a * a * b) - (a * b * b)) * 0.125
497 }.play)
500 method:: sumsqr
501 Sum of squares.
502 discussion::
503 Return the value of  (a*a) + (b*b). This is more efficient than using
504 separate unit generators for each operation.
505 code::
506 { (FSinOsc.ar(800) sumsqr: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
508 same as :
509 code::
512         var a, b;
513         a = FSinOsc.ar(800);
514         b = FSinOsc.ar(XLine.kr(200,500,5));
515         ((a * a) + (b * b)) * 0.125
516 }.play)
519 method:: difsqr
520 Difference of squares.
521 discussion::
522 Return the value of  (a*a) - (b*b). This is more efficient than using
523 separate unit generators for each operation.
524 code::
525 { (FSinOsc.ar(800) difsqr: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
527 same as :
528 code::
531         var a, b;
532         a = FSinOsc.ar(800);
533         b = FSinOsc.ar(XLine.kr(200,500,5));
534         ((a * a) - (b * b)) * 0.125
535 }.play)
538 method:: sqrsum
539 Square of the sum.
540 discussion::
541 Return the value of  (a + b)**2. This is more efficient than using
542 separate unit generators for each operation.
543 code::
544 { (FSinOsc.ar(800) sqrsum: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
546 same as :
547 code::
550         var a, b, c;
551         a = FSinOsc.ar(800);
552         b = FSinOsc.ar(XLine.kr(200,500,5));
553         c = a + b;
554         (c * c) * 0.125
555 }.play)
558 method:: sqrdif
559 Square of the difference.
560 discussion::
561 Return the value of  (a - b)**2. This is more efficient than using
562 separate unit generators for each operation.
563 code::
564 { (FSinOsc.ar(800) sqrdif: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
566 same as :
567 code::
570         var a, b, c;
571         a = FSinOsc.ar(800);
572         b = FSinOsc.ar(XLine.kr(200,500,5));
573         c = a - b;
574         (c * c) * 0.125
575 }.play)
578 method:: absdif
579 Absolute value of the difference. code:: abs(a - b) ::
580 discussion::
581 code::
582 { // creates a rhythm
583 var mul;
584 mul = 0.2 absdif: FSinOsc.ar(2, 0, 0.5);
585 FSinOsc.ar(440, 0, mul);
586 }.play;
589 method:: thresh
590 Thresholding.
591 discussion::
592 0 when a < b, otherwise a.
593 code::
594 { LFNoise0.ar(50, 0.5) thresh: 0.45 }.play // a low-rent gate
597 method:: amclip
598 Two quadrant multiply.
599 discussion::
600 0  when  b <= 0,  a*b  when  b > 0
601 code::
602 { WhiteNoise.ar.amclip(FSinOsc.kr(1,0.2)) }.play; // makes a sine envelope
605 method:: scaleneg
606 Scale negative part of input.
607 discussion::
608 a*b when a < 0, otherwise a.
609 code::
610 { FSinOsc.ar(500).scaleneg(Line.ar(1,-1,4)) }.play;
613 method:: clip2
614 Bilateral clipping.
615 discussion::
616 clips input wave a to +/- b
617 code::
620         var a;
621         a = Line.ar(-2, 2, 0.01);
622         a.clip2
623 }.plot2
626 { FSinOsc.ar(400).clip2(0.2) }.scope; // clipping distortion
628 { FSinOsc.ar(1000).clip2(Line.kr(0,1,8)) }.scope;
631 method:: wrap2
632 Bilateral wrapping.
633 discussion::
634 wraps input wave to +/- b
635 code::
638         var a;
639         a = Line.ar(-2, 2, 0.01);
640         a.wrap2
641 }.plot
644 { FSinOsc.ar(1000).wrap2(Line.kr(0,1.01,8)) }.scope;
647 method:: fold2
648 Bilateral folding.
649 discussion::
650 folds input wave a to +/- b
651 code::
654         var a;
655         a = Line.ar(-2, 2, 0.01);
656         a.fold2
657 }.plot
661 { FSinOsc.ar(1000).fold2(Line.kr(0,1,8)) }.scope;
664 method:: excess
665 Residual of clipping.
666 discussion::
667 Returns the difference of the original signal and its clipped form: (a - clip2(a,b)).
668 code::
671         var a;
672         a = Line.ar(-2, 2, 0.01);
673         a.excess
674 }.plot
677 { FSinOsc.ar(1000).excess(Line.kr(0,1,8)) }.play;