Pantophonic Monitoring of HOA (2D):
Guides (extension) | Libraries > Ambisonic Toolkit > Guides & Tutorials

Pantophonic Monitoring of HOA (2D)

Higher Order Ambisonic (HOA) 2D array decoding examples

The ATK offers HOA loudspeaker decoding via two methods:

Projection decoders require equally distributed loudspeakers. This is easy for 2D decoding, as all we need to do is to arrange loudspeakers in a polygon.

The ATK's HOA 2D projection decoder is HoaMatrixDecoder: *newPanto.

mode matching
The loudspeakers for mode matching decoders are not required to be equally distributed, however, the more evenly sampled an array is, the better the result.

The ATK includes two mode matching decoders: HoaMatrixDecoder: *newModeMatch & HoaMatrixDecoder: *newDiametric.

NOTE: If the ADT quark has been installed, the Ambisonic Decoder Toolbox can be used to return decoders designed via other methods.


In the examples to follow, we'll restrict ourselves to designing matrices with the assumption that all loudspeakers are equally distant from the array origin.


Before we start, evaluate the plotting functions found here:

We'll use these to evaluate the performance of the designed decoders.


Our most simple system for 2D decoding. If you haven't reviewed the discussion of quadraphonic panning in the context of pairwise panning laws, this would be a good time to do so.

Quad *newPanto (HOA1)

Here will use HoaMatrixDecoder: *newPanto to design a suitable matrix decoder for HOA1:

Performance plots

Let's view the performance by inspecting a few analysis plots.

Start with:

When we choose the energy optimised beam shape, the rV and rE vectors are the same length.

For an equally sampled array, we can predict the length of these vectors, which are measures of how localized a portion of the soundfield will appear in terms of velocity and energy.

You'll notice that we're seeing circles plotted. The soundfield is equally resolved in all directions.

Theoretical average values can be found:

Read these as a fraction of what we would expect for a real sound. As the values approach one, the phantom image matches the measure for a sound in the real world.

Try some of the other beam shapes and observe the plots and measures.

Let's try some other plots:

These plots illustrate the preformance of the decoder in terms of:

  1. localisation vector angular distortion
  2. phantom image spread
  3. amplitude and energy across the array

Front center is located at the center of the plots.

The first thing we're looking for in these plots is equal values in all directions. That's what we're seeing!

In particular, we see:

  1. No angular distortion. Phantom images will appear where they were intended. (That's panning!)
  2. Even image energy spread, which is associate with image resolution.
  3. Amplitude and energy remain constant across the array. No direction appears louder than another.


We should finish the radial part of the panning law with HoaNFCtrl. And to generate loudspeaker feeds, we'll need HoaDecodeMatrix to render:

Quad *newPanto (HOA3)

When we design a decoder a quadraphonic decoder for HOA3, surprisingly we'll see that the performance is the same as that seen for HOA1. The reasons for this are discussed in Ambisonic Enlightenment.

We can review the rule for 2D array resolution, to be clear.

Or... we can just use HoaMatrixDecoder: *newPanto to design a matrix decoder for HOA3. What we'll see is that the returned HOA3 quad decoder has the same performance at the previous HOA1 quad decoder:

Performance plots

Feel free to run the test plots:

We'll return the same results as earlier.

We can also compare measured results to theory:


In practice, we can recognize that truncating an HOA3 by hand will be more efficient for an undersample array:

NOTE: We don't have to truncate by hand if we don't want to. An HOA3 quad decoder will truncate inside the returned matrix.

If we truncate by hand we can save render time by using a lower order HoaNFCtrl.


For eight equally distributed loudspeakers, we'll also use HoaMatrixDecoder: *newPanto.

For this example we'll see that an octaphonic decoder for HOA3 performs much better than the equivalent for HOA1. The physical array is sampled high enough to return more resolved performance.

Octa *newPanto (HOA1)

Performance plots

Feel free to run the test plots:

Here we see all the performance measures are the same as for the HOA1 quad example, except for the amplitude measure. This is uniform, but it differs from the quad measurement. The reason for this is that we've matched the gain performance for energy:

As earlier, we see:

  1. No angular distortion
  2. Even image energy spread
  3. Constant amplitude and energy


The completed render network... same as for HOA1 quad, but for the octa decoder:

Octa *newPanto (HOA3)

An octaphonic array meets the array resolution required to reproduce 2D HOA3. (Hurrah!)

Here's the design code:

Feel free to run the test plots:

With all beam shapes (panning laws!) we see very good performance. As earlier, measures are even across the array. Also, the localisation vectors are long.

Compare measured results to theory:


Since the spatial sampling of the octa array meets HOA3, we won't truncate to save CPU:

NOTE: The earlier quad code wouldn't end up truncating, anyway, because we were doing a test.

7_0 Surround

Given an array of unevenly distributed loudspeakers, HoaMatrixDecoder: *newModeMatch is the decoder to choose.

What we'll see is the uneven array sampling leads to uneven performance measures.

For this example we'll see what happens with a less ideal array.

7_0 *newModeMatch (HOA3)

The ATK's mode matcher is not especially sophisticated when it comes to mode or degree truncation. The simple test we've seen before for 2D or 3D array resolution is made. For reasonably distributed arrays, we can get a good result.

We'll always want to review the returned performance to see if an acceptable decoder is returned.


Go ahead and run the test plots:

If you've kept the plot open for octa HOA3 with energy optimised beam, you'll see that the energy optimised 7_0 design returns fairly comparable performance within the front sixty degrees of the array.

However, as we move away from the front, the performance degrades.

NOTE: If we discard the center loudspeaker, we get a bit of a more even performance.

(Keep the plots up and design a new decoder w/out the center.)

Part of what is happening here is that the mode matcher is truncating from HOA3 to HOA2, as we have six loudspeakers rather then seven when the center is discarded.

If we try different orders and different beam shapes, we'll see that the performance varies significantly!

We can seek to quantify the performance of this designed decoder by inspecting:

What we see is that the energy performance varies!

This isn't surprising, as the mode matcher is trying to make up for the missing loudspeakers that are not found in the array.


Truncation happens inside the matrix, so we can just do the usual:

7_0 *ADT (HOA3)

For highly irregular loudspeaker arrays, other decoder design methods beyond simple mode matching are more likely to return more results. If we've installed the Ambisonic Decoder Toolbox, we'll have access to some of these.

Let's review an example for a 2D design.

First, we need to be sure to set local paths for ADT:

NOTE: We might want to consider adding these lines to the sclang startup file

We will start by specifying our decoder features and creating an ADT instance. In order to correctly manage the target gain normalisation, we'll treat the decoder returned by the ADT as a prototype. We'll then normalise the returned matrix later.

For a 2D design we have two design method choices: mode matching and AllRAD.1

If the ADT has been successfully started, we'll see this message in the post window: ADT initialized.

  1. Mode matching, aka pseudoinverse

    NOTE: The ADT's mode matcher includes an alpha parameter, which adjusts between directional accuracy and uniform loudness.
  2. AllRAD

    NOTE: AllRAD takes time!

If design of the prototype is successful, ADT will return: Result = 0.

To finish off the design, we'll do the following:

  1. load the prototype decoder created by the ADT
  2. create a new decoder and normalize to our chosen matching gain
  3. write out this new decoder, for later use


Given a successful design, we can run the same tests illustrated above: 7_0 *newModeMatch (HOA3).

[1] - The ADT doesn't appear to discard tesseral and zonal harmonics when designing mode matching or AllRad matrices, as would be expected for 2D designs.