The ATK store assets in its Application Support directory:
This includes three default directories:
These folders store the files shipped with the ATK. We can also optionally add our own
extensions folder, in which we can store kernels and matrices of our own design. Note this is different from SuperCollider's
Extensions folder. If we haven't yet added an
extensions directory, we can see where to put it by executing the following method:
There's a handy method that will build it for we in the expected structure:
This will create a directory structure that lives in our next to our default ATK assets. Note this creates both a matrices folder structure, and an identical kernels folder structure for storing our custom kernels. The full structure will look like this:
extensions(our custom additions)
Each of the folders (
HOA5>decoders, etc.) are empty and ready to store matrices (and kernels) for use with the ATK-SC3 (this package) and ATK-Reaper (more on that later). When we write a matrix using the ATK, it will store it in this directory structure by default, and will look here by default when asked to read in a matrix from file.
We can view this structure and any files you've stored there using the following method:
Each of these matrix subdirectories can have further subdirectories at your discretion, e.g. for particular projects or categories of matrices.
We'll start by writing a matrix file.
Let's create a first order A-format encoding matrix from a nine-point spherical t-design. For our purposes, we'll use a spherical designs with d = 2, giving a collection of uniformly distributed points on a sphere. The t-design we're using below can be found in Hardin and Sloan's Library of 3-D Designs. 1
This FoaEncoderMatrix is now ready to be used for encoding planewaves arriving from those nine uniformly distributed incidences. Within the ATK's classification hierarchy,
~encoder looks like this:
For fun, let's inspect:
There are three available file formats, each with a special purpose:
.txt: the most basic text file, writing the raw matrix only.
.yml: store the matrix along with metadata in a human readable format.
.mosl.txt: a text file formatted for use with ATK-Reaper JSFX-plugins.
Let's write this encoder matrix out in all three formats:
Because we only specified a file name, not a full path, the ATK will store the matrix in the default location. As we're writing an FoaEncoderMatrix, ATK can infer that it's an encoder in the FOA set. (We also know, we're dealing with a matrix operation.) Therefore, the ATK knows to put it in:
Had we specified a full path instead, it would have saved to that location.
Because this matrix encoder is somewhat unique, it would be helpful to provide a bit more information about it for future reference. This is where the
.yml file format comes in.
Note that the AtkMatrix: -writeToFile method has some optional arguments:
note can be a brief description, while an
attributeDictionary is a Dictionary for storing any info you'd like in the form of key:value pairs. Information found in the attributeDictionary can be retrieved via AtkMatrix: -fileParse. An example of this is illustrated below.
Now write this matrix and metadata to file... Be sure to specify the
.yml extension in order to write the metadata. Set overwrite
= true to force overwrite the file we wrote before with the same name and extension.
In the above examples, we've been reading/writing matrices encapsulated in the AtkMatrix subclasses. When writing from these objects, some the information can be inferred from them, such as the set (Ambisonic order, channel ordering, channel normalisation, e.g.
'HOA3', etc.) and type of matrix (e.g.
'encoder', 'decoder', 'xformer'). In the case of a raw matrix, the appropriate subclass must be called explicitly.
Metadata is useful to record more information about the matrix:
Now, given the matrix, a subclass instance can be created using the
*newFromMatrix class method. In this case we'll be using FoaEncoderMatrix: *newFromMatrix, as we're making an encoder.
/ATK/extension/matrices/...directory, set and type arguments are necessary when creating the
Matrixin order to locate the proper directory to store our file. If providing an absolute file path, set and type are recommended but not strictly enforced. This allows storing matrices outside the ATK paradigm, e.g. VBAP matrices, etc.
There it is:
If you'll be generating many matrices, it's advisable to organize our matrices into subfolders. For example, if you're algorithmically generating hundreds of matrices for a particular project or process, it makes sense to store them in a subfolder.
To do this, we can create subfolders inside our
~encoderis an FoaEncoderMatrix, the set (
'FOA') and type (
'encoder') arguments are inferred.
FoaEncoderMatrix: *newFromMatrix can be used to read the file back in. The ATK will know where to look (
extensions/matrices/enocoders/FOA) so we can simply specify the relative path of our
We wrote three encoder matrix files earlier. Let's now read them in. As when writing, the ATK looks in the extensions/matrices directory by default. Unless the matrix file is somewhere outside the default location, a filename will suffice to read it in. The type (
'xformer') is inferred from the object being instantiated.
We can even omit the file extension if we don't expect multiple file formats (
.txt, .yml, .mosl.txt) stored under the same name:
So, we'll need to specify the extension. As mentioned before, each file format determines what kind of information is stored in the file.
Lets have a look at what each file format gives us back:
We've now instantiated a new
~encoder by reading in the file that stored the matrix that we originally built using the planewave encoder: FoaEncoderMatrix: *newDirections (using the points of a nine-point t-design). As it turns out, a matrix encoder created by FoaEncoderMatrix: *newDirections can be used to build a decoder of the same geometry.3 Doing so just involves performing the Matrix: -pseudoInverse on the encoder's Matrix.4
Using these coefficients will return a
'velocity' decode (aka "strict soundfield" or "basic"). Loudspeakers should be positioned in the following directions (and in this order):
-dirInputsto know where our output channel signals are expected to be sent (in space!).
Let's go ahead and finish off the job and use the resulting raw matrix to create a decoder instance:
And... have a go!