muellmusik / Utopia

This is an attempt at a generic library of tools for making Network Music Apps in SuperCollider
43 stars 8 forks source link

add Republic Server #17

Closed telephon closed 7 years ago

telephon commented 7 years ago

This adds original Republic functionality, which allows us to locate in any OSC message a dispatcher to registered servers.

We just tested it and it runs nicely. A little under-the-hood, but very expressive. If you like it, we can also add documentation …

you can write stuff like Pbind(\where, Pseq([0, 5, 1], inf)), which sends to the first, fourth, and second participant. Maybe we could reintroduce \all again.

telephon commented 7 years ago

doesn't multichannel expand correctly. We'll have to do it differently.

muellmusik commented 7 years ago

Sorry, did take a look and was meaning to write up some comments: This seems sensible and useful. I'd talked (with you? Alberto?) about other approaches. A custom event type would seem the 'supported' approach, but is a bit cumbersome. The name RepublicServer (while highlighting its noble lineage :-) is a little misleading. It's not really a server IIUC (okay it is, but...), it's a sort of adaptor which looks for keys to decide which Server to route to. As this is generally useful, not just for recreating functionality, maybe a more generic and descriptive name might make sense?

Also, I'm kind of nervous about this as a design that drops in in place of a server. Have you really thought through all that might mean, and any pitfalls? Would it be cleaner to keep the Server object separate and make this a simple adaptor used only exactly where it should be?

telephon commented 7 years ago

Probably you are right. The aim is to make it really transparent, so any event that specifies a "where" will be redirected. You have to put the routing somewhere, and the good old way way to just spoof the lowest level - think deep packet inspection ;).

The main problem I ran into is that now the allocator scheme is far more intricate than it used to be, so that the actual nodes that are created on the different servers have the wrong ids. The allocators know nothing of "\where", because they are usually called much further up.

What we really need is an event type that flops before node id allocation happens.

This works, and could be used to distribute to multiple servers:

(
var flop = { |dict, keys|
    var values;
    keys = keys ?? { dict.keys.asArray };
    values = keys.collect { |x| dict.at(x) };
    values.flop.collect { |xs|
        var each = dict.copy;
        keys.do { |key, i| each.put(key, xs.at(i)) };
        each
    }.unbubble

};
Event.addEventType(\flop, { |server|
    var all;
    ~server = server;
    ~type = ~kind ? \note;
    all = flop.value(currentEnvironment, ~flopArgs);
    all.do { |each| each.play }
})
)

(
SynthDef(\sin, { | out=0, freq=440, sustain=0.05 |
    var env = EnvGen.kr(Env.perc(0.01, sustain, 0.2), doneAction: Done.freeSelf);
    Out.ar(out, SinOsc.ar(freq, 0, env))
}).add;

SynthDef(\saw, { | out=0, freq=440, sustain=0.05 |
    var env = EnvGen.kr(Env.perc(0.01, sustain, 0.2), doneAction: Done.freeSelf);
    Out.ar(out, Saw.ar(freq, env))
}).add;
)

(
Pbind(
    \type, \flop,
    \instrument, [\sin, \saw],
    \freq, [900, 50],   
).play;
)

we could simplify the note event a lot even, and then see how well it goes in terms of performance.

monodread commented 7 years ago

Hi Julian, Scott, just a utopia user's comment on the side: To have (again) the possibility of flexible targeting of recipients while playing would be really good & cool to have. I always thought that particularly the old 'where: \all' syntax, allowing for a "tutti" way of playing, gives nice dynamics of expanding and compressing the group size(s) during a performance. Quite a while ago Graham and I where working on a tool to also introduce some way of visualising this kind of routing-panning strategy (though never finished). Maybe now this is a good moment to pick it up again – I am however not part in any networking group for creating good test scenarios currently. :( will keep the idea in mind though. in any case: thanks for your work so far!

muellmusik commented 6 years ago

My thinking is that an event type is the way to do it. The inconvenience of this is having to specify this in your streams. Two possible solutions:

  1. Add the ability to extend a given event type (i.e. note)
  2. Make it possible to set the default event type (perhaps already possible?)
telephon commented 6 years ago
  1. Add the ability to extend a given event type (i.e. note)

You can do this:

Event.addEventType(\x, {
      ~myValue = ~thatOtherValue;
      ~type = ~kind ? \note;
      currentEnvironment.play
}
  1. Make it possible to set the default event type (perhaps already possible?)

that is a good idea. I think it is possible by setting the Event.defaultParentEvent.