VarGui shortcut builds quick building of slider / player guis for synths and sequencing
Part of: miSCellaneous
See also: VarGui, HS with VarGui
As described in its helpfile VarGui allows combined control of Synths, Pbinds / EventStreamPlayers and Tasks in one GUI. Many of its options though may not be relevant for most usages, also control specs were to be given directly (changed with v0.5). Shortcut build methods take advantage of SynthDef controlspec metadata, if defined (or global ControlSpecs), and autogenerate Pbinds for sequencing. Controls and Pbinds can be customized with options.
Main tools are the methods sVarGui (synth), pVarGui (pattern) and compound builders spVarGui / psVarGui. Methods sVarGui / pVarGui, applied to a single Symbol / String, produce a VarGui for one or more Synth(s) or Pbind(s) based on the referred single SynthDef (Exs. 1a, 1b, 2a, 2b). Both methods also apply to collections of SynthDef names (3a, 3b), whereas spVarGui and psVarGui, builders of mixed Synth / Pbind VarGuis, expect collections of two items which may be Symbols / Strings or collections of Symbols / Strings (3c).
1.) Synth GUIs
Example 1a: default instrument
(
s = Server.local;
Server.default = s;
s.boot;
)
// No metadata is defined with default instrument, per default global ControlSpecs are used.
// Here its definition from Event.sc:
(
SynthDef(\default, { arg out=0, freq=440, amp=0.1, pan=0, gate=1;
var z;
z = LPF.ar(
Mix.new(VarSaw.ar(freq + [0, Rand(-0.4,0.0), Rand(0.0,0.4)], 0, 0.3)),
XLine.kr(Rand(4000,5000), Rand(2500,3200), 1)
) * Linen.kr(gate, 0.01, 0.7, 0.3, 2);
OffsetOut.ar(out, Pan2.ar(z, pan, amp));
}, [\ir]).storeOnce;
)
// With the next line you should get a VarGui with controls for freq, amp, pan and gate.
// In SC 3.5.0 gate isn't stored anymore in global ControlSpecs, so it won't be there.
// If you encounter other differences, global ControlSpecs and / or the
// default instrument have probably been changed,
// see below how to display and change global Specs.
// In global ControlSpecs amp (and, if there, gate) default to 0,
// you have to raise both in order to hear sound after pressing the player button.
\default.sVarGui.gui;
// automatic use of global ControlSpecs turned off, Synths with default args
\default.sVarGui(useGlobalSpecs: false).gui;
// global specs, not all of them ControlSpecs, are stored in Spec.specs ...
Spec.specs.associationsDo(_.postln);
// ... they can be added or replaced with .add
// for default instrument examples
// we replace \amp spec with a new ControlSpec with default 0.1
Spec.add(\amp, [0, 1, \lin, 0, 0.1]);
// generating a number of Synths, controls can be excluded,
// parallel slider dragging with Alt, parallel button action with Shift-click
\default.sVarGui(exclude: [\gate, \pan], num: 3).gui;
// controls can be replaced ...
\default.sVarGui(ctrReplace: [\freq, [400, 440, \exp, 0, 420]], exclude: \gate).gui;
// ... and added, before or after the main block of controls from metadata or global ControlSpecs,
// this collection is empty here, so ctrBefore and ctrAfter are equivalent
\default.sVarGui(useGlobalSpecs: false, ctrBefore: [\freq, [400, 440, \exp, 0, 420]]).gui;
// bad definition, \freq is already used as global ControlSpec
\default.sVarGui(ctrBefore: [\freq, [300, 1000, \exp, 0, 440]]).gui; // WRONG
Example 1b: SynthDefs including metadata
SynthDef with defined controlspec metadata. The specs can be stored as ControlSpecs or Arrays, may also be Symbols / Strings refering to the global dictionary of Specs (Spec.specs). It's only convention to store specs under the key \specs, it can be anything else, and nothing prevents you from storing more than one dictionary of ControlSpecs per SynthDef - the VarGui shortcut methods have a metaKey arg (default: \specs) which determines where to lookup in the metadata dictionary.
(
SynthDef(\buzz, { arg freq = 400, out, gate = 1, freqDev = 0.01, att = 0.01, dec = 0.01, susLevel = 0.5, rel = 1,
cutoff = #[1000, 1000, 1000], rq = 0.25, amp = 0.2, preAmp = 1, maxDelay = 0.03;
var src, srcFreq, sig;
sig = Mix.fill(3, { |i|
// chorus spread over three registers
srcFreq = (2 ** i) * freq * (1 + Rand(freqDev.neg, freqDev)) / 2;
src = RLPF.ar(Saw.ar(srcFreq, preAmp), cutoff[i], rq).softclip * amp *
EnvGen.kr(Env.adsr(att, dec, susLevel, rel), gate, doneAction: 2);
// random spatialization (for sequencing) by L/R delay
[DelayL.ar(src, maxDelay, Rand(0, maxDelay)), DelayL.ar(src, maxDelay, Rand(0, maxDelay))]
}) ;
// ensure sample accurate output for events of short durations
OffsetOut.ar(out, sig);
}, metadata: (
specs: (
freq: [20, 5000, \exp, 0, 80],
gate: [0, 1.0, \lin, 0, 1],
freqDev: [0.0, 0.02, \lin, 0, 0.002],
att: [0.01, 0.2, \lin, 0, 0.01],
dec: [0.01, 0.2, \lin, 0, 0.01],
susLevel: [0.01, 1, \lin, 0, 0.5],
rel: [0.01, 2, \exp, 0, 1],
cutoff: [200, 5000, \exp, 0, 1000],
rq: [0.1, 0.9,\lin, 0, 0.2],
amp: [0.0, 1, \lin, 0, 0.2],
preAmp: [0.9, 5, \lin, 0, 1],
maxDelay: [0, 0.01, \lin, 0, 0.002]
),
// doesn't matter for VarGui if spec defined as Array or ControlSpec,
// an arbitrary number of arbitrarily named alternative Spec Events may be passed,
// for non-sequencing use adsr params may be dropped
basicSpecs: (
freq: [20, 5000, \exp, 0, 80],
gate: [0, 1.0, \lin, 0, 1],
cutoff: [200, 5000, \exp, 0, 1000],
rq: [0.1, 0.9,\lin, 0, 0.2],
amp: [0.0, 1, \lin, 0, 0.2],
preAmp: [0.9, 5, \lin, 0, 1]
)
)
).add;
)
// here metadata includes a gate spec with default 1
// metadata has priority over global ControlSpecs
// metaKey \specs used per default
\buzz.sVarGui.gui;
// use gui options for better arrangement
\buzz.sVarGui(num: 4).gui(tryColumnNum: 2, sliderHeight: 16);
// alternative metadata, metaKey to be passed,
// mostly sounds different from last version
// because of fixed max chorus-width param freqDev
\buzz.sVarGui(num: 4, metaKey: \basicSpecs).gui(tryColumnNum: 2);
2.) Sequencing GUIs
Controlling Pbinds / EventStreamPlayers with VarGui is based on (a) the setting of environmental variables and (b) the proper definition of Pbinds with funtional code (Event patterns and Functions) so that EventStreamPlayers get the updated variable values in the following events.
Basic example of a Pbind to get envir values:
p = Pbind(
\dur, Pfunc { ~dur } * Pseq([2,1,1], inf),
\legato, Pfunc { ~legato },
\amp, Pfunc { ~amp }
)
Especially when based on a SynthDef with a large number of args writing a Pbind can be lengthy, moreover redundant if there are many pbind pairs of the form
[ aSymbol, Pfunc { ~aSymbol } ]
The pVarGui method is going the opposite way: Pbind pairs get this most simple form for all args with metadata or global ControlSpecs defined, though it's possible to exclude keys and add respectively replace customized pairs before and after the automatically generated ones. All you need is a SynthDef that is suited for Pbind sequencing (known to SynthDescLib by being added, properly defined Envelopes).
WARNING: as a lot of the underlying Pbind structure (by default all of it !) is hidden, it's possible to call pVarGui without knowing anything about Patterns. Nevertheless it's highly recommended to be aware of the mechanisms of Pbind for applying useful sequencing customizations and having a look at the fully written Pbind examples in VarGui. Clearly: adding, replacing and excluding Pbind pairs without seeing the resulting code is a possible source of error, so if using VarGui this way better start slowly and go on stepwise. With the post option you can print out the ordered list of pairs.
Example 2a: default instrument
// for default instrument examples
// we replace \amp spec with a new ControlSpec with default 0.1
Spec.add(\amp, [0, 1, \lin, 0, 0.1]);
// Most simple example to get a VarGui controlling a Pbind / EventStreamPlayer with
// default instrument, control of duration and legato is automatically added.
// As with the sVarGui method synth controls are added when found in metadata definition
// or global ControlSpecs, different from sVarGui \gate is excluded by default.
\default.pVarGui.gui;
// adding a pattern pair - if it contains one of the keys \note, \midinote or \degree
// the freq pair is removed automatically, see posted Pbind pairs
\default.pVarGui(pAfter: [\degree, Pwhite(0,5)], post: true).gui;
// pattern pair replacement as in basic example above
\default.pVarGui(pReplace: [\dur, Pfunc { ~dur } * Prand([2,1,1], inf)] ).gui;
// adding a pattern pair after the main block of pairs,
// same effect as before
\default.pVarGui(pAfter: [\dur, Pkey(\dur) * Prand([2,1,1], inf)], post: true).gui;
// Internally a Pbind of this form had been generated (see post window),
// in each Event the second Stream with key \dur gets the value from the first,
// overrides it in the Event.
Pbind(
// pBefore pairs (optinally passed to pVarGui)
...
// these are always placed before the main block
\instrument, \default,
\dur, Pfunc { ~dur },
\legato, Pfunc { ~legato },
// main block of pairs corresponding to args for which
// spec definition was found (if not excluded or replaced),
// ordered like in SynthDef
\freq, Pfunc { ~freq },
\amp, Pfunc { ~amp },
\pan, Pfunc { ~pan },
// pAfter pairs (optinally passed to pVarGui)
\dur, Pkey(\dur) * Prand([2,1,1], inf)
)
// Additional arrayed control for simple step sequencing with random init values.
// The Pseq degree pattern is wrapped in a Plazy to make it independent from a
// specific Environment, playing and setting the variables will
// happen in a new Environment generated by the VarGui.
(
\default.pVarGui(
ctrBefore: [\a, { [0, 5, \lin, 1, rrand(0,6)] } ! 8 ],
pBefore: [\degree, Plazy { Pseq(~a, inf) } ]
).gui;
)
// A number of Pbinds and control sets can be generated with the num arg,
// control and pattern customization args take Functions (optionally of indices)
// for expansion.
// This a potentially powerful feature, also suited for producing a real mess !
// Especially think of possibly inappropriate ranges !
// If you are unsure try out evaluating code of the form ...
{ |i| ... } ! n
// ... separately before plugging in the shortcut methods.
// Here the Function passed to ctrBefore has no index arg,
// it just produces 4 different tuples of
// init values for the step sequencers,
// the pBefore Function determines 4 different octave registers
// quant arg ensures staying in sync based on the passed rhythmic patterns
(
\default.pVarGui(
/* ctrBefore: */ { [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 8 ] },
/* ctrReplace: */ [\dur, [0.2, 0.6, \lin, 0.2, 0.2]],
pBefore: { |i| [\degree, Plazy { Pseq(~a, inf) }, \octave, i+4] },
num: 4,
quant: 0.2,
post: true
).gui(tryColumnNum: 2);
)
Example 2b: SynthDefs including metadata
Automatic Pbind generation in VarGui shortcut builds is especially saving typing if SynthDefs have a lot of args and controlspec metadata defined.
// most simple, controls are built for all args with metadata defined
// arrayed args are detected and controls are established for a corresponding array
// SynthDef from above
\buzz.pVarGui.gui;
// use the exclude option to exclude from automatically generated controls and Pbind pairs
// you would want to do that for a static value or sequencing not to be gui-controlled
// always SynthDef default value 0.01 for attack time
\buzz.pVarGui(exclude: [\att], post: true).gui;
// sequencing without control
// RLP filter rq excluded from gui control and automatic Pbind pair generation,
// though added to Pbind pairs again as passed to pBefore (could also be pAfter)
\buzz.pVarGui(exclude: [\rq], pBefore: [\rq, Pseq([ 0.05, 0.8, 0.8, 0.8], inf)], post: true).gui;
// same effect on sound, but we have a useless rq control
\buzz.pVarGui(pAfter: [\rq, Pseq([ 0.05, 0.8, 0.8, 0.8], inf)], post: true).gui;
\buzz.pVarGui(pReplace: [\rq, Pseq([ 0.05, 0.8, 0.8, 0.8], inf)], post: true).gui;
// here the pBefore arg is useless as the Pfunc that takes controlled values
// comes after in execution and will overwrite the value per Event
\buzz.pVarGui(pBefore: [\rq, Pseq([ 0.05, 0.8, 0.8, 0.8], inf)], post: true).gui;
// establishing a cutoff freq rhythm for all three layers
// remember that in Pbinds arrayed args must be distinguished from the syntax for generating
// multiple synths per Event, this can be achieved by wrapping in an additional array
\buzz.pVarGui(pReplace: [\cutoff, Pfunc { [~cutoff] } * Pseq([3,1,1], inf) ]).gui;
// step sequencer for quartertone bassline
(
\buzz.pVarGui(
ctrAfter: [\a, { var lo = 25, hi = 50; [lo, hi, \lin, 0.5, rrand(lo*2, hi*2) / 2 ] } ! 8 ],
pBefore: [\midinote, Plazy { Pseq(~a, inf) } ],
post: true
).gui;
)
// step sequencer with two voices
// by passing functions different control ranges and registers are established
// both lines are in a quartertone scale but shifted by an eigthtone
// lines itself can be shifted by an offset ~add
// modifier keys can be used to perform parallel slider or button actions
// alt for parallel slider movement and shift for parallel button actions (VarGui)
(
\buzz.pVarGui(
ctrReplace: [\dur, [0.1, 0.2, \lin, 0.1, 0.2], \amp, [0.0, 0.5, \lin, 0, 0.3]],
ctrAfter: { |i| var d = 0.25;
[\add, [-12, 12, \lin, 0.5, 0],
\a, { [(i*d), 11.5 + (i*d), \lin, 0.25, rrand(0, 23) / 2 + (i*d)] } ! 8
] },
pBefore: { |i| [
\note, Plazy { Pseq(~a, inf) } + Pfunc { ~add },
\octave, 3 + (i*4) + Pwhite(0,1)
] },
quant: 0.2,
post: true,
num: 2
).gui(tryColumnNum: 2);
)
Example 2c: Combination of parameter control and pattern exchange (JITLib)
(
\buzz.pVarGui(
ctrReplace: [\freq, [20, 1000, \exp, 0, 80]],
pReplace: [
\cutoff, Pdefn(\cutoff, Pseq([3, 1, 1, 1, 1], inf)) * Pfunc { [~cutoff] },
\freq, Pdefn(\freq, Pseq([1, 1, 1.3, 1.2, 1], inf)) * Pfunc { ~freq }
]
).gui;
)
// evaluate step by step on the fly pattern changes before playing around with params
Pdefn(\freq, Pseq([1, 1, 1.7, 1.3, 1.2], inf));
Pdefn(\cutoff, Pseq([2, 1, 1], inf));
Pdefn(\freq, 1);
Pdefn(\cutoff, Pseq([1, 2, 1.7, 1.3, 1.2], inf));
3.) Mixed GUIs
To control Synths or Pbinds / EventStreamPlayers derived from more than one SynthDef sVarGui and pVarGui can be applied to collections.
Example 3a: Synths from different SynthDefs
// for default instrument examples
// we replace \amp spec with a new ControlSpec with default 0.1
Spec.add(\amp, [0, 1, \lin, 0, 0.1]);
// different synths
[\buzz, \default].sVarGui.gui
// in basic form this works equivalently ...
VarGui(synth: [\buzz, \default]).gui;
// ... but for customization the shortcut method sVarGui is more convenient,
// otherwise you'd have to pass or generate controls explicitely (5b).
// sVarGui and pVarGui, applied to SequenceableCollections, expect Dictionaries
// of pairs argName / arg, so you can pass Events.
// Their number must equal the collection's size.
(
[\buzz, \default].sVarGui(
(ctrReplace: [\freq, [97, 103, \exp, 0, 99]]),
(ctrReplace: [\freq, [194, 206, \exp, 0, 201]], exclude: \gate)
).gui;
)
// more synths
(
[\default, \buzz].sVarGui(
(ctrReplace: { [\freq, [194, 206, \exp, 0, rrand(194.0, 206)]] }, exclude: \gate, num: 4),
(ctrReplace: [\freq, [97, 103, \exp, 0, 99]])
).gui(tryColumnNum: 2, allowSynthBreak: false);
)
Example 3b: Pbinds from different SynthDefs
// overtones, deviations of pitch and pulsation
(
[\default, \buzz].pVarGui(
(ctrReplace: { |i| var f = (2*i + 1) * 100, d = 0.2, lo = 0.99, hi = 1.01;
[\freq, [f*lo, f*hi, 0, 0, f*rrand(lo,hi)], \dur, [d*lo, d*hi, 0, 0, d*rrand(lo,hi)] ] },
exclude: \gate,
post: true,
num: 4),
(ctrReplace: [\freq, [97, 103, \exp, 0, 99], \dur, [0.195, 0.205, 0, 0, 0.2] ])
).gui(tryColumnNum: 2, allowEnvirBreak: false)
)
// step sequencer
(
[\buzz, \default].pVarGui((
ctrBefore: [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 8 ],
ctrReplace: [\dur, [0.2, 0.4, \lin, 0.2, 0.2]],
pBefore: [\degree, Plazy { Pseq(~a, inf) }, \octave, 3],
quant: 0.2
),(
ctrBefore: [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 4 ],
ctrReplace: [\dur, [0.1, 0.3, \lin, 0.1, 0.2]],
pBefore: [\degree, Pfunc { [0, [0,4], [0,5]].choose } +
Plazy { Pseq(~a, inf) }, \octave, Pwhite(5,7) ],
quant: 0.2
)
).gui(tryColumnNum: 2, allowEnvirBreak: false);
)
Example 3c: Synths and Pbinds
// Pbind granulation with \buzz, controls and pbind pairs adapted and added,
// psVarGui (pbind input first) and spVarGui (synth input first)
// apply to collections of two items.
// If only one type of SynthDef is to be used for Pbind(s) or Synth(s)
// it may be a plain Symbol / String, the corresponding arg tuples may
// be given as plain (not collected) Dictionaries
// Keep in mind that nevertheless one Dictionary may produce
// more than one Synth (Pbind)
(
[\buzz, \default].psVarGui(
(
ctrReplace: [\dur, r = [0.01, 0.05, \lin, 0, 0.03],
\rel, r,
\freq, [100, 1000, \lin, 0, 100],
\amp, [0, 0.5, \lin, 0, 0.15],
\legato, [0.1, 2, \lin, 0, 0.5],
\freqDev, [0, 0.2, \lin, 0, 0.01]],
ctrBefore: [\durDev, [0, 1, \lin, 0, 0.01]],
pAfter: [\dur, Pkey(\dur) * Pfunc { x = 1 + ~durDev; rrand(1/x,x) }],
post: true
),(
ctrReplace: { [\dur, [0.01, 0.05, \lin, 0, 0.03],
\freq, [100, 1000, \lin, 0, rrand(100, 1000)]] },
exclude: \gate,
num: 4
)
).gui(tryColumnNum: 2, allowEnvirBreak: false);
)
// If more than one type of SynthDef is to be used for Pbind(s) or Synth(s)
// Symbols / Strings must be collected, also the corresponding Dictionaries
// spVarGui just takes input in reversed order (synth first).
// This is independant from representation in the GUI
// which can be determined by args sliderPriority (\var or \synth)
// and playerPriority (\stream or \synth)
(
[\default, [\buzz, \default]].spVarGui(
(
ctrReplace: { [\dur, [0.01, 0.05, \lin, 0, 0.03],
\freq, [100, 1000, \lin, 0, rrand(100, 1000)]] },
exclude: \gate,
num: 4
),[
(
ctrReplace: [\dur, r = [0.01, 0.05, \lin, 0, 0.03],
\rel, r,
\freq, [100, 1000, \lin, 0, 100],
\amp, [0, 0.5, \lin, 0, 0.15],
\legato, [0.1, 2, \lin, 0, 0.5],
\freqDev, [0, 0.2, \lin, 0, 0.01]],
ctrBefore: [\durDev, [0, 1, \lin, 0, 0.01]],
pAfter: [\dur, Pkey(\dur) * Pfunc { var x = 1 + ~durDev; rrand(1/x,x) }],
post: true
),(
ctrReplace: [\dur, r = [0.01, 0.05, \lin, 0, 0.03],
\freq, [100, 1000, \lin, 0, 100],
\amp, [0, 0.5, \lin, 0, 0.15],
\legato, [0.1, 2, \lin, 0, 0.5]],
ctrBefore: [\durDev, [0, 1, \lin, 0, 0.01],
\freqDev, [0, 0.2, \lin, 0, 0.01]],
pAfter: [\dur, Pkey(\dur) * Pfunc { var x = 1 + ~durDev; rrand(1/x,x) },
\freq, Pkey(\freq) * Pfunc { var x = 1 + ~freqDev; rrand(1/x,x) }],
post: true
)
]
).gui(tryColumnNum: 2, allowEnvirBreak: false, sliderPriority: \synth, playerPriority: \synth);
)
4.) Differences between shortcut builds and direct VarGui instantiation
.) Shortcut methods apply to Symbols / Strings or collections thereof for Synth and Pbind generation and control. Symbols / Strings refer to the corresponding SynthDefs, known to SynthDesLib.global. For passing Synths, nodeIDs, EventStreamPlayers, also Task Functions and Tasks, you would have to call VarGui directly.
.) Shortcuts and also direct instantiation (not before v0.5) are using SynthDef metadata and / or global ControlSpecs. Though customization options for specs (exclude, add, replace) are a main feature of the shortcut methods. As a compromise spec- and pbindmaker methods with these options may be plugged into direct instantiation (5b).
.) The pVarGui method invokes automatic Pbind generation with customization options for Pbind pairs (exclude, pBefore, pAfter, pReplace), VarGui expects Pbinds to be passed directly. As a compromise a pbindmaker method with these options may be plugged into direct instantiation (5b).
.) In shortcut methods the num arg causes coordinated expansion, all other args (except server) may optionally be given as Functions of indices. With VarGui input you'd have to pass lengthy nested Arrays or write something like { |i| ... } ! n for every arg explicitely, as sizes of input must match. As a compromise spec- and pbindmaker methods with num arg may be plugged into direct instantiation (5b).
.) Reordering / interleaving of controls of different Environments / Synths (VarGui helpfile Examples 5a and 5b) is not possible with shortcut methods. However this seems to be a quite special feature, with shortcut methods ordering of Synths / Pbinds is primarily defined by order of args, control customization options allow further modifications of order. Finally choosing sliderPriority (\synth or \var first) is a pure gui method option and applies to both ways of VarGui building.
5.) Shortcut method specifictions
Shortcut methods also take Functions, that should return args in a valid form. This can be used for defining controls in different ranges in combination with num. See examples above.
5a: core shortcut methods
aSynthDefName.sVarGui(ctrBefore, ctrReplace, ctrAfter, exclude, metaKey, useGlobalSpecs, num, server)
Instantiate a VarGui object for control of one or more Synth(s) derived from a SynthDef name (Symbol / String).
Per default controlspecs are taken from metadata definition, if defined with the SynthDef, or
the global dictionary Spec.specs. Controls can be excluded with exclude, added with
ctrBefore or ctrAfter and replaced with ctrReplace, this is also the order of operations.
ctrBefore - a spec pair collection of the form [ key, spec, ... ] where
key is the symbol of the control arg to be set and
spec can be a collection of the form [ minval, maxval, warp, step, default ]
defining the corresponding ControlSpec, a Symbol / String to look for a ControlSpec in the
global dictionary Spec.specs or a collection of specs of this form
for an arrayed control. Defaults to nil.
Also takes a Function of indices that returns a valid arg.
ctrReplace - a spec pair collection of a form like ctrBefore.
Also takes a Function of indices that returns a valid arg. Defaults to nil.
ctrAfter - a spec pair collection of a form like ctrBefore.
Also takes a Function of indices that returns a valid arg. Defaults to nil.
exclude - a collection of control keys (Symbols) to be excluded.
Also takes a Function of indices that returns a valid arg. Defaults to nil.
metaKey - Symbol. Key to lookup SynthDef metadata.
Also takes a Function of indices that returns a Symbol.
Defaults to \specs.
useGlobalSpecs - Boolean. Defines if to consider global ControlSpecs if
metadata is not given. Also takes a Function of indices that returns a Boolean.
Defaults to true.
num - Integer. Number of Synths to be controlled. Defaults to 1.
server - Server. The server to send node messages for synth control.
Defaults to the default server.
aSequenceableCollection.sVarGui(argDictionary1, ... , argDictionaryN, server)
Instantiate a VarGui object for control of Synths derived from a collection of SynthDef names (Symbols / Strings).
Options for Synth controls are taken from the corresponding arg Dictionaries.
Size of collection must equal N, the number of Dictionaries.
See aSynthDefName.sVarGui for valid arg syntax.
server - Server. The server to send node messages for synth control.
Defaults to the default server.
aSynthDefName.pVarGui(ctrBefore, ctrReplace, ctrAfter, durCtr, legatoCtr, pBefore, pReplace, pAfter, exclude, excludeGate, clock, quant, metaKey, useGlobalSpecs, post, trace, num)
Instantiate a VarGui object for control of one or more Pbind(s) / EventStreamPlayer(s),
derived from a SynthDef name (Symbol / String). One or more Pbind(s) with Pfunc pairs and
the corresponding environmental variable controls are generated,
controls for duration and legato are added.
Per default controlspecs are taken from metadata definition, if defined with the SynthDef, or
the global dictionary Spec.specs. Controls can be excluded with exclude, added with
ctrBefore or ctrAfter and replaced with ctrReplace; Pbind pairs can be excluded with exclude,
added with pBefore or pAfter and replaced with pReplace, this is the order of operations for
Synths and Pbind pairs. Note that exclude applies to Synth controls and Pbind pairs.
If an added Pbind pair with key \degree, \note or \midinote is detected, \freq is excluded
automatically from Pbind and controls. Gate control is excluded per default.
ctrBefore - a spec pair collection of the form [ key, spec, ... ] where
key is the symbol of the environmental variable to be set and
spec can be a collection of the form [ minval, maxval, warp, step, default ]
defining the corresponding ControlSpec, a Symbol / String to look for a ControlSpec in the
global dictionary Spec.specs or a collection of specs of this form
for an arrayed control if the environmental variable should have the value
of a collection itself. Defaults to nil.
Also takes a Function of indices that returns a valid arg.
ctrReplace - a spec pair collection of a form like ctrBefore.
Also takes a Function of indices that returns a valid arg. Defaults to nil.
ctrAfter - a spec pair collection of a form like ctrBefore.
Also takes a Function of indices that returns a valid arg. Defaults to nil.
durCtr - a controlspec of the form [ minval, maxval, warp, step, default ]
or a Symbol to look for a ControlSpec in the global dictionary Spec.specs.
Also takes a Function of indices that returns a valid arg.
Defaults to #[0.05, 3, \exp, 0, 0.2].
legatoCtr - a controlspec of the form [ minval, maxval, warp, step, default ]
or a Symbol to look for a ControlSpec in the global dictionary Spec.specs.
Also takes a Function of indices that returns a valid arg.
Defaults to #[0.1, 5, \exp, 0, 0.8].
pBefore - a Pbind pair collection of the form [ key, pattern, ... ].
Also takes a Function of indices that returns a Pbind pair collection. Defaults to nil.
pReplace - a Pbind pair collection of the form [ key, pattern, ... ].
Also takes a Function of indices that returns a Pbind pair collection. Defaults to nil.
pAfter - a Pbind pair collection of the form [ key, pattern, ... ].
Also takes a Function of indices that returns a Pbind pair collection. Defaults to nil.
exclude - a control key (Symbol) or a collection of control keys to be excluded from
Pbind pairs and controls. Also takes a Function of indices that returns a valid arg.
Defaults to nil.
excludeGate - Boolean. Determines if gate control should be excluded.
Also takes a Function of indices that returns a Boolean. Defaults to true.
clock - TempoClock, nil or collection thereof for playing streams.
Also takes a Function of indices that returns a valid arg.
Defaults to the default TempoClock.
quant - Quant, Float, nil or collection thereof used as quant data for playing streams.
Also takes a Function of indices that returns a valid arg.
Defaults to Quant.default (none).
metaKey - Symbol. Key to lookup SynthDef metadata.
Also takes a Function of indices that returns a Symbol.
Defaults to \specs.
useGlobalSpecs - Boolean. Defines if to consider global ControlSpecs if
metadata is not given. Also takes a Function of indices that returns a Boolean.
Defaults to true.
post - Boolean. Determines if to post order of Pbind pairs.
Also takes a Function of indices that returns a Boolean. Defaults to false.
trace - Boolean. Determines if EventStreamPlayer should post Events when playing.
Also takes a Function of indices that returns a Boolean. Defaults to false.
num - Integer. Number of Pbinds / EventStreamPlayers to be controlled. Defaults to 1.
aSequenceableCollection.pVarGui(argDictionary1, ... , argDictionaryN)
Instantiate a VarGui object for control of Pbinds / EventStreamPlayers derived from a
collection of SynthDef names (Symbols / Strings). Options for controls are taken from the corresponding
arg Dictionaries. Size of collection must equal N, the number of Dictionaries.
See aSynthDefName.pVarGui for valid arg syntax.
The following two methods are equivalent, just take opposite arg order.
This is independant of arrangement, which can be determined by gui args
sliderPriority (\var or \synth) and playerPriority (\stream or \synth).
aSequenceableCollection.spVarGui(sVarGuiArgDictionaries, pVarGuiArgDictionaries, server)
Instantiate a VarGui object for control of Synths and Pbinds / EventStreamPlayers
derived from SynthDef names (Symbols / Strings). Thus receiver must be of the form
[ synthNames, pbindSynthNames ], whereby synthNames and pbindSynthNames
may be Symbols / Strings or SequenceableCollections of Symbols / Strings.
sVarGuiArgDictionaries - arg Dictionary or SequenceableCollection thereof, whose size
must be equal to that of synthNames (if a collection).
See aSynthDefName.sVarGui for valid arg syntax.
Defaults to [].
pVarGuiArgDictionaries - arg Dictionary or SequenceableCollection thereof, whose size
must be equal to that of pbindSynthNames (if a collection).
See aSynthDefName.pVarGui for valid arg syntax.
Defaults to [].
server - Server. The server to send node messages for synth control.
Defaults to the default server.
aSequenceableCollection.psVarGui(pVarGuiArgDictionaries, sVarGuiArgDictionaries, server)
Instantiate a VarGui object for control of Pbinds / EventStreamPlayers and Synths
derived from SynthDef names (Symbols / Strings). Thus receiver must be of the form
[ pbindSynthNames, synthNames ], whereby pbindSynthNames and synthNames
may be Symbols / Strings or SequenceableCollections of Symbols / Strings.
pVarGuiArgDictionaries - arg Dictionary or SequenceableCollection thereof, whose size
must be equal to that of pbindSynthNames (if a collection).
See aSynthDefName.pVarGui for valid arg syntax.
Defaults to [].
sVarGuiArgDictionaries - arg Dictionary or SequenceableCollection thereof, whose size
must be equal to that of synthNames (if a collection).
See aSynthDefName.sVarGui for valid arg syntax.
Defaults to [].
server - Server. The server to send node messages for synth control.
Defaults to the default server.
5b: spec- and pbindmaker methods
In most cases you won't need this, except for reloading customized sequencing VarGuis (6). For special arrangements methods for making specdata and Pbinds of appropriate Pfuncs can be used for customizing control with direct VarGui instantiation. These methods take args in the same way as sVarGui and pVarGui.
// sVarGuiSpecs returns a list of spec pair lists of the form [\key, specArray, ...]
// derived from SynthDef metadata / global ControlSpecs,
// controls can be excluded, added and replaced
(
VarGui(
synth: [\default, \buzz],
synthCtr: \default.sVarGuiSpecs(exclude: \gate) ++
\buzz.sVarGuiSpecs(ctrReplace: [\amp, [0, 0.5, 0, 0, 0.1]])
).gui;
)
// shorter
(
[\default, \buzz].sVarGui(
(exclude: \gate),
(ctrReplace: [\amp, [0, 0.5, 0, 0, 0.1]])
).gui;
)
// as with sVarGui arguments can be functions of indices
(
VarGui(
synth: \default!4 ++ \buzz,
synthCtr:
\default.sVarGuiSpecs(num: 4, exclude: \gate,
ctrReplace: { |i| var x = i*100 + 400; [\freq, [x, x*1.1, 0, 0, x]] }) ++
\buzz.sVarGuiSpecs(ctrReplace: [\amp, [0, 0.5, 0, 0, 0.2]])
).gui(tryColumnNum: 2, allowSynthBreak: false);
)
// shorter
(
[\default, \buzz].sVarGui(
(num: 4, exclude: \gate, ctrReplace: { |i| var x = i*100 + 400; [\freq, [x, x*1.1, 0, 0, x]] }),
(ctrReplace: [\amp, [0, 0.5, 0, 0, 0.2]])
).gui(tryColumnNum: 2, allowSynthBreak: false);
)
// pVarGuiSpecs also returns a list of spec pair lists,
// just adds specs for dur and legato by default,
// pfuncPbinds returns appropriate Pbinds of Pfuncs
// additional pairs can be added
// however, compared to pVarGui, more coordination is the user's responsibility:
// specmaker and pbindmaker don't know about each other
// useless control \freq excluded explicitely here
(
VarGui(
varCtr:
\buzz.pVarGuiSpecs(ctrBefore: [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 8 ],
ctrReplace: [\dur, [0.2, 0.4, \lin, 0.2, 0.2]], exclude: \freq) ++
\default.pVarGuiSpecs(ctrBefore: [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 4 ],
ctrReplace: [\dur, [0.1, 0.3, \lin, 0.1, 0.2]], exclude: \freq),
stream:
\buzz.pfuncPbinds(pBefore: [\degree, Plazy { Pseq(~a, inf) }, \octave, 3]) ++
\default.pfuncPbinds(pBefore: [\degree, Pfunc { [0, [0,4], [0,5]].choose } +
Plazy { Pseq(~a, inf) }, \octave, Pwhite(5,7)], post: true),
quant: 0.2
).gui(tryColumnNum: 2, allowEnvirBreak: false);
)
// shorter
(
[\buzz, \default].pVarGui((
ctrBefore: [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 8 ],
ctrReplace: [\dur, [0.2, 0.4, \lin, 0.2, 0.2]],
pBefore: [\degree, Plazy { Pseq(~a, inf) }, \octave, 3],
quant: 0.2
),(
ctrBefore: [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 4 ],
ctrReplace: [\dur, [0.1, 0.3, \lin, 0.1, 0.2]],
pBefore: [\degree, Pfunc { [0, [0,4], [0,5]].choose } +
Plazy { Pseq(~a, inf) }, \octave, Pwhite(5,7) ],
quant: 0.2
)
).gui(tryColumnNum: 2, allowEnvirBreak: false);
)
aSynthDefName.sVarGuiSpecs(ctrBefore, ctrReplace, ctrAfter, exclude, metaKey, useGlobalSpecs, num)
Generate control data for one or more Synth(s) derived from a SynthDef name (Symbol / String).
Returns a grouped collection, also for num = 1.
Data can directly been used as input to VarGui's synthCtr arg.
This method can be used for control of Synths derived from more than one SynthDef in one VarGui
or combined control of Synths and Pbinds / EventStreamPlayers.
args - see aSynthDefName.sVarGui
aSynthDefName.pVarGuiSpecs(ctrBefore, ctrReplace, ctrAfter, durCtr, legatoCtr, exclude, excludeGate, metaKey, useGlobalSpecs, num)
Generate envir variable control data for one or more Environments derived from
a SynthDef name (Symbol / String). Returns a grouped collection, also for num = 1.
Data can directly been used as input to VarGui's varCtr arg.
This method can be used for control of Pbinds / EventStreamPlayers derived from
more than one SynthDef in one VarGui or combined control of Synths and
Pbinds / EventStreamPlayers.
args - see aSynthDefName.pVarGui with the exception of Pbind-related args
pBefore, pReplace, pAfter, clock, quant, post and trace
aSynthDefName.pfuncPbinds(pBefore, pReplace, pAfter, exclude, excludeGate, excludeDur, excludeLegato, metaKey, useGlobalSpecs, post, trace, num)
Generate Pbinds with Pfunc pairs derived from a SynthDef name (Symbol / String) and corresponding metadata
resp. global ControlSpecs. Duration and legato pairs are added by default.
If an added Pbind pair with key \degree, \note or \midinote is detected,
\freq is excluded automatically. Returns a collection, also for num = 1.
args - see aSynthDefName.pVarGui with the exception of clock, quant and control-related args
ctrBefore, ctrReplace, ctrAfter, durCtr, legatoCtr.
excludeDur - Boolean. Determines if \dur should be excluded from the Pbind.
Also takes a Function of indices that returns a Boolean. Defaults to false.
excludeLegato - Boolean. Determines if \legato should be excluded from the Pbind.
Also takes a Function of indices that returns a Boolean. Defaults to false.
6.) Save and load
A VarGui's slider state can be saved via save button and dialog. Loading is straightforward with Synths. You just have to give the correct path and synth arg (which maybe has to be an array).
// change slider positions and save
\buzz.sVarGui.gui;
// reload
VarGui.load("Path_To_XY", "XY", synth: \buzz).gui;
// change slider positions and save
\buzz.sVarGui(num: 4, metaKey: \basicSpecs).gui(tryColumnNum: 2);
// reload, synth arg must have corresponding size
VarGui.load("Path_To_XY", "XY", synth: \buzz ! 4).gui(tryColumnNum: 2);
VarGui only saves slider states, not the Pbind structure (would open a can of worms). So if you had a customized Pbind in the original setup you'd have to pass an appropriate Pbind together with load. This can also be a Pbind other than in the original setup. But if you want to restore you can nearly copy the input of the original cutomization into the pbindmaker method pfuncPbinds (5b).
// with no customization save and load also works straightforward
// change slider positions and save
\buzz.pVarGui.gui;
// standard pbind is (re-)autogenerated and fits the variables to be set
VarGui.load("Path_To_XY", "XY", stream: \buzz).gui;
// only controls are customized, save and load also works straightforward
// change slider positions, save and reload
(
[\default, \buzz].pVarGui(
(ctrReplace: { |i| var f = (2*i + 1) * 100, d = 0.2, lo = 0.99, hi = 1.01;
[\freq, [f*lo, f*hi, 0, 0, f*rrand(lo,hi)], \dur, [d*lo, d*hi, 0, 0, d*rrand(lo,hi)] ] },
exclude: \gate,
post: true,
num: 4),
(ctrReplace: [\freq, [97, 103, \exp, 0, 99], \dur, [0.195, 0.205, 0, 0, 0.2] ])
).gui(tryColumnNum: 2, allowEnvirBreak: false)
)
(
VarGui.load("Path_To_XY", "XY", stream: \default ! 4 ++ \buzz)
.gui(tryColumnNum: 2, allowEnvirBreak: false)
)
// change slider positions and save
(
[\buzz, \default].pVarGui((
ctrBefore: [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 8 ],
ctrReplace: [\dur, [0.2, 0.4, \lin, 0.2, 0.2]],
pBefore: [\degree, Plazy { Pseq(~a, inf) }, \octave, 3],
quant: 0.2
),(
ctrBefore: [\a, { [0, 6, \lin, 1, rrand(0,6) ] } ! 4 ],
ctrReplace: [\dur, [0.1, 0.3, \lin, 0.1, 0.2]],
pBefore: [\degree, Pfunc { [0, [0,4], [0,5]].choose } +
Plazy { Pseq(~a, inf) }, \octave, Pwhite(5,7) ],
quant: 0.2
)
).gui(tryColumnNum: 2, allowEnvirBreak: false);
)
// restoring pbind structure, note that pfuncPbinds always returns a collection
// and quant arg is separate in VarGui.new and VarGui.load
(
VarGui.load("Path_To_XY", "XY",
stream:
\buzz.pfuncPbinds(pBefore: [\degree, Plazy { Pseq(~a, inf) }, \octave, 3]) ++
\default.pfuncPbinds(pBefore: [\degree, Pfunc { [0, [0,4], [0,5]].choose } +
Plazy { Pseq(~a, inf) }, \octave, Pwhite(5,7) ]),
quant: 0.2
).gui(tryColumnNum: 2, allowEnvirBreak: false)
)