Trying to understand the factory dist:soft object


#1

Hi there, so i am trying to understand fully what is going on inside this object in the hopes of adapting some already written C++ code to work with the axoloti. I havnt yet come across the SMMUL function but have read the description of them in getting started but might need to have it explained in relation to something to properly underdstand, also nothing is really mentioned about the ___SSAT function which is used here.

In terms of this object, could anybody help me break down what is actually going on here as i cant make much out just from looking at the code.
For example the first line "int32_t ts = _SSAT(inletin,28);" Im really having a hard time understanding what even this is saying. Is it something like declaring the inlet to be a 32bit integer called 'ts', but unsure as to what the SSAT and the 28 are doing here.


Any help would be very much appreciated, thanks!


#2

Taking a look at the Axoloti firmware might help.

__SATT is the Signed Saturate function.

The first parameter is the value to be saturated.
The second parameter is the bit position to saturate to. Can be a value between 1 and 32.

This function returns the saturated value, and stores it in the ts variable in this case.

Found the function in this file:


#3

Thanks for the reply first of all.
So as this is all a bit new to me so i may ask silly questions! i had to look up what actually is numeric saturation, and the result i have come across the description where it says it basically carries out that operation but limited to a fixed min and max value.
This definition doesn't seem to make much sense in terms of bit positions ? do i have the correct definition ?


#4

__SSAT(x,n);

is functionally equivalent of

int ssat1(int x, int n){
int p = (1<<n-1)-1;
if (x>p) return p;
else if (x<-p-1) return -p-1;
else return x;
}

__SSAT maps to one single ARM processor instruction, that benefits execution speed and code size. It does require n to be resolvable to a constant at compile-time though.


#5

Let me have a try at working through this in pseudocode:

Number Format Reminder:

1 << 21 = 1.0 = 0x0020 0000
max val is 1023.999999523162841796875 = 0x7fff ffff

Psuedocode

// ts = _SSAT( inletin, 28 ), signed saturation
ts = inlet_in;

// same as if( inlet_in> 0x0fff ffff ){ inlet_in= 0x0fff ffff; }
if( ts > 127.99999 ) { ts = 127.99999; }
if( ts < -127.99999 ) { ts = -127.99999; }

tsq31 = 8 * ts;
tsq31p3 = tsq31 * tsq31 *tsq31
outlet_out = ts + ts / 2 - tsq31

Example:

inlet_in = 300; // 0x2580 0000
ts = SSAT( inlet_in ) = 127.999999523162841796875 // 0x0fff ffff

Normal numbers, Q21, hex

ts = 127.999999 , 268435453.902848, 0x0fff fffd
tsq31 = ts * 8 = 1023.999992, 2147483631.222784, 0x7fff ffef
tsq31p3 = tsq31^3 = ( 0x7fff ffef * 0x7fff ffef ) * 0x7fff ffef
tsq31p3 = 0x7FFF FFDE * 0x7fff ffef
tsq31p3 = 0x7FFF FFCD = 2147483597 = 1023.999975681304931640625

outlet_out = ts + ts / 2 - tsq31p3
outlet_out = 127.999999 + 63.999999 - 1023.999975681304931640625
outlet_out = -831.999975881304931640625 = -1744830413.4194304 = 0x9800 0033, or in simpler format, -0x67ff ffcd

Note that it appears this module inverts the signal! the in value was 300 and the out value was -832.

I made a spreadsheet in excel to test this, too. I'm not sure if I can attach it here.

References: