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:
Application Support
ATK
kernels
(ATK default)matrices
(ATK default)sounds
(ATK default)extensions
(our custom additions)kernels
matrices
FOA
decoders
encoders
xformers
HOA1
HOA2
...
HOAN
Each of the folders (FOA>encoders
, 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:
set | type | op | kind |
'FOA' | 'encoder' | 'matrix' | 'dirs' |
For fun, let's inspect:
After all that hard work (thanks ATK!), we want to store the result to a file for use in the future, and to use in ATK-Reaper plugins! 2
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: ../extensions/matrices/FOA/encoders
.
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
and attributeDictionary
. A 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. 'FOA'
, '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 AtkMatrix
from our Matrix
in 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 /encoders
, /decoders
, and /xformers
folders.
~encoder
is 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 subfolder/file.yml
:
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 ('encoder'
, 'decoder'
, '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:
.txt
format:
.mosl.txt
format:
.yml
format:
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):
-dirInputs
to 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!