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