Spatial audio question

Suppose one had an 8 speaker piece in the form of 8 mono .wav files.
Would ambisonics be a good approach to remap those to 6 or 4 speakers?

As the lead dev for the ATK project, I’d expect I would say, “Yes! Ambisonics would be great for this!”

You could also use PanAz for the job… or even VBAP, if you’d like.

My advice is to try some of these out, have a listen, try different setting…

Would I need to use higher-order ambisonics (warning: I do not know very well what I’m talking about …) to preserve more spatiality or would that make no difference at all in this case?

ah the fantastic problem of downmixing… if you don’t have the sources, then it’ll always be a compromise. Actually, it is always a compromise even with the sources but you can decide for each strand/stem/material what is the less worst option.

Do you have a 4 or 6 channel studio to remix in? Then you can try for each section of the piece which is best (amplitude based panning (including ambisonics because in the end it is what it is), or 1 to 1 assignation)

Good luck!

p

Here’s the rule for 2D Ambisonics:

~whatOrder2D = { |numChannels = 4|
	((numChannels - 2) / 2).floor.asInteger
};

And for your cases:

~whatOrder2D.value(4);  // -> 1
~whatOrder2D.value(6);  // -> 2

… and here’s a (nearly complete) example:

// 8 channel input...
// ... sort into LR pairs
~numInputs = 8;
~encodeDirs = Array.regularPolygon(~numInputs, pi/~numInputs, pi);
~encodeDirs = [ ~encodeDirs.keep(~numInputs.div(2)), ~encodeDirs.drop(~numInputs.div(2)).reverse ].flop.flatten;
~encodeDirs.raddeg;  // check angles (deg)

// 6 channel output...
// ... sort into LR pairs
~numOutputs = 6;
~decodeDirs = Array.regularPolygon(~numOutputs, pi/~numOutputs, pi);
~decodeDirs = [ ~decodeDirs.keep(~numOutputs.div(2)), ~decodeDirs.drop(~numOutputs.div(2)).reverse ].flop.flatten;
~decodeDirs.raddeg;  // check angles (deg)

// Ambisonic order...
~order = ~whatOrder2D.value(~numOutputs);

// design encoder and decoder...
// ... specify target beam shape
~beamShape = \energy;  // optimal for general decoding

~encoder = HoaMatrixEncoder.newDirections(~encodeDirs, order: ~order);
~decoder = HoaMatrixDecoder.newDirections(~decodeDirs, ~beamShape, order: ~order);

/*
NOTE:

We can use HoaMatrixDecoder:*newDirections because we have an equally spaced "pantophonic" loudspeaker array.
The result is the same as using HoaMatrixDecoder:*newPanto, but the returned channels are in the order we've sorted.
*/

/*
This isn't the complete UGen graph... but illustrates how to connect things up...
*/

{
	~inputSig = PlayBuf.ar(...);
	
	~outputSig = HoaDecodeMatrix.ar(
		HoaEncodeMatrix.ar(
			~inputSig,
			~encoder
		),
		~decoder
	)
}
2 Likes

Thanks, that gives me a very good starting point!