Forum rss-feed

Forum

Developers: Prototype open-source OSC EigenD agent available

STICKY

written by: geert

Hi everyone,

Given the current developer interest and barnone's motivation to dig into the code, Jim has spent some time creating a prototype EigenD agent that is able to output EigenD data streams directly through OSC.

This implementation is just a start and was quickly written in two days to bootstrap the learning process of users that wish to participate in the development. Its serves both as a documented example for creating agents as well as an initial step towards the OSC plans that we've been making. As time progresses, our OSC support will mature and the EigenD OSC protocol will be formalized in more detail, but this should give you an idea of the direction we're heading into. We've discussed various approaches towards how to handle the OSC representation over the network and have hit limitations of the network stack in the past due to the massive amount of performance data that the Eigenharp generates. This performance data is essential to the expressiveness of the Eigenharp and we obviously want to allow it to be exposed in as much detail as possible. The document named "OSC" that comes with this example agent briefly explains what we consider the best approach, it will mature as we further work on the OSC support.

The document named 'Roadmap' explains how to use this OSC agent and gives a high-level developer-centric explanation of EigenD's internal architecture. The source code is heavily documented and should make it easy to adapt towards any other functionalities that you might want to implement with an agent.

The source code can be found on GitHub in the 1.4 branch of EigenD. Here is a direct link towards the source of just the plg_osc agent:
https://github.com/Eigenlabs/EigenD/tree/1.4/plg_osc

More information about getting involved in EigenD development can be found on this wiki page:
http://www.eigenlabs.com/wiki/Developers/

Please realize that we have very limited resources to provide direct support to external developers as we're hard at work wrapping up the initial release of EigenD 2.0 and Workbench. We hope that this example will give you enough information to make EigenD development more accessible.

Take care,

Geert

written by: barnone

Fri, 14 Oct 2011 20:17:33 +0100 BST

re UDP overload. Yeah "duh" I should know that.

Re the empty string. Some feedback is that it might be problematic for some environments, ie: MAX. For example, if I create a message in MAX with an empty string, the string simply vanishes from the message, because typing in MAX is based on the value not a declared type. In MAX, the message would be received with 1 less parameter. Possible to detect of course but not ideal.

Maybe using a "-1" or simply a symbol like "-" would help.

I hate to change specs based on limitations of certain environments, but if the change is minor it can really help with ease of use.

re # of events a sec. My calculations were absolutely non scientific so it most likely is 2k per sec. Amazing data rate.


written by: jim

Fri, 14 Oct 2011 22:48:39 +0100 BST

Actually, duh myself.

The empty event ID is actually a valid event (look at the events off the breath pipe) so its not a good sentinel...

I think in our stuff as it stands, "." would parse as an empty event, so we could use that.

But how to represent end-of-event? We could have an extra field, true/false, where only the last message
would carry the false.


written by: bwong

Fri, 14 Oct 2011 23:36:21 +0100 BST

quoting dhjdhj >> John, I don't know when you last looked at Max but it's certainly not for offline composition....are you thinking of CSound?

Well, as a Csound user I take exception to the implication that Max/Msp is great for realtime and Csound is not. I am well aware that is the prevailing internet wisdom, primarily due to it being oft repeated by Max users. In fact I believed this viral meme to the extent that I spent a pile of money and effort on Max/Msp 5.0, only to find out I was actually getting better realtime performance from Csound. No doubt this can vary dependent on the type of synthesis involved.

That being said, though I have not done actual tests, my impression after some brief experimentation with Supercollider leads me to think it is probably better for realtime than either Csound or Max. Also without actually testing, my impression is that EigenD is far superior for realtime performance than any of the aforementioned products.


written by: barnone

Tue, 18 Oct 2011 06:19:11 +0100 BST

@bwong that would be a good separate thread discussion? I haven't even tried CSound yet. But looks cool.

@jim
Regarding the empty string in MAX. Turns out I can parse it off the OSC stack.

I've now created a MAX patch that properly channelizes the events into separate streams.

Here's a screenshot

MAX

In MAX things like unlimited number of channels are a bit challenging. I mocked this up with a 25 channel fixed buffer.

For me regarding the existing stream, it's easier to detect the key # going to 0. I am discarding the event name. However, I can see where you are headed and this is only one use case for a generic schema of events, so that is a hack to detect the 0 value.

>But how to represent end-of-event? We could have an extra field, true/false, where only the last message
would carry the false.

In fact, I just tried the breath pipe. Did not know it was hooked up as well. I see the "." event.

The boolean could work as well. I'd propose an integer 0 1 as faster to parse if that was desireable.

Or could pick a different character for end of event. Empty string actually works. Although something else as a reserved char might be clearer?

BTW, MAX seems to have no issue so far with the event volume. I haven't smoothed or decimated yet. Depends on response when I send to the audio device. Going to try CV to the modular as a first test.

Also, want to say as I dig into the architecture of EigenD, I am very impressed to say the least. You obviously have a very deep background in highly parallel systems.

Cheers,
Chris





written by: barnone

Tue, 18 Oct 2011 17:35:36 +0100 BST

Actually I have a question.

The first float in the output. I was expecting velocity but the value seems to change from 0. to 2. , sometimes to 3. and back to 0.

[edit] Ok, I think that is supposed to be the timestamp, unimplemented, which is fine. Would use that for external velocity detection.


written by: natcl

Tue, 18 Oct 2011 18:34:33 +0100 BST

Barnone, had a look at your max patch. I'm doing similar tracking but for the TUIO protocol (multitouch table)
I find it easier to use a poly~ object to do the processing, this way I can easily change the number of channels by changing the poly argument.

Also if anybody is curious, my friend has been working for a while on a Python DSP library which is much easier to use than Csound. It could be interesting to integrate it with an eigenharp: http://code.google.com/p/pyo/


written by: barnone

Tue, 18 Oct 2011 19:39:22 +0100 BST

@natcl
Nice tip. Question though. I haven't done much signal processing with MSP and poly~ is an MSP object.

Have a simple example of how you'd route this?


written by: natcl

Tue, 18 Oct 2011 20:36:20 +0100 BST

Hello barnone,

Actually there is no MSP to do at all when you use it in "data" mode. The big difference is that instead of using an normal inlet you would use the [in] object for data and the [in~] object for signals. so if you need 2 inlets you would put [in 1] and [in 2]
From your main patch you would then send the message "target #" (# being the instance of the patcher you want to talk to) followed by your message.

What poly really does is that is creates several instances of a patch under the hood and you can use the instance number to make each patch behave differently (route different info for example) It doesn't really care if you do data, audio or video in it.

Another nice thing is that in Max 6 you can now change the argument of the route object dynamically via it's right inlet which can be quite useful for these types of situation.

Let me know if you hit some walls !


written by: natcl

Tue, 18 Oct 2011 20:41:47 +0100 BST

I can't really test with the eigenharp data as I don't have a machine where I can easily compile now but I'll try to send you a small example patch with poly when I get home tonight.


written by: dhjdhj

Tue, 18 Oct 2011 21:16:08 +0100 BST

I still haven't had a chance to try any of this stuff (too much other stuff going on right now) but I have to say it warms my heart to see all the Max hacking starting to happen :-)


written by: geert

Wed, 19 Oct 2011 20:25:10 +0100 BST

Hi everyone,

I added two more example agents, not part of the public features, mostly for developer documentation.

You can find them here:
https://github.com/Eigenlabs/EigenD/tree/1.4/plg_primitive

Take care,

Geert


written by: NothanUmber

Wed, 19 Oct 2011 21:17:27 +0100 BST

Thanks a lot, Geert!
Had a look at the latch agent, this is a very nice example of an essential agent (many existing agents are comparable but most do a few strange things where I was not sure whether that is really necessary in general or just a tribute to some specific constraints I did not find out yet. This does not seem to be the case for the latch agent, this is much more straight forward :)
So I will try to do things the simple way first, too and if there are any things that additionally have to be considered - I'll find out sooner or later :)

Greetings,
NothanUmber


written by: NothanUmber

Wed, 19 Oct 2011 23:06:55 +0100 BST

   

def __minimum(self,m):
self[3].set_value(value)
self.native.set_minimum(m)
return True


set_value(m) I guess (same in __controller)

-------------------

#define _USE_MATH_DEFINES // necessary for MSVC, otherwise M_PI etc. are not defined
#include ANGLE_BRACKETOPEN cmath ANGLE_BRACKETCLOSE
// how can I post angle brackets without having the forum software interpreting it as a tag? Perhaps that should be disabled inside code blocks...

--------

~impl_t()
{
// root_t are objects wich can be tracked via
// weak pointers. Invalidate ourself here.
tracked_invalidate(); // why is this not done in the root_t destructor then?

-----------
clocksink_ticked
add_ticker
del_ticker
invalidate
root_wire
root_closed
root_opened
root_clock
root_latency

don't these methods cry for a default implementation in a template class (with the wire type as template parameter)? This code occurs in a huge bunch of agents as copy'n'paste.
---------------------------
void wire_closed() { delete this; } // this is suicide if a wire is instantiated on the stack (ok, it's a local utility class, so the impact is restricted.. ;) )
----------------------------------


written by: geert

Wed, 19 Oct 2011 21:57:53 +0100 BST

Oops, thanks for spotting that! Guess that's what you get for quickly renaming some stuff right at the end :-)


written by: geert

Wed, 19 Oct 2011 22:51:03 +0100 BST

@NothanNumber those methods are indeed repeated frequently, but often there are slight differences in the actual implementation. We do have some base classes like cfilter_t which are used throughout the source code. However for this example I want to explain everything involved.


written by: NothanUmber

Wed, 19 Oct 2011 23:37:14 +0100 BST

Ah, thanks! So cfilter and ufilter are essentially default implementations that agents which perform operations on incoming realtime or control data and forward those afterwards can use!
Will have a look in how far utilitizing those could make sense in my case tomorrow (on first sight it looks as it would).
Perhaps for that it helps to have a second look at the ranger agent regarding the question why the new implementation does not use cfilter anymore but does handle the real time part by itself now.


written by: barnone

Thu, 20 Oct 2011 00:06:34 +0100 BST

Back to the OSC agent for a sec.

If I start EigenD from the source build. I find I can load any factoey or user setup and connect the OSC agent to it.

1. Load the setup you want to add the agent to.

2. Execute these commands in the shell from you build folder.

tmp/bin/brpc '' exec osc output create

tmp/bin/brpc '' exec alpha keyboard 1 to osc output 1 connect

3. Save the setup.

Cool thing here is that I can use my Alpha with the complex modes including sending for example Midi to expert sleepers to generate CV, but I can also send the OSC stream to the bit that handles CV for expression.

This could also be useful I imagine for controlling things like an audio visual show.

At the monome gridfest last year, we had a huge projection wall and performance data was controlling a separate machine that was running visuals using "Processing". It was extremely cool way to generate visuals with actual interactions.


written by: barnone

Thu, 20 Oct 2011 00:36:05 +0100 BST

Can't wait to look at what you added in detail Geert.


written by: bwong

Thu, 20 Oct 2011 02:28:47 +0100 BST

Processing has an OSC library available that makes it a good choice for syncing up algorithmic video with music via OSC. I did a simple video/music project a couple of years ago using Csound and Processing with it.


written by: barnone

Thu, 20 Oct 2011 02:33:34 +0100 BST

mmm, @bwong, maybe you need to fire that up again!!??



Please log in to join the discussions