Im not sure if this is the right way to do it or conceptually wrong, but i think i get the result i was looking for. maybe there is room for adjustment. let me know what you think.
i have used FoaEncoderMatrix.newDirections
with an Array of [0, 0, 0, 0, 0]; and then i use FoaTransform
rotate
where the angle comes from the channelMask
. This way you can adjust the \channelMask.kr
, \centerMask.kr
and \panMax.kr
like i wanted them to behave. But i had to use trig
instead of timings.trigger
inside of the channelMask
which is a bit of a headscratcher to me.
(
var timingInformation = { |maxOverlap, trig, grainRate|
var rate = if(trig.rate == \audio, \ar, \kr);
var arrayOfTrigsAndPhases = maxOverlap.collect{ |i|
var localTrig = PulseDivider.perform(rate, trig, maxOverlap, i);
var hasTriggered = PulseCount.perform(rate, localTrig) > 0;
var localPhase = Sweep.perform(rate, localTrig, grainRate * hasTriggered);
[localTrig, localPhase];
};
var trigsAndPhasesArray = arrayOfTrigsAndPhases.flop;
(\trigger: trigsAndPhasesArray[0], \phase: trigsAndPhasesArray[1]);
};
var channelMask = { |trig, numChannels, channelMask, centerMask, panMax|
var rate = if(trig.rate == \audio, \ar, \kr);
var panChannels = Array.series(numChannels, -1 / numChannels, 2 / numChannels).wrap(-1.0, 1.0);
var panPositions = panChannels.collect { |pos| Dser([pos], channelMask) };
panPositions = panPositions ++ Dser([0], centerMask);
panChannels.debug(\panChannels);
Demand.perform(rate, trig, 0, Dseq(panPositions, inf) * panMax).lag(0.001);
};
var hanningWindow = { |phase, overlap|
var windowRate = phase / overlap;
(1 - (windowRate * 2pi).cos) / 2 * (windowRate < 1);
};
SynthDef(\ambisonics_test, {
var numChannels = 5;
var tFreq = \tFreq.kr(1);
var trig = Impulse.ar(tFreq);
var grainFreq = \freq.kr(440);
var timings = timingInformation.(numChannels, trig, grainFreq);
var pan = channelMask.(trig, numChannels - 1, \channelMask.kr(1), \centerMask.kr(1), \panMax.kr(1));
var grainWindow = hanningWindow.(timings.phase, \overlap.kr(1));
var sig = sin(timings.phase * 2pi) * grainWindow * \amp.kr(0.25);
sig = FoaEncode.ar(sig, FoaEncoderMatrix.newDirections(Array.fill(numChannels, 0)));
sig = FoaTransform.ar(sig, 'rotate', pan * pi);
sig = FoaDecode.ar(sig, FoaDecoderMatrix.newStereo);
Out.ar(\out.kr(0), sig);
}).add;
)
s.meter;
x = Synth(\ambisonics_test);
x.set(\panMax, 0.8);
x.set(\channelMask, 1);
x.free;
EDIT: okay, this seems to be similiar to @jordan example for each channel has a unique position maybe better to collect a number of FoaEncoderMatrix.newOmni
here.