Last active
October 23, 2023 21:48
-
-
Save Jennaltj/d5addd6a73d6e85a81c5 to your computer and use it in GitHub Desktop.
Arduino, openCV, EEG, Processing to Unity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void attentionEvent(int attentionLevel) | |
{ | |
attention = attentionLevel; | |
println("Attention:"+attentionLevel); | |
} | |
void poorSignalEvent(int sig){} | |
void meditationEvent(int meditationLevel) | |
{ | |
meditation = meditationLevel; | |
//meditation =51; | |
println("Meditation:"+meditationLevel); | |
} | |
void blinkEvent(int blinkStrength) | |
{ | |
blink = blinkStrength; | |
} | |
public void eegEvent(int delta, int theta,int low_alpha,int high_alpha, int low_beta, int high_beta, int low_gamma, int mid_gamma) | |
{} | |
void rawEvent(int[]raw){} | |
void stop() { | |
neuroSocket.stop(); | |
super.stop(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gab.opencv.*; | |
import processing.video.*; | |
import java.awt.*; | |
import oscP5.*; | |
import netP5.*; | |
OscP5 oscP5; | |
NetAddress myRemoteLocation; | |
Capture video; | |
OpenCV opencv; | |
float rectX,rectY; | |
float sendX,sendY; | |
float sendRY,sendRX; | |
//----------eeg----------// | |
import neurosky.*; | |
import org.json.*; | |
ThinkGearSocket neuroSocket; | |
boolean enableRawOutput = true; | |
int attention = 10; | |
int meditation = 10; | |
int blink=0; | |
float raw; | |
float angle =0.0; | |
float angleSpeed=0.5; | |
float sendSpeed;///// | |
float sendSpeed2; | |
float sendMe; | |
float sendBlink; | |
//----------ping--------// | |
import processing.serial.*; | |
float waterLevel; | |
float waterLevel_NUM; | |
float WL; | |
int i=1; | |
float sendWL; | |
Serial myPort; | |
//-----------sound--------// | |
import ddf.minim.*; | |
Minim minim; | |
AudioPlayer player; | |
//boolean playon= false; | |
//=========================// | |
void setup() { | |
size(640, 480); | |
frameRate(60);//////// | |
//--------choose camera----------------- | |
String[] cameras = Capture.list(); | |
if (cameras.length == 0) | |
{ | |
println("no cameras!"); | |
exit(); | |
} | |
else | |
{ | |
println("Available cameras:"); | |
for (int i = 0; i< cameras.length; i++) | |
{ | |
println(cameras[i]); | |
} | |
} | |
// video = new Capture(this,640/2,480/2,"Logitech Camera");//use other camera | |
video = new Capture(this,640/2,480/2); | |
//-------------end choose camera----------- | |
opencv = new OpenCV(this, 640/2, 480/2); | |
opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); | |
video.start(); | |
oscP5 = new OscP5(this, 57131); | |
myRemoteLocation = new NetAddress("127.0.0.1", 57130); | |
//-----------eeg----------// | |
ThinkGearSocket neuroSocket = new ThinkGearSocket(this); | |
try | |
{ | |
neuroSocket.start(); | |
} | |
catch (Exception e) | |
{ | |
} | |
//=========================// | |
//----------Ping-----------// | |
println(Serial.list()); | |
myPort = new Serial(this,Serial.list()[9],9600); | |
//=========================// | |
//recordWL.add(waterLevel_NUM); | |
//----------sound-----------// | |
minim = new Minim(this); | |
player = minim.loadFile("034.mp3"); | |
} | |
void draw() { | |
scale(2); | |
opencv.loadImage(video); | |
image(video, 0, 0 ); | |
noFill(); | |
stroke(0, 255, 0); | |
strokeWeight(3); | |
Rectangle[] faces = opencv.detect(); | |
println(faces.length); | |
for (int i = 0; i < faces.length; i++) { | |
rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height); | |
rectX= (faces[i].x+faces[i].width/2); | |
rectY= (faces[i].y+faces[i].height/2); | |
ellipse(rectX,rectY, 10,10); | |
sendX=(640-rectX)/5; | |
sendY=-rectY/5; | |
sendRY = map(sendX,70,118,14,-14); | |
sendRX = map(sendY,-11,-38,10,-10); | |
sendValue(sendX,sendY); | |
sendValueRo(sendRY,sendRX); | |
} | |
//---------------ping---------------// | |
String waterLevel = myPort.readStringUntil('\n'); | |
if (waterLevel!= null) | |
{ | |
waterLevel_NUM = int(trim(waterLevel)); | |
sendWL = map(waterLevel_NUM,1570,0,-75,30); | |
sendValueWL(sendWL); | |
} | |
else | |
{ | |
waterLevel_NUM=2000; | |
} | |
//---------------eeg-----------------// | |
//------ATTENTION | |
text("Attention:"+attention,10,20); | |
text("Meditation:"+meditation,10,40); | |
fill(blink,0,0); | |
if (waterLevel_NUM <800) | |
{ | |
sendMe = (sin(angle))*0.05; | |
angle += angleSpeed; | |
if (attention>=10) | |
{ | |
sendSpeed = -attention*0.010; | |
sendSpeed2 = 0; | |
} | |
else | |
{ | |
sendSpeed = 0; | |
sendSpeed2 = 0; | |
} | |
} | |
else | |
{ | |
sendSpeed = 0; | |
sendSpeed2 = 0; | |
} | |
println("Attention:"+attention); | |
println("sendSpeed:"+sendSpeed); | |
sendValueSp(sendSpeed); | |
sendValueSp2(sendSpeed2); | |
sendValueMe(sendMe); | |
println("sendMe:"+sendMe); | |
//-------BLINK | |
if (blink>100) | |
{ | |
sendBlink = map(blink,0,255,0,30000); | |
} | |
else | |
{ | |
sendBlink=0; | |
} | |
sendValueBlink(sendBlink); | |
println("blink:"+blink); | |
println("sendBlink:"+sendBlink); | |
//=======================// | |
//----------sound---------// | |
if (meditation>=50 && !player.isPlaying()) | |
{ | |
player.play(); | |
player.rewind(); | |
} | |
} | |
void captureEvent(Capture c) { | |
c.read(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Thanks the orginal author of this function! | |
void sendValue(float x, float y) //camera position | |
{ | |
OscMessage oscMess1 = new OscMessage("/sensorX"); | |
oscMess1.add(x); | |
OscMessage oscMess2 = new OscMessage("/sensorY"); | |
oscMess2.add(y); | |
oscP5.send(oscMess1, myRemoteLocation); | |
oscP5.send(oscMess2, myRemoteLocation); | |
} | |
void sendValueRo(float m, float n) //camera rotate | |
{ | |
OscMessage oscMess3 = new OscMessage("/sensorRY"); | |
oscMess3.add(m); | |
OscMessage oscMess4 = new OscMessage("/sensorRX"); | |
oscMess4.add(n); | |
oscP5.send(oscMess3, myRemoteLocation); | |
oscP5.send(oscMess4, myRemoteLocation); | |
} | |
void sendValueSp(float s) //eeg move speed | |
{ | |
OscMessage oscMess5 = new OscMessage("/sensorSp"); | |
oscMess5.add(s); | |
oscP5.send(oscMess5, myRemoteLocation); | |
} | |
void sendValueWL(float w)//water level | |
{ | |
OscMessage oscMess6 = new OscMessage("/sensorWL"); | |
oscMess6.add(w); | |
oscP5.send(oscMess6, myRemoteLocation); | |
} | |
void sendValueBlink(float b)//blink | |
{ | |
OscMessage oscMess7 = new OscMessage("/sensorBlink"); | |
oscMess7.add(b); | |
oscP5.send(oscMess7, myRemoteLocation); | |
} | |
void sendValueMe(float me)//blink | |
{ | |
OscMessage oscMess8 = new OscMessage("/sensorMe"); | |
oscMess8.add(me); | |
oscP5.send(oscMess8, myRemoteLocation); | |
} | |
void sendValueSp2(float s2) //eeg move speed | |
{ | |
OscMessage oscMess9 = new OscMessage("/sensorSp2"); | |
oscMess9.add(s2); | |
oscP5.send(oscMess9, myRemoteLocation); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma strict | |
var i :int =0; | |
var angle :float =0; | |
var speed : float = 0.05; | |
var dis: float; | |
function Start () { | |
} | |
function Update () { | |
var cam = GameObject.Find("Main Camera"); | |
var con = GameObject.Find("Controller"); | |
var cube = GameObject.Find("CubeMoveTest"); | |
dis = Vector3.Distance(cam.transform.position,transform.position); | |
if (dis<180) | |
{ | |
Application.LoadLevel("22"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma strict | |
var xChannel : float; | |
var yChannel : float; | |
var RYChannel : float; | |
var RXChannel : float; | |
function Update () { | |
var x = OscReceiver.messages[xChannel]; | |
var y = OscReceiver.messages[yChannel]; | |
var m = OscReceiver.messages[RYChannel]; | |
var n = OscReceiver.messages[RXChannel]; | |
transform.position = Vector3(x,y,0); | |
transform.eulerAngles = new Vector3(n,m,0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma strict | |
var dis: float; | |
var BlinkChannel : float; | |
var i :int =0; | |
var num:int = 0; | |
var num2:int =0; | |
var pass: boolean = true; | |
function start() | |
{ | |
} | |
function Update () { | |
if (pass == true);//why here is a ";" and works well? | |
{ var aa = GameObject.Find("test"); | |
var bb = GameObject.Find("Main Camera"); | |
var cc = GameObject.Find("Block"+num); | |
dis = Vector3.Distance(cc.transform.position,bb.transform.position); | |
if (dis<150 && dis >=0) | |
{ | |
var b = OscReceiver.messages[BlinkChannel]; | |
Debug.Log("b:"+b); | |
aa.transform.position = Vector3(aa.transform.position.x,b,aa.transform.position.z); | |
if (aa.transform.position.y>10000) | |
{ | |
for(i =0;i<1;i+=1) | |
{cc.transform.localPosition.y += 20000; | |
} | |
} | |
} | |
if(dis > 10000) | |
{ | |
pass = false; | |
if (num<2) | |
{ | |
num ++; | |
num2 =num-1; | |
} | |
else | |
{ | |
num=0; | |
num2 =2; | |
} | |
} | |
pass = true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma strict | |
var SpChannel : float; | |
var Sp2Channel : float; | |
var num: int; | |
var num2: int; | |
var pass: boolean = true; | |
var angle :float; | |
var speed : float = 0.05; | |
var turnround1 : boolean = false; | |
var turnround2 : boolean = false; | |
var turnback :boolean = false; | |
var s2: float; | |
function Start() | |
{ | |
num = 0; | |
num2 = 2; | |
} | |
function Update () { | |
if( pass == true) | |
{ | |
var s = OscReceiver.messages[SpChannel]; | |
var s2 = OscReceiver.messages[Sp2Channel]; | |
var aa = GameObject.Find("Main Camera"); | |
var bb = GameObject.Find("Block"+num); | |
var cc = GameObject.Find("Block"+num2); | |
var ww = GameObject.Find("CubeMoveTest"); | |
var ball = GameObject.Find("turntest"); | |
var tt0 = GameObject.Find("turn0"); | |
var tt1 = GameObject.Find("turn1"); | |
var dis2: float = Vector3.Distance(aa.transform.position,bb.transform.position); | |
var dist0: float = Vector3.Distance(aa.transform.position,tt0.transform.position); | |
var dist1: float = Vector3.Distance(aa.transform.position,tt1.transform.position); | |
angle = ww.transform.eulerAngles.y; | |
} | |
if(dis2 > 10000) | |
{ | |
pass = false; | |
if (num<2) | |
{ | |
num ++; | |
num2 =num-1; | |
} | |
else | |
{ | |
num=0; | |
num2 =2; | |
} | |
cc.transform.localPosition.y =0; | |
} | |
pass = true; | |
Debug.Log("num:"+num); | |
Debug.Log("num2:"+num2); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////////This is not written by me.....Thanks the author of this code///////////////// | |
using System.Collections; | |
using System.IO; | |
using System; | |
/// \mainpage | |
/// \section Overview | |
/// The .NET Visual C# library for the Make Controller Kit is designed | |
/// to make it as simple as possible for developers to integrate the | |
/// Make Controller Kit into their desktop applications, offering the | |
/// transparency that makes open source software so rewarding to work with. | |
/// You can communicate with the Make Controller Kit from your applications | |
/// over either an Ethernet or USB connection, or both. This library is | |
/// supplied both in source form and built, as MakeControllerOsc.dll | |
/// This document is a reference for MakeControllerOsc. | |
/// | |
/// \section Communication | |
/// Messages to and from the board conform to the OSC (Open Sound Control) protocol. | |
/// OSC is an open, transport-independent standard supported by an increasing | |
/// number of environments and devices. | |
/// | |
/// \subsection OSCmessages OSC Messages | |
/// OSC messages are represented by the class OscMessage, and consist of two elements: | |
/// - An address string for the device on the board youíre dealing with. | |
/// - A list of value(s) being sent to or from that device. The list of values is optional. | |
/// | |
/// From the perspective of OSC addresses, the Make Controller Kit is organized into a hierarchy of two or three layers: | |
/// - subsystems ñ classes of device, such as analog inputs, servo controllers, and digital outputs. | |
/// - devices ñ the index of a specific device within a subsystem. | |
/// If there is only one device in a subsystem, the device is not included in the OSC address. | |
/// - properties ñ different devices have different properties, such as the value of an analog input, | |
/// the position of a servo motor, or the state of an LED. | |
/// | |
/// OSC messages always begin with a slash, and use a slash to delimit each element in the address, | |
/// so an example OSC address string would look like: | |
/// \code /subsystem/device/property \endcode | |
/// | |
/// The second part of an OscMessage is a list of values to be sent to the specified address. | |
/// The OSC types that are used by the Make Controller Kit for these values are integers, | |
/// floats, and strings. The values in this list are simply separated by spaces, and the | |
/// list can be arbitrarily long. Most devices on the Make Controller Kit expect only one value. | |
/// For example, to set the position of servo 1, you might send a message which | |
/// in string form might look like: | |
/// \code /servo/1/position 512 \endcode | |
/// | |
/// This addressing scheme allows interactions with the board's various subsystems | |
/// and properties, and most importantly, accommodates the possibility of future or | |
/// custom devices on the board that have not yet been implemented or imagined. | |
/// If somebody creates, for example, a GPS extension to the board, communicating | |
/// with that device from this library is the same as for any other. More details | |
/// about OSC can be found at http://www.opensoundcontrol.org. | |
/// | |
/// \section sendingdata Sending Data | |
/// As previously mentioned, the Make Controller Kit can communicate over both | |
/// Ethernet and USB. Messages are sent as packets, both over USB and UDP, and | |
/// corresponding structures are used ñ UsbPacket and UdpPacket. Once youíve created | |
/// a packet, you can simply call its Send() method, with the OscMessage youíd like to send. | |
/// There are helper methods to create an OscMessage from a string, or you can pass in the OscMessage itself. | |
/// | |
/// For example, you might set up your UsbSend() routine to look something like: | |
/// \code public void usbSend(string text) | |
/// { | |
/// OscMessage oscM = Osc.StringToOscMessage(text); | |
/// oscUsb is an Osc object, connected to a UsbPacket object | |
/// oscUsb.Send(oscM); | |
/// } \endcode | |
/// If your data is already in the form of an OscMessage, you can call oscUsb.Send() directly. | |
/// | |
/// \section readingdata Reading Data | |
/// The Make Controller Kit must be polled in order to read data from it. To do this, | |
/// send an OscMessage with the address of the device youíd like to read, but omit | |
/// the list of values. When the board receives an OscMessage with no value, | |
/// it interprets that as a read request, and sends back an OscMessage with the | |
/// current value at the appropriate address. | |
/// | |
/// The .NET Make Controller Kit library conveniently provides handlers that will | |
/// call back a given function when an OscMessage with a given address string is received. | |
/// Your implementation could look something like: | |
/// \code// Set the handler in the constructor for a particular address | |
/// MyConstructor() | |
/// { | |
/// udpPacket = new UdpPacket(); | |
/// oscUdp = new Osc(udpPacket); | |
/// // A thread is started when the Osc object is created to read | |
/// // incoming messages. | |
/// oscUdp.SetAddressHandler("/analogin/0/value", Ain0Message); | |
/// } | |
/// | |
/// // The method you specified as the handler will be called back when a | |
/// // message with a matching address string comes back from the board. | |
/// public void AIn0Message(OscMessage oscMessage) | |
/// { | |
/// // write the message to a console, for example | |
/// mct.WriteLine("AIn0 > " + Osc.OscMessageToString(oscMessage)); | |
/// } \endcode | |
/// You could alternatively set a handler for all incoming messages by calling | |
/// the SetAllMessageHandler() method in your setup, instead of SetAddressHandler(). | |
/// | |
/// | |
//namespace MakingThings | |
//{ | |
/// <summary> | |
/// The OscMessage class is a data structure that represents | |
/// an OSC address and an arbitrary number of values to be sent to that address. | |
/// </summary> | |
public class OscMessage | |
{ | |
/// <summary> | |
/// The OSC address of the message as a string. | |
/// </summary> | |
public string Address; | |
/// <summary> | |
/// The list of values to be delivered to the Address. | |
/// </summary> | |
public ArrayList Values; | |
public OscMessage() | |
{ | |
Values = new ArrayList(); | |
} | |
} | |
public delegate void OscMessageHandler( OscMessage oscM ); | |
/// <summary> | |
/// The Osc class provides the methods required to send, receive, and manipulate OSC messages. | |
/// Several of the helper methods are static since a running Osc instance is not required for | |
/// their use. | |
/// | |
/// When instanciated, the Osc class opens the PacketIO instance that's handed to it and | |
/// begins to run a reader thread. The instance is then ready to service Send OscMessage requests | |
/// and to start supplying OscMessages as received back. | |
/// | |
/// The Osc class can be called to Send either individual messages or collections of messages | |
/// in an Osc Bundle. Receiving is done by delegate. There are two ways: either submit a method | |
/// to receive all incoming messages or submit a method to handle only one particular address. | |
/// | |
/// Messages can be encoded and decoded from Strings via the static methods on this class, or | |
/// can be hand assembled / disassembled since they're just a string (the address) and a list | |
/// of other parameters in Object form. | |
/// | |
/// </summary> | |
public class Osc : MonoBehaviour | |
{ | |
private UDPPacketIO OscPacketIO; | |
Thread ReadThread; | |
private bool ReaderRunning; | |
private OscMessageHandler AllMessageHandler; | |
Hashtable AddressTable; | |
void Start() { | |
//do nothing, init must be called | |
} | |
public void init(UDPPacketIO oscPacketIO){ | |
OscPacketIO = oscPacketIO; | |
// Create the hashtable for the address lookup mechanism | |
AddressTable = new Hashtable(); | |
ReadThread = new Thread(Read); | |
ReaderRunning = true; | |
ReadThread.IsBackground = true; | |
ReadThread.Start(); | |
} | |
/// <summary> | |
/// Make sure the PacketExchange is closed. | |
/// </summary> | |
~Osc() | |
{ | |
if (ReaderRunning) Cancel(); | |
//Debug.LogError("~Osc"); | |
} | |
public void Cancel() | |
{ | |
//Debug.Log("Osc Cancel start"); | |
if (ReaderRunning) | |
{ | |
ReaderRunning = false; | |
ReadThread.Abort(); | |
} | |
if (OscPacketIO != null && OscPacketIO.IsOpen()) | |
{ | |
OscPacketIO.Close(); | |
OscPacketIO = null; | |
} | |
//Debug.Log("Osc Cancel finished"); | |
} | |
/// <summary> | |
/// Read Thread. Loops waiting for packets. When a packet is received, it is | |
/// dispatched to any waiting All Message Handler. Also, the address is looked up and | |
/// any matching handler is called. | |
/// </summary> | |
private void Read() | |
{ | |
try | |
{ | |
while (ReaderRunning) | |
{ | |
byte[] buffer = new byte[1000]; | |
int length = OscPacketIO.ReceivePacket(buffer); | |
//Debug.Log("received packed of len=" + length); | |
if (length > 0) | |
{ | |
ArrayList messages = Osc.PacketToOscMessages(buffer, length); | |
foreach (OscMessage om in messages) | |
{ | |
if (AllMessageHandler != null) | |
AllMessageHandler(om); | |
OscMessageHandler h = (OscMessageHandler)Hashtable.Synchronized(AddressTable)[om.Address]; | |
if (h != null) | |
h(om); | |
} | |
} | |
else | |
Thread.Sleep(20); | |
} | |
} | |
catch (Exception e) | |
{ | |
//Debug.Log("ThreadAbortException"+e); | |
} | |
finally | |
{ | |
//Debug.Log("terminating thread - clearing handlers"); | |
//Cancel(); | |
//Hashtable.Synchronized(AddressTable).Clear(); | |
} | |
} | |
/// <summary> | |
/// Send an individual OSC message. Internally takes the OscMessage object and | |
/// serializes it into a byte[] suitable for sending to the PacketIO. | |
/// </summary> | |
/// <param name="oscMessage">The OSC Message to send.</param> | |
public void Send( OscMessage oscMessage ) | |
{ | |
byte[] packet = new byte[1000]; | |
int length = Osc.OscMessageToPacket( oscMessage, packet, 1000 ); | |
OscPacketIO.SendPacket( packet, length); | |
} | |
/// <summary> | |
/// Sends a list of OSC Messages. Internally takes the OscMessage objects and | |
/// serializes them into a byte[] suitable for sending to the PacketExchange. | |
/// </summary> | |
/// <param name="oms">The OSC Message to send.</param> | |
public void Send(ArrayList oms) | |
{ | |
byte[] packet = new byte[1000]; | |
int length = Osc.OscMessagesToPacket(oms, packet, 1000); | |
OscPacketIO.SendPacket(packet, length); | |
} | |
/// <summary> | |
/// Set the method to call back on when any message is received. | |
/// The method needs to have the OscMessageHandler signature - i.e. void amh( OscMessage oscM ) | |
/// </summary> | |
/// <param name="amh">The method to call back on.</param> | |
public void SetAllMessageHandler(OscMessageHandler amh) | |
{ | |
AllMessageHandler = amh; | |
} | |
/// <summary> | |
/// Set the method to call back on when a message with the specified | |
/// address is received. The method needs to have the OscMessageHandler signature - i.e. | |
/// void amh( OscMessage oscM ) | |
/// </summary> | |
/// <param name="key">Address string to be matched</param> | |
/// <param name="ah">The method to call back on.</param> | |
public void SetAddressHandler(string key, OscMessageHandler ah) | |
{ | |
Hashtable.Synchronized(AddressTable).Add(key, ah); | |
} | |
/// <summary> | |
/// General static helper that returns a string suitable for printing representing the supplied | |
/// OscMessage. | |
/// </summary> | |
/// <param name="message">The OscMessage to be stringified.</param> | |
/// <returns>The OscMessage as a string.</returns> | |
public static string OscMessageToString(OscMessage message) | |
{ | |
StringBuilder s = new StringBuilder(); | |
s.Append(message.Address); | |
foreach( object o in message.Values ) | |
{ | |
s.Append(" "); | |
s.Append(o.ToString()); | |
} | |
return s.ToString(); | |
} | |
/// <summary> | |
/// Creates an OscMessage from a string - extracts the address and determines each of the values. | |
/// </summary> | |
/// <param name="message">The string to be turned into an OscMessage</param> | |
/// <returns>The OscMessage.</returns> | |
public static OscMessage StringToOscMessage(string message) | |
{ | |
OscMessage oM = new OscMessage(); | |
Console.WriteLine("Splitting " + message); | |
string[] ss = message.Split(new char[] { ' ' }); | |
IEnumerator sE = ss.GetEnumerator(); | |
if (sE.MoveNext()) | |
oM.Address = (string)sE.Current; | |
while ( sE.MoveNext() ) | |
{ | |
string s = (string)sE.Current; | |
// Console.WriteLine(" <" + s + ">"); | |
if (s.StartsWith("\"")) | |
{ | |
StringBuilder quoted = new StringBuilder(); | |
bool looped = false; | |
if (s.Length > 1) | |
quoted.Append(s.Substring(1)); | |
else | |
looped = true; | |
while (sE.MoveNext()) | |
{ | |
string a = (string)sE.Current; | |
// Console.WriteLine(" q:<" + a + ">"); | |
if (looped) | |
quoted.Append(" "); | |
if (a.EndsWith("\"")) | |
{ | |
quoted.Append(a.Substring(0, a.Length - 1)); | |
break; | |
} | |
else | |
{ | |
if (a.Length == 0) | |
quoted.Append(" "); | |
else | |
quoted.Append(a); | |
} | |
looped = true; | |
} | |
oM.Values.Add(quoted.ToString()); | |
} | |
else | |
{ | |
if (s.Length > 0) | |
{ | |
try | |
{ | |
int i = int.Parse(s); | |
// Console.WriteLine(" i:" + i); | |
oM.Values.Add(i); | |
} | |
catch | |
{ | |
try | |
{ | |
float f = float.Parse(s); | |
// Console.WriteLine(" f:" + f); | |
oM.Values.Add(f); | |
} | |
catch | |
{ | |
// Console.WriteLine(" s:" + s); | |
oM.Values.Add(s); | |
} | |
} | |
} | |
} | |
} | |
return oM; | |
} | |
/// <summary> | |
/// Takes a packet (byte[]) and turns it into a list of OscMessages. | |
/// </summary> | |
/// <param name="packet">The packet to be parsed.</param> | |
/// <param name="length">The length of the packet.</param> | |
/// <returns>An ArrayList of OscMessages.</returns> | |
public static ArrayList PacketToOscMessages(byte[] packet, int length) | |
{ | |
ArrayList messages = new ArrayList(); | |
ExtractMessages(messages, packet, 0, length); | |
return messages; | |
} | |
/// <summary> | |
/// Puts an array of OscMessages into a packet (byte[]). | |
/// </summary> | |
/// <param name="messages">An ArrayList of OscMessages.</param> | |
/// <param name="packet">An array of bytes to be populated with the OscMessages.</param> | |
/// <param name="length">The size of the array of bytes.</param> | |
/// <returns>The length of the packet</returns> | |
public static int OscMessagesToPacket(ArrayList messages, byte[] packet, int length) | |
{ | |
int index = 0; | |
if (messages.Count == 1) | |
index = OscMessageToPacket((OscMessage)messages[0], packet, 0, length); | |
else | |
{ | |
// Write the first bundle bit | |
index = InsertString("#bundle", packet, index, length); | |
// Write a null timestamp (another 8bytes) | |
int c = 8; | |
while (( c-- )>0) | |
packet[index++]++; | |
// Now, put each message preceded by it's length | |
foreach (OscMessage oscM in messages) | |
{ | |
int lengthIndex = index; | |
index += 4; | |
int packetStart = index; | |
index = OscMessageToPacket(oscM, packet, index, length); | |
int packetSize = index - packetStart; | |
packet[lengthIndex++] = (byte)((packetSize >> 24) & 0xFF); | |
packet[lengthIndex++] = (byte)((packetSize >> 16) & 0xFF); | |
packet[lengthIndex++] = (byte)((packetSize >> 8) & 0xFF); | |
packet[lengthIndex++] = (byte)((packetSize) & 0xFF); | |
} | |
} | |
return index; | |
} | |
/// <summary> | |
/// Creates a packet (an array of bytes) from a single OscMessage. | |
/// </summary> | |
/// <remarks>A convenience method, not requiring a start index.</remarks> | |
/// <param name="oscM">The OscMessage to be returned as a packet.</param> | |
/// <param name="packet">The packet to be populated with the OscMessage.</param> | |
/// <param name="length">The usable size of the array of bytes.</param> | |
/// <returns>The length of the packet</returns> | |
public static int OscMessageToPacket(OscMessage oscM, byte[] packet, int length) | |
{ | |
return OscMessageToPacket(oscM, packet, 0, length); | |
} | |
/// <summary> | |
/// Creates an array of bytes from a single OscMessage. Used internally. | |
/// </summary> | |
/// <remarks>Can specify where in the array of bytes the OscMessage should be put.</remarks> | |
/// <param name="oscM">The OscMessage to be turned into an array of bytes.</param> | |
/// <param name="packet">The array of bytes to be populated with the OscMessage.</param> | |
/// <param name="start">The start index in the packet where the OscMessage should be put.</param> | |
/// <param name="length">The length of the array of bytes.</param> | |
/// <returns>The index into the packet after the last OscMessage.</returns> | |
private static int OscMessageToPacket(OscMessage oscM, byte[] packet, int start, int length) | |
{ | |
int index = start; | |
index = InsertString(oscM.Address, packet, index, length); | |
//if (oscM.Values.Count > 0) | |
{ | |
StringBuilder tag = new StringBuilder(); | |
tag.Append(","); | |
int tagIndex = index; | |
index += PadSize(2 + oscM.Values.Count); | |
foreach (object o in oscM.Values) | |
{ | |
if (o is int) | |
{ | |
int i = (int)o; | |
tag.Append("i"); | |
packet[index++] = (byte)((i >> 24) & 0xFF); | |
packet[index++] = (byte)((i >> 16) & 0xFF); | |
packet[index++] = (byte)((i >> 8) & 0xFF); | |
packet[index++] = (byte)((i) & 0xFF); | |
} | |
else | |
{ | |
if (o is float) | |
{ | |
float f = (float)o; | |
tag.Append("f"); | |
byte[] buffer = new byte[4]; | |
MemoryStream ms = new MemoryStream(buffer); | |
BinaryWriter bw = new BinaryWriter(ms); | |
bw.Write(f); | |
packet[index++] = buffer[3]; | |
packet[index++] = buffer[2]; | |
packet[index++] = buffer[1]; | |
packet[index++] = buffer[0]; | |
} | |
else | |
{ | |
if (o is string) | |
{ | |
tag.Append("s"); | |
index = InsertString(o.ToString(), packet, index, length); | |
} | |
else | |
{ | |
tag.Append("?"); | |
} | |
} | |
} | |
} | |
InsertString(tag.ToString(), packet, tagIndex, length); | |
} | |
return index; | |
} | |
/// <summary> | |
/// Receive a raw packet of bytes and extract OscMessages from it. Used internally. | |
/// </summary> | |
/// <remarks>The packet may contain a OSC message or a bundle of messages.</remarks> | |
/// <param name="messages">An ArrayList to be populated with the OscMessages.</param> | |
/// <param name="packet">The packet of bytes to be parsed.</param> | |
/// <param name="start">The index of where to start looking in the packet.</param> | |
/// <param name="length">The length of the packet.</param> | |
/// <returns>The index after the last OscMessage read.</returns> | |
private static int ExtractMessages(ArrayList messages, byte[] packet, int start, int length) | |
{ | |
int index = start; | |
switch ( (char)packet[ start ] ) | |
{ | |
case '/': | |
index = ExtractMessage( messages, packet, index, length ); | |
break; | |
case '#': | |
string bundleString = ExtractString(packet, start, length); | |
if ( bundleString == "#bundle" ) | |
{ | |
// skip the "bundle" and the timestamp | |
index+=16; | |
while ( index < length ) | |
{ | |
int messageSize = ( packet[index++] << 24 ) + ( packet[index++] << 16 ) + ( packet[index++] << 8 ) + packet[index++]; | |
/*int newIndex = */ExtractMessages( messages, packet, index, length ); | |
index += messageSize; | |
} | |
} | |
break; | |
} | |
return index; | |
} | |
/// <summary> | |
/// Extracts a messages from a packet. | |
/// </summary> | |
/// <param name="messages">An ArrayList to be populated with the OscMessage.</param> | |
/// <param name="packet">The packet of bytes to be parsed.</param> | |
/// <param name="start">The index of where to start looking in the packet.</param> | |
/// <param name="length">The length of the packet.</param> | |
/// <returns>The index after the OscMessage is read.</returns> | |
private static int ExtractMessage(ArrayList messages, byte[] packet, int start, int length) | |
{ | |
OscMessage oscM = new OscMessage(); | |
oscM.Address = ExtractString(packet, start, length); | |
int index = start + PadSize(oscM.Address.Length+1); | |
string typeTag = ExtractString(packet, index, length); | |
index += PadSize(typeTag.Length + 1); | |
//oscM.Values.Add(typeTag); | |
foreach (char c in typeTag) | |
{ | |
switch (c) | |
{ | |
case ',': | |
break; | |
case 's': | |
{ | |
string s = ExtractString(packet, index, length); | |
index += PadSize(s.Length + 1); | |
oscM.Values.Add(s); | |
break; | |
} | |
case 'i': | |
{ | |
int i = ( packet[index++] << 24 ) + ( packet[index++] << 16 ) + ( packet[index++] << 8 ) + packet[index++]; | |
oscM.Values.Add(i); | |
break; | |
} | |
case 'f': | |
{ | |
byte[] buffer = new byte[4]; | |
buffer[3] = packet[index++]; | |
buffer[2] = packet[index++]; | |
buffer[1] = packet[index++]; | |
buffer[0] = packet[index++]; | |
MemoryStream ms = new MemoryStream(buffer); | |
BinaryReader br = new BinaryReader(ms); | |
float f = br.ReadSingle(); | |
oscM.Values.Add(f); | |
break; | |
} | |
} | |
} | |
messages.Add( oscM ); | |
return index; | |
} | |
/// <summary> | |
/// Removes a string from a packet. Used internally. | |
/// </summary> | |
/// <param name="packet">The packet of bytes to be parsed.</param> | |
/// <param name="start">The index of where to start looking in the packet.</param> | |
/// <param name="length">The length of the packet.</param> | |
/// <returns>The string</returns> | |
private static string ExtractString(byte[] packet, int start, int length) | |
{ | |
StringBuilder sb = new StringBuilder(); | |
int index = start; | |
while (packet[index] != 0 && index < length) | |
sb.Append((char)packet[index++]); | |
return sb.ToString(); | |
} | |
private static string Dump(byte[] packet, int start, int length) | |
{ | |
StringBuilder sb = new StringBuilder(); | |
int index = start; | |
while (index < length) | |
sb.Append(packet[index++]+"|"); | |
return sb.ToString(); | |
} | |
/// <summary> | |
/// Inserts a string, correctly padded into a packet. Used internally. | |
/// </summary> | |
/// <param name="string">The string to be inserted</param> | |
/// <param name="packet">The packet of bytes to be parsed.</param> | |
/// <param name="start">The index of where to start looking in the packet.</param> | |
/// <param name="length">The length of the packet.</param> | |
/// <returns>An index to the next byte in the packet after the padded string.</returns> | |
private static int InsertString(string s, byte[] packet, int start, int length) | |
{ | |
int index = start; | |
foreach (char c in s) | |
{ | |
packet[index++] = (byte)c; | |
if (index == length) | |
return index; | |
} | |
packet[index++] = 0; | |
int pad = (s.Length+1) % 4; | |
if (pad != 0) | |
{ | |
pad = 4 - pad; | |
while (pad-- > 0) | |
packet[index++] = 0; | |
} | |
return index; | |
} | |
/// <summary> | |
/// Takes a length and returns what it would be if padded to the nearest 4 bytes. | |
/// </summary> | |
/// <param name="rawSize">Original size</param> | |
/// <returns>padded size</returns> | |
private static int PadSize(int rawSize) | |
{ | |
int pad = rawSize % 4; | |
if (pad == 0) | |
return rawSize; | |
else | |
return rawSize + (4 - pad); | |
} | |
} | |
//} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Make sure you have UDPPacketIO.cs and Osc.cs in the standard assets folder | |
var RemoteIP : String = "127.0.0.1"; | |
var SendToPort : int = 57131; | |
var ListenerPort : int = 57130; | |
var controller : Transform; | |
var handler : Osc; | |
// Messages are accessible from this instance in other scripts | |
static var messages : Array = [0]; | |
public function Start () | |
{ | |
// Set up OSC connection | |
var udp : UDPPacketIO = GetComponent("UDPPacketIO"); | |
udp.init(RemoteIP, SendToPort, ListenerPort); | |
handler = GetComponent("Osc"); | |
handler.init(udp); | |
// Listen to the channels set in the Processing sketch | |
handler.SetAddressHandler("/sensorX", ListenEvent);//-----camera positionX | |
handler.SetAddressHandler("/sensorY", ListenEvent);//-----camera positionY | |
handler.SetAddressHandler("/sensorRY", ListenEvent);//-----camera rotateY | |
handler.SetAddressHandler("/sensorRX", ListenEvent);//-----camera rotateX | |
handler.SetAddressHandler("/sensorSp", ListenEvent);//-----movespeed | |
handler.SetAddressHandler("/sensorWL", ListenEvent);//-----waterlevel | |
handler.SetAddressHandler("/sensorBlink", ListenEvent);//-----blink | |
handler.SetAddressHandler("/sensorMe", ListenEvent);//-----float | |
handler.SetAddressHandler("/sensorSp2", ListenEvent);//-----movespeed | |
} | |
public function ListenEvent(oscMessage : OscMessage) : void | |
{ | |
switch(oscMessage.Address){ | |
case "/sensorX": i = 0; break; | |
case "/sensorY": i = 1; break; | |
case "/sensorRY": i = 2; break; | |
case "/sensorRX": i = 3; break; | |
case "/sensorSp": i = 4; break; | |
case "/sensorWL": i = 5; break; | |
case "/sensorBlink":i = 6; break; | |
case "/sensorMe": i = 7; break; | |
case "/sensorSp2": i = 8; break; | |
} | |
// Make the data available | |
messages[i] = oscMessage.Values[0]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma strict | |
var WLChannel : float; | |
function Update () { | |
var w = OscReceiver.messages[WLChannel]; | |
transform.position = Vector3(transform.position.x,w,transform.position.z); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment