annotate src/melodyTriangle.cpp @ 38:330f2746fedd tip

Added keys help in a smaller font; changed loadness keyboard controls.
author samer
date Mon, 27 Feb 2012 20:09:10 +0000
parents 260cc4f4d70a
children
rev   line source
hekeus@6 1 #include "melodyTriangle.h"
hekeus@6 2 #include <GLUT/GLUT.h>
hekeus@6 3
samer@23 4 #define BUFFER_ZONE 64 // have to drag this far to snap out of triange.
samer@32 5 #define NUM_TEMPI 9
samer@38 6 #define NUMEL(a) sizeof(a)/sizeof(a[0])
samer@22 7
samer@32 8 static int tempi[]={20,30,45,60,90,120,150,180,240};
samer@32 9
samer@37 10 static ofxOscBundle& operator<<(ofxOscBundle &bundle, ofxOscMessage msg) {
samer@37 11 bundle.addMessage(msg); return bundle;
samer@37 12 }
samer@37 13
samer@37 14 static ofxOscSender& operator<<(ofxOscSender &sender, ofxOscMessage msg) {
samer@37 15 sender.sendMessage(msg);
samer@37 16 return sender;
samer@37 17 }
samer@37 18
samer@37 19 static ofxOscSender& operator<<(ofxOscSender &sender, ofxOscBundle bundle) {
samer@37 20 sender.sendBundle(bundle);
samer@37 21 return sender;
samer@37 22 }
samer@37 23
samer@25 24
samer@22 25 melodyTriangle::melodyTriangle(const char *host, int port, int numVoices,
samer@22 26 bool enableKeys,int voiceIdOffset,int receivePort):
samer@31 27 numVoices(numVoices), receivePort(receivePort), snapTruePos(enableKeys),
samer@37 28 enableKeys(enableKeys), randInit(false),allowExit(true), ratio(2), tempoIndex(4),
samer@38 29 display_msg(""), display_frames(0), display_font(NULL)
samer@22 30 {
samer@22 31 for (int i=0;i<numVoices;i++) voices[i]=new Voice(i+1+voiceIdOffset);
samer@22 32
hekeus@6 33 sender.setup( host,port );
hekeus@8 34 receiver.setup( receivePort );
samer@38 35 main_font.loadFont("/System/Library/Fonts/LucidaGrande.ttc",24);
samer@38 36 help_font.loadFont("/System/Library/Fonts/Menlo.ttc",16);
samer@38 37 //help_font.loadFont("/System/Library/Fonts/Courier.dfont",16);
hekeus@6 38 }
hekeus@6 39
samer@22 40 melodyTriangle::~melodyTriangle() {
samer@22 41 printf("Deleting voice objects...\n");
samer@22 42 for (int i=0;i<numVoices;i++) delete voices[i];
samer@22 43 }
samer@22 44
hekeus@6 45 //--------------------------------------------------------------
hekeus@6 46 void melodyTriangle::setup(){
samer@22 47 ofSetCircleResolution(64);
hekeus@6 48 ofBackground(0,0,0);
hekeus@6 49 ofSetWindowTitle("Melody Triangle");
samer@23 50 ofSetFrameRate(40); // caps framerate if vertical sync is off.
samer@18 51 ofEnableSmoothing();
samer@18 52
samer@18 53 // Set up triange coordinates.
samer@18 54 // NB. whatever happens here, the triangle must be
samer@18 55 // isosceles and left-right symmetric around x=x1.
samer@18 56 // Otherwise the clipping won't work
samer@22 57 fitTriangleIn(ofGetWidth(),ofGetHeight());
samer@37 58
samer@37 59 ofxOscBundle bundle;
samer@37 60 sender << ( bundle
samer@37 61 << msg("/tempo",tempi[tempoIndex])
samer@37 62 << msgCalibrate()
samer@37 63 << msgReplyTo());
hekeus@6 64
samer@25 65 voiceGrabbed=NULL;
samer@12 66 }
samer@12 67
hekeus@6 68 //--------------------------------------------------------------
hekeus@6 69 void melodyTriangle::update(){
samer@22 70 bool sendStart=false;
samer@22 71
samer@22 72 while( receiver.hasWaitingMessages() ) {
hekeus@8 73 // get the next message
hekeus@8 74 ofxOscMessage m;
hekeus@8 75 receiver.getNextMessage( &m );
samer@22 76 handleMessage(m);
hekeus@8 77 }
samer@15 78
samer@22 79 constrained=false;
samer@25 80 if (voiceGrabbed!=NULL){
samer@25 81 Voice *vg=voiceGrabbed;
samer@14 82 if (mouseX!=vg->posx || mouseY!=vg->posy){
samer@15 83 int clipx=mouseX, clipy=mouseY;
samer@15 84 bool clipped=clipToTriangle(&clipx,&clipy);
samer@37 85 ofxOscBundle bundle;
samer@15 86
samer@15 87 if (vg->inTriangle) {
hekeus@6 88
samer@15 89 if (clipped) {
samer@15 90 // check how far we clipped
samer@30 91 if (ofDist(clipx, clipy, mouseX, mouseY)>BUFFER_ZONE && allowExit) {
samer@15 92 // if far enough, we pop out of triangle and send
samer@37 93 bundle << msg("/death",vg->id);
samer@37 94 sender << bundle;
samer@15 95 vg->posx=mouseX;
samer@15 96 vg->posy=mouseY;
samer@15 97 vg->inTriangle=false;
samer@23 98 vg->status=Voice::pending;
samer@15 99 } else {
samer@15 100 // otherwise, we move to clipped point
samer@15 101 constrained=true;
samer@15 102 vg->posx=clipx;
samer@15 103 vg->posy=clipy;
samer@15 104 }
samer@15 105 } else { // not clipped; normal move
samer@15 106 vg->posx=mouseX;
samer@15 107 vg->posy=mouseY;
samer@15 108 }
samer@15 109 } else { // token was outside triangle
samer@15 110 vg->posx=mouseX;
samer@15 111 vg->posy=mouseY;
samer@15 112 if (!clipped){ // ie mouse now in triangle
samer@37 113 bundle << msg("/birth",vg->id)
samer@37 114 << msgAmplitude(vg->id,vg->amplitude)
samer@37 115 << ( randInit
samer@37 116 ? msg("/randinit",vg->id)
samer@37 117 : msgOctave(vg->id,vg->octave)
samer@37 118 );
samer@15 119 sendStart=true;
samer@15 120 vg->inTriangle=true;
samer@25 121 vg->truex=vg->truey=-1; // ie not known yet.
hekeus@6 122 }
hekeus@6 123 }
hekeus@6 124
samer@14 125 if (vg->inTriangle){
samer@37 126 bundle << msgPosition(vg);
samer@18 127 vg->status=Voice::moved;
samer@37 128 if (sendStart && vg->isActive) bundle << msg("/start",vg->id);
samer@37 129 sender << bundle;
hekeus@6 130 }
hekeus@6 131 }
hekeus@6 132 };
samer@22 133 }
samer@10 134
samer@22 135
samer@22 136
samer@22 137 //--------------------------------------------------------------
samer@22 138 void melodyTriangle::draw(){
samer@11 139 ofSetLineWidth(2);
samer@23 140 ofSetColor(60,60,60);
samer@10 141 ofFill();
samer@10 142 ofTriangle(x1, y1, x2, y2, x3, y3);
samer@10 143
samer@10 144 // draw smooth edge, brighter if a token is constrained
samer@23 145 if (constrained) ofSetColor(255,96,96);
samer@10 146 ofNoFill();
samer@10 147 ofTriangle(x1, y1, x2, y2, x3, y3);
samer@10 148
samer@25 149 for (int i=numVoices-1; i>=0; i--){
samer@32 150 voices[i]->draw(enableKeys && voices[i]->isInVoice(mouseX,mouseY));
hekeus@6 151 }
hekeus@6 152
samer@22 153 // display message if any
samer@23 154 if (display_frames!=0) {
samer@38 155 ofRectangle bbox=display_font->getStringBoundingBox(display_msg,0,0);
samer@22 156 ofSetColor(220,220,220);
samer@38 157 display_font->drawString(display_msg,
samer@23 158 (ofGetWidth()-bbox.width)/2, (ofGetHeight()-bbox.height)/2);
samer@23 159 if (display_frames>0) display_frames--;
samer@22 160 }
samer@25 161 if (ratio!=2) {
samer@25 162 ofSetColor(160,160,160);
samer@38 163 display_font->drawString(ofToString(ratio),16,ofGetHeight()-16);
samer@25 164 }
hekeus@6 165 }
hekeus@6 166
samer@22 167 bool melodyTriangle::clipToTriangle(int *x, int *y) {
samer@22 168 bool clipped;
samer@22 169
samer@22 170 if (*y>y2) { // off the bottom
samer@22 171 clipped=true;
samer@22 172 *y=y2;
samer@22 173 if (*x<x2) *x=x2;
samer@22 174 else if (*x>x3) *x=x3;
samer@22 175 } else { // have to be a bit cleverer
samer@22 176 bool reflect=false;
samer@22 177 if (*x<x1) { // work in reflected coordinates
samer@22 178 reflect=true;
samer@22 179 *x=2*x1-*x;
samer@22 180 }
samer@22 181
samer@22 182 int dx=(*x-x1), dy=(*y-y1); // deltas from top
samer@22 183 if (dx*DY13 > dy*DX13) {
samer@22 184 // (x,y) must be somewhere right of triangle now
samer@22 185 clipped=true;
samer@22 186 int dp=dx*DX13 + dy*DY13;
samer@22 187 if (dp<0) { *x=x1; *y=y1; } // off the top
samer@22 188 else if (dp>SQLEN13) { *x=x3; *y=y3; } // off the bottom right
samer@22 189 else { // project onto right edge
samer@22 190 *x=x1+dp*DX13/SQLEN13;
samer@22 191 *y=y1+dp*DY13/SQLEN13;
samer@22 192 }
samer@22 193 } else {
samer@22 194 clipped=false;
samer@22 195 }
samer@22 196
samer@22 197 if (reflect) *x=2*x1 - *x; // reflect back if necessary
samer@22 198 }
samer@22 199 return clipped;
samer@22 200 }
samer@22 201
samer@22 202
samer@22 203
samer@22 204 //- Keyboard ----------------------------------------------------------
samer@22 205
samer@25 206 void melodyTriangle::keyReleased(int key){
samer@25 207 if (enableKeys && key>='2' && key<='9') {
samer@25 208 ratio=2;
samer@25 209 }
samer@25 210 }
samer@38 211
samer@38 212 struct command {
samer@38 213 const char *key;
samer@38 214 const char *desc;
samer@38 215 };
samer@38 216
samer@38 217 struct command voice_commands[] = {
samer@38 218 // { "←", "fractional delay" },
samer@38 219 // { "→", "fractional advance" },
samer@38 220 // { "↑", "multiply note rate" },
samer@38 221 // { "↓", "divide note rate" },
samer@38 222 { "[right]", "fractional delay" },
samer@38 223 { "[left]", "fractional advance" },
samer@38 224 { "[up]", "multiply note rate" },
samer@38 225 { "[down]", "divide note rate" },
samer@38 226 { "[", "transpose octave down" },
samer@38 227 { "]", "transpose octave up" },
samer@38 228 { "{", "quieter" },
samer@38 229 { "}", "louder" },
samer@38 230 { "c", "change to nearby pattern" },
samer@38 231 { "s", "shuffle notes" },
samer@38 232 { "h", "this help screen" },
samer@38 233 { "H", "global keys help screen" },
samer@38 234 };
samer@38 235
samer@38 236 struct command global_commands[] = {
samer@38 237 { "<", "reduce tempo" },
samer@38 238 { ">", "increase tempo" },
samer@38 239 { "I", "toggle randomise on birth" },
samer@38 240 { "S", "save current pattern" },
samer@38 241 { "C", "calibrate triangle" },
samer@38 242 { "F", "toggle full screen" },
samer@38 243 { "R", "reset token positions" },
samer@38 244 { "Q", "quit" },
samer@38 245 { "H", "this help screen" },
samer@38 246 { "h", "token keys help screen" }
samer@38 247 };
samer@38 248
samer@23 249 void melodyTriangle::keyPressed(int key){
hekeus@6 250 if (enableKeys){
samer@25 251 if (key>='2' && key<='9') {
samer@25 252 ratio=key-'0';
samer@25 253 } else {
samer@25 254 printf("got key: %d.\n",key);
samer@25 255 switch (key) {
samer@25 256
samer@38 257 case '<':
samer@25 258 if (tempoIndex>0) tempoIndex--;
samer@37 259 sender << msg("/tempo",tempi[tempoIndex]);
samer@25 260 break;
samer@38 261 case '>':
samer@32 262 if (tempoIndex<NUM_TEMPI-1) tempoIndex++;
samer@37 263 sender << msg("/tempo",tempi[tempoIndex]);
samer@25 264 break;
samer@25 265
samer@37 266 case ' ': sender << msg("/marker"); break;
samer@37 267 case 'S': sender << msg("/save"); break;
samer@37 268 case 'r': sender << msg("/report"); break;
samer@38 269 case 'I':
samer@37 270 randInit ^= true;
samer@37 271 display_msg = (randInit?"randomise on birth":"no randomise on birth");
samer@38 272 display_font = &main_font;
samer@37 273 display_frames = 40;
samer@37 274 break;
samer@37 275 case 'C': {
samer@37 276 ofxOscBundle bundle;
samer@37 277 sender << (bundle << msgReplyTo() << msgCalibrate());
samer@37 278 break;
samer@37 279 }
samer@25 280 case 'F': ofToggleFullscreen(); break;
samer@25 281 case 'R': reset(); break;
samer@25 282 case 'Q': ofAppGlutWindow::exitApp();
samer@38 283 case '/': display_frames=0; break;
samer@38 284 case 'h':
samer@38 285 case 'H':
samer@38 286 case '?':
samer@38 287 display_frames = -1;
samer@38 288 display_msg = help_string(key!='h');
samer@38 289 display_font = &help_font;
samer@38 290 break;
samer@38 291
samer@30 292 case OF_KEY_ESC: setKeyboardEnable(false); break;
samer@25 293
samer@25 294 default: // otherwise, send key to all voices under mouse
samer@25 295 for (int i=0; i<numVoices; i++)
samer@25 296 if (voices[i]->isInVoice(mouseX,mouseY))
samer@25 297 voiceKeypress(voices[i],key);
samer@12 298 }
hekeus@6 299 }
samer@30 300 } else {
samer@30 301 if (key==OF_KEY_ESC) setKeyboardEnable(true);
samer@37 302 else sender << msg("/key",key);
samer@30 303 }
samer@23 304 }
samer@23 305
samer@23 306 void melodyTriangle::voiceKeypress(Voice *v, int key) {
samer@23 307 switch (key) {
samer@25 308 case 'a':
samer@32 309 if (v->inTriangle) {
samer@37 310 sender << msg(v->isActive ? "/stop" : "/start", v->id);
samer@32 311 }
samer@23 312 v->isActive=!v->isActive;
samer@23 313 break;
samer@37 314 case OF_KEY_LEFT: sender << msgShift(v->id,-1,ratio); break;
samer@37 315 case OF_KEY_RIGHT: sender << msgShift(v->id,1,ratio); break;
samer@37 316 case OF_KEY_UP: sender << msgPeriod(v->id,1,ratio); break;
samer@37 317 case OF_KEY_DOWN: sender << msgPeriod(v->id,ratio,1); break;
samer@37 318 case ']': sender << msgOctave(v->id, ++v->octave); break;
samer@37 319 case '[': sender << msgOctave(v->id, --v->octave); break;
samer@38 320 case '}': sender << msgAmplitude(v->id, v->louder()); break;
samer@38 321 case '{': sender << msgAmplitude(v->id, v->quieter()); break;
samer@37 322 case 'c': sender << msg("/change",v->id); v->status=Voice::pending; break;
samer@38 323 case 's': sender << msg("/shuffle",v->id); break;
samer@23 324 default: printf("unrecognised key: %d.\n",key);
hekeus@6 325 }
hekeus@6 326 }
hekeus@6 327
samer@38 328 inline int max(int x, int y) { return y>x ? y : x; }
samer@38 329
samer@38 330 string melodyTriangle::help_string(bool global) {
samer@38 331 stringstream buf;
samer@38 332 struct command *cmds;
samer@38 333 int n, maxw=0;
samer@38 334
samer@38 335 buf << " ( " << (global ? "GLOBAL" : "TOKEN") << " KEYBOARD CONTROLS ) \n\n";
samer@38 336 if (global) { cmds=global_commands; n=NUMEL(global_commands); }
samer@38 337 else { cmds=voice_commands; n=NUMEL(voice_commands); }
samer@38 338
samer@38 339 for (int i=0; i<n; i++) maxw=max(maxw,strlen(cmds[i].key));
samer@38 340 for (int i=0; i<n; i++) buf << setw(maxw) << cmds[i].key << " - " << cmds[i].desc << "\n";
samer@38 341
samer@38 342 buf << "\nPress '/' to dismiss.";
samer@38 343 return buf.str();
samer@38 344 }
samer@38 345
samer@38 346
samer@22 347 //- Mouse ------------------------------------------------------
hekeus@6 348
samer@22 349 void melodyTriangle::mouseDragged(int x, int y, int button){}
samer@23 350 void melodyTriangle::mouseMoved(int x, int y ){}
samer@23 351 void melodyTriangle::mousePressed(int x, int y, int button){
samer@25 352 // pick up first token under mouse
hekeus@6 353 for (int i=0; i<numVoices;i++){
samer@25 354 if (voices[i]->isInVoice(x,y)) {
samer@25 355 voiceGrabbed=voices[i];
samer@25 356 break;
samer@25 357 }
hekeus@6 358 }
hekeus@6 359 }
hekeus@6 360
samer@22 361 void melodyTriangle::mouseReleased(int x, int y, int button){
samer@25 362 if (voiceGrabbed!=NULL) {
samer@25 363 Voice *v=voiceGrabbed;
samer@31 364 if (v->status==Voice::clear && v->truex>=0) {
samer@25 365 v->posx=v->truex;
samer@25 366 v->posy=v->truey;
samer@25 367 v->truex=v->truey=-1;
samer@25 368 }
samer@25 369 voiceGrabbed=NULL;
samer@25 370 }
hekeus@6 371 }
hekeus@6 372
hekeus@6 373 //--------------------------------------------------------------
samer@22 374
hekeus@6 375 void melodyTriangle::windowResized(int w, int h){
samer@22 376 fitTriangleIn(w,h);
samer@37 377 sender << msgCalibrate();
samer@23 378 reset();
samer@22 379 }
hekeus@6 380
samer@23 381 void melodyTriangle::reset() {
samer@25 382 voiceGrabbed=NULL;
samer@23 383 for (int i=0;i<numVoices;i++) {
samer@23 384 Voice *v=voices[i];
samer@23 385 v->posx=x2+RADIUS+(numVoices-1-i)*36;
samer@23 386 v->posy=48;
samer@23 387 v->status=Voice::pending;
samer@25 388 v->isActive=true;
samer@23 389 if (v->inTriangle) {
samer@37 390 sender << msg("/death",v->id);
samer@23 391 v->inTriangle=false;
samer@23 392 }
samer@23 393 }
samer@23 394 }
samer@22 395
samer@22 396 // OSC Message handling -----------------------------------------
samer@22 397
samer@23 398 Voice *melodyTriangle::get_voice(int id) throw(bad_voice_id) {
samer@30 399 for (int i=0; i<numVoices; i++) {
samer@30 400 if (voices[i]->id==id) return voices[i];
samer@30 401 }
samer@30 402 throw bad_voice_id(id);
samer@23 403 }
samer@23 404
samer@22 405 void melodyTriangle::handleMessage(ofxOscMessage &m) {
samer@22 406 string msg_path=m.getAddress();
samer@23 407
samer@23 408 try {
samer@23 409 if (msg_path.compare(0,8,"/notify/")==0) {
samer@25 410 string msg=msg_path.substr(8);
samer@23 411 Voice *v=get_voice(m.getArgAsInt32(0));
samer@25 412
samer@32 413 cout << "Received " << msg_path << "\n";
samer@25 414 if (msg=="requested") v->status=Voice::waiting;
samer@25 415 else if (msg=="pending") v->status=Voice::pending;
samer@25 416 else if (msg=="received") {
samer@25 417 float x=m.getArgAsFloat(1);
samer@25 418 float y=m.getArgAsFloat(2);
samer@25 419 v->status=Voice::clear;
samer@31 420 if (snapTruePos) {
samer@31 421 if (voiceGrabbed==v) {
samer@31 422 v->truex=x;
samer@31 423 v->truey=y;
samer@31 424 } else {
samer@31 425 v->posx=x;
samer@31 426 v->posy=y;
samer@31 427 v->truex=v->truey=-1;
samer@31 428 }
samer@25 429 }
samer@31 430 printf("True position of %d: %4.1f, %4.1f\n",v->id,x,y);
samer@25 431 } else if (msg=="position") {
samer@23 432 int x=(int)m.getArgAsFloat(1);
samer@23 433 int y=(int)m.getArgAsFloat(2);
samer@23 434 v->posx=x;
samer@23 435 v->posy=y;
samer@23 436 v->inTriangle=!clipToTriangle(&x,&y);
samer@31 437 v->status=Voice::clear;
samer@25 438 if (voiceGrabbed==v) voiceGrabbed=NULL;
samer@25 439 } else if (msg=="running") {
samer@23 440 v->isActive = m.getArgAsInt32(1) ? true : false;
samer@25 441 } else if (msg=="params") {
samer@23 442 v->octave = m.getArgAsInt32(1);
samer@23 443 v->amplitude = m.getArgAsFloat(2);
samer@32 444 } else if (msg=="visible") {
samer@32 445 v->isVisible = m.getArgAsInt32(1);
samer@32 446 if (voiceGrabbed==v && !v->isVisible)
samer@32 447 voiceGrabbed=NULL;
samer@23 448 }
samer@23 449 } else if (msg_path=="/display") {
samer@23 450 display_msg=m.getArgAsString(0);
samer@23 451 display_frames=m.getArgAsInt32(1);
samer@38 452 display_font=&main_font;
samer@23 453 } else if (msg_path=="/font") {
samer@38 454 main_font.loadFont(m.getArgAsString(0),m.getArgAsInt32(1));
samer@30 455 } else if (msg_path=="/keyboard") { setKeyboardEnable(m.getArgAsInt32(0)); }
samer@23 456 else if (msg_path=="/reset") { reset(); }
samer@23 457 else if (msg_path=="/fullscreen") { ofSetFullscreen(m.getArgAsInt32(0)); }
samer@23 458 else if (msg_path=="/quit") { ofAppGlutWindow::exitApp(); }
samer@30 459 else if (msg_path=="/allowExit") { allowExit=m.getArgAsInt32(0); }
samer@23 460 else {
samer@23 461 cout << m.getAddress();
samer@23 462 for (int i=0; i<m.getNumArgs(); i++) {
samer@23 463 cout << " " << m.getArgTypeName(i) << ":";
samer@23 464 switch (m.getArgType(i)) {
samer@23 465 case OFXOSC_TYPE_INT32: cout << m.getArgAsInt32(i);
samer@23 466 case OFXOSC_TYPE_FLOAT: cout << m.getArgAsFloat(i);
samer@23 467 case OFXOSC_TYPE_STRING: cout << m.getArgAsString(i);
samer@23 468 default: cout << "unknown";
samer@23 469 }
samer@23 470 }
samer@23 471 cout<< "\n";
samer@22 472 }
samer@23 473 } catch (std::exception &ex) {
samer@23 474 cout << "** Error processing OSC message: " << ex.what() << "\n";
samer@22 475 }
hekeus@6 476 }
samer@22 477
samer@30 478 void melodyTriangle::setKeyboardEnable(bool en) {
samer@30 479 enableKeys=en;
samer@31 480 snapTruePos=en;
samer@30 481 display_msg=en ? "Keyboard enabled" : "Keybard disabled";
samer@30 482 display_frames=40;
samer@38 483 display_font=&main_font;
samer@30 484 }
samer@30 485
samer@22 486 // OSC Message sending -----------------------------------------
samer@22 487
samer@37 488 ofxOscMessage melodyTriangle::msgPosition(Voice *v){
samer@22 489
samer@22 490 ofxOscMessage m;
samer@22 491 ///track id x y left right top bottom area
samer@22 492 m.setAddress( "/track2d" );
samer@23 493 m.addIntArg( v->id );
samer@23 494 m.addIntArg( v->posx );
samer@23 495 m.addIntArg( v->posy );
samer@37 496 // printf("/track2d %i %i %i\n",v->id,v->posx,v->posy);
samer@37 497 return m;
samer@22 498 }
samer@37 499
samer@37 500 ofxOscMessage melodyTriangle::msgCalibrate(){
samer@22 501 ofxOscMessage m;
samer@22 502 m.setAddress( "/calibrate" );
samer@22 503 m.addIntArg( x1 );
samer@22 504 m.addIntArg( y1 );
samer@22 505 m.addIntArg( x2 );
samer@22 506 m.addIntArg( y2 );
samer@22 507 m.addIntArg( x3 );
samer@22 508 m.addIntArg( y3 );
samer@37 509 printf("/calibrate %i %i %i %i %i %i\n",x1,y1,x2,y2,x3,y3);
samer@37 510 return m;
samer@22 511 }
samer@22 512
samer@37 513 ofxOscMessage melodyTriangle::msgReplyTo(){
samer@22 514 ofxOscMessage m;
samer@22 515 m.setAddress( "/reply_to" );
samer@22 516 m.addIntArg( receivePort );
samer@22 517 printf("sent /reply_to %i\n",receivePort);
samer@37 518 return m;
samer@22 519 }
samer@22 520
samer@37 521 ofxOscMessage melodyTriangle::msgPeriod(int id, int num, int den) { return msg("/period",id,num,den); }
samer@37 522 ofxOscMessage melodyTriangle::msgShift(int id, int num, int den) { return msg("/shift",id,num,den); }
samer@37 523 ofxOscMessage melodyTriangle::msgOctave(int id, int oct) { return msg("/octave",id,oct); }
samer@22 524
samer@37 525 ofxOscMessage melodyTriangle::msgAmplitude(int id, float amp){
samer@22 526 ofxOscMessage m;
samer@22 527 m.setAddress("/amplitude");
samer@22 528 m.addIntArg(id);
samer@22 529 m.addFloatArg(amp);
samer@37 530 printf("/amplitude %i %1.3f\n",id,amp);
samer@37 531 return m;
samer@22 532 }
samer@22 533
samer@37 534 ofxOscMessage melodyTriangle::msg(const char *addr, int a, int b, int c) {
samer@32 535 ofxOscMessage m;
samer@32 536 m.setAddress(addr);
samer@32 537 m.addIntArg(a);
samer@32 538 m.addIntArg(b);
samer@32 539 m.addIntArg(c);
samer@37 540 printf("%s %i %i %i\n",addr,a,b,c);
samer@37 541 return m;
samer@32 542 }
samer@32 543
samer@37 544 ofxOscMessage melodyTriangle::msg(const char *addr, int a, int b) {
samer@32 545 ofxOscMessage m;
samer@32 546 m.setAddress(addr);
samer@32 547 m.addIntArg(a);
samer@32 548 m.addIntArg(b);
samer@37 549 printf("%s %i %i\n",addr,a,b);
samer@37 550 return m;
samer@32 551 }
samer@32 552
samer@37 553 ofxOscMessage melodyTriangle::msg(const char *addr, int a) {
samer@25 554 ofxOscMessage m;
samer@25 555 m.setAddress(addr);
samer@25 556 m.addIntArg(a);
samer@37 557 printf("%s %i\n",addr,a);
samer@37 558 return m;
samer@25 559 }
samer@25 560
samer@37 561 ofxOscMessage melodyTriangle::msg(const char *addr) {
samer@25 562 ofxOscMessage m;
samer@25 563 m.setAddress(addr);
samer@37 564 printf("%s\n",addr);
samer@37 565 return m;
samer@25 566 }
samer@22 567
samer@22 568 void melodyTriangle::fitTriangleIn(int width, int height) {
samer@22 569 int triHeight = height*0.75;
samer@22 570 int triHalfWidth = triHeight/sqrt(3);
samer@22 571
samer@22 572 x1=width/2;
samer@22 573 x2=x1-triHalfWidth;
samer@22 574 x3=x1+triHalfWidth;
samer@22 575 y1=(height-triHeight)/2;
samer@22 576 y2=y3=height - (height-triHeight)/2;
samer@22 577
samer@22 578 // used for clipping
samer@22 579 DX13=x3-x1; DY13=y3-y1;
samer@22 580 SQLEN13=DX13*DX13+DY13*DY13;
samer@22 581 }
samer@23 582
samer@23 583 const char *melodyTriangle::bad_voice_id::what() const throw() {
samer@23 584 std::stringstream out;
samer@23 585 printf("bad_voice_id(%d).\n",id);
samer@30 586 out << "Voice id " << id <<" not present.";
samer@23 587 return out.str().c_str();
samer@23 588 }