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