Muse OSC Server Examples


#1

Hey all,

Just posted a new example/tutorial on the dev blog about building simple OSC servers for receiving and parsing Muse data sent by MuseIO.

Check it out here: http://developer.choosemuse.com/research-tools-example/grabbing-data-from-museio-a-few-simple-examples-of-muse-osc-servers

It includes examples for C, Java, Python, Processing, and Max/MSP. Let us know here in this thread if there’s an example in another language you’d like to see!

thanks,
Tom and the Muse dev team


#2

Hi tom,

Can i see the example for C# (.Net) as well?

Thank you,
Min


#3

Hey Min,

I’ll try to add one soon!

Just googling around I found this library: https://bitbucket.org/pvarcholik/bespoke.osc/overview have you tried it out?

There’s another library recommended on the OSC website: http://opensoundcontrol.org/implementation/osc-net-v1-2 …but it looks like the project itself is no longer online. Might work just fine though.

Some other links that popped up:

Let me know if you try any of these out and if you like a particular one.


#4

Hey @tom

Feel free to include the below NodeJS + Sockets for a Web Browser example to your docs with a shout out for credit.

set up your project settings with npm
$ npm init

Install dependencies:


$ npm install --save shelljs
$ npm install --save node-osc
$ npm install --save socket.io

The NodeJS script:


var shell = require('shelljs');
var osc = require('node-osc');
var io = require('socket.io')(80);

Initialise runtime parameters (I pass them over process.argv in production builds based on config schemas)


settings.runtime = {
  device: 'Muse',
  ip: 'localhost',
  port: 5000,
  socketUpdateFrequency: 100 
 }

Create an object to store the values then set them to default values. You can add your own calculations in here too, just add them as another item eg- “custom: 0”


var response = {};
function reset() {
    response = {
        alpha: 0,
        battery: 1,
        custom: 0
    };
}
reset();

Create a connection to the Muse controller through muse-io so you can start receiving OSC messages. This must be run asynchronously in order to process the values that are returned from the service. If you are comfortable in managing async.series and async.apply, then you are encouraged to use them to wait until the OSC service is ready before proceeding.


var shellCommand = [
    'muse-io --device ', 
    settings.runtime.device, 
    ' --osc osc.udp://', 
    settings.runtime.ip, 
    ':', 
    settings.runtime.port
].join('');

shell.exec(shellCommand, {
    async:true, 
    silent:true
});

Connect via OSC to muse-io and update the in-memory object as data comes from the headset. The OSC messages come through very frequently so it is advised to read and translate the OSC messages first before sending over Sockets, which is why we’re just updating the response object. Refer to the documentation as to the OSC messages that are sent to add more readings.


oscServer = new osc.Server(settings.runtime.port, settings.runtime.ip);
oscServer.on('message', function (msg, rinfo) {
        if (msg[0].indexOf('/muse/batt') > -1) {
            response.battery = parseInt(parseFloat(msg[1]) / 100);
        }        
       if (msg[0].indexOf('/muse/elements/alpha_relative') > -1) {                
            var msgAvg = averageArray(msg, 1);
            response.alpha = msgAvg;
       }
       //... additional OSC messages
}

Now emit the stored object values at a manageable interval


var tick = setInterval(function () {
    io.emit('data', response);
}, settings.runtime.socketUpdateFrequency);

Here’s our utility function that allows us to average the values across the whole array. Each EEG reading will give you 4 values and in my case, I wanted to have the average of all 4.


function averageArray (ary, start) {
    var val = 0,
        start = start || 0;
    for (var i = start; i < ary.length; i++) {
        var toAdd = parseFloat(ary[i]);
        val += isNaN(toAdd) ? 0 : toAdd;
    };
    return val / ary.length;
}

Save the code as [B]muse.js[/B] and run with

$ node muse.js

Now create a HTML page and import the Socket.IO front end library (please refer to other online tutorials on this). In your JavaScript, you can simply listen to the emitted event and respond accordingly knowing you have the full data object we created in the previous steps.


socket.on('data', function(cmd){
    console.log(cmd.alpha, cmd.battery);
});

Now that you’re in the browser, connect it up to the phone’s GPS services, visualise in THREE.js/ WebGL, do cool stuff with Augmented Reality, control the lightbulbs over WiFi, Tweet things, connect an Arduino Leonardo and create a joystick/mouse/keyboard. Really, getting into the browser is the first step to effortless interoperability.

I hope that helps someone.

Cheers
Mic

*disclaimer: code provided “as is”. It has been adapted from a working code platform previously created with a lot more options and much more separation of concerns. This isn’t the most efficient way either, it has deliberately been written verbosely for learning purpose.


#5

Hey Min,

C# example is up! http://developer.choosemuse.com/rese…se-osc-servers

Note that it was written/built in Xamarin Studio (MonoDevelop) on a Mac. It should work fine in Visual Studio on a Windows machine as far as I know.

Something webby, perhaps in node.js like what Mic has described, is next on my list.


#6

Hi Tom

I tried the Muse OSC Server C example. And got a linker error when I try to build the project as shown below.
I found out this “[SIZE=11px]Undefined symbols for architecture x86_64:[/SIZE]” issue is a OS problem, there are a lot of solutions for this issue, but no of them helped me.
Could you give some hits on this issue? I am using Eclipse Luna, on Mac 10.11 OS,

Thanks in advance
Sean [SIZE=11px] [/SIZE]
[SIZE=11px]**** Build of configuration Release for project OSCServerTest [/SIZE]
[SIZE=11px] [/SIZE]
[SIZE=11px]make all [/SIZE]
[SIZE=11px]Building target: OSCServerTest[/SIZE]
[SIZE=11px]Invoking: Cross GCC Linker[/SIZE]
[SIZE=11px]gcc -L/Users/yongxiangwang/Documents/CPlusPlusExercise/liblo-0.28/lo -L/Users/yongxiangwang/Documents/CPlusPlusExercise/liblo-0.28/src -o “OSCServerTest” ./muse_liblo_example_server.o [/SIZE]
[SIZE=11px]Undefined symbols for architecture x86_64:[/SIZE]
[SIZE=11px] “_lo_arg_pp”, referenced from:[/SIZE]
[SIZE=11px] _generic_handler in muse_liblo_example_server.o[/SIZE]
[SIZE=11px] “_lo_server_thread_add_method”, referenced from:[/SIZE]
[SIZE=11px] _main in muse_liblo_example_server.o[/SIZE]
[SIZE=11px] “_lo_server_thread_free”, referenced from:[/SIZE]
[SIZE=11px] _main in muse_liblo_example_server.o[/SIZE]
[SIZE=11px] “_lo_server_thread_new”, referenced from:[/SIZE]
[SIZE=11px] _main in muse_liblo_example_server.o[/SIZE]
[SIZE=11px] “_lo_server_thread_start”, referenced from:[/SIZE]
[SIZE=11px] _main in muse_liblo_example_server.o[/SIZE]
[SIZE=11px]ld: symbol(s) not found for architecture x86_64[/SIZE]
[SIZE=11px]clang: error: linker command failed with exit code 1 (use -v to see invocation)[/SIZE]
[SIZE=11px]make: *** [OSCServerTest] Error 1[/SIZE]
[SIZE=11px] [/SIZE]
[SIZE=11px]
Build Finished ****[/SIZE]


#7

Hey SeanyP,

You need to have liblo installed. See here for details: http://liblo.sourceforge.net/


#8

Hi Tom

Thanks for your reply.

I did install the liblo library. By following the procedure that explained in README.txt or INSTALL.txt. I had the library installed.

And I Just uninstalled it and re-installed it again. And compile the project. The same linker error appears.

Regards
Sean


#9

Anyone else who also had same issue?? especially Mac users


#10

Hey SeanyP,

Can you try just directly compiling the example from the command line? The GCC command you have there doesn’t seem to be quite correct. Building right from Terminal, you might do something like:

 gcc example_server.c -L/path/to/liblo-0.28/src/.libs -llo -o example_server
 

So you were pointing your linker to liblo-0.28/lo, but the .dylib files are actually in liblo-0.28/src/.libs

However, it really would be better just to use the system liblo. To that end, you could do something like:

 gcc example_server.c -llo -o example_server
 

#11

Hi Tom

I should try this ages ago. It works perfect from command line. Thanks again.

Regards
Sean


#12

The python example doesn’t really explain how to pull other files such as muse/elements/alpha_relative(0) etc…

How can I import the relative values into my python chart program?


#13

Hey Tom,

You did a great job! Thank you for your work, it works perfectly for me :wink:

So, I can visualize all data but I don’t success to write a script which uses this data. I would like to process the data in the main script.
For example, if don’t success to call use data to do a “if” in the main. An error appears “cannot make a static reference to a non-static field” at the line “if(this.Alpha[1][compteurAlpha]>0))” in the main

[B]package[/B] example;

[B]import[/B] oscP5.*;

[B]public[/B] [B]class[/B] MuseOscServer {

   [B]static[/B] MuseOscServer [I]museOscServer[/I];
  
   OscP5 museServer;
   [B]static[/B] [B]int[/B] [I]recvPort[/I] = 5000;
  
   [B]double[/B] Alpha[][]=[B]new[/B] [B]double[/B][4][];
   [B]int[/B] compteurAlpha=0;
  

   [B]public[/B] [B]static[/B] [B]void[/B] main(String [] args) {
         museOscServer = [B]new[/B] MuseOscServer();
         museOscServer.museServer = [B]new[/B] OscP5(museOscServer, recvPort);
         [B]if[/B]([B][U]this[/U][/B].Alpha[1][[U]compteurAlpha[/U]]&gt;0)[U])[/U]{
               
         }
                }
  
   [B]void[/B] oscEvent(OscMessage msg){
         //System.out.println("### got a message " + [U]msg[/U]);
         [B]if[/B] (msg.checkAddrPattern("/muse/elements/alpha_relative")==[B]true[/B]) {
                [B]for[/B]([B]int[/B] i = 0; i &lt; 4; i++) {
                       System.[I]out[/I].print("Alpha on channel " + i + ": " + msg.get(i).floatValue() + "

“);
[B]this[/B].Alpha[i][[B]this[/B].compteurAlpha]=msg.get(i).floatValue();
[B]this[/B].compteurAlpha++;
}
}
[B]else[/B] [B]if[/B] (msg.checkAddrPattern(”/muse/elements/beta_relative")==[B]true[/B]) {
[B]for[/B]([B]int[/B] i = 0; i < 4; i++) {
System.[I]out[/I].print(“Beta on channel " + i + “: " + msg.get(i).floatValue() + “
”);
}
}
[B]else[/B] [B]if[/B] (msg.checkAddrPattern(”/muse/elements/theta_relative”)==[B]true[/B]) {
[B]for[/B]([B]int[/B] i = 0; i < 4; i++) {
System.[I]out[/I].print("Theta on channel " + i + ": " + msg.get(i).floatValue() + “
”);
}
}
}

}

If anyone have a solution, it would be great ^^