andrewm@0
|
1 /*
|
andrewm@0
|
2 * sensors.cpp
|
andrewm@0
|
3 *
|
andrewm@0
|
4 * Created on: May 28, 2014
|
andrewm@0
|
5 * Author: Victor Zappi
|
andrewm@0
|
6 */
|
andrewm@0
|
7
|
andrewm@0
|
8 #include <stdio.h>
|
andrewm@0
|
9 #include <pthread.h>
|
andrewm@0
|
10 #include <unistd.h>
|
andrewm@0
|
11 #include <math.h>
|
andrewm@0
|
12 #include <vector>
|
andrewm@0
|
13 #include "prio.h"
|
andrewm@0
|
14 #include "sensors.h"
|
andrewm@0
|
15 #include "OscillatorBank.h"
|
andrewm@0
|
16 #include "DboxSensors.h"
|
andrewm@0
|
17
|
andrewm@0
|
18
|
andrewm@0
|
19 //----------------------------------------
|
andrewm@0
|
20 // main extern variables
|
andrewm@0
|
21 //----------------------------------------
|
andrewm@0
|
22 extern vector<OscillatorBank*> gOscBanks;
|
andrewm@0
|
23 extern int gCurrentOscBank;
|
andrewm@0
|
24 extern int gNextOscBank;
|
andrewm@0
|
25 extern bool gShouldStop;
|
andrewm@0
|
26 extern int gVerbose;
|
andrewm@0
|
27
|
andrewm@0
|
28 float gSensor0LatestTouchPos = 0; // most recent pitch touch location [0-1] on sensor 0, used by render.cpp
|
andrewm@0
|
29 int gSensor0LatestTouchNum = 0; // most recent num of touches on sensor 0, used by render.cpp
|
andrewm@0
|
30 float gSensor1LatestTouchPos[5]; // most recent touche locations on sensor 1, used by render.cpp
|
andrewm@0
|
31 //float gSensor1LatestTouchSizes[5];
|
andrewm@0
|
32 int gSensor1LatestTouchCount; // most recent number touches on sensor 1, used by render.cpp
|
andrewm@0
|
33 int gSensor1LatestTouchIndex = 0; // index of last touch in gSensor1LatestTouchPos[5], used by render.cpp
|
andrewm@0
|
34 int gLastFSRValue = 1799; // most recent fsr value, used by render.cpp
|
andrewm@0
|
35
|
andrewm@0
|
36
|
andrewm@0
|
37 DboxSensors Sensors;
|
andrewm@0
|
38
|
andrewm@0
|
39
|
andrewm@0
|
40 //----------------------------------------
|
andrewm@0
|
41 // var shared with logger
|
andrewm@0
|
42 //----------------------------------------
|
andrewm@0
|
43 int s0TouchNum = 0;
|
andrewm@0
|
44 float s0Touches_[MAX_TOUCHES];
|
andrewm@0
|
45 float s0Size_[MAX_TOUCHES];
|
andrewm@0
|
46 int s0LastIndex;
|
andrewm@0
|
47
|
andrewm@0
|
48 int s1TouchNum = 0;
|
andrewm@0
|
49 float s1Touches_[MAX_TOUCHES];
|
andrewm@0
|
50 float s1Size_[MAX_TOUCHES];
|
andrewm@0
|
51 int s1LastIndex;
|
andrewm@0
|
52
|
andrewm@0
|
53 int fsr = 1799;
|
andrewm@0
|
54
|
andrewm@0
|
55
|
andrewm@0
|
56
|
andrewm@0
|
57 using namespace std;
|
andrewm@0
|
58
|
andrewm@0
|
59 int initSensorLoop(int sensorAddress0, int sensorAddress1, bool useNewSensors)
|
andrewm@0
|
60 {
|
andrewm@0
|
61 int tk0_bus = 1;
|
andrewm@0
|
62 int tk0_address = sensorAddress0;
|
andrewm@0
|
63 int tk1_bus = 1;
|
andrewm@0
|
64 int tk1_address = sensorAddress1;
|
andrewm@0
|
65 int tk_file = 0;
|
andrewm@0
|
66 int fsr_max = 1799;
|
andrewm@0
|
67 int fsr_pinNum = 4;
|
andrewm@0
|
68
|
andrewm@0
|
69 if(gVerbose==1)
|
andrewm@0
|
70 cout << "---------------->Init Control Thread" << endl;
|
andrewm@0
|
71
|
andrewm@0
|
72 if(Sensors.initSensors(tk0_bus, tk0_address, tk1_bus, tk1_address, tk_file, fsr_pinNum, fsr_max, useNewSensors)>0)
|
andrewm@0
|
73 {
|
andrewm@0
|
74 gShouldStop = 1;
|
andrewm@0
|
75 cout << "control cannot start" << endl;
|
andrewm@0
|
76 return -1;
|
andrewm@0
|
77 }
|
andrewm@0
|
78
|
andrewm@0
|
79 for(int i=0; i<MAX_TOUCHES; i++)
|
andrewm@0
|
80 {
|
andrewm@0
|
81 s0Touches_[i] = 0.0;
|
andrewm@0
|
82 s0Size_[i] = 0.0;
|
andrewm@0
|
83
|
andrewm@0
|
84 s1Touches_[i] = 0.0;
|
andrewm@0
|
85 s1Size_[i] = 0.0;
|
andrewm@0
|
86 }
|
andrewm@0
|
87
|
andrewm@0
|
88 return 0;
|
andrewm@0
|
89 }
|
andrewm@0
|
90
|
andrewm@0
|
91 void sensorLoop(void *)
|
andrewm@0
|
92 {
|
andrewm@0
|
93 timeval start, end;
|
andrewm@0
|
94 unsigned long elapsedTime;
|
andrewm@0
|
95 //float touchSize = 0; // once used for timbre
|
andrewm@0
|
96
|
andrewm@0
|
97
|
andrewm@0
|
98
|
andrewm@0
|
99 float *s0Touches;
|
andrewm@0
|
100 float *s0Size;
|
andrewm@0
|
101 int s0PrevTouchNum = 0;
|
andrewm@0
|
102 int s0SortedTouchIndices[MAX_TOUCHES];
|
andrewm@0
|
103 float s0SortedTouches[MAX_TOUCHES];
|
andrewm@0
|
104 float s0PrevSortedTouches[MAX_TOUCHES];
|
andrewm@0
|
105
|
andrewm@0
|
106 float *s1Touches;
|
andrewm@0
|
107 float *s1Size;
|
andrewm@0
|
108 int s1PrevTouchNum = 0;
|
andrewm@0
|
109 int s1SortedTouchIndices[MAX_TOUCHES];
|
andrewm@0
|
110 float s1SortedTouches[MAX_TOUCHES];
|
andrewm@0
|
111 float s1PrevSortedTouches[MAX_TOUCHES];
|
andrewm@0
|
112
|
andrewm@0
|
113 float freqScaler = 0;
|
andrewm@0
|
114 int fsrMin = 0;//50; // was 200
|
andrewm@0
|
115 int fsrMax = 1799;//1300; // was 800
|
andrewm@0
|
116 float vel = 0;
|
andrewm@0
|
117 float prevVel = 0;
|
andrewm@0
|
118 float filterMaxF = 0;
|
andrewm@0
|
119 if(gVerbose==1)
|
andrewm@0
|
120 dbox_printf("__________set Control Thread priority\n");
|
andrewm@0
|
121
|
andrewm@0
|
122 if(gVerbose==1)
|
andrewm@0
|
123 dbox_printf("_________________Control Thread!\n");
|
andrewm@0
|
124
|
andrewm@0
|
125 // get freq scaler, cos freqs must be scaled according to the wavetable used in the oscillator bank
|
andrewm@0
|
126 freqScaler = gOscBanks[gCurrentOscBank]->getFrequencyScaler();
|
andrewm@0
|
127 filterMaxF = gOscBanks[gCurrentOscBank]->filterMaxF;
|
andrewm@0
|
128
|
andrewm@0
|
129 // init time vals
|
andrewm@0
|
130 gettimeofday(&start, NULL);
|
andrewm@0
|
131
|
andrewm@0
|
132 // here we go, sensor loop until the end of the application
|
andrewm@0
|
133 while(!gShouldStop)
|
andrewm@0
|
134 {
|
andrewm@0
|
135 gettimeofday(&end, NULL);
|
andrewm@0
|
136 elapsedTime = ( (end.tv_sec*1000000+end.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
|
andrewm@0
|
137 if( elapsedTime<4000 )
|
andrewm@0
|
138 usleep(4000-elapsedTime);
|
andrewm@0
|
139 else
|
andrewm@0
|
140 dbox_printf("%d\n", (int)elapsedTime); // this print happens when something's gone bad...
|
andrewm@0
|
141
|
andrewm@0
|
142 if(Sensors.readSensors()==0)
|
andrewm@0
|
143 {
|
andrewm@0
|
144 s0TouchNum = Sensors.getTKTouchCount(0);
|
andrewm@0
|
145 s0Touches = Sensors.getTKXPositions(0);
|
andrewm@0
|
146 s0Size = Sensors.getTKTouchSize(0);
|
andrewm@0
|
147
|
andrewm@0
|
148 s1TouchNum = Sensors.getTKTouchCount(1);
|
andrewm@0
|
149 s1Touches = Sensors.getTKXPositions(1);
|
andrewm@0
|
150 s1Size = Sensors.getTKTouchSize(1);
|
andrewm@0
|
151
|
andrewm@0
|
152 for(int i=0; i<MAX_TOUCHES; i++)
|
andrewm@0
|
153 {
|
andrewm@0
|
154 s0Touches_[i] = s0Touches[i];
|
andrewm@0
|
155 s0Size_[i] = s0Size[i];
|
andrewm@0
|
156
|
andrewm@0
|
157 s1Touches_[i] = s1Touches[i];
|
andrewm@0
|
158 s1Size_[i] = s1Size[i];
|
andrewm@0
|
159 }
|
andrewm@0
|
160
|
andrewm@0
|
161 gSensor0LatestTouchNum = s0TouchNum;
|
andrewm@0
|
162 if(s0TouchNum > 0)
|
andrewm@0
|
163 {
|
andrewm@0
|
164 //-----------------------------------------------------------------------------------
|
andrewm@0
|
165 // timbre, speed and pitch
|
andrewm@0
|
166 //touchSize = 0; \\ once used for timbre
|
andrewm@0
|
167
|
andrewm@0
|
168 // if we have a number of touches different from previous round, track their order of arrival [calculated using distance comparison]
|
andrewm@0
|
169 if(s0PrevTouchNum!=s0TouchNum)
|
andrewm@0
|
170 {
|
andrewm@0
|
171 float distances[MAX_TOUCHES*(MAX_TOUCHES-1)]; // maximum number of current+previous touches between rounds with different num of touches
|
andrewm@0
|
172 int ids[MAX_TOUCHES*(MAX_TOUCHES-1)];
|
andrewm@0
|
173 // calculate all distance permutations between previous and current touches
|
andrewm@0
|
174 for(int i=0; i<s0TouchNum; i++)
|
andrewm@0
|
175 {
|
andrewm@0
|
176 for(int p=0; p<s0PrevTouchNum; p++)
|
andrewm@0
|
177 {
|
andrewm@0
|
178 int index = i*s0PrevTouchNum+p; // permutation id [says between which touches we are calculating distance]
|
andrewm@0
|
179 distances[index] = fabs(s0Touches[i]-s0PrevSortedTouches[p]);
|
andrewm@0
|
180 ids[index] = index;
|
andrewm@0
|
181 if(index>0)
|
andrewm@0
|
182 {
|
andrewm@0
|
183 // sort, from min to max distance
|
andrewm@0
|
184 float tmp;
|
andrewm@0
|
185 while(distances[index]<distances[index-1])
|
andrewm@0
|
186 {
|
andrewm@0
|
187 tmp = ids[index-1];
|
andrewm@0
|
188 ids[index-1] = ids[index];
|
andrewm@0
|
189 ids[index] = tmp;
|
andrewm@0
|
190
|
andrewm@0
|
191 tmp = distances[index-1];
|
andrewm@0
|
192 distances[index-1] = distances[index];
|
andrewm@0
|
193 distances[index] = tmp;
|
andrewm@0
|
194
|
andrewm@0
|
195 index--;
|
andrewm@0
|
196
|
andrewm@0
|
197 if(index == 0)
|
andrewm@0
|
198 break;
|
andrewm@0
|
199 }
|
andrewm@0
|
200 }
|
andrewm@0
|
201 }
|
andrewm@0
|
202 }
|
andrewm@0
|
203
|
andrewm@0
|
204 int sorted = 0;
|
andrewm@0
|
205 bool currAssigned[MAX_TOUCHES] = {false};
|
andrewm@0
|
206 bool prevAssigned[MAX_TOUCHES] = {false};
|
andrewm@0
|
207
|
andrewm@0
|
208 // track touches assigning index according to shortest distance
|
andrewm@0
|
209 for(int i=0; i<s0TouchNum*s0PrevTouchNum; i++)
|
andrewm@0
|
210 {
|
andrewm@0
|
211 int currentIndex = ids[i]/s0PrevTouchNum;
|
andrewm@0
|
212 int prevIndex = ids[i]%s0PrevTouchNum;
|
andrewm@0
|
213 // avoid double assignment
|
andrewm@0
|
214 if(!currAssigned[currentIndex] && !prevAssigned[prevIndex])
|
andrewm@0
|
215 {
|
andrewm@0
|
216 currAssigned[currentIndex] = true;
|
andrewm@0
|
217 prevAssigned[prevIndex] = true;
|
andrewm@0
|
218 s0SortedTouchIndices[currentIndex] = prevIndex;
|
andrewm@0
|
219 sorted++;
|
andrewm@0
|
220 }
|
andrewm@0
|
221 }
|
andrewm@0
|
222 // we still have to assign a free index to new touches
|
andrewm@0
|
223 if(s0PrevTouchNum<s0TouchNum)
|
andrewm@0
|
224 {
|
andrewm@0
|
225 for(int i=0; i<s0TouchNum; i++)
|
andrewm@0
|
226 {
|
andrewm@0
|
227 if(!currAssigned[i])
|
andrewm@0
|
228 s0SortedTouchIndices[i] = sorted++; // assign next free index
|
andrewm@0
|
229
|
andrewm@0
|
230 // update tracked value
|
andrewm@0
|
231 s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
|
andrewm@0
|
232 s0PrevSortedTouches[i] = s0SortedTouches[i];
|
andrewm@0
|
233 if(s0SortedTouchIndices[i]==s0TouchNum-1)
|
andrewm@0
|
234 s0LastIndex = i;
|
andrewm@0
|
235
|
andrewm@0
|
236 // accumulate sizes for timbre
|
andrewm@0
|
237 //touchSize += s0Size[i];
|
andrewm@0
|
238 }
|
andrewm@0
|
239 }
|
andrewm@0
|
240 else // some touches have disappeared...
|
andrewm@0
|
241 {
|
andrewm@0
|
242 // ...we have to shift all indices...
|
andrewm@0
|
243 for(int i=s0PrevTouchNum-1; i>=0; i--)
|
andrewm@0
|
244 {
|
andrewm@0
|
245 if(!prevAssigned[i])
|
andrewm@0
|
246 {
|
andrewm@0
|
247 for(int j=0; j<s0TouchNum; j++)
|
andrewm@0
|
248 {
|
andrewm@0
|
249 // ...only if touches that disappeared were before the current one
|
andrewm@0
|
250 if(s0SortedTouchIndices[j]>i)
|
andrewm@0
|
251 s0SortedTouchIndices[j]--;
|
andrewm@0
|
252 }
|
andrewm@0
|
253 }
|
andrewm@0
|
254 }
|
andrewm@0
|
255 // done! now update
|
andrewm@0
|
256 for(int i=0; i<s0TouchNum; i++)
|
andrewm@0
|
257 {
|
andrewm@0
|
258 // update tracked value
|
andrewm@0
|
259 s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
|
andrewm@0
|
260 s0PrevSortedTouches[i] = s0SortedTouches[i];
|
andrewm@0
|
261 if(s0SortedTouchIndices[i]==s0TouchNum-1)
|
andrewm@0
|
262 s0LastIndex = i;
|
andrewm@0
|
263
|
andrewm@0
|
264 // accumulate sizes for timbre
|
andrewm@0
|
265 //touchSize += s0Size[i];
|
andrewm@0
|
266 }
|
andrewm@0
|
267 }
|
andrewm@0
|
268 }
|
andrewm@0
|
269 else // nothing's changed since last round
|
andrewm@0
|
270 {
|
andrewm@0
|
271 for(int i=0; i<s0TouchNum; i++)
|
andrewm@0
|
272 {
|
andrewm@0
|
273 // update tracked value
|
andrewm@0
|
274 s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
|
andrewm@0
|
275 s0PrevSortedTouches[i] = s0SortedTouches[i];
|
andrewm@0
|
276
|
andrewm@0
|
277 // accumulate sizes for timbre
|
andrewm@0
|
278 //touchSize += s0Size[i];
|
andrewm@0
|
279 }
|
andrewm@0
|
280 }
|
andrewm@0
|
281
|
andrewm@0
|
282 if(s0TouchNum == 0)
|
andrewm@0
|
283 s0LastIndex = -1;
|
andrewm@0
|
284
|
andrewm@0
|
285 // timbre
|
andrewm@0
|
286 //touchSize = (touchSize > 0.7) ? 1 : touchSize/0.7;
|
andrewm@0
|
287 //gOscBanks[gCurrentOscBank]->hopNumTh = log((1-touchSize)+1)/log(2)*20000;
|
andrewm@0
|
288 //gOscBanks[gCurrentOscBank]->hopNumTh = 0;
|
andrewm@0
|
289
|
andrewm@0
|
290
|
andrewm@0
|
291 // pitch, controlled by last touch
|
andrewm@0
|
292 //prevTouchPos = touch[touchIndex];
|
andrewm@0
|
293 //touchPos = (s0SortedTouches[s0TouchNum-1]-0.5)/0.5; // from [0,1] to [-1,1]
|
andrewm@0
|
294 gSensor0LatestTouchPos = s0SortedTouches[s0TouchNum-1];
|
andrewm@0
|
295 //touchPos = s0Touches[0];
|
andrewm@0
|
296 //gOscBanks[gCurrentOscBank]->pitchMultiplier = pow(2, touchPos);
|
andrewm@0
|
297 //-----------------------------------------------------------------------------------
|
andrewm@0
|
298
|
andrewm@0
|
299
|
andrewm@0
|
300
|
andrewm@0
|
301 //-----------------------------------------------------------------------------------
|
andrewm@0
|
302 // note on
|
andrewm@0
|
303 //if(s0PrevTouchNum == 0)
|
andrewm@0
|
304 // gOscBanks[gCurrentOscBank]->play();
|
andrewm@0
|
305 // fsr = Sensors.getFSRVAlue();
|
andrewm@0
|
306 fsr = gLastFSRValue;
|
andrewm@0
|
307 //dbox_printf("fsr: %d\n", fsr);
|
andrewm@0
|
308 if(!gOscBanks[gCurrentOscBank]->note)
|
andrewm@0
|
309 {
|
andrewm@0
|
310 vel = fsr;
|
andrewm@0
|
311 vel /= (float)(fsrMax-fsrMin);
|
andrewm@0
|
312
|
andrewm@0
|
313 vel = 1-vel;
|
andrewm@0
|
314 dbox_printf("Attack vel: %f\n", vel);
|
andrewm@0
|
315 gOscBanks[gCurrentOscBank]->play(vel);
|
andrewm@0
|
316 prevVel = vel;
|
andrewm@0
|
317 }
|
andrewm@0
|
318 else if(gOscBanks[gCurrentOscBank]->getEnvelopeState() != env_release)
|
andrewm@0
|
319 {
|
andrewm@0
|
320 fsr = (fsr > fsrMax) ? fsrMax : fsr;
|
andrewm@0
|
321 vel = (fsr < fsrMin) ? fsrMin : fsr;
|
andrewm@0
|
322 vel -= fsrMin;
|
andrewm@0
|
323 vel /= (float)(fsrMax-fsrMin);
|
andrewm@0
|
324 vel = 1-vel;
|
andrewm@0
|
325 if(vel > prevVel)
|
andrewm@0
|
326 {
|
andrewm@0
|
327 gOscBanks[gCurrentOscBank]->afterTouch(vel);
|
andrewm@0
|
328 prevVel = vel;
|
andrewm@0
|
329 }
|
andrewm@0
|
330 }
|
andrewm@0
|
331 //-----------------------------------------------------------------------------------
|
andrewm@0
|
332 }
|
andrewm@0
|
333 else
|
andrewm@0
|
334 {
|
andrewm@0
|
335 //prevFsr = 1799;
|
andrewm@0
|
336 //prevTouchPos = -1;
|
andrewm@0
|
337 //-----------------------------------------------------------------------------------
|
andrewm@0
|
338 // note off
|
andrewm@0
|
339 if(s0PrevTouchNum > 0)
|
andrewm@0
|
340 {
|
andrewm@0
|
341 if(gOscBanks[gCurrentOscBank]->state==bank_playing)
|
andrewm@0
|
342 gOscBanks[gCurrentOscBank]->stop();
|
andrewm@0
|
343 }
|
andrewm@0
|
344 //-----------------------------------------------------------------------------------
|
andrewm@0
|
345 }
|
andrewm@0
|
346
|
andrewm@0
|
347
|
andrewm@0
|
348
|
andrewm@0
|
349 // sensor 2
|
andrewm@0
|
350 //-----------------------------------------------------------------------------------
|
andrewm@0
|
351 //filter - calculated even when no touches on first sensor, to filter also release tail
|
andrewm@0
|
352 gOscBanks[gCurrentOscBank]->filterNum = s1TouchNum;
|
andrewm@0
|
353
|
andrewm@0
|
354 gSensor1LatestTouchCount = gOscBanks[gCurrentOscBank]->filterNum;
|
andrewm@0
|
355 for(int i = 0; i < gSensor1LatestTouchCount; i++) {
|
andrewm@0
|
356 gSensor1LatestTouchPos[i] = s1Touches[i];
|
andrewm@0
|
357 //gSensor1LatestTouchSizes[i] = s1Size[i];
|
andrewm@0
|
358 }
|
andrewm@0
|
359
|
andrewm@0
|
360 /* for(int i=0; i<gOscBanks[gCurrentOscBank]->filterNum; i++)
|
andrewm@0
|
361 {
|
andrewm@0
|
362 // touch pos is linear but freqs are log
|
andrewm@0
|
363 gOscBanks[gCurrentOscBank]->filterFreqs[i] = ((exp(s0Touches[i]*4)-1)/(exp(4)-1))*filterMaxF*freqScaler;
|
andrewm@0
|
364 //gOscBanks[gCurrentOscBank]->filterQ[i] = size[i]*5*(1+touch[i]*1000)*freqScaler;
|
andrewm@0
|
365 gOscBanks[gCurrentOscBank]->filterQ[i] = s0Size[i];
|
andrewm@0
|
366 if(gOscBanks[gCurrentOscBank]->filterFreqs[i]>500*freqScaler)
|
andrewm@0
|
367 gOscBanks[gCurrentOscBank]->filterPadding[i] = 1+100000*( (gOscBanks[gCurrentOscBank]->filterFreqs[i]-500*freqScaler)/(filterMaxF-500)*freqScaler );
|
andrewm@0
|
368 else
|
andrewm@0
|
369 gOscBanks[gCurrentOscBank]->filterPadding[i] = 1;
|
andrewm@0
|
370 }*/
|
andrewm@0
|
371
|
andrewm@0
|
372 // each touch on sensor 2 is a notch filter, whose Q is determined by touch size
|
andrewm@0
|
373 for(int i=0; i<gOscBanks[gCurrentOscBank]->filterNum; i++)
|
andrewm@0
|
374 {
|
andrewm@0
|
375 // map touch pos [which is linear] on freqs exponentially
|
andrewm@0
|
376 float freq = ((exp(s1Touches[i]*4)-1)/EXP_DENOM)*filterMaxF;
|
andrewm@0
|
377 gOscBanks[gCurrentOscBank]->filterFreqs[i] = freq*freqScaler;
|
andrewm@0
|
378 // also size is mapped exponentially on Q
|
andrewm@0
|
379 float siz = (exp(s1Size[i])-1)/1.71828;
|
andrewm@0
|
380 gOscBanks[gCurrentOscBank]->filterQ[i] = siz*( (filterMaxF-freq)/filterMaxF * 0.9 + 0.1 ); // size weight on Q decreases with frequency
|
andrewm@0
|
381 }
|
andrewm@0
|
382 //-----------------------------------------------------------------------------------
|
andrewm@0
|
383
|
andrewm@0
|
384
|
andrewm@0
|
385
|
andrewm@0
|
386 //-----------------------------------------------------------------------------------
|
andrewm@0
|
387 // sort touches on sensor 2
|
andrewm@0
|
388 if(s1TouchNum > 0)
|
andrewm@0
|
389 {
|
andrewm@0
|
390 // if we have a number of touches different from previous round, track their order of arrival [calculated using distance comparison]
|
andrewm@0
|
391 if(s1PrevTouchNum!=s1TouchNum)
|
andrewm@0
|
392 {
|
andrewm@0
|
393 float distances[MAX_TOUCHES*(MAX_TOUCHES-1)]; // maximum number of current+previous touches between rounds with different num of touches
|
andrewm@0
|
394 int ids[MAX_TOUCHES*(MAX_TOUCHES-1)];
|
andrewm@0
|
395 // calculate all distance permutations between previous and current touches
|
andrewm@0
|
396 for(int i=0; i<s1TouchNum; i++)
|
andrewm@0
|
397 {
|
andrewm@0
|
398 for(int p=0; p<s1PrevTouchNum; p++)
|
andrewm@0
|
399 {
|
andrewm@0
|
400 int index = i*s1PrevTouchNum+p; // permutation id [says between which touches we are calculating distance]
|
andrewm@0
|
401 distances[index] = fabs(s1Touches[i]-s1PrevSortedTouches[p]);
|
andrewm@0
|
402 ids[index] = index;
|
andrewm@0
|
403 if(index>0)
|
andrewm@0
|
404 {
|
andrewm@0
|
405 // sort, from min to max distance
|
andrewm@0
|
406 float tmp;
|
andrewm@0
|
407 while(distances[index]<distances[index-1])
|
andrewm@0
|
408 {
|
andrewm@0
|
409 tmp = ids[index-1];
|
andrewm@0
|
410 ids[index-1] = ids[index];
|
andrewm@0
|
411 ids[index] = tmp;
|
andrewm@0
|
412
|
andrewm@0
|
413 tmp = distances[index-1];
|
andrewm@0
|
414 distances[index-1] = distances[index];
|
andrewm@0
|
415 distances[index] = tmp;
|
andrewm@0
|
416
|
andrewm@0
|
417 index--;
|
andrewm@0
|
418
|
andrewm@0
|
419 if(index == 0)
|
andrewm@0
|
420 break;
|
andrewm@0
|
421 }
|
andrewm@0
|
422 }
|
andrewm@0
|
423 }
|
andrewm@0
|
424 }
|
andrewm@0
|
425
|
andrewm@0
|
426 int sorted = 0;
|
andrewm@0
|
427 bool currAssigned[MAX_TOUCHES] = {false};
|
andrewm@0
|
428 bool prevAssigned[MAX_TOUCHES] = {false};
|
andrewm@0
|
429
|
andrewm@0
|
430 // track touches assigning index according to shortest distance
|
andrewm@0
|
431 for(int i=0; i<s1TouchNum*s1PrevTouchNum; i++)
|
andrewm@0
|
432 {
|
andrewm@0
|
433 int currentIndex = ids[i]/s1PrevTouchNum;
|
andrewm@0
|
434 int prevIndex = ids[i]%s1PrevTouchNum;
|
andrewm@0
|
435 // avoid double assignment
|
andrewm@0
|
436 if(!currAssigned[currentIndex] && !prevAssigned[prevIndex])
|
andrewm@0
|
437 {
|
andrewm@0
|
438 currAssigned[currentIndex] = true;
|
andrewm@0
|
439 prevAssigned[prevIndex] = true;
|
andrewm@0
|
440 s1SortedTouchIndices[currentIndex] = prevIndex;
|
andrewm@0
|
441 sorted++;
|
andrewm@0
|
442 }
|
andrewm@0
|
443 }
|
andrewm@0
|
444 // we still have to assign a free index to new touches
|
andrewm@0
|
445 if(s1PrevTouchNum<s1TouchNum)
|
andrewm@0
|
446 {
|
andrewm@0
|
447 for(int i=0; i<s1TouchNum; i++)
|
andrewm@0
|
448 {
|
andrewm@0
|
449 if(!currAssigned[i])
|
andrewm@0
|
450 s1SortedTouchIndices[i] = sorted++; // assign next free index
|
andrewm@0
|
451
|
andrewm@0
|
452 // update tracked value
|
andrewm@0
|
453 s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
|
andrewm@0
|
454 s1PrevSortedTouches[i] = s1SortedTouches[i];
|
andrewm@0
|
455 if(s1SortedTouchIndices[i]==s1TouchNum-1)
|
andrewm@0
|
456 s1LastIndex = i;
|
andrewm@0
|
457 }
|
andrewm@0
|
458 }
|
andrewm@0
|
459 else // some touches have disappeared...
|
andrewm@0
|
460 {
|
andrewm@0
|
461 // ...we have to shift all indices...
|
andrewm@0
|
462 for(int i=s1PrevTouchNum-1; i>=0; i--)
|
andrewm@0
|
463 {
|
andrewm@0
|
464 if(!prevAssigned[i])
|
andrewm@0
|
465 {
|
andrewm@0
|
466 for(int j=0; j<s1TouchNum; j++)
|
andrewm@0
|
467 {
|
andrewm@0
|
468 // ...only if touches that disappeared were before the current one
|
andrewm@0
|
469 if(s1SortedTouchIndices[j]>i)
|
andrewm@0
|
470 s1SortedTouchIndices[j]--;
|
andrewm@0
|
471 }
|
andrewm@0
|
472 }
|
andrewm@0
|
473 }
|
andrewm@0
|
474 // done! now update
|
andrewm@0
|
475 for(int i=0; i<s1TouchNum; i++)
|
andrewm@0
|
476 {
|
andrewm@0
|
477 // update tracked value
|
andrewm@0
|
478 s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
|
andrewm@0
|
479 s1PrevSortedTouches[i] = s1SortedTouches[i];
|
andrewm@0
|
480 if(s1SortedTouchIndices[i]==s1TouchNum-1)
|
andrewm@0
|
481 s1LastIndex = i;
|
andrewm@0
|
482 }
|
andrewm@0
|
483 }
|
andrewm@0
|
484 }
|
andrewm@0
|
485 else // nothing's changed since last round
|
andrewm@0
|
486 {
|
andrewm@0
|
487 for(int i=0; i<s1TouchNum; i++)
|
andrewm@0
|
488 {
|
andrewm@0
|
489 // update tracked value
|
andrewm@0
|
490 s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
|
andrewm@0
|
491 s1PrevSortedTouches[i] = s1SortedTouches[i];
|
andrewm@0
|
492 }
|
andrewm@0
|
493 }
|
andrewm@0
|
494 }
|
andrewm@0
|
495
|
andrewm@0
|
496 if(s1TouchNum > 0)
|
andrewm@0
|
497 {
|
andrewm@0
|
498 gSensor1LatestTouchIndex = s1LastIndex;
|
andrewm@0
|
499 }
|
andrewm@0
|
500 else
|
andrewm@0
|
501 s1LastIndex = -1;
|
andrewm@0
|
502
|
andrewm@0
|
503 /* dbox_printf("-----------------------------\nnum: %d, latest: %d\n", s1TouchNum, gSensor1LatestTouchIndex);
|
andrewm@0
|
504 for(int i=0; i<s1TouchNum; i++)
|
andrewm@0
|
505 dbox_printf("\t%f\n", gSensor1LatestTouchPos[i]);
|
andrewm@0
|
506 dbox_printf("------\n");
|
andrewm@0
|
507 for(int i=0; i<s1TouchNum; i++)
|
andrewm@0
|
508 dbox_printf("\t%f\n", s1SortedTouches[i]);*/
|
andrewm@0
|
509
|
andrewm@0
|
510
|
andrewm@0
|
511
|
andrewm@0
|
512 // update variables for both sensors
|
andrewm@0
|
513 s0PrevTouchNum = s0TouchNum;
|
andrewm@0
|
514 s1PrevTouchNum = s1TouchNum;
|
andrewm@0
|
515 }
|
andrewm@0
|
516 else
|
andrewm@0
|
517 dbox_printf("Come on instrument!\n"); //break
|
andrewm@0
|
518
|
andrewm@0
|
519 gettimeofday(&start, NULL);
|
andrewm@0
|
520 }
|
andrewm@0
|
521
|
andrewm@0
|
522 dbox_printf("sensor thread ended\n");
|
andrewm@0
|
523 }
|
andrewm@0
|
524
|
andrewm@0
|
525 void *keyboardLoop(void *)
|
andrewm@0
|
526 {
|
andrewm@0
|
527 if(gVerbose==1)
|
andrewm@0
|
528 cout << "_________________Keyboard Control Thread!" << endl;
|
andrewm@0
|
529
|
andrewm@0
|
530 char keyStroke = '.';
|
andrewm@0
|
531 cout << "Press q to quit." << endl;
|
andrewm@0
|
532
|
andrewm@0
|
533 float speed;
|
andrewm@0
|
534
|
andrewm@0
|
535 do
|
andrewm@0
|
536 {
|
andrewm@0
|
537 keyStroke = getchar();
|
andrewm@0
|
538 while(getchar()!='\n'); // to read the first stroke
|
andrewm@0
|
539
|
andrewm@0
|
540 switch (keyStroke)
|
andrewm@0
|
541 {
|
andrewm@0
|
542 //----------------------------------------------------------------------------
|
andrewm@0
|
543 case 'a':
|
andrewm@0
|
544 gOscBanks[gCurrentOscBank]->hopNumTh = 0;
|
andrewm@0
|
545 gOscBanks[gCurrentOscBank]->play(1);
|
andrewm@0
|
546 //cout << "Note on" << endl;
|
andrewm@0
|
547 break;
|
andrewm@0
|
548 case 's':
|
andrewm@0
|
549 if(gOscBanks[gCurrentOscBank]->state==bank_playing)
|
andrewm@0
|
550 {
|
andrewm@0
|
551 gOscBanks[gCurrentOscBank]->stop();
|
andrewm@0
|
552 //cout << "Note off" << endl;
|
andrewm@0
|
553 }
|
andrewm@0
|
554 break;
|
andrewm@0
|
555 //----------------------------------------------------------------------------
|
andrewm@0
|
556 case '[':
|
andrewm@0
|
557 gOscBanks[gCurrentOscBank]->freqMovement-=0.05;
|
andrewm@0
|
558 if(gOscBanks[gCurrentOscBank]->freqMovement<0)
|
andrewm@0
|
559 gOscBanks[gCurrentOscBank]->freqMovement = 0;
|
andrewm@0
|
560 //cout << "gOscBanks[gCurrentOscBank]->FreqMov: " << gOscBanks[gCurrentOscBank]->freqMovement << endl;
|
andrewm@0
|
561 break;
|
andrewm@0
|
562 case ']':
|
andrewm@0
|
563 gOscBanks[gCurrentOscBank]->freqMovement+=0.05;
|
andrewm@0
|
564 if(gOscBanks[gCurrentOscBank]->freqMovement>1)
|
andrewm@0
|
565 gOscBanks[gCurrentOscBank]->freqMovement = 1;
|
andrewm@0
|
566 //cout << "gOscBanks[gCurrentOscBank]->FreqMov: " << gOscBanks[gCurrentOscBank]->freqMovement << endl;
|
andrewm@0
|
567 break;
|
andrewm@0
|
568 //----------------------------------------------------------------------------
|
andrewm@0
|
569 case '<':
|
andrewm@0
|
570 speed = gOscBanks[gCurrentOscBank]->getSpeed() - 0.1 ;
|
andrewm@0
|
571 gOscBanks[gCurrentOscBank]->setSpeed(speed);
|
andrewm@0
|
572 dbox_printf("Speed: %f\n", speed);
|
andrewm@0
|
573
|
andrewm@0
|
574 break;
|
andrewm@0
|
575 case '>':
|
andrewm@0
|
576 speed = gOscBanks[gCurrentOscBank]->getSpeed() + 0.1 ;
|
andrewm@0
|
577 gOscBanks[gCurrentOscBank]->setSpeed(speed);
|
andrewm@0
|
578 dbox_printf("Speed: %f\n", speed);
|
andrewm@0
|
579 break;
|
andrewm@0
|
580 case '0':
|
andrewm@0
|
581 speed = 0.1;
|
andrewm@0
|
582 gOscBanks[gCurrentOscBank]->setSpeed(speed);
|
andrewm@0
|
583 dbox_printf("Speed: %f\n", speed);
|
andrewm@0
|
584 break;
|
andrewm@0
|
585 case '1':
|
andrewm@0
|
586 speed = 0.5;
|
andrewm@0
|
587 gOscBanks[gCurrentOscBank]->setSpeed(speed);
|
andrewm@0
|
588 dbox_printf("Speed: %f\n", speed);
|
andrewm@0
|
589 break;
|
andrewm@0
|
590 case '2':
|
andrewm@0
|
591 speed = 1;
|
andrewm@0
|
592 gOscBanks[gCurrentOscBank]->setSpeed(speed);
|
andrewm@0
|
593 dbox_printf("Speed: %f\n", speed);
|
andrewm@0
|
594 break;
|
andrewm@0
|
595 case '3':
|
andrewm@0
|
596 speed = 2;
|
andrewm@0
|
597 gOscBanks[gCurrentOscBank]->setSpeed(speed);
|
andrewm@0
|
598 dbox_printf("Speed: %f\n", speed);
|
andrewm@0
|
599 break;
|
andrewm@0
|
600 case '4':
|
andrewm@0
|
601 speed = 3;
|
andrewm@0
|
602 gOscBanks[gCurrentOscBank]->setSpeed(speed);
|
andrewm@0
|
603 dbox_printf("Speed: %f\n", speed);
|
andrewm@0
|
604 break;
|
andrewm@0
|
605 //----------------------------------------------------------------------------
|
andrewm@0
|
606 case 'z':
|
andrewm@0
|
607 gOscBanks[gCurrentOscBank]->setJumpHop(0);
|
andrewm@0
|
608 break;
|
andrewm@0
|
609 case 'x':
|
andrewm@0
|
610 gOscBanks[gCurrentOscBank]->setJumpHop(100);
|
andrewm@0
|
611 break;
|
andrewm@0
|
612 case 'c':
|
andrewm@0
|
613 gOscBanks[gCurrentOscBank]->setJumpHop(600);
|
andrewm@0
|
614 break;
|
andrewm@0
|
615 case 'v':
|
andrewm@0
|
616 gOscBanks[gCurrentOscBank]->setJumpHop(1100);
|
andrewm@0
|
617 break;
|
andrewm@0
|
618 case 'b':
|
andrewm@0
|
619 gOscBanks[gCurrentOscBank]->setJumpHop(2000);
|
andrewm@0
|
620 break;
|
andrewm@0
|
621 case 'n':
|
andrewm@0
|
622 gOscBanks[gCurrentOscBank]->setJumpHop(gOscBanks[gCurrentOscBank]->getLastHop());
|
andrewm@0
|
623 break;
|
andrewm@0
|
624 //----------------------------------------------------------------------------
|
andrewm@0
|
625 case 'q':
|
andrewm@0
|
626 gShouldStop = true;
|
andrewm@0
|
627 break;
|
andrewm@0
|
628 case 'o':
|
andrewm@0
|
629 gNextOscBank = (gCurrentOscBank + 1) % gOscBanks.size();
|
andrewm@0
|
630 break;
|
andrewm@0
|
631 default:
|
andrewm@0
|
632 break;
|
andrewm@0
|
633 //----------------------------------------------------------------------------
|
andrewm@0
|
634 }
|
andrewm@0
|
635 usleep(1000); /* Wait 1ms to avoid checking too quickly */
|
andrewm@0
|
636 }
|
andrewm@0
|
637 while (keyStroke!='q');
|
andrewm@0
|
638
|
andrewm@0
|
639 cout << "keyboard thread ended" << endl;
|
andrewm@0
|
640
|
andrewm@0
|
641 return (void *)0;
|
andrewm@0
|
642 }
|