HISE Docs

Math

The Math class is a collection of math functions that can be used in the scripting engine. It is a feature-complete clone of the "official" Javascript Math object .

Unless specified otherwise, the value type of the function is double . Most of the functions are pretty self-explanatory if you managed to get through high school, but there are a few special function that deserve a more detailed explanation.

If you're going to start out with SNEX or use the expression nodes in scriptnode, you might be happy to know that this class is also available there.

Class methods

abs

Returns the absolute (unsigned) value.

Math.abs(var value)



acos

Calculates the acosine value (radian based).

Math.acos(var value)



acosh

Calculates the acosh value (radian based).

Math.acosh(var value)



asin

Calculates the asine value (radian based).

Math.asin(var value)



asinh

Calculates the asinh value (radian based).

Math.asinh(var value)



atan

Calculates the atan value (radian based).

Math.atan(var value)



atanh

Calculates the atanh value (radian based).

Math.atanh(var value)



ceil

Rounds up the value.

Math.ceil(var value)



cos

Calculates the cosine value (radian based).

Math.cos(var value)



cosh

Calculates the cosh value (radian based).

Math.cosh(var value)



exp

Calculates the exp value.

Math.exp(var value)



floor

Rounds down the value.

Math.floor(var value)



fmod

Returns the remainder when dividing value with limit.

Math.fmod(var value, var limit)


This is usually useful for two use cases:

  1. Get the fractional part: Math.fmod(19.52, 1.0) == 0.52)
  2. Loop around a range limit: Math.fmod(13.2, 12.0) == 1.2

Note that if you're using it for the latter use case, the function Math.wrap() might be a better candidate as it correctly wraps around negative values too.

from0To1

Converts a normalised value (between 0 and 1) to a range defined by the JSON data in rangeObj.

Math.from0To1(var value, var rangeObj)


Converting between value ranges is a pretty common task when writing scripts. This function will scale a normalized input value from (0...1) to a given output range which allows you to switch between different domains without excessive math formula usage. The inverse process can be achieved with Math.to0to1 .

The second parameter will define a range and you can either use a JSON object or a fix object created by a FixObjectFactory . The latter will significantly improve the performance of this function because it doesn't have to look up the dynamic properties but uses a internal LUT to create the C++ range object.

A range object has up to 5 properties:

Note that the interval and the skew factor property are mutually exclusive: you either want to skew the output or you want discrete steps .

Unfortunately there are multiple types of range definitions used across HISE so there is not a single property set, but it tries to cope with them all and automatically detects which range property set to use:

Domain Property Names Additional information
scriptnode MinValue , MaxValue , SkewFactor , StepSize , Inverted the range object from scriptnode parameters
UI components min , max , middlePosition , stepSize , Inverted the range object from a UI component's JSON. Note that it uses the middle position to calculate the skew factor (this introduces a small overhead so make sure to use another mode if performance is critical)
MIDI Automation Start , End , Skew , Interval , Inverted the range object from a MIDI automation connection MIDI automation connection

You can use Math.skew() in order to convert a mid position value to a skew factor.

Take a look at the example how to use it with a fix object factory:

// define a prototype using the scriptnode syntax
reg prototype = {
	"MinValue": 20.0,
	"MaxValue": 20000.0,
	"SkewFactor": 0.6
};

// pass that into the factory to create a fix object
const var f1 = Engine.createFixObjectFactory(prototype);

// create a fix object (think JSON but faster)
const var range = f1.create();

// 9.5% slower than just calling Math.pow() (which is the baseline for this function)
const var x = Math.from0To1(0.5, range);

// 34% slower than just calling Math.pow
const var y = Math.from0To1(0.5, prototype);

// There's a small rounding error because of single precision vs. double precision
// but that shouldn't have a real world impact
Console.assertTrue(Math.abs(x - y) < 0.001);


log

Calculates the log value (with base E).

Math.log(var value)



log10

Calculates the log value (with base 10).

Math.log10(var value)



max

Returns the bigger number.

Math.max(var first, var second)



min

Returns the smaller number.

Math.min(var first, var second)



pow

Calculates the power of base and exponent.

Math.pow(var base, var exp)


Be aware that this is a rather costly operation, so if you just want to square the value, the plain ol' x*x will get you there faster.

randInt

Returns a random integer between the low and the high values.

Math.randInt(var low, var high)



random

Returns a random number between 0.0 and 1.0.

Math.random()



range

Limits the value to the given range.

Math.range(var value, var lowerLimit, var upperLimit)



round

Rounds the value to the next integer.

Math.round(var value)



sign

Returns the sign of the value.

Math.sign(var value)



sin

Calculates the sine value (radian based).

Math.sin(var value)



sinh

Calculates the sinh value (radian based).

Math.sinh(var value)



skew

Returns the skew factor for the given mid point.

Math.skew(var start, var end, var midPoint)


The raw usage of this function allows you to simulate the range behaviour from the Math.from0to1() method:

const var skewFactor = Math.skew(0.0, 20000.0, 1000.0);
const var midPoint = Math.pow(0.5, 1.0 / skewFactor) * 20000.0; // => 1000

However the most interesting use case for this would be if you want to convert a range object from a mid point to a skew factor based range definition for increased performance:

// This is a range how it would come from a UI component
// it defines the curve with a middle position
const var p1 = {
	min: 20.0,
	max: 20000.0,
	middlePosition: 1000.0
}

// Using a skew-based range avoids an additional log calculation
// in the conversion functions
const var p2 = {
	MinValue: p1.min,
	MaxValue: p1.max,
	SkewFactor: Math.skew(p1.min, p1.max, p1.middlePosition)
};

// We're caring about performance here so we use fix objects:
const var f1 = Engine.createFixObjectFactory(p1);
const var f2 = Engine.createFixObjectFactory(p2);
const var o1 = f1.create();
const var o2 = f2.create();

{
	.profile(" - mid point with JSON");

	for(i = 0; i < 100000; i++)
		Math.from0To1(0.5, p1);
}

{
	.profile(" - skew factor with JSON");

	for(i = 0; i < 100000; i++)
		Math.from0To1(0.5, p2);
}

{
	.profile(" - mid point with fix object");

	for(i = 0; i < 100000; i++)
		Math.from0To1(0.5, o1);
}

{
	.profile(" - skew factor with fix object");

	for(i = 0; i < 100000; i++)
		Math.from0To1(0.5, o2);
}

/* Results:
- mid point with JSON: 83.185 ms
- skew factor with JSON: 29.896 ms
- mid point with fix object: 27.032 ms
- skew factor with fix object: 24.955 ms
*/

As you can see, the performance can be drastically improved from 83ms to 25ms by using both the skew() function and a fix object.

smoothstep

Calculates a smooth transition between the lower and the upper value.

Math.smoothstep(var input, var lower, var upper)


This function is very popular in graphics programming because it allows a seemless transition between two values, but there are certainly a few interesting use cases for DSP scripting / MIDI processing too. A good explanation of this function can be found here .


sqr

Calculates the square (xx) of the value.

Math.sqr(var value)



sqrt

Calculates the square root of the value.

Math.sqrt(var value)



tan

Calculates the tan value (radian based).

Math.tan(var value)



tanh

Calculates the tanh value (radian based).

Math.tanh(var value)



to0To1

Converts a value inside a range defined by the JSON data in range obj to a normalised value.

Math.to0To1(var value, var rangeObj)


This function will take a range defined by a JSON object and convert values back and to the normalized range of 0...1 .

Take a look at the Math.from0To1() function for a detailed description on how to use this method.

toDegrees

Converts radian (0...2PI) to degree (0...3600).

Math.toDegrees(var value)



toRadians

Converts degree (0...3600) to radian (0...2PI).

Math.toRadians(var value)



wrap

Wraps the value around the limit (always positive).

Math.wrap(var value, var limit)


Unlike its sibling fmod() , this function will not behave weird with negative values, so if you rely on it to loop around correctly with negative numbers, use this instead.

// fmod will not wrap around zero
Console.print(Math.fmod(-1.0, 19.0)); // -> -1.0

// wrap will... wrap around zero
Console.print(Math.wrap(-1.0, 19.0)); // -> 18.0