CLASS:: FoaEncoderMatrix
summary:: First Order Ambisonic (FOA) encoder matrices
categories:: Libraries>Ambisonic Toolkit>FOA>Encoding
related:: Classes/FoaEncoderKernel, Classes/FoaEncode

DESCRIPTION::
Generates encoding matrices required by the Ambisonic Toolkit's first order encoder, link::Classes/FoaEncode::.



CLASSMETHODS::

METHOD:: newOmni
Omnidirectional encoder (monophonic).

discussion:: An omnidirectional soundfield can be regarded in two ways: a soundfield with an infinite number of planewaves arriving in all directions, or a soundfield with no directions. In a well aligned, dampend studio environment, this usually sounds "in the head", while in concert hall listening usually appears as omnipresent.

To control the soundfield, link::Classes/FoaPush:: and link::Classes/FoaFocus:: can be applied to either "push" or "focus" an omnidirectional soundfield into a planewave, giving the soundfield an angle of arrival. footnote:: In combination with distance scaling, link::#*newOmni:: and link::Classes/FoaPush:: can be used to implement Menzies' "W-panning" technique. See: D. Menzies, "W-panning and O-format, tools for object spatialization," in Proceedings of the Audio Engineering Society 22nd International Conference on Virtual, Synthetic and Entertainment Audio, Espoo, Finland, 2002.::



METHOD:: newDirection
Planewave encoder (monophonic).

argument:: theta
Azimuth angle, in radians: pi to -pi

argument:: phi
Elevation anglein radians: pi/2 to -pi/2

discussion:: This is the classic Ambisonic encoding (panning) function. SuperCollider's inbuilt link::Classes/PanB:: and the Ambisonic Toolkit's link::Classes/FoaPanB:: implement this encoder as a UGen, and allow dynamically changing strong::theta:: and strong::phi::.



METHOD:: newStereo
Stereophonic encoder.

argument:: angle
Soundfield distortion angle, in radians: pi/2 to -pi/2

discussion:: The stereophonic signal is encoded as two planewaves. When strong::angle:: = 0, the left and right channels of the input signal arrive at code:: [90, -90] :: degrees. strong::angle:: = pi/4 distorts the arrivals to code:: [45, -45] :: degrees. strong::angle:: = pi/2, places both the left and right inputs at front centre, code:: [0, 0] :: degrees. This behaviour matches that of the Ambisonic Toolkit's first order image warping UGens: link::Classes/FoaFocus::, link::Classes/FoaZoom::, link::Classes/FoaPush::, and link::Classes/FoaPress::.



METHOD:: newQuad
Quadraphonic encoder.

discussion:: The quadraphonic signal is encoded as four planewaves arriving at code:: [ 45, 135, -135, -45 ] :: degrees. This encoding is equivalent to placing infinitely distant loudspeakers around a soundfield microphone in an anechoic chamber.



METHOD:: new5_0
5.0 encoder.

discussion:: The 5.0 signal is encoded as five planewaves arriving at code:: [ 0, 30, 110, -110, -30 ] :: degrees. This encoding is equivalent to placing infinitely distant loudspeakers around a soundfield microphone in an anechoic chamber.



METHOD:: new7_0
7.0 encoder.

discussion:: The 7.0 signal is encoded as seven planewaves arriving at code:: [ 0, 30, 90, 135, -135, -90, -30 ] :: degrees. This encoding is equivalent to placing infinitely distant loudspeakers around a soundfield microphone in an anechoic chamber.



METHOD:: newPanto
Pantophonic (2D) regular polygon encoder.

argument:: numChans
number of input channel feeds

argument:: orientation
code::'flat':: or code::'point'::

discussion:: Inputs are in anti-clockwise order. The position of the first input channel is either centre or left of centre. link::#-dirChannels:: may be used to query resulting input channel directions. This encoding is equivalent to placing infinitely distant loudspeakers around a soundfield microphone in an anechoic chamber.



METHOD:: newPeri
Periphonic (3D) dual ring, regular cylindrical encoder.

argument:: numChanPairs
Number of channel pairs. (Half the total number of input channel feeds.)

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

argument:: orientation
code::'flat':: or code::'point'::


discussion:: Inputs are in anti-clockwise order, beginning with the top ring. The position of the first speaker is either centre or left of centre. link::#-dirChannels:: may be used to query resulting loudspeaker directions. This encoding is equivalent to placing infinitely distant loudspeakers around a soundfield microphone in an anechoic chamber.



METHOD:: newDirections
Virtual loudspeaker or microphone encoder, suitable for varied periphonic and pantophonic arrays.

argument:: directions
An array of directions of the virtual loudspeakers or microphones. Specify in radians.

Rank 1 arrays return pantophonic, while rank 2 arrays return periphonic. E.g.,
code::
// 2D:
~directions = [ theta0, theta1, ... thetaN ];
::
code::
// 3D:
~directions = [ [ theta0, phi0 ], [ theta1, phi1 ], ... [ thetaN, phiN ] ];
::

argument:: pattern
Virtual microphone pattern, code::nil::, or 0 to 1.

definitionList::
## code::nil:: || strong::directions:: specifies virtual loudspeaker positions
## 0 to 1 || strong::directions:: specifies a microphone array with patterns:
    table::
    ## strong::pattern:: || strong::microphone::
    ## 0.0 || Omni
    ## 0.5 || Cardioid
    ## 1.0 || Bi-directional
    ::
    If strong::pattern:: is an link::Classes/Array::, individual microphone patterns are specified.
::


discussion:: link::#-newDirections:: is the Ambisonic Toolkit's most versatile first order encoder. Arbitrary input loudspeaker and/or microphone arrays may be specified.

code::
// Periphonic (3D) encoder, a 1/2 dome of 13 loudspeakers
// [[0, 0], [45, 0], [90, 0], [135, 0], [-180, 0], [-135, 0], [-90, 0], [-45, 0],
//  [45, 35.3], [135, 35.3], [-135, 35.3], [-45, 35.3], [0, 90]]

~directions = pi/180 * [[0, 0], [45, 0], [90, 0], [135, 0], [-180, 0], [-135, 0], [-90, 0],
    [-45, 0], [45, 35.3], [135, 35.3], [-135, 35.3], [-45, 35.3], [0, 90]];
~encoder = FoaEncoderMatrix.newDirections(~directions);

// inspect
~encoder.dirChannels * 180/pi;
::

code::
// Periphonic (2D) encoder, 3 cardioid microphones
// See: http://www.michaelgerzonphotos.org.uk/microphones-calrecs.html
// [60, -180, -60]

~directions = pi/180 * [60, -180, -60];
~pattern = 0.5;
~encoder = FoaEncoderMatrix.newDirections(~directions, ~pattern);

// inspect
~encoder.dirChannels * 180/pi;
::

code::
// Periphonic (2D) encoder, 1 omni and 2 cardioid microphones
// [0, 45, -45]

~directions = pi/180 * [0, 45, -45];
~pattern = [0, 0.5, 0.5];
~encoder = FoaEncoderMatrix.newDirections(~directions, ~pattern);

// inspect
~encoder.dirChannels * 180/pi;
::


METHOD:: newZoomH2
link::http://www.zoom.co.jp/english/products/h2/##ZoomH2:: (pantophonic) encoder.

argument:: angles
Angles for front left and back left microphones, in radians. (The corresponding right microphones are mirrored across the y-axis.) Defaults to code:: [pi/3, 3/4*pi] :: .

note:: anchor::newzoomh2note:: The encoder reverses the labels for front and back of the link::http://www.zoom.co.jp/english/products/h2/##ZoomH2::. This is done so that directions are are preserved from the point of view of a field recording operator. With the link::http://www.zoom.co.jp/english/products/h2/##ZoomH2::'s display facing the operator (for ease of monitoring), sounds arriving in front of the operator will be encoded in the front of the soundfield. See also link::#newzoomdiscussion#Discussion:: below.::

argument:: pattern
Microphone pattern footnote::The default value, 0.5857, is derived from measurements made by Farina, and is a hyper-cardioid response with a zero at 135 degrees. See: link::http://pcfarina.eng.unipr.it/Public/Brahma/Zoom-H2/Polar-ZoomH2.xls:: ::, 0 to 1:

table::
## strong::pattern:: || strong::virtual microphone::
## 0.0 || Omni
## 0.5 || Cardioid
## 1.0 || Bi-directional
::


argument:: k
Post-encoding Y scalar.
note::Please see further discussion of strong::k:: link::#newzoomh2k#here::::

discussion::
anchor::newzoomdiscussion::
A four channel recording made by the link::http://www.zoom.co.jp/english/products/h2/##ZoomH2:: will be returned as two stereo .wav files named:

list::
## SRxxxF.wav
## SRxxxR.wav
::

Presuming the link::http://www.zoom.co.jp/english/products/h2/##ZoomH2:: is oriented as described link::#newzoomh2note#here::, the following illustrates correct input for the encoder:
code::
// ZoomH2 records two stereo .wav files:
//       SRxxxF.wav
//       SRxxxR.wav
// correct input for FoaEncoderMatrix.newZoomH2 is:

~in = [ SRxxxR.at(0), SRxxxR.at(1), SRxxxF.at(0), SRxxxF.at(1) ]
::

anchor::newzoomh2k::
The encoder includes a Y scalar, strong::k::, and an auditioned adjustment is usually necessary to improve the resulting image. As the link::http://www.zoom.co.jp/english/products/h2/##ZoomH2::'s polar patterns are not consistent across frequency, and the capsules are not coincident, imaging is not always consistent. Touching strong::k:: can go some way towards remedy-ing this.

note::
strong::k:: = 1.7378 is a value that has been found suitable for matching link::http://www.radio.uqam.ca/ambisonic/comparative_recording.html##Courville::'s link::http://www.zoom.co.jp/english/products/h2/##ZoomH2:: footnote:: Courville orients his ZoomH2 so that the labelled front of the device faces the front of the sound scene. This is front/back reversed as regards -newZoomH2. If you choose to encode Courville's example files, you'll need to follow with FoaMirrorX.:: and Soundfield recordings. footnote:: See: http://www.radio.uqam.ca/ambisonic/comparative_recording.html ::
::


METHOD:: newAtoB
A-format to B-format encoder. Encodes to a variety of tetrahedral orientations and W channel weights.


argument:: orientation
Orientation of the A-format tetrahedron.

table::
## strong::orientation:: || strong::angles:: ([theta, phi] in degrees)
## code::'flu':: || code:: [[45.0,  35.3], [-45.0, -35.3], [135.0, -35.3], [-135.0,  35.3]] ::
## code::'fld':: || code:: [[45.0, -35.3], [-45.0 , 35.3], [135.0,  35.3], [-135.0, -35.3]] ::
## code::'flr':: || code:: [[54.7,   0.0], [-54.7,   0.0], [180.0,  54.7], [ 180.0, -54.7]] ::
## code::'fud':: || code:: [[ 0.0,  54.7], [  0.0, -54.7], [125.7,   0.0], [-125.7,   0.0]] ::
## code::'fbd':: || code:: [[ 0.0,   0.0], [180.0, -70.5], [112.2,  28.1], [-112.2,  28.1]] ::
## code::'fbu':: || code:: [[ 0.0,   0.0], [180.0,  70.5], [112.2, -28.1], [-112.2, -28.1]] ::
## code::'flru':: || code:: [[67.8,  28.1], [-67.8,  28.1], [  0.0, -70.5], [ 180.0,   0.0]] ::
## code::'flrd':: || code:: [[67.8, -28.1], [-67.8, -28.1], [  0.0,  70.5], [ 180.0,   0.0]] ::
::

argument:: weight
The W weight factor.

table::
## strong::weight:: || strong::kind:: || strong::W scale::
## code::'dec':: || Decorrelated (on the sphere) || 1/sqrt(3)
## code::'can':: || Canonical (B-format) || 1/sqrt(2)
## code::'uns':: || Unscaled || 1
## code::'car':: || Cardioid || sqrt(3)
::


discussion::
The A-format encoder is often used in conjunction with the link::Classes/FoaDecoderMatrix#*newBtoA:: B-format decoder to form signal processing networks which preserve the spatial encoding as is described link::Classes/FoaDecoderMatrix#btoadiscuss#here::.

On its own, link::#*newAtoB:: is often used to author immersive, periphonic (3D) decorrelated soundfields.



INSTANCEMETHODS::
private:: init2D, init3D, initInv2D, initInv3D, initAtoB, initOmni, initDirection, initStereo, initQuad, init5_0, init7_0, initDirections, initPanto, initPeri, initZoomH2, printOn


METHOD:: kind
Answers the kind of encoder

discussion::

code::
// encoder
~encoder = FoaEncoderMatrix.newQuad

// inspect
~encoder.kind
::

code::
// encoder
~encoder = FoaEncoderMatrix.newPeri

// inspect
~encoder.kind
::


METHOD:: dim
Answers the number of encoder dimensions: 2D or 3D.

discussion::

code::
// encoder
~encoder = FoaEncoderMatrix.newQuad

// inspect
~encoder.dim
::

code::
// encoder
~encoder = FoaEncoderMatrix.newPeri

// inspect
~encoder.dim
::



METHOD:: numChannels
Answers the number of input channels (virtual loudspeakers or microphones).

discussion::

code::
// encoder
~encoder = FoaEncoderMatrix.newQuad

// inspect
~encoder.numChannels
::

code::
// encoder (two rings of 6)
~encoder = FoaEncoderMatrix.newPeri(6)

// inspect
~encoder.numChannels
::



METHOD:: dirChannels
Answers the direction of virtual loudspeaker or microphone feeds, with angles in radians.

returns:: A rank 1 array for pantophonic, and rank 2 array for periphonic. E.g.,
code::
// 2D:
[ theta0, theta1, ... thetaN ]
::
code::
// 3D
[ [ theta0, phi0 ], [ theta1, phi1 ], ... [ thetaN, phiN ] ]
::

code::
// encoder
~encoder = FoaEncoderMatrix.newQuad

// inspect
~encoder.dirChannels * 180/pi
::

code::
// encoder (two rings of 6)
~encoder = FoaEncoderMatrix.newPeri(6)

// inspect
~encoder.dirChannels * 180/pi
::



METHOD:: matrix
Answers the encoding matrix




METHOD:: numOutputs
Answers the number of outputs for the encoder. 3 for 2D and 4 for 3D.


METHOD:: dirOutputs
A convenience method providing polymorphism with link::Classes/FoaEncoderMatrix#-dirOutputs::.

returns::

list::
## for 2D: code:: [ inf, inf, inf ] ::
## for 3D: code:: [ inf, inf, inf , inf ] ::
::


METHOD:: numInputs
A synonym for link::#-numChannels::


METHOD:: dirInputs
A synonym for link::#-dirChannels::



EXAMPLES::

Please see link::Classes/FoaEncode#Examples::.
