title:: Introducing the Ambisonic Toolkit
summary:: Introduction to the Ambisonic Toolkit
categories:: Libraries>Ambisonic Toolkit
keyword::Atk

section:: The paradigm

The Ambisonic Toolkit (ATK) brings together a number of classic and novel tools and transforms for the artist working with Ambisonic surround sound and makes these available to the SuperCollider3 user. The toolset in intended to be both ergonomic and comprehensive, and is framed so that the user is encouraged to ‘think Ambisonically’. By this, it is meant the ATK addresses the holistic problem of creatively controlling a complete soundfield, allowing and encouraging the artist to think beyond the placement of sounds in a sound-space (sound-scene paradigm). Instead the artist is encouraged to attend to the impression and imaging of a soundfield, therefore taking advantage of the native soundfield-kernel paradigm the Ambisonic technique presents.

The ATK's production model is illustrated below:

image::atknetwork.png#ATK paradigm::

Here you'll see that the ATK breaks down the task of working with Ambisonics into three separate elements:

definitionlist::
## Author || Capture or synthesise an Ambisonic soundfield.
## Image || Spatially filter an Ambisonic soundfield.
## Monitor || Playback or render an Ambisonic soundfield.
::

The below sections go into more detail as to the specifics of each task. For examples that show more concise examples for usage in SynthDef and NRT, see link::Guides/ATK-SynthDef-Examples::


section:: Authoring

Most users approaching Ambisonics are usually presented with two avenues to author an Ambisonic soundfield: capture a natural soundfield directly with a Soundfield microphone, footnote::J.-M. Batke, "The B-Format Microphone Revised," presented at the Ambisonics Symposium 2009, Graz, 2009.
:: or author a planewave from a monophonic signal. footnote::D. G. Malham and A. Myatt, "3-D Sound Spatialization using Ambisonic Techniques," Computer Music Journal, vol. 19, no. 4, pp. 58-70, 1995.:: SuperCollider's inbuilt link::Classes/PanB:: provides the latter solution.

The ATK provides a much wider palate of authoring tools via link::Classes/FoaEncode::. These include:

list::
## emphasis::planewave: :: classic directional encoding
## emphasis::omnidirectional: :: a soundfield from everywhere
## emphasis::virtual loudspeaker array: :: transcoding standard formats
## emphasis::pseudoinverse microphone array: :: encoding from discrete microphones or signals
::

The emphasis::pseudoinverse:: encoding technique provides the greatest flexibility, and can be used with both microphone arrays and synthetic signals. In the absence of a Soundfield microphone, this feature gives the opportunity to deploy real-world microphone arrays (omni, cardioid, etc.) to capture natural soundfields. With synthetic signals, emphasis::pseudoinverse:: encoding is usually regarded as the method of choice to generate spatially complex synthetic Ambisonic images. In combination with the ATK's link::#Imaging#imaging:: tools these can then be compositionally controlled as required.

See link::Classes/FoaEncode::, link::Classes/FoaEncoderMatrix:: and link::Classes/FoaEncoderKernel:: for more details about encoding.



section:: Imaging

For the artist, the real power of the ATK is found in the imaging transforms. These are spatial domain filters which reorient, reshape or otherwise spatially filter an input soundfield. Many users will be familiar with the soundfield rotation transform, as SuperCollider provides the inbuilt link::Classes/Rotate2::.

The ATK provides a much wider and comprehensive toolset, including:

list::
## emphasis::rotation: :: soundfield rotation about an axis
## emphasis::mirror: :: soundfield reflection across an axis
## emphasis::directivity: :: soundfield directivity
## emphasis::dominance: :: adjust directional gain of soundfield
## emphasis::focus: :: focus on a region of a soundfield
## emphasis::push: :: push a soundfield in a direction
::

The imaging tools are provided in two forms: link::Classes/FoaXform##static:: and link::Classes/FoaTransform##dynamic:: implementations. While most transforms are provided in both categories, a number are found in only one guise. footnote::It is also useful to note that the link::Classes/FoaTransform##dynamic:: transforms are also available as individual UGens. However, users are advised to use link::Classes/FoaTransform:: for convenience.::

See link::Classes/FoaTransform::, link::Classes/FoaXform:: and link::Classes/FoaXformerMatrix:: for more details about imaging.


subsection:: Reading imaging illustrations

As artists working with sound, we should expect most users to be very capable expert listeners, and able to audition the results of spatial filtering of an input soundfield. However, it is often convenient to view a visual representation of the effect of a transform. The ATK illustrates a number of its included transforms in the form shown below.

On the left hand side of the figures a plot of the unchanged soundfield is illustrated. The X-Y axis is shown, viewed from above with the top of the plot corresponding to the front of the soundfield. Eight planewaves are encoded arriving from cardinal directions:

list::
## Front
## Front-Left
## Left
## Back-Left
## Back
## Back-Right
## Right
## Front-Right
::


emphasis::Front::, emphasis::Left::, emphasis::Back-Left:: and emphasis::Back:: are noted with an associated gain, in dB. Individual planewaves are coloured with respect to the gain scale at the far left of the figures.

With changing strong::angle::, we see the encoded planewaves both move towards the front of the image (to a single planewave at the extreme) and change gain in link::#zoom#ZoomX::. When strong::angle:: is 90 degrees, the planewave at emphasis::Front:: has been increased to 6dB, while emphasis::Back:: has disappeared. footnote::Decreased to -inf dB::

anchor::zoom::
image::../Classes/zoom_fig.png#ZoomX imaging::

link::#push#PushX:: also distorts the incident angles of the encoded planewaves. However, here we see two differences with link::#zoom#ZoomX::. Firstly, the gains of the individual elements don't vary as considerably, and the encoded planewaves are illustrated as moving off the perimeter of the plot.

Moving from the edge of the diagram towards the centre emphasis::does not imply:: the sound moves from the edge of the loudspeakers towards the centre, as one might expect. Instead, what we are seeing is the loss of directivity. Moving towards the centre means a planewave moves toward becoming omnidirectional, or without direction. (This becomes clearer when we look at link::#direct#DirectO::.)

With link::#push#PushX::, when strong::angle:: is 90 degrees, all encoded planewaves have been pushed to the front of the image, and gain is retained at 0 dB for all elements.

anchor::push::
image::../Classes/push_fig.png#PushX imaging::

link::#direct#DirectO:: adjusts the directivity of the soundfield across the origin. Here we see all elements collapsing towards the centre of the plot. At this point the soundfield is omnidirectional, or directionless.

anchor::direct::
image::../Classes/direct_fig.png#DirectO imaging::

See link::Classes/FoaZoomX::, link::Classes/FoaPushX:: and link::Classes/FoaDirectO:: for more details about these illustrated transforms.



section:: Monitoring

Perhaps one of the most celebrated aspects of the Ambisonic sound technique has been its design as a hierarchal reproduction system, able to target a number of varying loudspeaker arrays. Users may be familiar with SuperCollider's inbuilt regular polygon decoder, link::Classes/DecodeB2::.

The ATK provides a much wider palate of optimised monitoring tools via link::Classes/FoaDecode::. These include:

list::
## emphasis::stereo UHJ: :: classic Ambisonic stereo decoding
## emphasis::binaural: :: measured and synthetic HRTFs
## emphasis::regular 2D & 3D: :: single and dual polygons
## emphasis::diametric 2D & 3D: :: flexible semi-regular arrays
## emphasis::5.0: :: link::http://www.brucewiggins.co.uk/##Wiggins:: optimised decoders
::

While the emphasis::regular:: decoders will be suitable for many users, emphasis::diametric:: decoding enables the greatest flexibility, and allows the user to design substantially varying semi-regular arrays suitable for a wide variety of playback situations.

note:: All decoders presume loudspeakers are placed at equal radii from the origin of the array, and gain is normalised. Loudspeaker arrays with unequal radii may be realised if the resulting wavefront arrival times are compensated through the use of delay lines.::


See link::Classes/FoaDecode::, link::Classes/FoaDecoderMatrix:: and link::Classes/FoaDecoderKernel:: for more details about decoding.


section:: Installation

The ATK library for SuperCollider3 is distributed via the link::http://sc3-plugins.sourceforge.net##sc3-plugins:: project. If you're reading this document, these extensions have most likely been corectly installed.

Additionally, the ATK has a number of dependencies. Please install the following:

list::
##link::http://quarks.svn.sourceforge.net/viewvc/quarks/MathLib/##MathLib:: Quark. See: link::Guides/UsingQuarks::

##link::http://www.ambisonictoolkit.net/wiki/tiki-index.php?page=Downloads#ATK_Kernels#ATK Kernels::

##link::http://www.ambisonictoolkit.net/wiki/tiki-index.php?page=Downloads#ATK_Example_Soundfiles#ATK Example Soundfiles::
::

section:: Examples

The examples below are intended to briefly illustrate playback and imaging of soundfields with the ATK. The user is encouraged to explore the ATK's documentation to gain a deeper understanding of the flexibility of these tools.

As the Ambisonic technique is a hierarchal system, numerous options for playback are possible. These include two channel stereo, two channel binaural, pantophonic and full 3D periphonic. With the examples below, we'll take advantage of this by first choosing a suitable decoder with with to audition.

subsection:: Choose a decoder

A number of decoders are defined below. Please choose one suitable for your system. Also, don't forget to define code:: ~renderDecode :: !

note:: If you choose a kernel decoder, link::Classes/FoaDecoderKernel::, be sure to free the kernel after use. ::

code::
// ------------------------------------------------------------
// switch to internal server, and boot
(
        s = Server.internal;
        Server.default = s;
        s.boot;
)


// ------------------------------------------------------------
// choose a decoder

// stereophonic / binaural
~decoder = FoaDecoderMatrix.newStereo(131/2 * pi/180, 0.5) // Cardioids at 131 deg
~decoder = FoaDecoderKernel.newUHJ                         // UHJ (kernel)
~decoder = FoaDecoderKernel.newSpherical                   // synthetic binaural (kernel)
~decoder = FoaDecoderKernel.newCIPIC                       // KEMAR binaural (kernel)


// pantophonic (2D)
~decoder = FoaDecoderMatrix.newQuad(k: 'dual')             // psycho optimised quad
~decoder = FoaDecoderMatrix.newQuad(pi/6, 'dual')          // psycho optimised narrow quad
~decoder = FoaDecoderMatrix.new5_0                         // 5.0
~decoder = FoaDecoderMatrix.newPanto(6, k: 'dual')         // psycho optimised hex


// periphonic (3D)
~decoder = FoaDecoderMatrix.newPeri(k: 'dual')             // psycho optimised cube
~decoder = FoaDecoderMatrix.newDiametric(                  // psycho optimised bi-rectangle
    pi/180 * [[30, 0], [-30, 0], [90, 35.3], [-90, 35.3]],
    'dual'
)


// inspect
~decoder.kind


// ------------------------------------------------------------
// define ~renderDecode
(
~renderDecode = { arg in, decoder;
    var kind;
    var fl, bl, br, fr;
    var fc, lo;
    var sl, sr;
    var flu, blu, bru, fru;
    var fld, bld, brd, frd;
    var slu, sru, sld, srd;


    kind = decoder.kind;

    case
        { decoder.numChannels == 2 }
            {
                // decode to stereo (or binaural)
                FoaDecode.ar(in, decoder)
            }
        { kind == 'quad' }
            {
                // decode (to quad)
                #fl, bl, br, fr = FoaDecode.ar(in, decoder);

                // reorder output to match speaker arrangement
                [fl, fr, bl, br]
            }
        { kind == '5.0' }
            {
                // decode (to 5.0)
                #fc, fl, bl, br, fr = FoaDecode.ar(in, decoder);
                lo = Silent.ar;

                // reorder output to match speaker arrangement
                [fl, fr, fc, lo, bl, br]
            }
        { kind == 'panto' }
            {
                // decode (to hex)
                #fl, sl, bl, br, sr, fr = FoaDecode.ar(in, decoder);

                // reorder output to match speaker arrangement
                [fl, fr, sl, sr, bl, br]
            }
        { kind == 'peri' }
            {
                // decode (to cube)
                #flu, blu, bru, fru, fld, bld, brd, frd = FoaDecode.ar(in, decoder);

                // reorder output to match speaker arrangement
                [flu, fru, blu, bru, fld, frd, bld, brd]
            }
        { kind == 'diametric' }
            {
                // decode (to bi-rectangle)
                #fl, fr, slu, sru, br, bl, srd, sld = FoaDecode.ar(in, decoder);

                // reorder output to match speaker arrangement
                [fl, fr, bl, br, slu, sru, sld, srd]
            };
}
)

// ------------------------------------------------------------
// now we're ready to try the examples below!
// ------------------------------------------------------------
::


subsection:: Produced via the Ambisonic Toolkit

The following three sound examples are excerpts from recordings produced via the ATK.

If you haven't already choosen a code:: ~decoder:: and defined code:: ~renderDecode ::, do so link::#choose_a_decoder#now::.


code::
// ------------------------------------------------------------
// B-format examples, produced via the ATK
// B-format soundfile read from disk


// read a whole sound into memory
// remember to free the buffer later!
// (boot the server, if you haven't!)
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Anderson-Pacific_Slope.wav")
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Howle-Calling_Tunes.wav")
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Pampin-On_Space.wav")



(
{
    var sig;                            // audio signal


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

    // ------------------------------------------------------------
    // test sig
    sig = PlayBuf.ar(~sndbuf.numChannels, ~sndbuf, doneAction:2);   // soundfile


    // ------------------------------------------------------------
    // decode (via ~renderDecode)
    ~renderDecode.value(sig, ~decoder)

}.scope;
)

// free buffer
~sndbuf.free
// ------------------------------------------------------------
::

note:: strong::Soundfile Credits::

list::
## Joseph Anderson, "Pacific Slope," Epiphanie Sequence, Sargasso SCD28056
## Tim Howle, "Calling Tunes," 20 Odd Years, FMR FMRCD316-0711
## Juan Pampin, "On Space," Les Percussions de Strasbourg 50th Anniversary Edition, Classics Jazz France 480 6512
::

::


subsection:: Natural soundfields, with imaging transforms

This example illustrates the application of various spatial filtering transforms to natural soundfields, recorded via the Soundfield microphone.

The soundfield is controlled by link::Classes/MouseY::, which specifies the transform strong::angle:: argument (90 deg to 0 deg; top to bottom of display). With the mouse at the bottom of the display, the recorded soundfield is unchanged. At the top, the transform is at its most extreme.

If you haven't already choosen a code:: ~decoder:: and defined code:: ~renderDecode ::, do so link::#choose_a_decoder#now::.

note:: See link::Classes/FoaTransform:: for further details.::

code::
// ------------------------------------------------------------
// B-format examples, natural soundfield with imaging transform
// B-format soundfile read from disk

// choose transformer
~transformer = 'zoomX'
~transformer = 'pushX'
~transformer = 'directO'



// read a whole sound into memory
// remember to free the buffer later!
// (boot the server, if you haven't!)
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Hodges-Purcell.wav")
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Leonard-Orfeo_Trio.wav")
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Courville-Dialogue.wav")
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Leonard-Chinook.wav")
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Leonard-Fireworks.wav")
~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Anderson-Nearfield.wav")


(
{
    var sig;                            // audio signal
    var angle;                          // angle control


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

    // gain ---> top            = 90 deg
    //           bottom         = 0 deg
    angle = MouseY.kr(pi/2, 0);


    // ------------------------------------------------------------
    // test sig
    sig = PlayBuf.ar(~sndbuf.numChannels, ~sndbuf, doneAction:2);   // soundfile

    // ------------------------------------------------------------
    // transform
    sig = FoaTransform.ar(sig, ~transformer, angle);


    // ------------------------------------------------------------
    // decode (via ~renderDecode)
    ~renderDecode.value(sig, ~decoder)

}.scope;
)

// free buffer
~sndbuf.free
// ------------------------------------------------------------
::

note:: strong::Soundfile Credits::

list::
## P. Hodges, "Purcell - Passacaglia (King Arthur)," Sound of Space: ambisonic surround sound. [Online]. Available: http://soundofspace.com/ambisonic_files/52 [Accessed: 03-Nov-2011].
## J. Leonard, "The Orfeo Trio & TetraMic," Sound of Space: ambisonic surround sound. [Online]. Available: http://soundofspace.com/ambisonic_files/41 [Accessed: 03-Nov-2011].
## D. Courville, "Comparative Surround Recording," Ambisonic Studio | Comparative Surround Recording, 2007. [Online]. Available: http://www.radio.uqam.ca/ambisonic/comparative_recording.html [Accessed: 26-Jul-2011].
## J. Leonard, ""A couple of Chinook helicopters," Sound of Space: ambisonic surround sound, 20-Mar-2008. [Online]. Available: http://soundofspace.com/ambisonic_files/47. [Accessed: 03-Nov-2011].
## J. Leonard, “Fireworks,” Sound of Space: ambisonic surround sound, 25-Aug-2009. [Online]. Available: http://soundofspace.com/ambisonic_files/37. [Accessed: 03-Nov-2011].
## Joseph Anderson, "Nearfield source," [unpublished recording]
::

::
