! title Non Mixer User Manual ! author Jonathan Moore Liles #(email,male@tuxfamily.org) -- Table Of Contents : User Manual :: The Mixer / Mixer < non-mixer-complex.png The Non-Mixer is a stand-alone audio mixer, utilizing JACK as an audio subsystem. At the time of writing, the architecture of Non-Mixer is unique. By making the mixer stand-alone, concepts such as busses, sends, and inserts are eliminated, as the same goals can be achieved by simply adding more strips to the mixer. Start by creating a new project (menu item `Project\/New`). / New Project < new-project.png After the project has been created. Hit `a` or choose `Mixer\/Add Strip` from the menu to add a new strip to the mixer. ::: Display Options The display options, found in the `Options\/Display` submenu may be adjusted to suit your needs. Set the color scheme, widget style, and other graphic options to your liking. These options are global and affect all projects. ::: Mixer Groups Groups serve several purposes. Firstly, they allow for some organization of strips. Groups also allow parallel relationships of mixer strips to be made explicit. This has important performance implications in JACK2. Non Mixer supports an unlimited number of groups, each of which can contain an unlimited number of mixer strips. :::: How to Choose Groupings All strips in a group should be completely parallel with no feedback loop connections. A typical group might be named 'Input' and contain all input strips (strips that accept input from Non Timeline and have outputs all connecting to some master bus). To put it another way, if you have 100 inputs strips with identical output configurations (e.g. stereo or B-Format), that all connect to a master bus, then you have a candidate for a group. :::: Considering JACK Overhead JACK provides immense flexibility. But, as in most situations, that flexibility comes with a cost. In JACK the cost is a context switch per client. This applies /even for many clients which belong to the same process/, as in Non Mixer. Various factors go into determining the price of a context switch on any given system. It's not very expensive, but it does add up. It becomes problematic in sessions involving many clients (think 100s), each of which having a small DSP load (often smaller than the cost of JACK's context context switch). JACK *could* be smart enough to recognize that some clients belong to the same process and could be executed serially without requiring a context switch, but at the time of writing neither JACK1 nor JACK2's scheduling is that smart. If you're mixing a normal song (couple of dozen tracks) at low latency, this overhead will probably account for less than 1% of the total DSP load. If you're mixing an entire orchestra at ultra-low latency, then it might account for a quarter or more of the total DSP load. Groups mitigate this cost by reducing the number of JACK clients required for a mix. Strips in a group will execute serially without context switches or thread synchronization--reducing the total JACK overhead. However, if you have several groups, then they may all by run in parallel by JACK2. A mixer which uses a single JACK client (which is basically the way everything other than Non Mixer has been designed) is not a viable solution by this author's definition, because such a mixer cannot be from/to any other JACK clients without introducing an extra period of latency. To illustrate this point here are some figures from an actual song session including the whole Non suite plus a sampler, a synth and an ambisonics convolution reverb with a total of 13 strips in 4 groups in different configurations on the same system. JACK's DSP load figures are interpreted thus: if at a 2.7ms software latency setting the average time a proces cycle takes to complete is 2.7ms, then the DSP load is 100%. The usable ceiling on DSP load is 80%. This is true for both JACK1 and JACK2. The difference is that JACK2 may use all available CPU cores to execute the graph \(if there are enough clients in parallel signal flow\). 32-bit Intel Core2 Duo @1.6Ghz -r 48000 -p 256 -n 2 (5.3ms) [[ JACK Ver, Groups, DSP Load [[ JACK1, N, 39% [[ JACK1, Y, 27% [[ JACK2, N, 24% [[ JACK2, Y, 31% AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 256 -n 2 (5.3ms) [[ JACK Ver, Groups, DSP Load [[ JACK1, N, 28% [[ JACK1, Y, 12% [[ JACK2, N, 12% [[ JACK2, Y, 11% AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 128 -n 2 (2.7ms) [[ JACK Ver, Groups, DSP Load [[ JACK1, N, 29% [[ JACK1, Y, 17% [[ JACK2, N, 17% [[ JACK2, Y, 17% AMD FX-8350 @ 4.2Ghz 64-bit -r 48000 -p 32 -n 2 (0.7ms) [[ JACK Ver, Groups, DSP Load [[ JACK1, N, x [[ JACK1, Y, x [[ JACK2, N, 43% [[ JACK2, Y, 41% As you can see, for multiprocessor systems, JACK2 clearly has an advantage even without grouping. Of course, results will vary depending on the system and the mix. On the dual core system, performance actually degraded with JACK2 when using groups--this is because the number of parallel flows that JACK2 detected was reduced and the second core was being under utilized. Similarly, the performance of the 8-core AMD system doesn't seem that great even in the ungrouped mode--this is because the DSP load of each individual client is around the same as the cost of the context switching. It's a wash either way (if each strip had more or more complex modules on it, then the ungrouped mode would probably perform better). Since JACK1 cannot take advantage of more than 1 CPU core, there is no benefit to parallelism and grouped mode always outperforms ungrouped mode. So, for maximum capacity the combination of a multicore CPU with JACK2 and mixer groups is best. # All strips in a group *MUST* have the same output configuration. All # outputs will be mixed together by identity. That is, the 'AUX \(A\)' # outputs of each strip will be mixed together into a single 'AUX \(A\)' # output of the group. A strip within a group whose output # configuration differs from the group configuration will be marked as # invalid and will not be executed. :::: Creating a New Group Groups can be created by selecting the group dropdown on any mixer strip and choosing 'New Group'. A window will popup asking for a group name. Group names must be unique. The group will then be created and the selected strip added to it. :::: Adding a Strip to an Existing Group To add a strip to an existing group, simply select a group name from the group dropdown on the strip. :::: Removing a Strip from a Group Select '---' from the group dropdown. The strip will be removed from the group and will run in an independent JACK client. :::: Removing a Group Groups are destroyed automatically as soon as they contain zero strips. ::: Mixer Strips / Mixer Strip < single-strip.png Each mixer strip has a name and color, each of which may be defined by the user. Names, but not colors, must be unique. In addition, each strip has controls to move it left or right (the arrows) in the display and to remove it entirely (the 'X'). Strips start out in /narrow/ mode, with the /fader/ view enabled. Click the desired button to toggle the mode or view. Each strip has a context menu which lists the available options and their associated key-bindings. To bring up the context menu, `Right The fader view comprises a large gain control and digital peak meter indicator. These are automatically connected to the default gain and meter modules of the strip's signal chain. To see how an audio signal traveling through this strip will be processed, switch to its /signal/ view. :::: Navigation A strip is focused when you click on it. Focus can be moved among strips with the `Tab` and `Shift-Tab` keys. :::: Control The focused strip can be moved in the display order via the `[` and `]` keys. `Delete` removes a strip (with confirmation dialog). `n` and `w` set the focused strip's width to /narrow/ or /wide/, respectively, and `f` and `s` switch between /fader/ and /signal/ views. The strip's context menu can be invoked without the mouse by hitting the `Menu` key (assuming your keyboard has one). :::: Signal Chain The signal chain view of a mixer strip provides a way to view and manipulate the signal processing of a mixer strip. ::::: Modules / Modules < modules.png All signal processing in Non Mixer occurs in /Modules/. Modules are signal processing abstractions providing ports for audio and control I\/O and, in addition, some simple user interface. Sink and source modules carry audio out of and into JACK. Modules are displayed as named blocks. Some modules (e.g. the Meter module) may have additional GUI components. Each module has zero or more audio I\/O ports and zero or more control ports. Audio routing between modules is handled automatically. Modules with mono audio configurations (one channel in, one channel out) can be automatically adjusted to support any number of discrete channels. Modules with more (related) channels, however, introduce restrictions on the order in which modules can be chained. An indicator in the upper left-hand corner of each module block indicates whether the module has any parameters bound to controls. Non Mixer has several built-in modules. They are: = JACK = Performs JACK I\/O = Gain = Applies gain in dB = Meter = Digital Peak Meter = Mono Pan = Performs intensity panning of a mono signal into a stereo signal. = Plugin = Hosts a LADSPA plugin :::::: OSC Control The input parameters of all modules are controllable via OSC, regardless of whether the parameter is set as controllable. The format of the automatically generated OSC path names is as follows: > /strip/[STRIP_NAME]/[MODULE_NAME]/[PARAMETER_NAME] The UDP port that the OSC server binds to can be set by providing the `--osc-port` command-line option. Without this option, a random port will be bound automatically (the exact OSC URL will always be printed to the console as a line beginning with "OSC: "). The default path accepts a float value between 0.0 and 1.0 (a Control Voltage like signal) which will be automatically scaled to the allowable range of the control. A path ending in \/unscaled is also available, which accepts exact values, which will be clamped to the allowable range. For example: > /strip/[STRIP_NAME]/[MODULE_NAME]/[PARAMETER_NAME]/unscaled If same module\/plugin is used twice in a signal chain (e.g. multiple Gain stages), then a position dependent sequence number will be appended to the module name. For example, a path might look like the following: > /strip/Foo/Gain.1/Gain_(dB) For the second instance of the Gain module on the strip named 'Foo'. Non-DAW accesses these same signals via a more advanced signal routing layer on top of OSC. Any module parameter is easily controlled via Control Sequences in Non-DAW without the need to specify an OSC URL. :::::: Manipulation Left-clicking on a module brings up a Module Parameter Editor window for the selected module. Right-clicking on a module brings up a context menu allowing you manipulate the module, as well as to pick a new module to insert before the selected one in the chain. Middle-clicking on a module toggles its activation state (the audio signal will bypass inactive modules). Control+Right-clicking on a module causes it to be removed from the chain (modules added by default cannot be removed). The focused module may also be controlled via the keyboard. `Menu` brings up the context menu for the focused module. `Space` opens the module parameter editor, `b` toggles the bypassed state, and `Delete` removes the module from the chain (without confirmation!). `Control-X`, `Control-C` and `Control-V`, cut, copy, and paste modules, respectively. Modules may be copied within or across chain boundaries. The normal module I\/O constraints also apply to pasted modules. :::::: Module Parameter Editor / Module Parameter Editor < gverb-parameters-knobs.png The Module Parameter Editor is used to alter the values of a module's parameters, and in addition, to bind its parameters to controls. A menu button in the upper left-hand corner allows you to select between knob, vertical slider and horizontal slider controls. / Horizontal Sliders < gverb-parameters-hsliders.png / Vertical Sliders < gverb-parameters-vsliders.png Underneath each control is a bind button. Clicking adds a new control to the chain's /Controls/ view and binds it to the parameter in question. For simplicity, only one control at a time may be bound to a given parameter. :::::: Controls / Control View < controls.png The control view of a chain groups together all of the controls bound to parameters of modules in that chain. The default mode of controls is /Manual/. Right click on a control to bring up a menu which will allow you to select one of the available control I\/O methods to use. When /Control Voltage/ (CV) is selected, a CV input port will be created on the containing mixer strip's JACK client. The control will now accept values from that input. A control bound and configured in this way can then be connected to the output of a Non-DAW control sequence using your favorite connection manager. { NOTE: { All knob and slider controls respond to mousewheel { events. Hold down the `Ctrl` key while scrolling the mousewheel to { achieve finer resolution. ::::::: Control Voltages The control voltage concept should be familiar to anyone who has experience with analog modular synthesizers. MIDI, while having definite advantages in many respects, multiplexes control data in such a way as to make connecting one MIDI control to a parameter involve a significant inconvenience, usually requiring the adjustment of settings on both ends of the connection in order to separate the control data streams. Control Voltages, on the other hand, provide a simple 1:1 source to sink relationship and offer much higher resolution, both in time and value, than can be natively expressed through MIDI. The chief advantage of CV in the context of Non-DAW is the ease with which an control sequence can be connected to a mixer module parameter. If you have a MIDI controller that you'd like to use to control parameters of Non-Mixer, consider /jm2cv/, a JACK MIDI to Control Voltage daemon which was written by Peter Nelson specifically for use with Non-Mixer. jm2cv can be acquired by: > git clone git://fuzzle.org/jm2cv.git { NOTE: { The use of Control Signals (OSC) should be preferred for most types { of parameter automation, as LADSPA plugins are incapable of { processing Control Voltage signals at full audio resolution anyway. :::::: Spatialization / Spatialization Control on a Strip < spatialization-on-strip.png Non-Mixer supports Ambisonic spatialization via the excellent amb-\* LADSPA plugin set and others. Whenever a LADSPA plugin is added to a strip whose set of parameters include parameters named Azimuth and Elevation, Non-Mixer will detect this and automatically attach a Spatializer control to these parameters. The Spatializer will be displayed at the bottom of the mixer strip. A larger version of the control may also be found in the Module Parameter Editor. / Larger Spatialization Control < spatialization-in-mpe.png The spatialization control may be visualized as moving the sound source across the surface of a hemispherical dome enclosing the listener. The output of the spatializing plugin may be routed into a decoding plugin following it the same strip or, more usefully, the output of a number of Ambisonic panning plugins on different strips may be routed (through JACK) into a single master decoder instance on a final strip. ::: Projects A Non-Mixer project is a directory where Non-Mixer keeps the strip settings, project specific settings, and some meta-data. A project is completely self-contained. You can rename a project as simply as: > $ mv Project-A Project-B :::: JACK I/O Each mixer strip is presented as a separate JACK "client". This helps to avoid the necessity of internally duplicating JACK's routing logic and, with JACK2, permits the possibility of parallel execution of mixer strip signal chains. The JACK client name of each strip will correspond to the name of the strip. { NOTE: { The JACK API makes implementing this far more difficult and kludgey than it should have to be. { Please petition your local JACK developer to accept jack_client_set_name() into the API. / Patchage < non-mixer-and-non-daw-in-patchage.png