[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [sc-users] recording mouse gestures



That's excellent. Thanks again for all your help Alberto.

Happy New Year everyone,

Iain












Em Qui, 2015-12-31 às 11:34 +0100, alberto.decampo escreveu:
> Hi Iain, 
> 
> > On 30/12/2015, at 21:10 , Iain Mott <mott@xxxxxxxxxxxxxxx> wrote:
> > 
> > Thanks very much Alberto. I didn't have any luck compiling the source
> > and may start a new thread about that. I'll try these files and folders
> > in the mean time. I did however manage to incorporate KtlLoop in to my
> > existing code using your examples and it's working very well. 
> 
> ok
> > 
> > One more question: is it possible for a KtlLoop object, that is
> > controlling a particular synth, to control another synth (from another
> > synthdef) or ndef with the same parameters?  Or is it necessary to
> > duplicate?
> 
> Yes, possible, and there are several options: 
> 
> 1. give the KtlLoop a function that looks up and evaluates a list of functions,
> 
> ~funcsx = List[];
> KtlLoop(\x, { |ev| ~funcsx.do(_.value(ev) ) });
> 
> KtlLoop(\x).func.value;
> ~funcsx.add({ |ev| "0: e.g. synth 1".post; ev.postln });
> KtlLoop(\x).func.value((ev: \test));
> 
> // add some events to the list
> KtlLoop(\x).startRec;
> KtlLoop(\x).recordEvent((\dist: 1, \azim: 0.5)); 
> KtlLoop(\x).stopRec;
> 
> KtlLoop(\x).play;
> ~funcsx.add({ |ev| "1: e.g. visuals 1".post; ev.postln });
> 
> // take first function out again
> ~funcsx.removeAt(0);
> 
> // etc 
> 
> 
> 2. Use MFunc (in quark adclib) as a very flexible list of functions
> than can be added/removed, enabled/disabled, switched in sets, 
> etc etc:
> 
> // make a empty MFunc, and put it into a KtlLoop
> ~xf = MFunc();
> KtlLoop(\y, ~xf);
> 
> ~xf = KtlLoop(\y).func;
> ~xf.add(\synth1, { |ev| "mfunc: synth1".post; ev.postln });
> ~xf.value((ev: \test));
> 
> // add an event to the list
> KtlLoop(\y).startRec;
> KtlLoop(\y).recordEvent((\dist: 1, \azim: 0.5)); 
> KtlLoop(\y).stopRec;
> 
> KtlLoop(\y).play;
> 
> // change synth func
> ~xf.add(\synth1, { |ev| "mfunc: SYNTH1! - ".post; ev.postln });
> KtlLoop(\y).play;
> 
> // add a second one:
> ~xf.add(\viz1, { |ev| "mfunc: viz1 - ".post; ev.postln });
> KtlLoop(\y).play;
> 
> // turn off synth1 control:
> ~xf.disable(\synth1);
> KtlLoop(\y).play;
> 
> // etc etc 
> 
> 
> hth, 
> best adc
> 
> > Specifically in this project, I'd like to use the recorded data in the
> > KtlLoop objects to control not only spatializing synths, but a also
> > secondary and separate processes performing graphics (this graphic work
> > could perhaps be done from within the spatializing synths, but I'd like
> > to keep it separate).
> > 
> > Best,
> > 
> > Iain
> > 
> > 
> > 
> > 
> > 
> > Em Qua, 2015-12-30 às 15:06 +0100, alberto.decampo escreveu:
> >> Hi Iain, 
> >> 
> >> hm, it is actually several things that changed in the JITlib updates from 3.6.6 to 3.7,
> >> and a lot of other things got fixed for 3.7, so it is worth trying to compile it. 
> >> 
> >> In case this takes too long, or you run into trouble, 
> >> you can try replacing files in SCCLassLibrary to get at least the JITlib updates:
> >> 
> >> 1. just the entire TaskProxyGui file:
> >> https://github.com/supercollider/supercollider/tree/master/SCClassLibrary/JITLib/GUI/TaskProxyGui.sc
> >> 
> >> 2. all JITLib Guis:
> >> https://github.com/supercollider/supercollider/tree/master/SCClassLibrary/JITLib/GUI
> >> 
> >> 3. entire JITLib folder:
> >> https://github.com/supercollider/supercollider/tree/master/SCClassLibrary/JITLib
> >> 
> >> best adc
> >> 
> >>> On 29/12/2015, at 21:01 , Iain Mott <mott@xxxxxxxxxxxxxxx> wrote:
> >>> 
> >>> It's 3.6.6, which is the most recent package for Ubuntu available here:
> >>> https://launchpad.net/~supercollider/+archive/ubuntu/ppa
> >>> 
> >>> I'll try compiling the source, but if that gets too complicated, where
> >>> do I place that override? I tried now inserting it at the end
> >>> of /usr/share/SuperCollider/SCClassLibrary/JITLib/GUI/TaskProxyGui.sc.
> >>> When I restarted SC and ran the KtlLoopGui line, it gave a long list of
> >>> errors which I'll paste below.
> >>> 
> >>> Thanks,
> >>> 
> >>> Iain 
> >>> 
> >>> ERROR: Message 'key' not understood.
> >>> RECEIVER:
> >>> Instance of TaskProxy {    (0x36ddce8, gc=AC, fmt=00, flg=00, set=04)
> >>> instance variables [9]
> >>>   source : instance of Function (0x474afb8, size=2, set=2)
> >>>   pattern : instance of Prout (0x3f5f778, size=1, set=2)
> >>>   envir : instance of Event (0x148d788, size=5, set=3)
> >>>   clock : nil
> >>>   quant : nil
> >>>   condition : true
> >>>   reset : nil
> >>>   player : nil
> >>>   playQuant : nil
> >>> }
> >>> ARGS:
> >>> PATH: /home/iain/projects/ambisonics/sc/adc.sc
> >>> CALL STACK:
> >>> 	DoesNotUnderstandError:reportError   0x383eef8
> >>> 		arg this = <instance of DoesNotUnderstandError>
> >>> 	Nil:handleError   0x381ce38
> >>> 		arg this = nil
> >>> 		arg error = <instance of DoesNotUnderstandError>
> >>> 	Thread:handleError   0x3841f38
> >>> 		arg this = <instance of Thread>
> >>> 		arg error = <instance of DoesNotUnderstandError>
> >>> 	Object:throw   0x373fcd8
> >>> 		arg this = <instance of DoesNotUnderstandError>
> >>> 	Object:doesNotUnderstand   0x381e4e8
> >>> 		arg this = <instance of TaskProxy>
> >>> 		arg selector = 'key'
> >>> 		arg args = [*0]
> >>> 	TaskProxyGui:getState   0x381dca8
> >>> 		arg this = <instance of TdefGui>
> >>> 	TaskProxyGui:checkUpdate   0x381e018
> >>> 		arg this = <instance of TdefGui>
> >>> 		var newState = nil
> >>> 		var playState = nil
> >>> 	JITGui:object_   0x381e178
> >>> 		arg this = <instance of TdefGui>
> >>> 		arg obj = <instance of TaskProxy>
> >>> 	TaskProxyGui:object_   0x3847448
> >>> 		arg this = <instance of TdefGui>
> >>> 		arg obj = <instance of TaskProxy>
> >>> 	EventLoopGui:object_   0x353e6b8
> >>> 		arg this = <instance of KtlLoopGui>
> >>> 		arg obj = <instance of KtlLoop>
> >>> 	< closed FunctionDef >  (no arguments or variables)
> >>> 	Interpreter:interpretPrintCmdLine   0x120b748
> >>> 		arg this = <instance of Interpreter>
> >>> 		var res = nil
> >>> 		var func = <instance of Function>
> >>> 		var code = "KtlLoopGui(k, parent: w, bou..."
> >>> 		var doc = <instance of ScelDocument>
> >>> 		var ideClass = nil
> >>> 	Process:interpretPrintCmdLine   0x3a12448
> >>> 		arg this = <instance of Main>
> >>> ^^ The preceding error dump is for ERROR: Message 'key' not understood.
> >>> RECEIVER: a TaskProxy
> >>> ERROR: Message 'key' not understood.
> >>> RECEIVER:
> >>> Instance of TaskProxy {    (0x36ddce8, gc=AC, fmt=00, flg=00, set=04)
> >>> instance variables [9]
> >>>   source : instance of Function (0x474afb8, size=2, set=2)
> >>>   pattern : instance of Prout (0x3f5f778, size=1, set=2)
> >>>   envir : instance of Event (0x148d788, size=5, set=3)
> >>>   clock : nil
> >>>   quant : nil
> >>>   condition : true
> >>>   reset : nil
> >>>   player : nil
> >>>   playQuant : nil
> >>> }
> >>> ARGS:
> >>> PATH: /home/iain/projects/ambisonics/sc/adc.sc
> >>> 
> >>> PROTECTED CALL STACK:
> >>> 	Meta_MethodError:new	0x2f4b580
> >>> 		arg this = DoesNotUnderstandError
> >>> 		arg what = nil
> >>> 		arg receiver = a TaskProxy
> >>> 	Meta_DoesNotUnderstandError:new	0x2f4d540
> >>> 		arg this = DoesNotUnderstandError
> >>> 		arg receiver = a TaskProxy
> >>> 		arg selector = key
> >>> 		arg args = [  ]
> >>> 	Object:doesNotUnderstand	0x10ad240
> >>> 		arg this = a TaskProxy
> >>> 		arg selector = key
> >>> 		arg args = nil
> >>> 	TaskProxyGui:getState	0x29c0080
> >>> 		arg this = a TdefGui
> >>> 	TaskProxyGui:checkUpdate	0x29c0a00
> >>> 		arg this = a TdefGui
> >>> 		var newState = nil
> >>> 		var playState = nil
> >>> 	EventLoopGui:checkUpdate	0x29f4300
> >>> 		arg this = a KtlLoopGui
> >>> 		var newState = ( 'object': KtlLoop('sp1'), 'scaler': 1, 'inverted': 0,
> >>> 'isReversed': 0, 
> >>> 'looped': 0, 'shift': 0, 'name': sp1, 'numLists': 0, 'isRecording':
> >>> 0, 
> >>> 'listIndex': 0, 'rescaled': 0 )
> >>> 		var playState = nil
> >>> 	KtlLoopGui:checkUpdate	0x29f8940
> >>> 		arg this = a KtlLoopGui
> >>> 		var newState = ( 'object': KtlLoop('sp1'), 'scaler': 1, 'inverted': 0,
> >>> 'isReversed': 0, 
> >>> 'looped': 0, 'shift': 0, 'name': sp1, 'numLists': 0, 'isRecording':
> >>> 0, 
> >>> 'listIndex': 0, 'rescaled': 0 )
> >>> 	a FunctionDef	0x28ceb80
> >>> 		sourceCode = "<an open Function>"
> >>> 	Routine:prStart	0x224ac00
> >>> 		arg this = a Routine
> >>> 		arg inval = 1451417746.0578
> >>> 
> >>> CALL STACK:
> >>> 	DoesNotUnderstandError:reportError   0x37d7278
> >>> 		arg this = <instance of DoesNotUnderstandError>
> >>> 	< closed FunctionDef >   0x37d6c48
> >>> 		arg error = <instance of DoesNotUnderstandError>
> >>> 	Integer:forBy   0x7feafc042948
> >>> 		arg this = 0
> >>> 		arg endval = 2
> >>> 		arg stepval = 2
> >>> 		arg function = <instance of Function>
> >>> 		var i = 2
> >>> 		var j = 1
> >>> 	SequenceableCollection:pairsDo   0x3813628
> >>> 		arg this = [*4]
> >>> 		arg function = <instance of Function>
> >>> 	Scheduler:seconds_   0x3810c18
> >>> 		arg this = <instance of Scheduler>
> >>> 		arg newSeconds = 1451417746.5586
> >>> 	Meta_AppClock:tick   0x3812218
> >>> 		arg this = <instance of Meta_AppClock>
> >>> 		var saveClock = <instance of Meta_SystemClock>
> >>> 	Process:tick   0x38130a8
> >>> 		arg this = <instance of Main>
> >>> ^^ The preceding error dump is for ERROR: Message 'key' not understood.
> >>> RECEIVER: a TaskProxy
> >>> 
> >>> 
> >>> 
> >>> 
> >>> 
> >>> 
> >>> 
> >>> 
> >>> Em Ter, 2015-12-29 às 19:28 +0100, alberto.decampo escreveu:
> >>>>> On 29/12/2015, at 18:58 , Iain Mott <mott@xxxxxxxxxxxxxxx> wrote:
> >>>>> 
> >>>>> Many thanks for your help Alberto. I'm testing these examples now. One
> >>>>> thing I notice, when I run:
> >>>>> 
> >>>>> KtlLoopGui(k, parent: w, bounds: 310@180).skipjack.dt_(0.05); 
> >>>>> 
> >>>>> in the code for the "KtlLoop.help" window, it results in the following
> >>>>> warning:
> >>>>> 
> >>>>> WARNING: TdefGui : object a TaskProxy not accepted!
> >>>>> a SkipJack
> >>>> 
> >>>> I fixed this a while ago in current SC.
> >>>> which version of SC are you using? 
> >>>> best is a current 3.7 alpha build. 
> >>>> If you need to stick to an earlier version (3.6.6?), 
> >>>> you can overwrite the “accepts" method of TaskProxyGui with this one:
> >>>> 
> >>>> + TaskProxyGui {
> >>>> 	accepts { |obj| ^obj.isNil or: { obj.isKindOf(PatternProxy) } }
> >>>> }
> >>>> 
> >>>> hth, best adc
> >>>> 
> >>>>> Much the same thing happens when I run "e = KtlLoopGui(k, bounds:
> >>>>> 250@180);" in the KtlLoopGui help file.
> >>>>> 
> >>>>> 
> >>>>> Is there another Quark that i need to install? I installed
> >>>>> JITLibExtensions and JITMIDIKtl.
> >>>>> 
> >>>>> 
> >>>>> Iain 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> Em Ter, 2015-12-29 às 14:15 +0100, alberto.decampo escreveu:
> >>>>>> // and here an example with 8 synths ktlloops and guis:
> >>>>>> 
> >>>>>> (
> >>>>>> s.scope(8); 
> >>>>>> 
> >>>>>> SynthDef(\spat, { |out, amp = 0.2, dens = 300, freq = 600, rq = 0.01, azim = 0, dist = 1|
> >>>>>> 	var snd = Ringz.ar(Dust2.ar(300), freq, 0.01) * amp;
> >>>>>> 	var ring = PanAz.ar(8, snd, azim); 
> >>>>>> 	var panned = (snd * (1/8)).blend(ring, dist);
> >>>>>> 	Out.ar(out, panned);
> >>>>>> }).add;
> >>>>>> 
> >>>>>> // make an 8 8chan pannable synths
> >>>>>> ~spats = 8.collect { 
> >>>>>> 	Synth(\spat, [
> >>>>>> 		\freq, exprand(300, 3000), \dens, exprand(50, 500),
> >>>>>> 		\azim, 2.0.rand;
> >>>>>> 	]);
> >>>>>> };
> >>>>>> 
> >>>>>> // make 8 ktlloops for them
> >>>>>> ~ktlps = ~spats.collect { |sp, i| 
> >>>>>> 	var ktlname = ("sp" ++ i).asSymbol;
> >>>>>> 	var ktloop = KtlLoop(ktlname, { |ev| sp.set(\azim, ev.azim, \dist, ev.dist) });
> >>>>>> 	ktloop.object = sp;
> >>>>>> };
> >>>>>> 
> >>>>>> ~wins = ~ktlps.collect { |kl, i|
> >>>>>> 	var w, sl2d;
> >>>>>> 	w = Window("KtlLoop.help", Rect(320 * (i % 4), 380 * (i div: 4), 320, 380).postln).front;
> >>>>>> 	w.view.addFlowLayout;
> >>>>>> 	sl2d = Slider2D(w, Rect(5,5,190,190))
> >>>>>> 	.action_({ |sl|
> >>>>>> 		var polar = Polar(sl.x * 2 - 1, sl.y * 2 - 1);
> >>>>>> 		var azim = polar.angle / pi; // scale to 0, 2
> >>>>>> 		var dist = polar.magnitude; 
> >>>>>> 	
> >>>>>> 		var event = (azim: azim, dist: dist);
> >>>>>>      // store it,
> >>>>>> 		kl.recordEvent(event.put(\type, \set));
> >>>>>>      // and set the object from it
> >>>>>> 		kl.object.set(\azim, azim, \dist, dist);
> >>>>>> 	});
> >>>>>> 
> >>>>>> 	// make an eventloopgui for KtlLoop
> >>>>>> 	KtlLoopGui(kl, parent: w, bounds: 310@180).skipjack.dt_(0.05);
> >>>>>> };
> >>>>>> )
> >>>>>> 
> >>>>>>> On 29/12/2015, at 13:53 , alberto.decampo <alberto.decampo@xxxxxxxxx> wrote:
> >>>>>>> 
> >>>>>>> Hi Ian, 
> >>>>>>> 
> >>>>>>>> On 29/12/2015, at 12:22 , Iain Mott <mott@xxxxxxxxxxxxxxx> wrote:
> >>>>>>>> 
> >>>>>>>> A question about KtlLoop: 
> >>>>>>>> 
> >>>>>>>> in the sample code in the help file for KtlLoop, the sound to be
> >>>>>>>> controlled is defined within a node proxy definition (ndef). 
> >>>>>>> 
> >>>>>>> yes. should also work with plain synths, example below.
> >>>>>>> Ndefs are really convenient placeholders for single synths, 
> >>>>>>> which are easy to control, modify, play, pause, stop, 
> >>>>>>> they remember their settings etc. etc., so I tend to use them 
> >>>>>>> rather than raw synths most of the time. 
> >>>>>>> 
> >>>>>>> Also, I just updated some things in the KtlLoop quarks, so please update.
> >>>>>>> 
> >>>>>>>> 
> >>>>>>>> The thing or things that I'm wishing to control are instances of a
> >>>>>>>> synthdef that perform 2D spatialisation. These receive their audio input
> >>>>>>>> via busses and perform ambisonic encoding and other steps in response to
> >>>>>>>> distance and azimuth data received via the "set" method. So it's the
> >>>>>>>> distance and azimuth data for each sound source that I wish to record
> >>>>>>>> and play back (rather than x and y coords from the mouse directly). 
> >>>>>>> 
> >>>>>>> what you want to control is freely definable, so distance and azimuth should also work. 
> >>>>>>> 
> >>>>>>> for rescaling movements in space, using x y and converting to azim/dist in the synth func 
> >>>>>>> may actually work nicely :-)
> >>>>>>> 
> >>>>>>>> 
> >>>>>>>> What I was thinking of doing was to create an array of KtlLoop objects
> >>>>>>>> for each of the instances synthdef. Something like this:
> >>>>>>> 
> >>>>>>> 
> >>>>>>>> number_of_sound_sources.do { arg i;	
> >>>>>>>> 
> >>>>>>>> k[i] = KtlLoop(2Dspatializerinstances[i]);
> >>>>>>>> 
> >>>>>>>> };
> >>>>>>>> 
> >>>>>>>> 
> >>>>>>>> This however gives a "wrong type" error.
> >>>>>>>> 
> >>>>>>>> Can synthdef instances be controlled by KtlLoop and if so how?
> >>>>>>> 
> >>>>>>> yes, based on your question, something like this:
> >>>>>>> 
> >>>>>>> SynthDef(\spat, { |out, amp = 0.2, dens = 300, freq = 600, rq = 0.01, azim = 0, dist = 1|
> >>>>>>> 	var snd = Ringz.ar(Dust2.ar(300), freq, 0.01) * amp;
> >>>>>>> 	var ring = PanAz.ar(8, snd, azim); 
> >>>>>>> 	var panned = (snd * (1/8)).blend(ring, dist);
> >>>>>>> 	Out.ar(out, panned);
> >>>>>>> }).add;
> >>>>>>> 
> >>>>>>> s.scope(8); 
> >>>>>>> 
> >>>>>>> // make an 8chan pannable sound
> >>>>>>> ~sp1 = Synth(\spat, [\freq, 600]);
> >>>>>>> 
> >>>>>>> // move ~sp1 - azim goes from 0..2, because it uses PanAz
> >>>>>>> ~sp1.set(\azim, 0.5);
> >>>>>>> ~sp1.set(\azim, 1);
> >>>>>>> 
> >>>>>>> ~sp1.set(\dist, 0); // in center of all 8
> >>>>>>> ~sp1.set(\dist, 0.5); // centered on chans 5, 6, but present in all
> >>>>>>> ~sp1.set(\dist, 1.0); // just on chans 5, 6
> >>>>>>> 
> >>>>>>> // a KtlLoop for sp1
> >>>>>>> k = KtlLoop(\sp1, { |ev| ~sp1.set(\azim, ev.azim, \dist, ev.dist) });
> >>>>>>> k.object = ~sp1;
> >>>>>>> k.func.postcs;
> >>>>>>> (
> >>>>>>> w = Window("KtlLoop.help", Rect(0,500, 400, 550)).front;
> >>>>>>> w.view.addFlowLayout;
> >>>>>>> ~sl2d = Slider2D(w, Rect(0,0,190,190))
> >>>>>>> .action_({ |sl|
> >>>>>>> 	var polar = Polar(sl.x * 2 - 1, sl.y * 2 - 1);
> >>>>>>> 	var azim = polar.angle / pi; // scale to 0, 2
> >>>>>>> 	var dist = polar.magnitude; 
> >>>>>>> 	
> >>>>>>> 	var event = (azim: azim, dist: dist);
> >>>>>>>     // store it,
> >>>>>>> k.recordEvent(event.put(\type, \set));
> >>>>>>>     // and set the object from it
> >>>>>>> k.object.set(\azim, azim, \dist, dist);
> >>>>>>> });
> >>>>>>> 
> >>>>>>> // make an eventloopgui for KtlLoop
> >>>>>>> KtlLoopGui(k, parent: w, bounds: 310@180).skipjack.dt_(0.05);
> >>>>>>> )
> >>>>>>> // a second synth would be
> >>>>>>> ~sp2 = Synth(\spat, [\freq, 800, \dens, 200]);
> >>>>>>> 
> >>>>>>> // or make an array of synths 
> >>>>>>> ~spats = 8.collect {  Synth(\spat, [\freq, exrand(300, 3000), \dens, 200]); };
> >>>>>>> 
> >>>>>>> …
> >>>>>>> but that will need a lot more admin by hand that Ndefs can take care of very easily. 
> >>>>>>> 
> >>>>>>>> I did try entering the name of the synthdef itself as an argument to
> >>>>>>>> KtlLoop and this produced no error, but I didn't go any further with
> >>>>>>>> this. Not understanding ndef, I also tried redefining a synthdef
> >>>>>>>> instance within an ndef - this produced a string of errors. 
> >>>>>>> 
> >>>>>>> Try going thru the Ndef helpfile, it has lots of examples :-)
> >>>>>>> 
> >>>>>>> best adc
> >>>>>> 
> >>>>>> 
> >>>>>> _______________________________________________
> >>>>>> sc-users mailing list
> >>>>>> 
> >>>>>> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> >>>>>> archive: https://listarc.bham.ac.uk/marchives/sc-users/
> >>>>>> search: https://listarc.bham.ac.uk/lists/sc-users/search/
> >>>>> 
> >>>>> 
> >>>>> 
> >>>>> _______________________________________________
> >>>>> sc-users mailing list
> >>>>> 
> >>>>> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> >>>>> archive: https://listarc.bham.ac.uk/marchives/sc-users/
> >>>>> search: https://listarc.bham.ac.uk/lists/sc-users/search/
> >>>> 
> >>>> 
> >>>> _______________________________________________
> >>>> sc-users mailing list
> >>>> 
> >>>> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> >>>> archive: https://listarc.bham.ac.uk/marchives/sc-users/
> >>>> search: https://listarc.bham.ac.uk/lists/sc-users/search/
> >>> 
> >>> 
> >>> 
> >>> _______________________________________________
> >>> sc-users mailing list
> >>> 
> >>> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> >>> archive: https://listarc.bham.ac.uk/marchives/sc-users/
> >>> search: https://listarc.bham.ac.uk/lists/sc-users/search/
> >> 
> >> 
> >> _______________________________________________
> >> sc-users mailing list
> >> 
> >> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> >> archive: https://listarc.bham.ac.uk/marchives/sc-users/
> >> search: https://listarc.bham.ac.uk/lists/sc-users/search/
> > 
> > 
> > 
> > _______________________________________________
> > sc-users mailing list
> > 
> > info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> > archive: https://listarc.bham.ac.uk/marchives/sc-users/
> > search: https://listarc.bham.ac.uk/lists/sc-users/search/
> 
> 
> _______________________________________________
> sc-users mailing list
> 
> info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
> archive: https://listarc.bham.ac.uk/marchives/sc-users/
> search: https://listarc.bham.ac.uk/lists/sc-users/search/



_______________________________________________
sc-users mailing list

info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: https://listarc.bham.ac.uk/marchives/sc-users/
search: https://listarc.bham.ac.uk/lists/sc-users/search/