Limiting/compressing ambisonic signals

I’m trying to do live ambisonic coding, and worried about amplitudes getting a little out of hand. when live coding i don’t have time to monitor and adjust every signal before it hits the master bus, so I want to put a limiter on the output, but i’m not sure the best way to do it with ambisonics while maintaining the spatial resolution.

What’s the best way to limit an ambisonic signal with the goal of maintaining as much spatial coherence as possible while also protecting speakers / ears?

My limited understanding of ambisonics suggests I could limit the first channel (zeroth order) of an ambisonic signal as necessary and then just make the exact same adjustments to all the other channels? is that correct?

var sig = ambisonic_signal;
Compander.ar(sig[0], sig, slopeAbove: 0.1)

My limited understanding of ambisonics suggests I could limit the first channel (zeroth order) of an ambisonic signal as necessary and then just make the exact same adjustments to all the other channels? is that correct?

My intuition says that this should work, but I’m not 100% sure. Ambisonics experts may want to chime in.

The IEM plugins have a multi-band compressor that does not alter the spatial image: IEM Plug-in Suite. You can use it with the VSTPlugin extension (VSTPlugin v0.6.0 -- final release!)

@gman, for your application, live safety level control, compressing / limiting the complete signal with respect to the first channel (W, aka degree zero) will do the job.

For your example code, you’ve swapped the in and control args, though. To be explicit, this is what we’re after:

// presuming first order Ambisonics created via 
// the ATK, or SC3's inbuilt encoder, PanB
//
// myFoa is the Ambisonic signal to be compressed

myW = myFoa.at(0);  // use this as the control

myCompFoa = Compander.ar(in: myFoa, control: myW, slopeAbove: 0.1);  // compress
1 Like

ahh thank you! too bad this forum doesn’t have inline function documentation!!!

I haven’t really used the VSTPlugin ugen much, but i do think it would get a lot of use for ambisonics. there are a lot of good plugins for ambisonic stuff that I’m not totally sure how to replicate in sc

… also… in the abstract, here are three sensible approaches to dynamic control of Ambisonic signals:

  1. control against the Soundfield Pressure Level
  2. control against the Soundfield Energy Level
  3. control in the Angular Domain (aka A-format)

The ATK includes the tools necessary for the job. If we have a first order signal, we can use FoaSFPL or FoaWp for method 1. For method 2, we can FoaSFWL or FoaWs.

Note, for these first two options we’ll need to make our own “home brew” compressor network rather than directly using Compander. As these first two compress all of the channels together, we won’t have any spatial distortion. So that’s nice!


The 3rd method is what I tend to use when mastering. The idea is to decompose from the Spherical Domain (aka B-format) to the Angular Domain (aka A-format). This gives us a collection of mono virtual microphones distributed across the sphere. Then we apply whatever dynamic control we’d like—SC3’s inbuilt dynamic controls can do the job. Once we’ve done whatever, we then recompose back into the Spherical Domain (aka B-format).

If we’re in first order, we can just do something like this:

// presuming first order Ambisonics created via 
// the ATK, or SC3's inbuilt encoder, PanB
//
// myFoa is the Ambisonic signal to be compressed

myAfmt = FoaDecode.ar(myFoa, FoaDecoderMatrix.newBtoA);  // decode into a tetrahedron
myCompAfmt = CompanderD.ar(in: myAfmt, slopeAbove: 0.1);    // compress each channel of tetrahedron separately
myCompFoa = FoaEncode.ar(myCompAfmt, FoaEncoderMatrix.newAtoB);  // reencode from tetrahedron

In this very simple example we’ve only made a minimal sampling of the soundfield, so we risk experiencing spatial distortion—which will be similar to what happens when we use two unlinked compressors with a stereo signal. If we oversample the sphere and use the cardioid beam shape (called \car for FOA UGens and \controlled for HOA UGens), then we can reduce the spatial distortion introduced by dynamic control. Essentially we’d be using oversampling and the cardioid beam shape to smooth the operation of the compressor across the sphere. (We can think of this as spatially low pass filtering the compression.)

  • Have a review of Spherical Decomposition to discover the joys of soundfield decomposition and recomposition.
  • And see FoaAnalyze for the ATK’s various FOA analyzer UGens.
  • Have fun!
3 Likes

I’m not sure if i’ve read this spatial decomposition article! need to look into it!