pabloriera / lode

Live coding with Ordinary Differential Equations
5 stars 1 forks source link

Using ProxySpace #4

Open munshkr opened 5 years ago

munshkr commented 5 years ago

I was playing around with Lode, and remembered that ProxySpace has a lot of functionality already baked in for live coding with synths, from connecting synths together, to easily adding effects like reverbs and delays. What's rather cumbersome right now is that, whenever you want to change the equations you have to go back to the editor with the odes.yaml, edit it, save it, and then go back to SC. You could simplify all this and always stay in SC by writing a class that executes a Python script that generates the .so files. The end result would look like this (from the live coder perspective):

p = ProxySpace.push(s);

// This executes a Python script that parsers the equations (from command line arguments)
// and generates a .so that Oderk4 will load on construction.
(
Lode.generate(\hopf,
  \x, "2*pi*y*w + (e*x-x*(x*x+y*y))*100.0",
  \y, "-2*pi*x*w + (e*y-y*(x*x+y*y))*100.0",
  \params, [\w, 0.1, \e, 440])
)

// Oderk4 parses a list of key, value pairs for parameters, so that order of parameters
// does not matter... e.g. Oderk4.ar(\hopf, \w, 0.3, \e, 300)

~hopf = { Oderk4.ar(\hopf) }
~hopf.play

~lfo = { LFNoise2.kr(30, 300, 500) };
~hopf = { Oderk4.ar(\Hopf, \e, ~lfo.kr) }

~lfo = 220;

// Clear with fadeout
p.clear(4);

Using ProxySpace also simplifies the whole In/Out and Bus management you were playing with.

What do you think?

munshkr commented 5 years ago

Actually, Lode.generate could also generate a SynthDef with the parameters. This way, there is no need for Oderk4 to parse the parameter names, and remember their order.

This works now with the current Oderk4 implementation:

(
SynthDef.new(\hopf, {
  Out.ar(\out.ar(0), Oderk4.ar(\Hopf, \w.ar(0.3), \e.ar(300)));
}).add;
)

f = { |key=\default| SynthDescLib.global.at(key).def.func };

p = ProxySpace.push(s);

~hopf.play;
~hopf[0] = f.(\hopf);

// fxs
~hopf[10] = \filter -> { |sig| FreeVerb.ar(RLPF.ar(sig, SinOsc.kr(0.25).range(5000,10000))) * SinOsc.kr(8).range(0.25,0.75) };
~hopf[11] = \filter -> { |sig| Mix.ar([sig[0], DelayN.ar(sig[1], 1, 0.125)]) };

// patterns!
~hopf[30] = \set -> Pbind(\e, Pwhite(220, 440), \w, Pseq([0.01, 0.2, 0.1], inf), \dur, 0.25);

// map synths to parameters
~pe = { LFNoise2.kr(30, 300, 500) };
~hopf.set(\e, ~pe);

Connecting some ODE to another ODEs parameter would be something like this:

// map some ODE to another ODE
~hopf2 = f.(\hopf);
~hopf2.set(\out, ~pw)
~hopf.set(\w, ~pw)

But it has some issues right now. For some reason, ~hopf2 outputs to ~pw but also outputs sound to 0. Probably a multichannel expansion behavior that I'm missing.

pabloriera commented 5 years ago

(I closed the issue accidentally)

Regarding writing the equations directly on SC and not using the yaml, it would be a great alternative, but I don't know how easy is to call python from Supercollider. It sure could be done, but I was using the FoxDot way of communicating with SC, so it was handy to have a python side.

But is true that for the stage and for debugging it could be very useful to work directly on SC, by using ProxySpace live coding style.