<!doctype html>Guide to Mosca | SuperCollider 3.12.2 Help var scdoc_title = 'Guide to Mosca'; var scdoc_sc_version = '3.12.2'; Guide to Mosca: Filter: Basic Setup Binaural Speaker Array GUI components Top left Top Right Right Botom Left Botom Right Initialisation options Binaural or Raw output Coded control Embed SuperCollider synth in a Mosca source Runnig Mosca Without a GUI Automation OSSIA Serial devices & head tracking Using IEM ambisonic decoders Effect Insert Guide (extension) | Libraries > Ambisonic Toolkit | Libraries > HOA Guide to Mosca Extension Usagae exemples for Mosca See also: Mosca A video tutorial for Mosca is available online The user can set up a project directory with an "auto" subdirectory. A Folder containig room impulse resonses (RIRs) must also be provided for reverb convolutions. RIRs should have the first 100 or 120ms silenced to act as "tail" reverberator. For convenience, please download the "moscaproject.zip" file on the Mosca page which contains the file structure, example RIRs and B-format recordings as well as other information and demos. Note that the RIR example is recorded at 48kHz Basic Setup Binaural ( Server.killAll; // Make sure no servers are booted yet o = s.options; o.numInputBusChannels = 32; // Allow for many possible inputs o.numOutputBusChannels = 2; // Stereo output for binaural rendering o.numAudioBusChannels = 2048; o.numWireBufs = 512; s.waitForBoot { // Booting scsynth server before setting up Mosca // Create global variables passed as Mosca's arguments ~decoder = FoaDecoderKernel.newCIPIC(21, s, s.sampleRate.asInteger); // ATK Binaural s.sync; ~moscaInstance = Mosca( //projDir: "/path/to/project/folder", decoder: ~decoder ).gui(); }; ) Speaker Array The initialisation example below is intended for rendering on the 19.2 Dome at Le SCRIME (University of Bordeaux, France) with the 2nd order "internal" decoder. This speaker setup allows for 3rd order ambisonic with a custom ADT decoder (commented out). Speaker coefficients are given in the following format for 3-dimensional loudspeaker arrays with units in degrees and metres: [AZIMUTH, ELEVATION, RADIUS]. The elevation coefficient should be omitted for 2-dimensional arrays: [AZIMUTH, RADIUS]. See the AmbiDecoderToolbox tutorial for further information as well as Mosca for information on the decoder argument.( Server.killAll; // Make sure no servers are running yet o = s.options; o.numInputBusChannels = 32; // Allow for many possible inputs o.numOutputBusChannels = 24; o.numAudioBusChannels = 2048; o.numWireBufs = 512; s.waitForBoot { // Booting scsynth server before setting up Mosca // Create global variables passed as Mosca's arguments // ~decoder = ChateauBonnefont3; // ADT Dome ~decoder = "internal"; // use the internal decoder available up to order 2 (FMHDecode1) ~order = 2; ~out = 4; // The speacker array starts at the 5th output of the soundcard ~sub = [0, 1]; // 2 subwoofers are plugged into outputs 0 and 1 ~setup = [ [ 0, 90, 1.601], [ -45, 50, 1.565 ], [ -135, 50, 1.565 ], [ 135, 50, 1.565 ], [ 45, 50, 1.565 ], [ -30, 20, 2.062 ], [ -90, 20, 2.062 ], [ -150, 20, 2.062 ], [ 150, 20, 2.062 ], [ 90, 20, 2.062 ], [ 30, 20, 2.062 ], [ -22.5, -3, 2.829 ], [ -67.5, -3, 2.829 ], [ -112.5, -3, 2.829 ], [ -157.5, -3, 2.829 ], [ 157.5, -3, 2.829 ], [ 112.5, -3, 2.829 ], [ 67.5, -3, 2.829 ], [ 22.5, -3, 2.829 ] ]; MIDIIn.connect(); // must connect to MIDI for MMC synch s.sync; ~moscaInstance = Mosca( // projDir: "/path/to/project/folder", speaker_array:~setup, maxorder:~order, outbus:~out, suboutbus:~sub, decoder: ~decoder ).gui(); }; ) GUI components Top left Source index number ("Source 1" initially). you can change the selected source by right clicking on the background, openning or closing a drop down-menu. Once sources are placed around the center of the pannel, they can be selected again with a left click in their vicinity. HW-in. Toggle this to read audio from hardware inputs. The user must specify the number of channels and the staring bus (starting with zero) in the two fields beneath the toggle. Note this will override any loaded sound file. It is up to the user to manage the start busses for the various source. If for example source 1 is a 4 channel signal and starts on bus zero, a second stereo source must use a starting bus of 4 or higher. SC-in. Get audio in from a SuperCollider synth. The user needs to specify the number of channels in the GUI but does not need to specify the starting bus. Like HW-in, selecting SC-in for a particular source will disable any sound file that has been loaded. see the exemple below in Using Supercollider synths as inputs. load. Load a sound file for a given source. stream. Stream a sound file from disk for a given source. Loop. Loop the loaded soudfile file. audition. Use this button to audition a given source. Note that the transport also plays and cues sounds, the "audition" button should only be used to test sounds with the interface. Library. Drop-down menu for selecting spatializer Ugens. See Description/Sources in Mosca for more informations. Level. Adjust the source's level. Doppler amount. Adjust the source's doppler amount. Contraction. Allows the expension of the signal from spatially focussed to omnidirectional, mainly accomplished with cross-fades between B-format signals an their W component. Distant Reverb. Drop-down menu for selecting distant reverb types. see Description/Reverberation in Mosca for more informations. Dst. amount. If a Distant Reverb is selected, this controls the distant reverberation amount for the current source. Dst. room/delay. If "freeverb" is selected for Distant Reverb, this controls the local "room size" parameter. If "allpass" is selected, the value is applayed to the local delay time. Dst. damp/decay. If "freeverb" is selected for Distant Reverb, this controls the local"room dampenning" parameter. If "allpass" is selected, the value is applayed to the local decay speed. Close Reverb. Adjust the source's proximal reverberation amount. Angle. If the source is stereo, this controls the angle of the virtual speaker pair. The default is 1.05 radians (60 degrees). Rotate. If the source is 4 channel and above (B-format), this controls the rotation of the signal on the horizontal plane. Directivity. If the source is 4 channel and above (B-format) and the "ATK" Library is selected, this controls the directivity of the B-format signal (see ATK documentation) Spread / Diffuse. If the "ATK" Library is selected, these toggles allow the user to select two other methods to diffuse the signal omni-directionally. See "spread diffusion encoder" and "frequency spreading encoder" in FoaEncode Grain rate. If the "Josh" Library is selected, this controls the rate at which new grains are created (in Hz). Window size. If the "Josh" Library is selected, this controls The window size in seconds. Rand. win. If the "Josh" Library is selected, this controls a randomness factor for Window size. see MonoGrainBF Top Right show aux. Open and close an auxiliary controller window for a source. These sliders do not affect spatialisation, however the data produced is sent to any "registered" SuperCollider synth. After Initialising the GUI, see the exemple below in Using Supercollider synths as inputs. show data. Open or close a data window for all sources showing all parameters. show nodes. Show SuperCollider node tree. record audio. Records audio as a wav file to the project directory defined by the "projDir" class method. The number of channels recorded and the starting bus are defined by the "recchans" and "recbus" arguments respectively. blips. Check this box to include audible blips at the begining of the recording. This may be useful when post synchronising the recorded audio with footage taken on a video camera. Right Z-axis. Manipulate the Z-axis of the current source. Botom Left Automation transport. Includes a "play/stop" button, a return to start button, a record button and a "snapshot" button of current values. The Automation transport also contains a slider to move the "play head". Loaded sounds which are not looped will start at the beginning of the file, at "0" on the transport, and the transport fader may be used to advance through these sounds as well as advance through the recorded automations. save auto / load auto. Save/load to/from a chosen directory. Slave to MMC. Slave the transport to incoming Midi Machine Control data. This has been tested with Ardour and Jack on Linux. Loop. Loop the transport. Botom Right Close Reverb. Drop-down menu for selecting close reverb types. see Description/Reverberation in Mosca for more informations. Cls. room/delay. If "freeverb" is selected for Close Reverb, this controls the global "room size" parameter. If "allpass" is selected, the value is applayed to the global delay time. Dst. damp/decay. If "freeverb" is selected for close Reverb, this controls the global "room dampenning" parameter. If "allpass" is selected, the value is applayed to the global decay speed. M. Master output level. X. Listener's position on the X axis in meters. Y. Listener's position on the Y axis in meters. Z. Listener's position on the Z axis in meters. H. Listener's orientation around the Z axis in radiants. P. Listener's orientation around the X axis in radiants. R. Listener's orientation around the Y axis in radiants. Initialisation options Binaural or Raw output The exemple below offers different rendering and output options. The raw output setup is comented out, to enable it instead of binaural, simply switch the comments between the "o.numOutputBusChannels" the "~decoder", the "~order" and the "setup" variables. "raw format" and "raw output" are ignored if a decoder is provided so thy do not need to be comented to initialize binaural rendering.( ~supercoll = OSSIA_Device("SC"); // Create and name OSSIA_Device to contain all parameters ~supercoll.exposeOSC; // Evaluate this line while OSSIA/score is learning incoming OSC Server.killAll; // Make sure no servers are booted yet o = s.options; o.numInputBusChannels = 32; // Allow for many possible inputs o.numOutputBusChannels = 2; // Stereo output for binaural rendering // o.numOutputBusChannels = 22; // 13 non-ambisonic + 9 B-format (2nd order) o.numAudioBusChannels = 2048; o.numWireBufs = 512; s.waitForBoot { // Booting scsynth server before setting up Mosca // Create global variables passed as Mosca's arguments ~decoder = FoaDecoderKernel.newCIPIC(21, s, s.sampleRate.asInteger); // ATK Binaural // ~decoder = nil; // Raw output ~order = 1; // ~order = 2; ~out = 0; // Use te first available Output ~sub = nil; // No subwoofers ~setup = nil; // No speaker setup (headphones) /* ~setup = [ [ -60, 18, 10 ], [ 60, 18, 10 ], [ 0, 18, 10 ], [ -120, 18, 10 ], [ 120, 18, 10 ], [ 180, 18, 10 ], [ 0, 90, 10 ], [ -60, 51, 10 ], [ 60, 51, 10 ], [ 0, 51, 10 ], [ 180, 51, 10 ], [ -120, 51, 10 ], [ 120, 51, 10 ] ]; // 13.1 speaker setup for "Planetario De Pamplona" */ MIDIIn.connect(); // must connect to MIDI for MMC synch s.sync; ~moscaInstance = Mosca( // projDir: "/path/to/project/folder", nsources: 18, // Set the number of sources width: 850, // Set initial GUI size dur: 360, // Set transport duration // rirBank: "/path/to/rirBank/folder", server:s, parentOssiaNode:~supercoll, decoder: ~decoder, maxorder:~order, speaker_array:~setup, outbus:~out, suboutbus:~sub, rawformat:'FuMa', // Set Ambisonic Format for raw B-format output, use FuMa for using Ambdec external decoder rawoutbus:14 // Set raw B-format output bus, spearate from the non-ambisonic signal from "outbus" ).gui(); } ) Coded control An instance of the Mosca GUI and its sources may be controlled by SuperCollider code using the functions defined in the class MoscaBase. Similarly, Mosca parameters may be used to modulate synths. See the file MoscaBase.sc in the source for the available options. The following example shows the control of the Cartesian coordinates of source 1 with the setCartesian function.( // orbit derived from code by WillS: http://cplussplussatplay.blogspot.com.br/2011/09/ // simple-2d-orbit.html // "constants" var grav_const = 6.6742e-11; var earth_mass = 5.975e24; // variables var radius = 60.37814e6; var angle = 0; var grav_accel = 0; var body_pos_x = 1.4e6; // An X axis position of the body to be attracted var body_pos_y = 7.5e5; // A Y axis position of the body to be attracted var body_vel_x = 0.0; // Body velocity split into two components, X and Y var body_vel_y = 8.5e3; ~scale = 10000000 * 0.17; ~orbit = true; // set ~orbit to false to turn orbit off (see after end of block) Routine { while ( {~orbit}, { radius = (pow(body_pos_x, 2) + pow(body_pos_y, 2)).sqrt; grav_accel = (grav_const * (earth_mass / pow(radius, 2))); angle = atan2(body_pos_x, body_pos_y); body_vel_x = body_vel_x + (sin(angle) * grav_accel); body_vel_y = body_vel_y + (cos(angle) * grav_accel); body_pos_x = (body_pos_x - body_vel_x); body_pos_y = (body_pos_y - body_vel_y); ~moscaInstance.setCartesian(1, body_pos_x / ~scale, body_pos_y / ~scale, body_pos_y / ~scale / 5); 0.02.wait; }; ); }.play; ) ~orbit = false // turn off orbit Embed SuperCollider synth in a Mosca source A single SuperCollider synth may be embedded in a Mosca source and receive source-specific and global data from the Mosca GUI.// For a list of Mosca data available to synths, run the folowing line: Mosca.printSynthParams; // The following assumes existence a Mosca instance named ~moscaInstance ( // set Doppler amount and effect ~moscaInstance.setDoppler(1, 0.5); ~moscaInstance.setLocalEffect(1, "FreeVerb"); ~moscaInstance.setLocalAmount(1, 0.01); SynthDef("test-out", { | outbus=0, freq=440, radAzimElev = #[0,0,0], orientation = #[0,0,0], amp = 0 | var source, source2, point, delEnv; var dis = Lag.kr(radAzimElev[0], 0.1); var freqAdjust = dis * 40; SendTrig.kr(Impulse.kr(1), 0, amp ); // debug delEnv = Env.dadsr(0.2, attackTime: 0.1, decayTime: inf, sustainLevel: 0.9); // envelope with an onset delay equal to lag buffer source = Pulse.ar(freq + freqAdjust, width: dis, mul: EnvGen.kr(delEnv, doneAction: 2)); Out.ar(outbus, source); // or try stereo. Don't forget to put 2 channels for embedSynth // and getSCBuse below. Comment out the Out.ar above //source2 = Pulse.ar(freq + 23 + freqAdjust, width: dis, mul: EnvGen.kr(delEnv, doneAction: 2)); // Out.ar(outbus, [source, source2]); }).send(s); ~moscaInstance.embedSynth(1, 1, // first source, mono synth triggerFunc:{~mySynth = Synth.new("test-out", [\freq, 420, \outbus, ~moscaInstance.getSCBus(1, 1), \radAzimElev, #[0,0,0] ]).onFree({"done".postln;})} ); ) Runnig Mosca Without a GUI Automation As a first step, run the first block of code above in these Examples to open a Mosca GUI. Record some Automation data and save to disk, taking note of the address. Edit the block of code below to include the correct paths for your saved Automation file. Run the code and use the commands below the block to control playback. Server.killAll; o = s.options; o.numInputBusChannels = 32; o.numOutputBusChannels = 2; o.numAudioBusChannels = 2048; o.numWireBufs = 512; s.waitForBoot { // Booting scsynth server before setting up Mosca // Create global variables passed as Mosca's arguments ~decoder = FoaDecoderKernel.newCIPIC(21, s, s.sampleRate.asInteger); // ATK Binaural MIDIIn.connect(); // must connect to MIDI for MMC synchronisation s.sync; ~moscaInstance = Mosca( //projDir: "/path/to/project/folder", decoder: ~decoder ); ~moscaInstance.control.load("/path/to/your/automation/file"); ~moscaInstance.loadNonAutomationData("/path/to/your/automation/file"); }; ) ~moscaInstance.blindControlPlay // play Automation ~moscaInstance.blindControlStop // stop Automation ~moscaInstance.control.seek(5.0) // jump to the 5 second mark // Use this block to free a no-gui Mosca instance when finished ( ~moscaInstance.free; ~decoder.free; MIDIIn.disconnect(inport: 0, device: 0); ) OSSIA With or without the GUI, once the Mosca's root node has been exposed through an OSSIA_Device, all parameters are accessible from OSSIA/score or any other application able to communicate through OSC or OSCQuerry. See Ossia library reference for SuperCollider. For simple OSC communication, you can learn all of mosca's parameters easealy by creating and naming OSC device in OSSIA/score (keep deffault ports and adresses), then right clicking on the device and selecting the "learning" mode. you can then start mosca with a deffault OSSIA_Device and runnig the "~myOssiaDevice.exposeOSC()" method. All parameters should then appear in score's "learning" window. NOTE: The ".exposeOSC()" method will send all messages to the OSC device for learning. it can be called before, during or after Mosca's initialisation. Regardless, it is only relevant if score is in OSC learning mode, or if the parameters have already been learned. If no OSSIA_Device was passed to Mosca as the "parentOssiaNode" argument (above example), on will be created internaly. It can then be accessed and exposed wih the~moscaInstance.parentOssiaNode.exposeOSC(); method. Simply make sure to enable "learning" in OSSIA/score before running it. Serial devices & head tracking The Arduino and 9-Axes Motion Shield and supporting Arduino board such as the Uno (tested) should be placed on top of the headphones with the USB socket of the Arduino directed to the left of the user. In this orientation the USB cable can run down left-hand side of headphones together with audio lead. Use the Arduino project files in the directory "arduinoHeadTrack" in the git sources to configure the Arduino and shield. See https://www.arduino.cc for more information on the Arduino. When using Mosca with a head-tracker, it is useful to access the serial device with a persistant name. To do this on Debian/Ubuntu Linux, first get information about an attached device with a line such as: udevadm info -a -p $(udevadm info -q path -n /dev/ttyACM0) Search for the block of data that contains reference to the Arduino and take note of the values for idVendor and idProduct. Then create a file /etc/udev/rules.d/10-local.rules and add contents such as the following (edit this line and above to your needs): ACTION=="add", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0043", MODE:="0666", SYMLINK+="head_tracker" To load this without rebooting, type: sudo udevadm control --reload-rules Then disconnect and reconnect your device. In the above example it can be accessed at /dev/head_tracker for example.( Server.killAll; o = s.options; o.numInputBusChannels = 32; o.numOutputBusChannels = 2; o.numAudioBusChannels = 2048; o.numWireBufs = 512; s.waitForBoot { // Booting scsynth server before setting up Mosca // Create global variables passed as Mosca's arguments ~decoder = FoaDecoderKernel.newCIPIC(21, s, s.sampleRate.asInteger); // ATK Binaural s.sync; ~moscaInstance = Mosca(projDir: "/path/to/your/moscaproject", nsources: 12, width: 865, dur: 60, decoder: ~decoder, offsetheading: -2.6, recchans: 2, recbus: 0).gui().headTracker("/dev/head_tracker"); s.sync; // use the following to experiment with heading adjustments ~moscaInstance.offsetHeading(0.38); }; ) // If you close the Mosca window, don't forget to free the decoder afterwards ~decoder.free; Using IEM ambisonic decoders NOTE: Testing! The "IEM Plugin Suite" of VST3 plugins must be installed to run this example.// Mosca uses N3D normalisation for higher order ambisonics (up to the 5th order) and it is necessary to create a "preset" file for the IEM plugin used. Run the following to first create a preset and then to experiment with in BinauralDecoder.vst3 plugin with 2nd order ambisonics. s.boot; // make sure the server is running VSTPlugin.clear // run this line in case of accidental blackbanning of plugin. VSTPlugin.search; // see the plugin you wish to use ( SynthDef(\dummy, { arg bus; VSTPlugin.ar(In.ar(bus, 2)); }).add; ~synth = Synth(\dummy); ~vstDecoder = VSTPluginController.new(~synth).open("BinauralDecoder.vst3"); ~vstDecoder.gui; ) // set GUI to 2nd order with N3D normalisation and save as "2ndOrder". Close GUI. ~synth.free; // free dummy synth // Now run Mosca with the IEM BinauralDecoder and with 2nd order ambisonic encoding/decoding. ( ~supercoll = OSSIA_Device("SC"); // Create and name OSSIA_Device to contain all parameters ~supercoll.exposeOSC; // Evaluate this line while OSSIA/score is learning incoming OSC Server.killAll; // Make sure no servers are booted yet o = s.options; o.numInputBusChannels = 32; // Allow for many possible inputs //o.numOutputBusChannels = 2; // Stereo output for binaural rendering o.numOutputBusChannels = 18; // 13 non-ambisonic + 9 B-format (2nd order) o.numAudioBusChannels = 2048; o.numWireBufs = 512; s.waitForBoot { // Booting scsynth server before setting up Mosca // Create global variables passed as Mosca's arguments ~decoder = "BinauralDecoder.vst3"; ~order = 2; ~out = 0; // Use te first available Output ~sub = nil; // No subwoofers ~setup = nil; // No speaker setup (headphones) s.sync; ~moscaInstance = Mosca( nsources: 6, // Set the number of sources dur: 360, // Set transport duration // rirBank: "/path/to/rirBank/folder", server:s, parentOssiaNode:~supercoll, decoder: ~decoder, vstPreset: "2ndOrder", maxorder:~order, speaker_array:~setup, outbus:~out, suboutbus:~sub, ).gui(size: 700); } ) Effect Insert NOTE: work in progress (currently retired) /* In the GUI, play something in source #1. Filter it with a synth. Note that the source and the filter may be launched in either order. */ SynthDef(\Echo, {|aformatIn, aformatOut| var sig, delayTime = 0.6; sig = In.ar(aformatOut, 4); delayTime = 0.6; sig = CombC.ar(sig*0.5, 2, delayTime, 6) + sig; Out.ar(aformatIn, sig) }).add; y = Synth(\Echo, [\aformatIn, ~moscaInstance.getFoaInsertIn(1), \aformatOut, ~moscaInstance.getFoaInsertOut(1)], addAction: \addToTail); y.free; // free the filter ~moscaInstance.releaseInsert(1) // return to sound with no filter // If you have an external decoder, try this with a 2nd order mono source (will use 12- // channel A-format) SynthDef(\Filter, {|aformatIn, aformatOut| var sig = In.ar(aformatOut, 12); sig = RLPF.ar(sig, FSinOsc.kr( 0.2, 0, 3600, 4000), 0.9); Out.ar(aformatIn, sig) }).add; z = Synth(\Filter, [\aformatIn, ~moscaInstance.getSoaInsertIn(1), \aformatOut, ~moscaInstance.getSoaInsertOut(1)], addAction: \addToTail); z.free; // free the filter ~moscaInstance.releaseInsert(1) // return to sound with no filter helpfile source: /home/iain/.local/share/SuperCollider/downloaded-quarks/Mosca/HelpSource/Guide/guide-Mosca.schelplink::Guide/guide-Mosca::