Hi,
I wish to record my quadriphonic work (square plan type LeftFront, RightFront, LeftBack, RightBack) toward binaural involving consequently some kind of HRTF filter. Is there a way, an existing Ugen able to do that on SuperCollider?
Thanks,
Y.
Have you checked out the ambisonic toolkit plugin? its in sc3-plugin. See if you have FoaDecode
installed?
Nope.
I have the latest version 3.13.0, but no FoaDecode
.
It is weird because it is listed on GitHub code source.
Maybe I should compile it from the source?
Jumping straight to compiling from source is quite extreme, and wouldnāt fix your issue here.
sc3-plugins is a separate download. What operating system are you on, and how did you install supercollider?
Once you have it installed, you use it like thisā¦
s.waitForBoot {
~decoder = FoaDecoderKernel.newListen(1002, s);
s.sync;
{
var ambi = ....some ambi signal;
FoaDecode.ar(ambi, ~decoder);
}.play
}
OS X 12.6.7 (Monterey)
SuperCollider 3.13.0 downloaded from this page (3.13.0 universal binary, macOS 10.14 and later).
What do you mean by āsome ambi signal
ā?
I do not use any ambisonic tools. I have four channels output as the UGen Pan4
does.
I am not too familiar with ambisonic as you can guess.
The little I understand seems we have to convert the 4-channel array to some kind of ambisonic matrix. Am I right and is it possible?
You have to install the quark as well:
Ok! Super Thanks! I got it (I mean the ATK quark ).
s.waitForBoot {
~binaural_decoder = FoaDecoderKernel.newListen(1002, s);
s.sync;
{
var quad = ....some quad signal;
var ambi = FoaEncode.ar(quad, FoaEncoderMatrix.newPanto(4));
var binaural = FoaDecode.ar(ambi, ~binaural_decoder);
}.play
}
There are many subtitles to this, but the above is the basic use case.
Your last code does not work!
I did it with the first one but there is some kind of confusion with the speakersā order according to the panoramic of Pan4
:
(
s.waitForBoot {
~encoder = FoaEncoderMatrix.newQuad;
//~encoder.dirChannels = [ -45, 45, -135, 135 ].degrad;
~decoder = FoaDecoderKernel.newListen(1002, s);
s.sync;
{
var ambi = FoaEncode.ar(Pan4.ar(PinkNoise.ar(0.5), MouseX.kr(-1,1), MouseY.kr(-1,1)), ~encoder);
FoaDecode.ar(ambi, ~decoder);
}.play
}
)
Maybe I do not use the right encoder/decoder ā¦
Yup, Pan4
uses a non ambisonic friendly LF, RF, LR, RR format. Use this insteadā¦
s.waitForBoot {
~binaural_decoder = FoaDecoderKernel.newListen(1002, s);
s.sync;
{
var mono = PinkNoise.ar(0.2);
var ambi = FoaPanB.ar(
mono,
MouseX.kr(-pi, pi)
);
var binaural = FoaDecode.ar(ambi, ~binaural_decoder);
binaural
}.play
}
The fact is my work outputs a four channels array as Pan4
does.
Is there any doc about the ambisonic format?
I am going to study all that, and if I find a happy outcome I will send feedback.
Meanwhile, any help is welcome.
In that case, you can convert to the expected quad format like thisā¦
var oldPan ....;
var newPan = [oldPan[0], oldPan[1], oldPan[3], oldPan[2]];
It just swaps the back speakers.
Now you can use that with FoaEncoderMatrix.newQuad
.
And yes, the ambisonic toolkit has a (perhaps too) indepth tutorial in the help docs.
Yes, I know about that.
Maybe is the pink noise making the confusion. I did it with sine waves and it sounds like it is ok.
Now, the issue is to bring my outputs to the encoder.
~encodeBus=Bus.audio(s, 4);
a = Synth(\mainOutputSynth, [\out, ~encodeBus]);
...
var ambi = FoaEncode.ar(~encodeBus, ~encoder);
But no sound!
Now, it looks like it is ok with:
var ambi = FoaEncode.ar(InBus.ar(~encodeBus, 4), ~encoder);
Thanks for sharing this. Iāve also been wanting to get into binaural for some time. This code is a great place to start.
Apologies if Iām hijacking here, but Iām trying to wrap my head around how this binaural might work with multichannel expansion. I.e., letās say that I have an array of 8 signals. Right now, Iāve got code that looks like this:
verbSend = Pan2.ar(signals, pan).sum;
Where verbSend is the panned and summed stereo signal, signals is an array of mono signals, and pan is an array of pan values.
Now if I wanted to replace the panned values with an array of binaural values, Iām guessing that naively adding .sum isnāt going to return the 2-channel binaural output Iām expecting.
I.e,
var binaural = FoaDecode.ar(signals, binaural_pan).sum;
isnāt going to do what I want, correct?
What would be the best way to do that?
TLDR: yes that works fine, but you might have your encode/decode the wrong way around.
Here is how to quickly test it.
Not in any SynthDef nor in any function, just right in the main window, evaluate this line by line and watch the post window, it will show you the layout of the signal.
~sig = SinOsc.ar()!8; // [ a SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc, a SinOsc ]
~pan = Pan2.ar(~sig, 0).sum; // [ a BinaryOpUGen, a BinaryOpUGen ]
Here above how the Pan2 line returned an array of two channels, thats your stereo.
~bin = FoaPanB.ar(~sig, 0).sum; // [ a BinaryOpUGen, a BinaryOpUGen, a BinaryOpUGen, a BinaryOpUGen ]
And here it turns the mono signals into one ambisonic channel.
If you remove the .sum
it gives you 8*4 channels in an array.
This is the wrong way around, you encode into ambisonic, and decode out. If you want to pan mono signals around a 2D circle, FoaPanB
is your friend. It is an encoder, although not explicitly stated. Now to move the sound closer to the centre, check out FoaProximity
, but that works on an ambisonic signal.
On the āperhaps too indepthā front, the documentation includes a fairly verbose review of FOA decoding.
Two use cases very close to the problem raised by @Yann_Ics can be found in the Binaural discussion. (BTW, Discussion of FOA encoding can be found on this page.)
For this exact transcoding problem (Quad to Binaural) we could use FoaEncoderMatrix: *newQuad
for the job; though, weād need to sort the initial quad channel ordering to match that expected by *newQuad
.
In this case, the easiest way would be to use FoaEncoderMatrix: *newDirections
:
// define encoder matrix
~directions = [ 45, -45, 135, -135 ].degrad; // quad: LeftFront, RightFront, LeftBack, RightBack
~encoder = FoaEncoderMatrix.newDirections(~directions); // choose for Yann_Ics
~decoder = FoaDecoderKernel.newSpherical; // kernel decoders should be freed after use!!
/*
... presume ~myQuad is available...
*/
// transcode...
~myBinaural = FoaDecode.ar(FoaEncode.ar(~myQuad, ~encoder), ~decoder);