SuperCollider CLASSES (extension)

FoaDecoderMatrix
ExtensionExtension

First Order Ambisonic (FOA) decoder matrices
Inherits from: AtkMatrix : Object

Description

Generates decoding matrices required by the Ambisonic Toolkit's first order decoder, FoaDecode.

Class Methods

*newMono (theta: 0, phi: 0, pattern: 0)

Virtual microphone monophonic decoder.

Arguments:

theta

Azimuth angle, in radians: pi to pi.neg.

phi

Elevation angle, in radians: pi/2 to pi.neg/2.

pattern

Virtual microphone pattern, 0 to 1:
patternvirtual microphone
0.0Omni
0.5Cardioid
(3-sqrt(3))/2Super-cardioid
0.75Hyper-cardioid
1.0Bi-directional

For equivalences to decoder k, please see decoder%20k.

Discussion:

The virtual microphone decoder returns a single monophonic channel, and can be used to "listen in" to the soundfield at the specified azimuth and elevation.

*newStereo (angle, pattern: 0.5)

Virtual microphone stereophonic decoder.

Arguments:

angle

The half angle of the stereo pair, in radians: 0 to pi., Default: pi/2

pattern

Virtual microphone pattern, 0 to 1:
patternvirtual microphone
0.0Omni
0.5Cardioid
(3-sqrt(3))/2Super-cardioid
0.75Hyper-cardioid
1.0Bi-directional

For equivalences to decoder k, please see decoder%20k.

Discussion:

Standard coincident stereo microphone configurations1 :

// Default: Cardioids at 180 deg
~decoder = FoaDecoderMatrix.newStereo

// Cardioids at 131 deg
~angle = (131/2).degrad
~pattern = 0.5
~decoder = FoaDecoderMatrix.newStereo(~angle, ~pattern)

// Super-cardioids at 115 deg
~angle = (115/2).degrad
~pattern = (3-sqrt(3))/2
~decoder = FoaDecoderMatrix.newStereo(~angle, ~pattern)

// Hyper-cardioids at 105 deg
~angle = (105/2).degrad
~pattern = 0.75
~decoder = FoaDecoderMatrix.newStereo(~angle, ~pattern)

// Blumlein
~angle = (90/2).degrad
~pattern = 1.0
~decoder = FoaDecoderMatrix.newStereo(~angle, ~pattern)
NOTE: While the virtual microphone stereophonic decoder is very easy and convenient, for production work the authors advise using the UHJ ( FoaDecoderKernel: *newUHJ ) decoder.2

*newQuad (angle, k: 'single')

Optimised quadraphonic decoder with variable loudspeaker angle.

Arguments:

angle

The half angle of the front (and rear) loudspeaker pair. Defaults to pi/4, a square. In radians.

k

The k factor of the decoder. May be specified as a float: 0.5 to 1.0. Or more conviently by name:

  • 'single'
  • 'dual'
  • 'velocity'
  • 'energy'
  • 'controlled'

Discussion:

The outputs are in anti-clockwise order. The position of the first speaker is left of centre. -dirChannels may be used to query resulting loudspeaker directions.

Varying angle allows a number of flexible quadraphonic decoders to be generated. E.g, angle = pi/6 returns a decoder with loudspeakers at [ 30, 150, -150, 30 ] degrees.

Please see decoder%20k for further discussion on k.

*new5_0 (irregKind: 'focused')

Bruce Wiggins' optimised ITU 5.0 decoders.3

Arguments:

irregKind

Three kinds are available:

  • 'focused'
  • 'equal'
  • 'four'

Discussion:

The outputs are in anti-clockwise order. The position of the first speaker is centre. -dirChannels may be used to query resulting loudspeaker directions.

irregKind = 'focused' returns a focused, but front weighted image. 'equal' equalises the angles across the image. 'four' is similar to 'equal', but doesn't use the centre speaker.

*newPanto (numChans: 4, orientation: 'flat', k: 'single')

Pantophonic (2D) regular polygon decoder.

Arguments:

numChans

number of loudspeaker feeds

orientation

'flat' or 'point'

k

The k factor of the decoder. May be specified as a float: 0.5 to 1.0. Or more conviently by name:

  • 'single'
  • 'dual'
  • 'velocity'
  • 'energy'
  • 'controlled'

Discussion:

The outputs are in anti-clockwise order. The position of the first speaker is either centre or left of centre. -dirChannels may be used to query resulting loudspeaker directions.

Used in conjunction with FoaDecode: *ar the resulting decoder is equivalent to DecodeB2: *ar (SuperCollider's inbuilt decoder), albeit with the addition of variable k and dual-band optimised psychoacoustic decoding. DecodeB2: *ar is a "controlled opposites" decoder ( k = 'controlled' ) with a gain of 6dB greater than *newPanto.

Please see decoder%20k for further discussion on k.

*newPeri (numChanPairs: 4, elevation: 0.61547970867039, orientation: 'flat', k: 'single')

Periphonic (3D) dual ring, regular cylindrical decoder.

Arguments:

numChanPairs

Number of channel pairs. (Half the total number of loudspeaker feeds.)

elevation

Elevation of the upper ring, measured from the origin. In radians.

orientation

'flat' or 'point'

k

The k factor of the decoder. May be specified as a float: 0.5 to 1.0. Or more conviently by name:

  • 'single'
  • 'dual'
  • 'velocity'
  • 'energy'
  • 'controlled'

Discussion:

The outputs are in anti-clockwise order, beginning with the top ring. The position of the first speaker is either centre or left of centre. -dirChannels may be used to query resulting loudspeaker directions.

Please see decoder%20k for further discussion on k.

*newDiametric (directions, k: 'single')

Gerzon's classic diametric decoder, suitable for varied periphonic and pantophonic loudspeaker arrays.4

Arguments:

directions

An array of directions for half of the loudspeaker feeds for the desired decoder. Specify in radians.

Rank 1 arrays return pantophonic, while rank 2 arrays return periphonic. E.g.,

// 2D:
~directions = [ theta0, theta1, ... thetaN ];

// 3D:
~directions = [ [ theta0, phi0 ], [ theta1, phi1 ], ... [ thetaN, phiN ] ];
k

The k factor of the decoder. May be specified as a float: 0.5 to 1.0. Or more conviently by name:

  • 'single'
  • 'dual'
  • 'velocity'
  • 'energy'
  • 'controlled'

Discussion:

directions specifies only half of the loudspeakers for the resulting array, the remaining loudspeakers are diametrically opposite (through the origin). -dirChannels may be used to query resulting loudspeaker directions.

// Pantophonic (2D) decoder with four channels arranged in a rectangle:
// [ 30, -30, -150, 150 ]

// specify 1/2 the desired directions
~directions = [ 30, -30 ].degrad;
~decoder = FoaDecoderMatrix.newDiametric(~directions);

// inspect
~decoder.dirChannels.raddeg

// Periphonic (3D) decoder with eight channels arranged in a bi-rectangle:
// [ [ 30, 0 ], [ -30, 0 ], [ 90, 35.3 ], [ -90, 35.3 ],
//   [ -150, -0 ], [ 150, -0 ], [ -90, -35.3 ], [ 90, -35.3 ] ]

// specify 1/2 the desired directions
~directions = [[ 30, 0 ], [ -30, 0 ], [ 90, 35.3 ], [ -90, 35.3]].degrad;
~decoder = FoaDecoderMatrix.newDiametric(~directions);

// inspect
~decoder.dirChannels.raddeg

Please see decoder%20k for further discussion on k.

*newBtoA (orientation: 'flu', weight: 'dec')

B-format to A-format decoder. Decodes to a variety of tetrahedral orientations and W channel weights.

Arguments:

orientation

Orientation of the A-format tetrahedron.
orientationangles ([theta, phi] in degrees)
'flu'[[45.0, 35.3], [-45.0, -35.3], [135.0, -35.3], [-135.0, 35.3]]
'fld'[[45.0, -35.3], [-45.0 , 35.3], [135.0, 35.3], [-135.0, -35.3]]
'flr'[[54.7, 0.0], [-54.7, 0.0], [180.0, 54.7], [ 180.0, -54.7]]
'fud'[[ 0.0, 54.7], [ 0.0, -54.7], [125.7, 0.0], [-125.7, 0.0]]
'fbd'[[ 0.0, 0.0], [180.0, -70.5], [112.2, 28.1], [-112.2, 28.1]]
'fbu'[[ 0.0, 0.0], [180.0, 70.5], [112.2, -28.1], [-112.2, -28.1]]
'flru'[[67.8, 28.1], [-67.8, 28.1], [ 0.0, -70.5], [ 180.0, 0.0]]
'flrd'[[67.8, -28.1], [-67.8, -28.1], [ 0.0, 70.5], [ 180.0, 0.0]]

weight

The W weight factor.

For convenience, equivalent virtual microphone pattern and decoding k are also listed.
weightkindW scalevirtual microphonepatterndecodingk
'dec'Decorrelated (on the sphere)1/sqrt(3)Hyper-cardioid0.75strict soundfield'velocity'
'can'Canonical (B-format)1/sqrt(2)sqrt(6)/(1+sqrt(6))sqrt(2/3)
'uns'Unscaled1Super-cardioid(3-sqrt(3))/2energy optimised'energy'
'car'Cardioidsqrt(3)Cardioid0.5controlled opposites'controlled'

Discussion:

 The B-format to A-format decoder is primarily intended to be used in conjuction with the A-format to B-format encoder, FoaEncoderMatrix: *newAtoB. Though the use of BtoA/AtoB decoder/encoder pairs, signal processing networks can be constructed which preserve the spatial encoding found in the original input B-format signal.

In order to reconstruct the original B-format signal, matching orientation and weight for both decoding and encoding should be chosen. For most applications the default weight ('dec') is a good choice. This weight decodes to four planewaves. Setting weight to 'uns' returns an energy optimised decoding. For Dynamic Range Control processing, 'uns' is often a good choice.

// ------------------------------------------------------------
// Single stage allpass ambience in A-format
//
// mono pink noise source
// FoaPanB encoder
//
// quad decoder


// decoder matrix
~decoder = FoaDecoderMatrix.newQuad

// b-to-a, a-to-b matrices
~b2a = FoaDecoderMatrix.newBtoA
~a2b = FoaEncoderMatrix.newAtoB

// inspect
~decoder.kind
~decoder.numChannels
~decoder.dirChannels.raddeg

(
{
    var sig;                            // audio signal
    var azim;                        // azimuth control
    var fl, bl, br, fr;                 // quad output channels
    var delaytime, decaytime;        // allpass parameters


    // display decoder
    "Ambisonic decoding via % decoder".format(~decoder.kind).postln;

    // ------------------------------------------------------------
    // parameters
    delaytime = 0.1;
    decaytime = 0.2;

    // azimuth -> hard left     = back
    //            centre        = centre
    //            hard right    = back
    azim = MouseX.kr(pi, -pi);

    // ------------------------------------------------------------
    // test sig
    sig = PinkNoise.ar * LFPulse.ar(2.0); // enveloped mono pink noise


    // ------------------------------------------------------------
    // encode to b-format
    sig = FoaPanB.ar(sig, azim);

    // ------------------------------------------------------------
    // b-to-a --> allpass --> a-to-b
    sig = FoaDecode.ar(sig, ~b2a);
    sig = AllpassN.ar(sig, delaytime, Array.fill(4, {delaytime}).rand, decaytime);
    sig = FoaEncode.ar(sig, ~a2b);


    // ------------------------------------------------------------
    // decode (to quad)
    #fl, bl, br, fr = FoaDecode.ar(sig, ~decoder);
    [fl, fr, bl, br]    // reorder output to match speaker arrangement

}.scope;
)
// ------------------------------------------------------------

*newHoa1 (ordering: 'acn', normalisation: 'n3d')

A first order Ambisonic format exchange decoder. Decodes traditional B-format to a variety of formats.

Arguments:

ordering

Input Ambisonic channel component ordering.
orderingkind
'acn'Ambisonic Channel Number (ACN)
'sid'Single Index Designation (SID)

normalisation

Spherical harmonic normalisation method.
normalisationkind
'n3d'Orthonormal basis for 3D decomposition (N3D)
'sn3d'Semi-normalised basis for 3D decomposition (SN3D)

Discussion:

Decoding means decoding from traditional B-format to another Ambisonic channel componenent orderding and normalisation. In other words, from Gerzon (aka Furse-Malham) ordering with MaxN normalisation to some other standard scheme.

NOTE: Hoa1 in the method name *newHoa1 refers to Higher Order Ambisonic (HOA) encoding format, Ambisonic order = 1.

*newAmbix1

A first order Ambisonic format exchange decoder. Decodes traditional B-format to AmbiX. A convenience alias to *newHoa1.

Discussion:

Decoding means decoding from traditional B-format to another Ambisonic channel componenent orderding and normalisation. In this case, from Gerzon (aka Furse-Malham) ordering, MaxN normalisation to the AmbiX encoding scheme (ACN ordering, SN3D normalisation).

*newFromFile (filePathOrName)

Create an FoaEncoderMatrix by loading a matrix from a file.

Arguments:

filePathOrName

Can be a path relative to your /extensions/matrices/decoders folder:

Atk.getMatrixExtensionPath('decoders').fullPath

Otherwise a full path to your matrix file.

Discussion:

See the Guide to ATK Matrix Files for more information.

*newFromMatrix (aMatrix, set, type)

From superclass: AtkMatrix

Create an instance from a raw 2D Matrix.

Arguments:

aMatrix

A Matrix in the form of

Matrix.with([[row1],[row2],...[rowN]])
set

'FOA', 'HOA1', 'HOA2', ... etc. Set describes both the signal set and the tool set, encompassing the Ambisonic order, as well as channel ordering and normalisation.

type

'decoder', 'encoder', or 'xformer'.

NOTE: set and type will be required if the AtkMatrix will subsequently be written to a file.

Decoder k

The default k ( 'single' ), for decoders accepting k as an argument, returns an 'energy' optimised (aka "maximum energy" or "max rE") decoder. 'dual' returns a dual-band psychoacoustically optimised decoder.5 The 'dual' decoder is the optimum choice for small scale studio or domestic settings. 'single' is suitable for larger, mid-scale environments. 'velocity' returns "strict soundfield" (aka "planewave" or "basic") decoding.6 'controlled' returns "controlled opposites" decoding (aka "minimum energy" or "in phase"), which is often preferred in large-scale, concert environments.7 (SuperCollider's inbuilt decoder, DecodeB2: *ar, is a "controlled opposites" decoder. See this discussion.)

Given a uniform periphonic (3D) distribution of loudspeakers, e.g. a Platonic solid, some useful virtual microphone equivalences:
keyworddecodingvirtual microphonepattern
'velocity'strict soundfieldHyper-cardioid0.75
'energy'energy optimisedSuper-cardioid(3-sqrt(3))/2
'controlled'controlled oppositesCardioid0.5

The k keywords translate to numerical values as follows:
keywordk for pantophonic (2D)k for periphonic (3D)
'velocity'11
'energy'1/sqrt(2)1/sqrt(3)
'controlled'1/21/3

NOTE: For large-scale concert presentation, the authors advise auditioning values of k between those noted for 'energy' and 'controlled'.

Inherited class methods

Instance Methods

-set

From superclass: AtkMatrix

Describes both the signal set and the tool set, encompassing the Ambisonic order, as well as channel ordering and normalisation.

Answers 'FOA', aka traditional B-format:
Ambisonic OrderChannel OrderingChannel Normalisation
1stGerzon (aka Furse-Malham)MaxN

-type

Returns:

'decoder'

-op

From superclass: AtkMatrix

Answers 'matrix', i.e. the type of operation used to compute the resulting signals.

-kind

From superclass: AtkMatrix

Answers the kind of decoder

Discussion:

// decoder
~decoder = FoaDecoderMatrix.newQuad

// inspect
~decoder.kind
// decoder
~decoder = FoaDecoderMatrix.newPeri

// inspect
~decoder.kind

-dim

Answers the number of decoder dimensions: 2D or 3D.

Discussion:

// decoder
~decoder = FoaDecoderMatrix.newQuad

// inspect
~decoder.dim
// decoder
~decoder = FoaDecoderMatrix.newPeri

// inspect
~decoder.dim

-numChannels

Answers the number of loudspeaker feeds (output channels).

Discussion:

// decoder (narrow quad)
~decoder = FoaDecoderMatrix.newQuad(pi/6)

// inspect
~decoder.numChannels
// decoder (two rings of 6)
~decoder = FoaDecoderMatrix.newPeri(6)

// inspect
~decoder.numChannels

-dirChannels

Answers the direction of loudspeaker feeds, with angles in radians.

Returns:

A rank 1 array for pantophonic, and rank 2 array for periphonic. E.g.,

// 2D:
[ theta0, theta1, ... thetaN ]

// 3D
[ [ theta0, phi0 ], [ theta1, phi1 ], ... [ thetaN, phiN ] ]

Discussion:

Loudspeakers should be place at the angles returned (with equal radii).

// decoder (narrow quad)
~decoder = FoaDecoderMatrix.newQuad(pi/6)

// inspect
~decoder.dirChannels.raddeg
// decoder (two rings of 6)
~decoder = FoaDecoderMatrix.newPeri(6)

// inspect
~decoder.dirChannels.raddeg
// Pantophonic (2D) decoder with four channels arranged in a rectangle:
~directions = [ 30, -30 ].degrad
~decoder = FoaDecoderMatrix.newDiametric(~directions)

// inspect
~decoder.dirChannels.raddeg
// Periphonic (3D) decoder with eight channels arranged in a bi-rectangle:
~directions = [[ 30, 0 ], [ -30, 0 ], [ 90, 35.3 ], [ -90, 35.3]].degrad
~decoder = FoaDecoderMatrix.newDiametric(~directions)

// inspect
~decoder.dirChannels.raddeg

-matrix

From superclass: AtkMatrix

Answers the decoding matrix

-shelfFreq

-shelfFreq = value

If the decoder is dual-band psychoacoustically optimised, get or set the shelf filter frequency, in Hz.

Discussion:

shelfFreq defaults to 400Hz, which is suitable for a well aligned domestic or studio space. shelfFreq may be set up to 700Hz, for a tight sweet-spot, and very focused single user listening.

-shelfK

If the decoder is dual-band psychoacoustically optimised, get or set the shelf k.

Discussion:

If set, shelfK is optimised for the chosen decoder, and should be left at the assigned value unless one is an expert user.

-numOutputs

A synonym for -numChannels

-dirOutputs

A synonym for -dirChannels

-numInputs

Answers the number of inputs for the decoder. 3 for 2D and 4 for 3D.

-dirInputs

A convenience method providing polymorphism with FoaEncoderMatrix: -dirInputs.

Returns:

  • for 2D: [ inf, inf, inf ]
  • for 3D: [ inf, inf, inf, inf ]

-info

From superclass: AtkMatrix

A convenience method to post the properties of the matrix, including metadata if the matrix was loaded from a .yml file.

-fileParse

From superclass: AtkMatrix

If the instance was created by loading a .yml file, this method returns the IdentityDictionary containing the parsed metadata. This can be useful if anything was stored in the metadata that can be subsequently used once reloaded, such as encoding directions, rotations, etc.

NOTE: For simply a quick glance at the metadata, it's recommended to use -info.

-filePath

From superclass: AtkMatrix

Answers the path of the file used to create the instance, or nil if not created by loading a matrix from a file.

-fileName

From superclass: AtkMatrix

Answers the name of the file used to create the instance, or nil if not created by loading a matrix from a file.

-writeToFile (fileNameOrPath, note, attributeDictionary, overwrite: false)

From superclass: AtkMatrix

Write the matrix to a file

Arguments:

fileNameOrPath

A String of the file name. The file extension determines the format:

  • .yml allows for additional user-specified metadata (recommended).
  • .txt writes the matrix coefficients only, in rows.
  • .mosl.txt creates basic matrix files compatible with the ATK for Reaper, a set of JSFX plugins for the Reaper DAW.

You may provide a full path if you would like to save the file somewhere other than the default location in the Atk extensions folder. See the Discussion below for more information.

note

A String that is a short description or bit of info about the matrix to store for future reference.

attributeDictionary

A Dictionary containing any information that's useful to store in key:value pairs. Keys that match getters in the AtkMatrix will take precedence over the defaults. See the Discussion for more details.

overwrite

A boolean specifying whether you'd like to force overwriting an existing file of the same name and extension.

Discussion:

The Guide to ATK Matrix Files offers examples and more discussion regarding writing and reading matrices and metadata, including how to generate matrices for use in Reaper.

Inherited instance methods

Examples

Please see FoaDecode: Examples.

[1] - Sengpiel Audio provides a useful tool to visualise resulting imaging: http://www.sengpielaudio.com/Visualization-Blumlein-E.htm
[3] - Irregular decoders in the Ambisonic Toolkit are kindly provided by Bruce Wiggins: http://www.brucewiggins.co.uk/. See also: B. Wiggins, I. Paterson-Stephens, V. Lowndes, and S. Berry, "The design and optimisation of surround sound decoders using heuristic methods," in Proceedings of UKSIM 2003: Conference on Computer Simulation, Cambridge, England, 2003.
[4] - See: M. A. Gerzon, "Practical Periphony: The Reproduction of Full-Sphere Sound," in Proceedings of the 65th Audio Engineering Engineering Society Convention, London, 1980, p. 10.
[5] - See: E. Benjamin, R. Lee, and A. Heller, "Is My Decoder Ambisonic?," in Proceedings of the 125th Audio Engineering Society Convention, San Francisco, 2008.
[6] - While "strict soundfield" decoding is usually not preferred for first order Ambisonics audition, it is usually a good choice for use in signal processing networks.
[7] - See: D. G. Malham, "Experience with Large Area 3-D Ambisonic Sound Systems," Proceedings of the Institute of Acoustics, vol. 14, no. 5, pp. 209–215, Nov. 1992.