Transforms (spatial domain filter) a first order ambisonic signal (B-format). FoaXform applies static transforms, for dynamic transforms see FoaTransform.
in |
The B-format signal, an array: [w, x, y, z] |
xformer |
FoaXformerMatrix instance. |
mul |
Output will be multiplied by this value. |
add |
This value will be added to the output. |
An array of channels, the transformed B-format signal.
The examples below are intended to briefly illustrate some of the first order tranform options made available in the Ambisonic Toolkit. The user is encouraged to carefully review the features of FoaXformerMatrix to gain a deeper understanding of the flexibility of these tools.
Available transformers include rotations, mirroring, directivity (spatial low pass fitering), dominance (image warping), and a variety of dominance related transforms.
As the Ambisonic technique is a hierarchal system, numerous options for playback are possible. These include two channel stereo, two channel binaural, pantophonic and full 3D periphonic. With the examples below, we'll take advantage of this by first choosing a suitable decoder with with to audition.
Choose a decoder suitable for your system, as illustrated here. You'll end up definining ~decoder
and ~renderDecode
.
Rotation is one of the most used soundfield transforms. In this case we'll it to centre the subject of a field recording.
If you haven't already choose a ~decoder
and defined ~renderDecode
, do so now.
// ------------------------------------------------------------ // rotate xformer // b-format soundfile read from disk // define xformer matrix ~xformer = FoaXformerMatrix.newRotate // no rotation --> try this 1st ~xformer = FoaXformerMatrix.newRotate(-110.degrad) // by -110deg --> try this 2nd // inspect ~encoder.kind ~encoder.numChannels ~encoder.dirChannels.raddeg // read a whole sound into memory // remember to free the buffer later! // (boot the server, if you haven't!) ~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Leonard-Chinook.wav") ( { var sig; // audio signal // display xformer & decoder "Ambisonic transforming via % xformer".format(~xformer.kind).postln; "Ambisonic decoding via % decoder".format(~decoder.kind).postln; // ------------------------------------------------------------ // test sig sig = PlayBuf.ar(~sndbuf.numChannels, ~sndbuf, BufRateScale.kr(~sndbuf), doneAction:2); // soundfile // ------------------------------------------------------------ // transform sig = FoaXform.ar(sig, ~xformer); // ------------------------------------------------------------ // decode (via ~renderDecode) ~renderDecode.value(sig, ~decoder) }.scope; ) // free buffer ~sndbuf.free // ------------------------------------------------------------
In mirroring through the origin and delaying the soundfield, we can generate a new set of echos in this fireworks field recording.
If you haven't already choose a ~decoder
and defined ~renderDecode
, do so now.
// ------------------------------------------------------------ // mirrorO xformer // b-format soundfile read from disk // define xformer matrix ~xformer = FoaXformerMatrix.newMirrorO // inspect ~encoder.kind ~encoder.numChannels ~encoder.dirChannels.raddeg // read a whole sound into memory // remember to free the buffer later! // (boot the server, if you haven't!) ~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Leonard-Fireworks.wav") ( { var sig; // audio signal var delSig; // delayed signal var freq; // lp frequency var delay; // delay time var scale; // delay gain (as scale) // display xformer & decoder "Ambisonic transforming via % xformer".format(~xformer.kind).postln; "Ambisonic decoding via % decoder".format(~decoder.kind).postln; // ------------------------------------------------------------ // parameters freq = 1200; // in Hz delay = 0.5; // in seconds scale = 9.neg.dbamp; // ------------------------------------------------------------ // test sig sig = PlayBuf.ar(~sndbuf.numChannels, ~sndbuf, BufRateScale.kr(~sndbuf), doneAction:2); // soundfile // ------------------------------------------------------------ // delay, lp and gain delSig = LPF.ar(DelayN.ar(sig, delay, delay), freq, scale); // ------------------------------------------------------------ // transform delSig = FoaXform.ar(delSig, ~xformer); // ------------------------------------------------------------ // sum (comment this out to hear original signal) sig = sig + delSig; // sig = delSig; // or listen to the mirrored sig // ------------------------------------------------------------ // decode (via ~renderDecode) ~renderDecode.value(sig, ~decoder) }.scope; ) // free buffer ~sndbuf.free // ------------------------------------------------------------
Dominance adjusts the gain of a soundfield in a particular direction. Here we'll increase the amount of reverberation in this natural soundfield recording. As the image is warped at the same time, we'll also hear the frontal stage widen.
If you haven't already choose a ~decoder
and defined ~renderDecode
, do so now.
// ------------------------------------------------------------ // dominateX xformer // b-format soundfile read from disk // define xformer matrix ~xformer = FoaXformerMatrix.newDominateX // no dominance --> try this 1st ~xformer = FoaXformerMatrix.newDominateX(-3.0) // increase gain at rear // inspect ~encoder.kind ~encoder.numChannels ~encoder.dirChannels.raddeg // read a whole sound into memory // remember to free the buffer later! // (boot the server, if you haven't!) ~sndbuf = Buffer.read(s, Atk.userSoundsDir ++ "/b-format/Leonard-Orfeo_Trio.wav") ( { var sig; // audio signal // display xformer & decoder "Ambisonic transforming via % xformer".format(~xformer.kind).postln; "Ambisonic decoding via % decoder".format(~decoder.kind).postln; // ------------------------------------------------------------ // test sig sig = PlayBuf.ar(~sndbuf.numChannels, ~sndbuf, BufRateScale.kr(~sndbuf), doneAction:2); // soundfile // ------------------------------------------------------------ // transform sig = FoaXform.ar(sig, ~xformer); // ------------------------------------------------------------ // decode (via ~renderDecode) ~renderDecode.value(sig, ~decoder) }.scope; ) // free buffer ~sndbuf.free // ------------------------------------------------------------