845 lines
17 KiB
Text
845 lines
17 KiB
Text
|
title:: Operators
|
||
|
categories:: Language, Common methods
|
||
|
summary:: common unary and binary operators
|
||
|
related:: Reference/Adverbs
|
||
|
|
||
|
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::.
|
||
|
|
||
|
This is a list of some of the common unary and binary operators that are implemented by several classes.
|
||
|
See the specific classes for details and other operators.
|
||
|
|
||
|
You can see which classes implements a specific operator by clicking on the method name.
|
||
|
|
||
|
section:: Unary Operators
|
||
|
Unary operators may be written in two ways:
|
||
|
code::
|
||
|
a.operator
|
||
|
operator(a)
|
||
|
::
|
||
|
|
||
|
|
||
|
subsection:: Arithmetics
|
||
|
|
||
|
method:: neg
|
||
|
Inversion.
|
||
|
discussion::
|
||
|
code::
|
||
|
{
|
||
|
var a;
|
||
|
a = FSinOsc.ar(300);
|
||
|
[ a, a.neg ]
|
||
|
}.plot
|
||
|
::
|
||
|
|
||
|
method:: reciprocal
|
||
|
Reciprocal (1/x).
|
||
|
|
||
|
method:: abs
|
||
|
Absolute value.
|
||
|
|
||
|
method:: floor
|
||
|
Next lower integer.
|
||
|
discussion::
|
||
|
code::
|
||
|
{
|
||
|
var a;
|
||
|
a = Line.ar(-1, 1, 0.01);
|
||
|
[ a, a.floor ]
|
||
|
}.plot
|
||
|
::
|
||
|
|
||
|
method:: ceil
|
||
|
Next higher integer.
|
||
|
discussion::
|
||
|
code::
|
||
|
{
|
||
|
var a;
|
||
|
a = Line.ar(-1, 1, 0.01);
|
||
|
[ a, a.ceil ]
|
||
|
}.plot
|
||
|
::
|
||
|
|
||
|
method:: frac
|
||
|
Fractional part.
|
||
|
|
||
|
method:: sign
|
||
|
Sign function.
|
||
|
returns::
|
||
|
-1 when a < 0, +1 when a > 0, 0 when a is 0
|
||
|
|
||
|
method:: squared
|
||
|
Squared value.
|
||
|
returns::
|
||
|
code:: a*a ::
|
||
|
|
||
|
method:: cubed
|
||
|
Cubed value.
|
||
|
returns::
|
||
|
code:: a*a*a ::
|
||
|
|
||
|
method:: sqrt
|
||
|
Square root.
|
||
|
discussion::
|
||
|
The definition of square root is extended for signals so that sqrt(a) when a<0 returns
|
||
|
-sqrt(-a).
|
||
|
|
||
|
method:: exp
|
||
|
Exponential.
|
||
|
|
||
|
|
||
|
subsection:: Musical acoustics
|
||
|
|
||
|
|
||
|
method:: midicps
|
||
|
Convert MIDI note number to cycles per second.
|
||
|
discussion::
|
||
|
code::
|
||
|
{
|
||
|
Saw.ar(Line.kr(24,108,10).midicps, 0.2)
|
||
|
}.play
|
||
|
::
|
||
|
|
||
|
method:: cpsmidi
|
||
|
Convert cycles per second to MIDI note.
|
||
|
|
||
|
method:: midiratio
|
||
|
Convert an interval in MIDI notes into a frequency ratio.
|
||
|
|
||
|
method:: ratiomidi
|
||
|
Convert a frequency ratio to an interval in MIDI notes.
|
||
|
|
||
|
method:: dbamp
|
||
|
Convert decibels to linear amplitude.
|
||
|
|
||
|
method:: ampdb
|
||
|
Convert linear amplitude to decibels.
|
||
|
|
||
|
method:: octcps
|
||
|
Convert decimal octaves to cycles per second.
|
||
|
|
||
|
method:: cpsoct
|
||
|
Convert cycles per second to decimal octaves.
|
||
|
|
||
|
subsection:: Random operators
|
||
|
|
||
|
See also link::Guides/Randomness::
|
||
|
|
||
|
method::rand
|
||
|
Returns an evenly distributed random value between this and zero.
|
||
|
code::
|
||
|
10.rand;
|
||
|
|
||
|
{ SinOsc.ar(110).rand }.plot;
|
||
|
::
|
||
|
|
||
|
method::rand2
|
||
|
Returns an evenly distributed random value between [+this ... - this].
|
||
|
code::
|
||
|
10.rand2;
|
||
|
|
||
|
{ SinOsc.ar(110).rand2 }.plot;
|
||
|
::
|
||
|
|
||
|
method::linrand
|
||
|
Returns a linearly distributed random value between this and zero.
|
||
|
code::
|
||
|
10.linrand;
|
||
|
|
||
|
{ SinOsc.ar(110).linrand }.plot;
|
||
|
::
|
||
|
|
||
|
|
||
|
method::bilinrand
|
||
|
Returns a linearly distributed random value between [+this ... - this].
|
||
|
code::
|
||
|
10.bilinrand;
|
||
|
|
||
|
{ SinOsc.ar(110).bilinrand }.plot;
|
||
|
::
|
||
|
|
||
|
method::sum3rand
|
||
|
Returns a value from a gaussian-like random distribution between this and zero.
|
||
|
Larry Polansky's poor man's gaussian generator, follows the formula:
|
||
|
|
||
|
code::
|
||
|
{ 1.0.rand }.dup(3).sum - 1.5 * (2/3)
|
||
|
::
|
||
|
|
||
|
code::
|
||
|
10.sum3rand;
|
||
|
|
||
|
{ SinOsc.ar(110).sum3rand }.plot;
|
||
|
::
|
||
|
|
||
|
method::coin
|
||
|
Returns one or zero with the probability given by the argument.
|
||
|
code::
|
||
|
0.4.coin;
|
||
|
|
||
|
{ SinOsc.ar(110).coin }.plot;
|
||
|
::
|
||
|
|
||
|
|
||
|
subsection:: Other
|
||
|
|
||
|
|
||
|
method:: log
|
||
|
Natural logarithm.
|
||
|
discussion::
|
||
|
code::
|
||
|
{
|
||
|
var a, e;
|
||
|
e = exp(1);
|
||
|
a = Line.ar(e, 1/e, 0.01);
|
||
|
a.log
|
||
|
}.plot
|
||
|
::
|
||
|
|
||
|
method:: log2
|
||
|
Base 2 logarithm.
|
||
|
|
||
|
method:: log10
|
||
|
Base 10 logarithm.
|
||
|
|
||
|
method:: sin
|
||
|
Sine.
|
||
|
|
||
|
method:: cos
|
||
|
Cosine.
|
||
|
|
||
|
method:: tan
|
||
|
Tangent.
|
||
|
|
||
|
method:: asin
|
||
|
Arcsine.
|
||
|
|
||
|
method:: acos
|
||
|
Arccosine.
|
||
|
|
||
|
method:: atan
|
||
|
Arctangent.
|
||
|
|
||
|
method:: sinh
|
||
|
Hyperbolic sine.
|
||
|
|
||
|
method:: cosh
|
||
|
Hyperbolic cosine.
|
||
|
|
||
|
method:: tanh
|
||
|
Hyperbolic tangent.
|
||
|
|
||
|
method:: distort
|
||
|
Nonlinear distortion.
|
||
|
discussion::
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a;
|
||
|
a = Line.ar(-4, 4, 0.01);
|
||
|
a.distort
|
||
|
}.plot
|
||
|
)
|
||
|
|
||
|
{ FSinOsc.ar(500, 0.0, XLine.kr(0.1, 10, 10)).distort * 0.25 }.scope;
|
||
|
::
|
||
|
|
||
|
method:: softclip
|
||
|
Nonlinear distortion.
|
||
|
discussion::
|
||
|
Distortion with a perfectly linear region from -0.5 to +0.5
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a;
|
||
|
a = Line.ar(-2, 2, 0.01);
|
||
|
a.softclip
|
||
|
}.plot
|
||
|
)
|
||
|
|
||
|
|
||
|
{ FSinOsc.ar(500,0.0, XLine.kr(0.1, 10, 10)).softclip * 0.25 }.scope(2);
|
||
|
::
|
||
|
|
||
|
method:: isPositive
|
||
|
Test if signal is >= 0.
|
||
|
|
||
|
method:: isNegative
|
||
|
Test if signal is < 0.
|
||
|
|
||
|
method:: isStrictlyPositive
|
||
|
Test if signal is > 0.
|
||
|
|
||
|
section:: Binary Operators
|
||
|
Three different syntaxes can be used for binary operators consisting of letters:
|
||
|
code::
|
||
|
operator(a, b)
|
||
|
|
||
|
a operator: b
|
||
|
|
||
|
a.operator(b)
|
||
|
::
|
||
|
Operators consisting of symbols are written like this:
|
||
|
code::
|
||
|
a + b
|
||
|
::
|
||
|
|
||
|
subsection:: Arithmetics
|
||
|
|
||
|
method:: +
|
||
|
Addition.
|
||
|
|
||
|
method:: -
|
||
|
Subtraction.
|
||
|
|
||
|
method:: *
|
||
|
Multiplication.
|
||
|
|
||
|
method:: /
|
||
|
Division.
|
||
|
|
||
|
method:: %
|
||
|
Floating point modulo.
|
||
|
|
||
|
method:: **
|
||
|
Exponentiation. When used with UGens which produce a negative signal this function extends the usual definition of
|
||
|
exponentiation and returns code::neg(neg(a) ** b)::. This allows exponentiation of negative signal values by noninteger exponents. For the normal behaviour use pow (see below).
|
||
|
|
||
|
method:: pow
|
||
|
Exponentiation.
|
||
|
|
||
|
method:: lcm
|
||
|
Least common multiple. This definition extends the usual definition and returns a negative number if strong::any of the operands:: is negative. This makes it consistent with the lattice-theoretical interpretation and its idempotency, commutative, associative, absorption laws.
|
||
|
|
||
|
Following the example of the programming language J (see: link::Guides/J-concepts-in-SC::), lcm is analogous to logical strong::and:: (see also: link::http://www.jsoftware.com/papers/eem/gcd.htm::).
|
||
|
|
||
|
|
||
|
code::
|
||
|
lcm(4, 6);
|
||
|
lcm(1, 1); // and
|
||
|
lcm(1624, 26);
|
||
|
lcm(1624, -26);
|
||
|
lcm(-1624, -26);
|
||
|
lcm(513, gcd(513, 44)) // absorption law -> 513.
|
||
|
::
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var mx = MouseX.kr(-20, 20);
|
||
|
var my = MouseY.kr(-20, 20);
|
||
|
SinOsc.ar(SinOsc.kr(0.3) * 20 lcm: [mx, my] * 30 + 500) * 0.1
|
||
|
}.play;
|
||
|
)
|
||
|
::
|
||
|
|
||
|
|
||
|
method:: gcd
|
||
|
Greatest common divisor. This definition extends the usual definition and returns a negative number if strong::both operands:: are negative. This makes it consistent with the lattice-theoretical interpretation and its idempotency, commutative, associative, absorption laws.
|
||
|
|
||
|
"greater" means "divisible by" in this interpretation, so code::gcd(-1, -1):: returns a negative number. This is necessary to make the whole system consistent (fundamental law of arithmetics, idempotency and absorption laws would fail). See examples below.
|
||
|
|
||
|
Following the example of the programming language J (see: link::Guides/J-concepts-in-SC::), gcd is analogous to logical strong::or:: (see also: link::http://www.jsoftware.com/papers/eem/gcd.htm::).
|
||
|
|
||
|
code::
|
||
|
gcd(4, 6);
|
||
|
gcd(0, 1); // or
|
||
|
gcd(1024, 256);
|
||
|
gcd(1024, -256);
|
||
|
gcd(-1024, -256); // "greater" means "divisible by" in this case, so this returns a negative number.
|
||
|
gcd(-1024, lcm(-1024, 256)) // absorption law -> -1024.
|
||
|
gcd(66, 54) * lcm(66, 54) == (66 * 54); // true
|
||
|
::
|
||
|
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var mx = MouseX.kr(-200, 200);
|
||
|
var my = MouseY.kr(-200, 200);
|
||
|
SinOsc.ar(SinOsc.kr(0.3) * 20 gcd: [mx, my] * 30 + 500) * 0.1
|
||
|
}.play;
|
||
|
)
|
||
|
::
|
||
|
|
||
|
Here is an overview of how negative numbers are treated:
|
||
|
|
||
|
code::
|
||
|
|
||
|
lcm(4, 6) // -> 12. "least multiple" interpreted as smallest in Z
|
||
|
lcm(4, -6) // -> -12 "least multiple" interpreted as smallest in Z
|
||
|
lcm(-4, -6) // -> -12 "least multiple" interpreted as smallest in Z
|
||
|
|
||
|
gcd(4, 6) // -> 2 "greatest divisor" interpreted as highest in Z
|
||
|
gcd(4, -6) // -> 2 "greatest divisor" is interpreted as highest in Z
|
||
|
gcd(-4, -6) // -> -2 "greatest divisor" is interpreted as *inverse* in Z. This is the only necessary asymmetry.
|
||
|
::
|
||
|
|
||
|
|
||
|
subsection:: Comparisons
|
||
|
|
||
|
method:: <
|
||
|
Less than.
|
||
|
|
||
|
method:: <=
|
||
|
Less than or equal.
|
||
|
|
||
|
method:: >
|
||
|
Greater than.
|
||
|
discussion::
|
||
|
With UGens, this can be useful for triggering purposes, among other things:
|
||
|
code::
|
||
|
(
|
||
|
{ // trigger an envelope
|
||
|
var trig;
|
||
|
trig = SinOsc.ar(1) > 0;
|
||
|
Out.ar(0,
|
||
|
EnvGen.kr(Env.perc, trig, doneAction: Done.none)
|
||
|
* SinOsc.ar(440,0,0.1)
|
||
|
)
|
||
|
}.play
|
||
|
)
|
||
|
|
||
|
// trigger a synth
|
||
|
(
|
||
|
SynthDef("help-EnvGen",{ arg out=0;
|
||
|
Out.ar(out,
|
||
|
EnvGen.kr(Env.perc,1.0,doneAction: Done.freeSelf)
|
||
|
* SinOsc.ar(440,0,0.1)
|
||
|
)
|
||
|
}).add;
|
||
|
|
||
|
// This synth has no output. It only checks amplitude of input and looks for a transition from < 0.2
|
||
|
// to > 0.2
|
||
|
|
||
|
{ SendTrig.kr(Amplitude.kr(SoundIn.ar(0)) > 0.2) }.play;
|
||
|
|
||
|
// OSCFunc to trigger synth
|
||
|
OSCFunc({ "triggered".postln; Synth.new("help-EnvGen") },'/tr', s.addr);
|
||
|
)
|
||
|
::
|
||
|
|
||
|
method:: >=
|
||
|
Greater than or equal.
|
||
|
|
||
|
method:: ==
|
||
|
Equal.
|
||
|
|
||
|
method:: !=
|
||
|
Not equal.
|
||
|
|
||
|
subsection:: Other
|
||
|
|
||
|
method:: <!
|
||
|
Return first argument.
|
||
|
|
||
|
code::
|
||
|
// this is useful when two ugens need to be called, but only one of their outputs is needed
|
||
|
(
|
||
|
{
|
||
|
var a, b, c;
|
||
|
a = Dseq([1, 2, 3, 4], inf).dpoll("a");
|
||
|
b = Dseq([1955, 1952, 1823, 1452], inf).dpoll("b");
|
||
|
c = (a <! b).dpoll("------> a <! b = "); // c only
|
||
|
Duty.kr(0.4, 0, c);
|
||
|
0.0
|
||
|
}.play
|
||
|
)
|
||
|
::
|
||
|
|
||
|
method:: min
|
||
|
Minimum.
|
||
|
discussion::
|
||
|
code::
|
||
|
{ // distorts and envelopes z
|
||
|
var z;
|
||
|
z = FSinOsc.ar(500);
|
||
|
z min: FSinOsc.ar(0.1);
|
||
|
}.play;
|
||
|
::
|
||
|
|
||
|
method:: max
|
||
|
Maximum.
|
||
|
discussion::
|
||
|
code::
|
||
|
{ // modulates and envelopes z
|
||
|
var z;
|
||
|
z = FSinOsc.ar(500);
|
||
|
z max: FSinOsc.ar(0.1);
|
||
|
}.play;
|
||
|
::
|
||
|
|
||
|
method:: round
|
||
|
Quantization by rounding. Rounds a to the nearest multiple of b.
|
||
|
|
||
|
method:: trunc
|
||
|
Quantization by truncation. Truncate a to a multiple of b.
|
||
|
|
||
|
method:: hypot
|
||
|
Hypotenuse. Returns the square root of the sum of the squares of a and b. Or equivalently, the distance from the origin
|
||
|
to the point (x, y).
|
||
|
discussion::
|
||
|
In this example, hypot is used to calculate a doppler shift pitch and amplitude based on distance.
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var x, y, distance, velocity, pitchRatio, amplitude;
|
||
|
// object travels 200 meters in 6 secs (=120kph) passing 10 meters
|
||
|
// from the listener
|
||
|
x = 10;
|
||
|
y = LFSaw.kr(1/6, 0, 100);
|
||
|
distance = hypot(x, y);
|
||
|
velocity = Slope.kr(distance);
|
||
|
pitchRatio = (344 - velocity) / 344; // speed of sound is 344 meters/sec
|
||
|
amplitude = 10 / distance.squared;
|
||
|
FSinOsc.ar(1000 * pitchRatio, 0, amplitude)
|
||
|
}.play)
|
||
|
::
|
||
|
The next example uses the distance to modulate a delay line.
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var x, y, distance, velocity, pitchRatio, amplitude, motorSound;
|
||
|
// object travels 200 meters in 6 secs (=120kph) passing 10 meters
|
||
|
// from the listener
|
||
|
x = 10;
|
||
|
y = LFSaw.kr(1/6, 0, 100);
|
||
|
distance = hypot(x, y);
|
||
|
amplitude = 40 / distance.squared;
|
||
|
motorSound = RLPF.ar(FSinOsc.ar(200, 0, LFPulse.ar(31.3, 0, 0.4)), 400, 0.3);
|
||
|
DelayL.ar(motorSound, 110/344, distance/344, amplitude)
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: hypotApx
|
||
|
Hypotenuse approximation. Returns an approximation of the square root of the sum of the squares of x and y.
|
||
|
discussion::
|
||
|
The formula used is :
|
||
|
code::
|
||
|
abs(x) + abs(y) - ((sqrt(2) - 1) * min(abs(x), abs(y)))
|
||
|
::
|
||
|
hypotApx is used to implement Complex method magnitudeApx.
|
||
|
This should not be used for simulating a doppler shift because it is discontinuous. Use hypot.
|
||
|
|
||
|
See also link::#.hypot::, link::#.atan2::.
|
||
|
|
||
|
method:: atan2
|
||
|
Returns the arctangent of y/x.
|
||
|
discussion::
|
||
|
OK, now we can add a pan to the link::#.hypot:: doppler examples by using atan2 to find the azimuth,
|
||
|
or direction angle, of the sound source.
|
||
|
Assume speakers at +/- 45 degrees and clip the direction to between those.
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var x, y, distance, velocity, pitchRatio, amplitude, azimuth, panValue;
|
||
|
// object travels 200 meters in 6 secs (=120kph) passing 10 meters
|
||
|
// from the listener
|
||
|
x = 10;
|
||
|
y = LFSaw.kr(1/6, 0, 100);
|
||
|
distance = hypot(x, y);
|
||
|
velocity = Slope.kr(distance);
|
||
|
pitchRatio = (344 - velocity) / 344; // speed of sound is 344 meters/sec
|
||
|
amplitude = 10 / distance.squared;
|
||
|
azimuth = atan2(y, x); // azimuth in radians
|
||
|
panValue = (azimuth / 0.5pi).clip2(1);
|
||
|
Pan2.ar(FSinOsc.ar(1000 * pitchRatio), panValue, amplitude)
|
||
|
}.play)
|
||
|
|
||
|
(
|
||
|
{
|
||
|
var x, y, distance, velocity, pitchRatio, amplitude, motorSound,
|
||
|
azimuth, panValue;
|
||
|
// object travels 200 meters in 6 secs (=120kph) passing 10 meters
|
||
|
// from the listener
|
||
|
x = 10;
|
||
|
y = LFSaw.kr(1/6, 0, 100);
|
||
|
distance = hypot(x, y);
|
||
|
amplitude = 40 / distance.squared;
|
||
|
motorSound = RLPF.ar(FSinOsc.ar(200, 0, LFPulse.ar(31.3, 0, 0.4)), 400, 0.3);
|
||
|
azimuth = atan2(y, x); // azimuth in radians
|
||
|
panValue = (azimuth / 0.5pi).clip2(1); // make a value for Pan2 from azimuth
|
||
|
Pan2.ar(DelayL.ar(motorSound, 110/344, distance/344), panValue, amplitude)
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: ring1
|
||
|
Ring modulation plus first source.
|
||
|
discussion::
|
||
|
Return the value of ((a*b) + a). This is more efficient than using
|
||
|
separate unit generators for the multiply and add.
|
||
|
|
||
|
See also link::#.*::, link::#.ring1::, link::#.ring2::, link::#.ring3::, link::#.ring4::.
|
||
|
code::
|
||
|
{ (FSinOsc.ar(800) ring1: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
|
||
|
::
|
||
|
same as :
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
((a * b) + a) * 0.125
|
||
|
}.play)
|
||
|
::
|
||
|
normal ring modulation:
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
(a * b) * 0.125
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: ring2
|
||
|
Ring modulation plus both sources.
|
||
|
discussion::
|
||
|
Return the value of ((a*b) + a + b). This is more efficient than using
|
||
|
separate unit generators for the multiply and adds.
|
||
|
code::
|
||
|
{ (FSinOsc.ar(800) ring2: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
|
||
|
::
|
||
|
same as :
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
((a * b) + a + b) * 0.125
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: ring3
|
||
|
Ring modulation variant.
|
||
|
discussion::
|
||
|
Return the value of (a*a *b). This is more efficient than using
|
||
|
separate unit generators for each multiply.
|
||
|
code::
|
||
|
{ (FSinOsc.ar(800) ring3: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
|
||
|
::
|
||
|
same as :
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
(a * a * b) * 0.125;
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: ring4
|
||
|
Ring modulation variant.
|
||
|
discussion::
|
||
|
Return the value of ((a*a *b) - (a*b*b)). This is more efficient than using
|
||
|
separate unit generators for each operation.
|
||
|
code::
|
||
|
{ (FSinOsc.ar(800) ring4: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
|
||
|
::
|
||
|
same as :
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
((a * a * b) - (a * b * b)) * 0.125
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: sumsqr
|
||
|
Sum of squares.
|
||
|
discussion::
|
||
|
Return the value of (a*a) + (b*b). This is more efficient than using
|
||
|
separate unit generators for each operation.
|
||
|
code::
|
||
|
{ (FSinOsc.ar(800) sumsqr: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
|
||
|
::
|
||
|
same as :
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
((a * a) + (b * b)) * 0.125
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: difsqr
|
||
|
Difference of squares.
|
||
|
discussion::
|
||
|
Return the value of (a*a) - (b*b). This is more efficient than using
|
||
|
separate unit generators for each operation.
|
||
|
code::
|
||
|
{ (FSinOsc.ar(800) difsqr: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
|
||
|
::
|
||
|
same as :
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
((a * a) - (b * b)) * 0.125
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: sqrsum
|
||
|
Square of the sum.
|
||
|
discussion::
|
||
|
Return the value of (a + b)**2. This is more efficient than using
|
||
|
separate unit generators for each operation.
|
||
|
code::
|
||
|
{ (FSinOsc.ar(800) sqrsum: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
|
||
|
::
|
||
|
same as :
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b, c;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
c = a + b;
|
||
|
(c * c) * 0.125
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: sqrdif
|
||
|
Square of the difference.
|
||
|
discussion::
|
||
|
Return the value of (a - b)**2. This is more efficient than using
|
||
|
separate unit generators for each operation.
|
||
|
code::
|
||
|
{ (FSinOsc.ar(800) sqrdif: FSinOsc.ar(XLine.kr(200,500,5))) * 0.125 }.play;
|
||
|
::
|
||
|
same as :
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a, b, c;
|
||
|
a = FSinOsc.ar(800);
|
||
|
b = FSinOsc.ar(XLine.kr(200,500,5));
|
||
|
c = a - b;
|
||
|
(c * c) * 0.125
|
||
|
}.play)
|
||
|
::
|
||
|
|
||
|
method:: absdif
|
||
|
Absolute value of the difference. code:: abs(a - b) ::
|
||
|
discussion::
|
||
|
code::
|
||
|
(
|
||
|
{ // creates a rhythm
|
||
|
var mul = 0.2 absdif: FSinOsc.ar(2, 0, 0.5);
|
||
|
FSinOsc.ar(440, 0, mul);
|
||
|
}.play;
|
||
|
)
|
||
|
::
|
||
|
|
||
|
method:: moddif
|
||
|
On a circle, there are two distances between two points. This operator returns the smaller value of the two.
|
||
|
discussion::
|
||
|
code::
|
||
|
{ Line.ar(0, 4, 0.01).moddif(0) }.plot;
|
||
|
(
|
||
|
{
|
||
|
var mul = 0.2 moddif: FSinOsc.ar(2, 0, 0.5);
|
||
|
FSinOsc.ar(440, 0, mul);
|
||
|
}.play;
|
||
|
)
|
||
|
::
|
||
|
|
||
|
method:: thresh
|
||
|
Thresholding.
|
||
|
discussion::
|
||
|
0 when a < b, otherwise a.
|
||
|
code::
|
||
|
{ LFNoise0.ar(50, 0.5) thresh: 0.45 }.play // a low-rent gate
|
||
|
::
|
||
|
|
||
|
method:: amclip
|
||
|
Two quadrant multiply.
|
||
|
discussion::
|
||
|
0 when b <= 0, a*b when b > 0
|
||
|
code::
|
||
|
{ WhiteNoise.ar.amclip(FSinOsc.kr(1,0.2)) }.play; // makes a sine envelope
|
||
|
::
|
||
|
|
||
|
method:: scaleneg
|
||
|
Scale negative part of input.
|
||
|
discussion::
|
||
|
a*b when a < 0, otherwise a.
|
||
|
code::
|
||
|
{ FSinOsc.ar(500).scaleneg(Line.ar(1,-1,4)) }.play;
|
||
|
::
|
||
|
|
||
|
method:: clip2
|
||
|
Bilateral clipping.
|
||
|
discussion::
|
||
|
clips input wave a to +/- b
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a;
|
||
|
a = Line.ar(-2, 2, 0.01);
|
||
|
a.clip2
|
||
|
}.plot2
|
||
|
)
|
||
|
|
||
|
{ FSinOsc.ar(400).clip2(0.2) }.scope; // clipping distortion
|
||
|
|
||
|
{ FSinOsc.ar(1000).clip2(Line.kr(0,1,8)) }.scope;
|
||
|
::
|
||
|
|
||
|
method:: wrap2
|
||
|
Bilateral wrapping.
|
||
|
discussion::
|
||
|
wraps input wave to +/- b
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a;
|
||
|
a = Line.ar(-2, 2, 0.01);
|
||
|
a.wrap2
|
||
|
}.plot
|
||
|
)
|
||
|
|
||
|
{ FSinOsc.ar(1000).wrap2(Line.kr(0,1.01,8)) }.scope;
|
||
|
::
|
||
|
|
||
|
method:: fold2
|
||
|
Bilateral folding.
|
||
|
discussion::
|
||
|
folds input wave a to +/- b
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a;
|
||
|
a = Line.ar(-2, 2, 0.01);
|
||
|
a.fold2
|
||
|
}.plot
|
||
|
)
|
||
|
|
||
|
|
||
|
{ FSinOsc.ar(1000).fold2(Line.kr(0,1,8)) }.scope;
|
||
|
::
|
||
|
|
||
|
method:: excess
|
||
|
Residual of clipping.
|
||
|
discussion::
|
||
|
Returns the difference of the original signal and its clipped form: (a - clip2(a,b)).
|
||
|
code::
|
||
|
(
|
||
|
{
|
||
|
var a;
|
||
|
a = Line.ar(-2, 2, 0.01);
|
||
|
a.excess
|
||
|
}.plot
|
||
|
)
|
||
|
|
||
|
{ FSinOsc.ar(1000).excess(Line.kr(0,1,8)) }.play;
|
||
|
::
|
||
|
|