HISE Docs

FixObjectFactory

This class allows you to create a custom data structure that can be used to build different containers with a very dense data layout. This can be very useful in a MIDI processing context where you need to define a custom data model to fit your algorithm: In most scenarios that require a custom MIDI processing script, you will most likely need a data container that stores varying amounts of data. With this class you can tailor the data structure to your exact requirement and then use one of the available data structures for a convenient implementation.

The data layout will be defined by a JSON object (prototype) that you need to pass into Engine.createFixObjectFactory() . This will return a factory object that can be used to instantiate containers or single objects.

A notable feature of this class is that you can supply a custom comparison function that will be used by the data containers for the indexOf() , contains() methods.

Advantages

On the first look this doesn't look particularly interesting, as anything here can also be implemented using the stock data containers of HiseScript. Howewer there are a few advantages that make this a bit (or a lot) more convenient:

The Prototype

The prototype JSON object will define the object data layout. It basically looks like any other JSON object and every property you define will be a data member of the fix object. However there are a few limitations:

The fix object is typed, that means that if you pass in an integer value, it will create an integer member. If you pass in an array, it will use the first element to figure out what type to use.

The values of the property will be used as "default" values and every object will be initialised with these.

Here are a few (real world) examples of JSON objects that can be used as prototype:

// Use this to store the event IDs of a chord that is created
// from a single note
const var f1 = Engine.createFixObjectFactory({
	eventId: 0,
	chordIds: [0, 0, 0] // this assumes that the chord is a triad
});

// Use this to store the time of the note on
const var f1 = Engine.createFixObjectFactory({
	eventId: 0,
	pitchFactor: 1.0,
	startUptime: 0.0
});

// Use this to store whether the note was played while a keyswitch
// was held down
const var f1 = Engine.createFixObjectFactory({
	eventId: 0,
	triggeredWithC1: false,
	triggeredWithD1: false
});

After you've created a factory, you can either create single instance objects or a data container with additional functionality.


Class methods

create

Creates a single object from the prototype layout.

FixObjectFactory.create()


Calling this method will create a single object with the supplied data layout. The returned object is NOT a JSON object, but a custom object type with these properties:

However from a workflow perspective, it behaves just like a JSON object:

You can of course put these objects into a JS array or JSON object, however it's highly recommended to use one of the special data containers instead. If you do so, you will most likely need to create a single object alongside the data container and then use this as "interface object" for shuffling data in and out of the container:

const var f1 = Engine.createFixObjectFactory({
	"myValue": 17,
	"someOtherValue": 42.0
});

// Creates a preallocated array with the given size
const var list = f1.createArray(64);

// Creates an object for interacting with the array above
const var obj = f1.create();

Console.print(trace(obj));

// Now we want to push an object with both values zero
// into the list. 
obj.myValue = 0;
obj.someOtherValue = 0.0;

// This will not insert a reference into the array but copy the 
// data values from the current state of obj
list.push(obj);

// You can also call trace with a FixObjectArray and it will dump it like a JSON
Console.print(trace(list));

// this function will perform a bitwise comparison of the data
const var idx = list.indexOf(obj);
Console.print(idx); // => 0

obj.myValue = 90;

// Now it won't find the element because we changed it.
// Note that that's different from the default JS behaviour
// because we are not storing a reference to the object in the 
// array but a copy!
const var idx2 = list.indexOf(obj);

Console.print(idx2); // => -1


createArray

Creates a fixed size array with the given number of elements.

FixObjectFactory.createArray(int numElements)


This function will create and return a preallocated array using the prototype data layout. The returned object is a FixObjectArray and shares a lot of methods with its default JS counterpart.

createStack

Creates an unordered stack.

FixObjectFactory.createStack(int numElements)


This function will create and return a unordered stack container with the maximum length specified by the parameter. The returned object is a FixObjectStack and offers a few advantages over the default array.

getTypeHash

Returns the hash code for the memory layout which factors in member IDs, order and type.

FixObjectFactory.getTypeHash()



setCompareFunction

Registers a function that will be used for comparison. If you pass in a string it will only compare the given property.

FixObjectFactory.setCompareFunction(var newCompareFunction)


A lot of operations and methods of the data containers will require some kind of comparison operation: indexing, sorting, etc. all need to decide whether an element is supposed to be equal (or greater or less). The default comparison compares every single property of the object, but this might not what you need in your logic.

This is where this function comes in handy as it allows you to define different comparison functions. There are three options available:

  1. Compare a single property. This can be achieved by passing in the ID of the property as a string into the function. It will then ignore all other properties and just factor in this property for sorting, indexing, etc.
  2. Compare multiple properties. This can be achieved by passing up to 4 IDs separated by a comma. It will then compare all those the properties
  3. Define a custom JS function by passing in a callable object into the method. The function you pass in needs to have two parameters and must return either -1 , 1 or 0 depending on the relation between the two objects (this is similar to Engine.sortWithFunction() )
const var f1 = Engine.createFixObjectFactory({
	"eventId": 0,
	"noteNumber": 0
});

// This will make all indexing functions only look for the eventID
f1.setCompareFunction("eventId");

Be aware that using the third option has a noticeable performance impact so only use this as last resort.