/** * Fetches muse-io udp packets from port localhost:4545 and reads OSC paths: * /muse/elements/delta_relative * /muse/elements/theta_relative * /muse/elements/alpha_relative * /muse/elements/beta_relative * /muse/elements/gamma_relative * * Calculates mean delta, theta, alpha, beta and gamma values (and st.dev.) * from all channels and which /muse/elements/is_good value is >= 0.5. * If there are no good values at all, reports 0.5 value and maximum st.dev. * (of uniform distribution between [0,1]) * * Also measures: * /muse/elements/experimental/concentration * /muse/elements/experimental/mellow */ int main(int argc, char** argv) { const unsigned int port = 4545; std::cout << "MUSE TEST OSC (UDP PORT 4545) LISTENER" << std::endl; fflush(stdout); UdpSocket sock; sock.bindTo(port); if(!sock.isOk()) return -1; // failure [retry?] PacketReader pr; PacketWriter pw; std::vector<int> connectionQuality; bool hasConnection = false; float delta = 0.0f, theta = 0.0f, alpha = 0.0f, beta = 0.0f, gamma = 0.0f; while(sock.isOk()){ if(hasConnection){ float q = 0.0f; for(auto qi : connectionQuality) if(qi > 0) q++; q = q / connectionQuality.size(); // printf("EEQ: D:%.2f T:%.2f A:%.2f B:%.2f G:%.2f [QUALITY: %.2f]\n", delta, theta, alpha, beta, gamma, q); printf("EEQ POWER: %.2f [QUALITY %.2f]\n", log(exp(delta)+exp(theta)+exp(alpha)+exp(beta)+exp(gamma)), q); fflush(stdout); } if(sock.receiveNextPacket(30)){ pr.init(sock.packetData(), sock.packetSize()); Message* msg; while(pr.isOk() && ((msg = pr.popMessage()) != 0)){ Message::ArgReader r = msg->match("/muse/elements/is_good"); if(r.isOk() == true){ // matched // there are 4 ints telling connection quality std::vector<int> quality; while(r.nbArgRemaining()){ if(r.isInt32()){ int32_t i; r = r.popInt32(i); quality.push_back((int)i); } else{ r = r.pop(); } } if(quality.size() > 0){ connectionQuality = quality; } bool connection = false; for(auto q : quality) if(q > 0) connection = true; hasConnection = connection; } // gets relative frequency bands.. r = msg->match("/muse/elements/delta_absolute"); if(r.isOk()){ float f1, f2, f3, f4; if(r.popFloat(f1).popFloat(f2).popFloat(f3).popFloat(f4).isOkNoMoreArgs()){ std::vector<float> v; v.push_back(f1); v.push_back(f2); v.push_back(f3); v.push_back(f4); // calculates mean according to connection quality float mean = 0.0f; float samples = 0.0f; for(unsigned int i=0;i<connectionQuality.size() && i<v.size();i++){ if(connectionQuality[i] > 0){ mean += exp(v[i]); samples++; } } if(samples > 0.0f){ mean /= samples; mean = log(mean); } else mean = 0.5f; // mean value without data delta = mean; } } r = msg->match("/muse/elements/theta_absolute"); if(r.isOk()){ float f1, f2, f3, f4; if(r.popFloat(f1).popFloat(f2).popFloat(f3).popFloat(f4).isOkNoMoreArgs()){ std::vector<float> v; v.push_back(f1); v.push_back(f2); v.push_back(f3); v.push_back(f4); // calculates mean according to connection quality float mean = 0.0f; float samples = 0.0f; for(unsigned int i=0;i<connectionQuality.size() && i<v.size();i++){ if(connectionQuality[i] > 0){ mean += exp(v[i]); samples++; } } if(samples > 0.0f){ mean /= samples; mean = log(mean); } else mean = 0.5f; // mean value without data theta = mean; } } r = msg->match("/muse/elements/alpha_absolute"); if(r.isOk()){ float f1, f2, f3, f4; if(r.popFloat(f1).popFloat(f2).popFloat(f3).popFloat(f4).isOkNoMoreArgs()){ std::vector<float> v; v.push_back(f1); v.push_back(f2); v.push_back(f3); v.push_back(f4); // calculates mean according to connection quality float mean = 0.0f; float samples = 0.0f; for(unsigned int i=0;i<connectionQuality.size() && i<v.size();i++){ if(connectionQuality[i] > 0){ mean += exp(v[i]); samples++; } } if(samples > 0.0f){ mean /= samples; mean = log(mean); } else mean = 0.5f; // mean value without data alpha = mean; } } r = msg->match("/muse/elements/beta_absolute"); if(r.isOk()){ float f1, f2, f3, f4; if(r.popFloat(f1).popFloat(f2).popFloat(f3).popFloat(f4).isOkNoMoreArgs()){ std::vector<float> v; v.push_back(f1); v.push_back(f2); v.push_back(f3); v.push_back(f4); // calculates mean according to connection quality float mean = 0.0f; float samples = 0.0f; for(unsigned int i=0;i<connectionQuality.size() && i<v.size();i++){ if(connectionQuality[i] > 0){ mean += exp(v[i]); samples++; } } if(samples > 0.0f){ mean /= samples; mean = log(mean); } else mean = 0.5f; // mean value without data beta = mean; } } r = msg->match("/muse/elements/gamma_absolute"); if(r.isOk()){ float f1, f2, f3, f4; if(r.popFloat(f1).popFloat(f2).popFloat(f3).popFloat(f4).isOkNoMoreArgs()){ std::vector<float> v; v.push_back(f1); v.push_back(f2); v.push_back(f3); v.push_back(f4); // calculates mean according to connection quality float mean = 0.0f; float samples = 0.0f; for(unsigned int i=0;i<connectionQuality.size() && i<v.size();i++){ if(connectionQuality[i] > 0){ mean += exp(v[i]); samples++; } } if(samples > 0.0f){ mean /= samples; mean = log(mean); } else mean = 0.5f; // mean value without data gamma = mean; } } } } } return 0; }
void CBodyBasics::ParseOSC() { // UDP stuff PacketReader pr; PacketWriter pw; if (recvsock.isOk() && recvsock.receiveNextPacket(1 /* timeout, in ms */)) { pr.init(recvsock.packetData(), recvsock.packetSize()); oscpkt::Message *msg; while (pr.isOk() && (msg = pr.popMessage()) != 0) { // parse IP address std::string c = recvsock.packetOrigin().asString(); std::string delim = ":"; size_t pos = 0; std::string token; while ((pos = c.find(delim)) != std::string::npos) { token = c.substr(0, pos); c = token; } std::string s = "Server: received message from " + c + "\n"; printFucker(s); // // parse messages // // CONNECT if (msg->match("/connect").isOkNoMoreArgs()) { // find empty client - check existing list int foundmatch = 0; for (int i = 0; i < clients.size(); i++) { if (clients[i].address == c) // already in list { printFucker("RECONNECTING TO HOST " + c + ":\n"); clients[i].active = 1; foundmatch = 1; break; } } if (foundmatch == 0) // add new client to first free slot { for (int i = 0; i < clients.size(); i++) { if (clients[i].active == false) // add here { printFucker("ADDING CONNECTION TO HOST " + c + ":\n"); clients[i].address = c; clients[i].active = true; clients[i].socket.connectTo(c, SENDPORT); foundmatch = 1; break; } } } if (foundmatch == 0) // out of slots { std::string s = "Out of slots!!!\n"; printFucker(s); } } // DISCONNECT else if (msg->match("/disconnect").isOkNoMoreArgs()) { for (int i = 0; i < clients.size(); i++) { if (clients[i].address == c) // shut it off { printFucker("DISCONNECTING FROM HOST " + c + ":\n"); clients[i].active = false; break; } } } // ADDQUERY else if (msg->match("/addQuery")){ Message::ArgReader arg(msg->arg()); // reader for arguments KinectQuery kq; // new query obect if (arg.isStr()) // first value should be string { std::string firstString; arg.popStr(firstString); // figure out query type if (firstString == "joint") kq.type = 0; else if (firstString == "trigger") kq.type = 1; else if (firstString == "toggle") kq.type = 2; else if (firstString == "controller") kq.type = 3; else if (firstString == "motion") kq.type = 4; printFucker("query type: " + std::to_string(kq.type) + "\n"); } // parse remaining args based on type // joint if (kq.type == 0) // we want either: // string... stringn int string (enumerated joints) // or // int string (all joints) { // check first arg: if (arg.isInt32()) { // first arg is int: omni mode kq.omni = 1; // omni: send all joints each frame int p; arg.popInt32(p); kq.mode = p; // 0 (world) or 1 (body) orientation for output // check second arg if (arg.isStr()) { // in omni mode, next arg should be a string std::string p; arg.popStr(p); kq.message = p; // message for OSC argument with joint data inside kq.valid = 1; // valid query } } else if (arg.isStr()) { // first arg is string: individual joints kq.omni = 0; std::string p; arg.popStr(p); if (j2i.count(p) == 1) kq.joints.push_back(j2i[p]); // first joint to use while (arg.nbArgRemaining()) { // iterate until int if (arg.isStr()) { std::string f; arg.popStr(f); // another joint if(j2i.count(f)==1) kq.joints.push_back(j2i[f]); } else { break; // get outta here } } // check next-to-last arg: if (arg.isInt32()) { // first arg is int: omni mode int f; arg.popInt32(f); kq.mode = f; // 0 (world) or 1 (body) orientation for output // check last arg if (arg.isStr()) { // in omni mode, next arg should be a string std::string f; arg.popStr(f); kq.message = f; // message for OSC argument with joint data inside kq.valid = 1; // valid query } } } if (kq.valid == 1) { // DEBUG printFucker("ADDING JOINT QUERY for host " + c + ":\n"); printFucker("OMNI: " + std::to_string(kq.omni) + " "); if (kq.omni == 0) { printFucker("JOINTS: "); for (int j = 0; j < kq.joints.size(); j++) { printFucker(std::to_string(kq.joints[j]) + " "); } } printFucker("MODE: " + std::to_string(kq.mode) + " "); printFucker("MESSAGE: " + kq.message + "\n"); // PUSH ONTO STACK for (int i = 0; i < clients.size(); i++) { if (clients[i].address == c && clients[i].active == true) // add here { // avoid duplicate queries by message int ismatched = -1; for (int j = 0; j < clients[i].query.size(); j++) { if (clients[i].query[j].message == kq.message) // match { ismatched = j; break; } } if (ismatched == -1) // new message { clients[i].query.push_back(kq); printFucker("ADDED QUERY SLOT: " + std::to_string(clients[i].query.size() - 1)); break; } else // replace old message in queue with same query name { clients[i].query[ismatched] = kq; printFucker("REPLACED QUERY SLOT: " + std::to_string(ismatched)); break; } } } } } } else { std::string s = "Server: unhandled message! \n"; printFucker(s); } } } }