robert@464: /* robert@464: * sensors.cpp robert@464: * robert@464: * Created on: May 28, 2014 robert@464: * Author: Victor Zappi robert@464: */ robert@464: robert@464: #include robert@464: #include robert@464: #include robert@464: #include robert@464: #include robert@464: #include "prio.h" robert@464: #include "sensors.h" robert@464: #include "OscillatorBank.h" robert@464: #include "DboxSensors.h" robert@464: robert@464: robert@464: //---------------------------------------- robert@464: // main extern variables robert@464: //---------------------------------------- robert@464: extern vector gOscBanks; robert@464: extern int gCurrentOscBank; robert@464: extern int gNextOscBank; robert@464: extern int gShouldStop; robert@464: extern int gVerbose; robert@464: robert@464: float gSensor0LatestTouchPos = 0; // most recent pitch touch location [0-1] on sensor 0, used by render.cpp robert@464: int gSensor0LatestTouchNum = 0; // most recent num of touches on sensor 0, used by render.cpp robert@464: float gSensor1LatestTouchPos[5]; // most recent touche locations on sensor 1, used by render.cpp robert@464: //float gSensor1LatestTouchSizes[5]; robert@464: int gSensor1LatestTouchCount; // most recent number touches on sensor 1, used by render.cpp robert@464: int gSensor1LatestTouchIndex = 0; // index of last touch in gSensor1LatestTouchPos[5], used by render.cpp robert@464: int gLastFSRValue = 1799; // most recent fsr value, used by render.cpp robert@464: robert@464: robert@464: DboxSensors Sensors; robert@464: robert@464: robert@464: //---------------------------------------- robert@464: // var shared with logger robert@464: //---------------------------------------- robert@464: int s0TouchNum = 0; robert@464: float s0Touches_[MAX_TOUCHES]; robert@464: float s0Size_[MAX_TOUCHES]; robert@464: int s0LastIndex; robert@464: robert@464: int s1TouchNum = 0; robert@464: float s1Touches_[MAX_TOUCHES]; robert@464: float s1Size_[MAX_TOUCHES]; robert@464: int s1LastIndex; robert@464: robert@464: int fsr = 1799; robert@464: robert@464: robert@464: robert@464: using namespace std; robert@464: robert@464: int initSensorLoop(int sensorAddress0, int sensorAddress1, int sensorType) robert@464: { robert@464: int tk0_bus = 1; robert@464: int tk0_address = sensorAddress0; robert@464: int tk1_bus = 1; robert@464: int tk1_address = sensorAddress1; robert@464: int tk_file = 0; robert@464: int fsr_max = 1799; robert@464: int fsr_pinNum = 4; robert@464: robert@464: if(gVerbose==1) robert@464: cout << "---------------->Init Control Thread" << endl; robert@464: robert@464: if(Sensors.initSensors(tk0_bus, tk0_address, tk1_bus, tk1_address, tk_file, fsr_pinNum, fsr_max, sensorType)>0) robert@464: { robert@464: gShouldStop = 1; robert@464: cout << "control cannot start" << endl; robert@464: return -1; robert@464: } robert@464: robert@464: for(int i=0; igetFrequencyScaler(); robert@464: filterMaxF = gOscBanks[gCurrentOscBank]->filterMaxF; robert@464: robert@464: // init time vals robert@464: gettimeofday(&start, NULL); robert@464: robert@464: // here we go, sensor loop until the end of the application robert@464: while(!gShouldStop) robert@464: { robert@464: gettimeofday(&end, NULL); robert@464: elapsedTime = ( (end.tv_sec*1000000+end.tv_usec) - (start.tv_sec*1000000+start.tv_usec) ); robert@464: if( elapsedTime<4000 ) robert@464: usleep(4000-elapsedTime); robert@464: else robert@464: dbox_printf("%d\n", (int)elapsedTime); // this print happens when something's gone bad... robert@464: robert@464: if(Sensors.readSensors()==0) robert@464: { robert@464: s0TouchNum = Sensors.getTKTouchCount(0); robert@464: s0Touches = Sensors.getTKXPositions(0); robert@464: s0Size = Sensors.getTKTouchSize(0); robert@464: robert@464: s1TouchNum = Sensors.getTKTouchCount(1); robert@464: s1Touches = Sensors.getTKXPositions(1); robert@464: s1Size = Sensors.getTKTouchSize(1); robert@464: robert@464: for(int i=0; i 0) robert@464: { robert@464: //----------------------------------------------------------------------------------- robert@464: // timbre, speed and pitch robert@464: //touchSize = 0; \\ once used for timbre robert@464: robert@464: // if we have a number of touches different from previous round, track their order of arrival [calculated using distance comparison] robert@464: if(s0PrevTouchNum!=s0TouchNum) robert@464: { robert@464: float distances[MAX_TOUCHES*(MAX_TOUCHES-1)]; // maximum number of current+previous touches between rounds with different num of touches robert@464: int ids[MAX_TOUCHES*(MAX_TOUCHES-1)]; robert@464: // calculate all distance permutations between previous and current touches robert@464: for(int i=0; i0) robert@464: { robert@464: // sort, from min to max distance robert@464: float tmp; robert@464: while(distances[index]=0; i--) robert@464: { robert@464: if(!prevAssigned[i]) robert@464: { robert@464: for(int j=0; ji) robert@464: s0SortedTouchIndices[j]--; robert@464: } robert@464: } robert@464: } robert@464: // done! now update robert@464: for(int i=0; i 0.7) ? 1 : touchSize/0.7; robert@464: //gOscBanks[gCurrentOscBank]->hopNumTh = log((1-touchSize)+1)/log(2)*20000; robert@464: //gOscBanks[gCurrentOscBank]->hopNumTh = 0; robert@464: robert@464: robert@464: // pitch, controlled by last touch robert@464: //prevTouchPos = touch[touchIndex]; robert@464: //touchPos = (s0SortedTouches[s0TouchNum-1]-0.5)/0.5; // from [0,1] to [-1,1] robert@464: gSensor0LatestTouchPos = s0SortedTouches[s0TouchNum-1]; robert@464: //touchPos = s0Touches[0]; robert@464: //gOscBanks[gCurrentOscBank]->pitchMultiplier = pow(2, touchPos); robert@464: //----------------------------------------------------------------------------------- robert@464: robert@464: robert@464: robert@464: //----------------------------------------------------------------------------------- robert@464: // note on robert@464: //if(s0PrevTouchNum == 0) robert@464: // gOscBanks[gCurrentOscBank]->play(); robert@464: // fsr = Sensors.getFSRVAlue(); robert@464: fsr = gLastFSRValue; robert@464: //dbox_printf("fsr: %d\n", fsr); robert@464: if(!gOscBanks[gCurrentOscBank]->note) robert@464: { robert@464: vel = fsr; robert@464: vel /= (float)(fsrMax-fsrMin); robert@464: robert@464: vel = 1-vel; robert@464: dbox_printf("Attack vel: %f\n", vel); robert@464: gOscBanks[gCurrentOscBank]->play(vel); robert@464: prevVel = vel; robert@464: } robert@464: else if(gOscBanks[gCurrentOscBank]->getEnvelopeState() != env_release) robert@464: { robert@464: fsr = (fsr > fsrMax) ? fsrMax : fsr; robert@464: vel = (fsr < fsrMin) ? fsrMin : fsr; robert@464: vel -= fsrMin; robert@464: vel /= (float)(fsrMax-fsrMin); robert@464: vel = 1-vel; robert@464: if(vel > prevVel) robert@464: { robert@464: gOscBanks[gCurrentOscBank]->afterTouch(vel); robert@464: prevVel = vel; robert@464: } robert@464: } robert@464: //----------------------------------------------------------------------------------- robert@464: } robert@464: else robert@464: { robert@464: //prevFsr = 1799; robert@464: //prevTouchPos = -1; robert@464: //----------------------------------------------------------------------------------- robert@464: // note off robert@464: if(s0PrevTouchNum > 0) robert@464: { robert@464: if(gOscBanks[gCurrentOscBank]->state==bank_playing) robert@464: gOscBanks[gCurrentOscBank]->stop(); robert@464: } robert@464: //----------------------------------------------------------------------------------- robert@464: } robert@464: robert@464: robert@464: robert@464: // sensor 2 robert@464: //----------------------------------------------------------------------------------- robert@464: //filter - calculated even when no touches on first sensor, to filter also release tail robert@464: gOscBanks[gCurrentOscBank]->filterNum = s1TouchNum; robert@464: robert@464: gSensor1LatestTouchCount = gOscBanks[gCurrentOscBank]->filterNum; robert@464: for(int i = 0; i < gSensor1LatestTouchCount; i++) { robert@464: gSensor1LatestTouchPos[i] = s1Touches[i]; robert@464: //gSensor1LatestTouchSizes[i] = s1Size[i]; robert@464: } robert@464: robert@464: /* for(int i=0; ifilterNum; i++) robert@464: { robert@464: // touch pos is linear but freqs are log robert@464: gOscBanks[gCurrentOscBank]->filterFreqs[i] = ((exp(s0Touches[i]*4)-1)/(exp(4)-1))*filterMaxF*freqScaler; robert@464: //gOscBanks[gCurrentOscBank]->filterQ[i] = size[i]*5*(1+touch[i]*1000)*freqScaler; robert@464: gOscBanks[gCurrentOscBank]->filterQ[i] = s0Size[i]; robert@464: if(gOscBanks[gCurrentOscBank]->filterFreqs[i]>500*freqScaler) robert@464: gOscBanks[gCurrentOscBank]->filterPadding[i] = 1+100000*( (gOscBanks[gCurrentOscBank]->filterFreqs[i]-500*freqScaler)/(filterMaxF-500)*freqScaler ); robert@464: else robert@464: gOscBanks[gCurrentOscBank]->filterPadding[i] = 1; robert@464: }*/ robert@464: robert@464: // each touch on sensor 2 is a notch filter, whose Q is determined by touch size robert@464: for(int i=0; ifilterNum; i++) robert@464: { robert@464: // map touch pos [which is linear] on freqs exponentially robert@464: float freq = ((exp(s1Touches[i]*4)-1)/EXP_DENOM)*filterMaxF; robert@464: gOscBanks[gCurrentOscBank]->filterFreqs[i] = freq*freqScaler; robert@464: // also size is mapped exponentially on Q robert@464: float siz = (exp(s1Size[i])-1)/1.71828; robert@464: gOscBanks[gCurrentOscBank]->filterQ[i] = siz*( (filterMaxF-freq)/filterMaxF * 0.9 + 0.1 ); // size weight on Q decreases with frequency robert@464: } robert@464: //----------------------------------------------------------------------------------- robert@464: robert@464: robert@464: robert@464: //----------------------------------------------------------------------------------- robert@464: // sort touches on sensor 2 robert@464: if(s1TouchNum > 0) robert@464: { robert@464: // if we have a number of touches different from previous round, track their order of arrival [calculated using distance comparison] robert@464: if(s1PrevTouchNum!=s1TouchNum) robert@464: { robert@464: float distances[MAX_TOUCHES*(MAX_TOUCHES-1)]; // maximum number of current+previous touches between rounds with different num of touches robert@464: int ids[MAX_TOUCHES*(MAX_TOUCHES-1)]; robert@464: // calculate all distance permutations between previous and current touches robert@464: for(int i=0; i0) robert@464: { robert@464: // sort, from min to max distance robert@464: float tmp; robert@464: while(distances[index]=0; i--) robert@464: { robert@464: if(!prevAssigned[i]) robert@464: { robert@464: for(int j=0; ji) robert@464: s1SortedTouchIndices[j]--; robert@464: } robert@464: } robert@464: } robert@464: // done! now update robert@464: for(int i=0; i 0) robert@464: { robert@464: gSensor1LatestTouchIndex = s1LastIndex; robert@464: } robert@464: else robert@464: s1LastIndex = -1; robert@464: robert@464: /* dbox_printf("-----------------------------\nnum: %d, latest: %d\n", s1TouchNum, gSensor1LatestTouchIndex); robert@464: for(int i=0; ihopNumTh = 0; robert@464: gOscBanks[gCurrentOscBank]->play(1); robert@464: //cout << "Note on" << endl; robert@464: break; robert@464: case 's': robert@464: if(gOscBanks[gCurrentOscBank]->state==bank_playing) robert@464: { robert@464: gOscBanks[gCurrentOscBank]->stop(); robert@464: //cout << "Note off" << endl; robert@464: } robert@464: break; robert@464: //---------------------------------------------------------------------------- robert@464: case '[': robert@464: gOscBanks[gCurrentOscBank]->freqMovement-=0.05; robert@464: if(gOscBanks[gCurrentOscBank]->freqMovement<0) robert@464: gOscBanks[gCurrentOscBank]->freqMovement = 0; robert@464: //cout << "gOscBanks[gCurrentOscBank]->FreqMov: " << gOscBanks[gCurrentOscBank]->freqMovement << endl; robert@464: break; robert@464: case ']': robert@464: gOscBanks[gCurrentOscBank]->freqMovement+=0.05; robert@464: if(gOscBanks[gCurrentOscBank]->freqMovement>1) robert@464: gOscBanks[gCurrentOscBank]->freqMovement = 1; robert@464: //cout << "gOscBanks[gCurrentOscBank]->FreqMov: " << gOscBanks[gCurrentOscBank]->freqMovement << endl; robert@464: break; robert@464: //---------------------------------------------------------------------------- robert@464: case '<': robert@464: speed = gOscBanks[gCurrentOscBank]->getSpeed() - 0.1 ; robert@464: gOscBanks[gCurrentOscBank]->setSpeed(speed); robert@464: dbox_printf("Speed: %f\n", speed); robert@464: robert@464: break; robert@464: case '>': robert@464: speed = gOscBanks[gCurrentOscBank]->getSpeed() + 0.1 ; robert@464: gOscBanks[gCurrentOscBank]->setSpeed(speed); robert@464: dbox_printf("Speed: %f\n", speed); robert@464: break; robert@464: case '0': robert@464: speed = 0.1; robert@464: gOscBanks[gCurrentOscBank]->setSpeed(speed); robert@464: dbox_printf("Speed: %f\n", speed); robert@464: break; robert@464: case '1': robert@464: speed = 0.5; robert@464: gOscBanks[gCurrentOscBank]->setSpeed(speed); robert@464: dbox_printf("Speed: %f\n", speed); robert@464: break; robert@464: case '2': robert@464: speed = 1; robert@464: gOscBanks[gCurrentOscBank]->setSpeed(speed); robert@464: dbox_printf("Speed: %f\n", speed); robert@464: break; robert@464: case '3': robert@464: speed = 2; robert@464: gOscBanks[gCurrentOscBank]->setSpeed(speed); robert@464: dbox_printf("Speed: %f\n", speed); robert@464: break; robert@464: case '4': robert@464: speed = 3; robert@464: gOscBanks[gCurrentOscBank]->setSpeed(speed); robert@464: dbox_printf("Speed: %f\n", speed); robert@464: break; robert@464: //---------------------------------------------------------------------------- robert@464: case 'z': robert@464: gOscBanks[gCurrentOscBank]->setJumpHop(0); robert@464: break; robert@464: case 'x': robert@464: gOscBanks[gCurrentOscBank]->setJumpHop(100); robert@464: break; robert@464: case 'c': robert@464: gOscBanks[gCurrentOscBank]->setJumpHop(600); robert@464: break; robert@464: case 'v': robert@464: gOscBanks[gCurrentOscBank]->setJumpHop(1100); robert@464: break; robert@464: case 'b': robert@464: gOscBanks[gCurrentOscBank]->setJumpHop(2000); robert@464: break; robert@464: case 'n': robert@464: gOscBanks[gCurrentOscBank]->setJumpHop(gOscBanks[gCurrentOscBank]->getLastHop()); robert@464: break; robert@464: //---------------------------------------------------------------------------- robert@464: case 'q': robert@464: gShouldStop = true; robert@464: break; robert@464: case 'o': robert@464: gNextOscBank = (gCurrentOscBank + 1) % gOscBanks.size(); robert@464: break; robert@464: default: robert@464: break; robert@464: //---------------------------------------------------------------------------- robert@464: } robert@464: usleep(1000); /* Wait 1ms to avoid checking too quickly */ robert@464: } robert@464: while (keyStroke!='q'); robert@464: robert@464: cout << "keyboard thread ended" << endl; robert@464: robert@464: return (void *)0; robert@464: }