Mercurial > hg > soniczoomios
view testApp.mm @ 25:f42a00e3f22d
Logs condensed slightly. Questionnaire button enable.
double precision location!!!
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Fri, 01 Feb 2013 17:39:19 +0000 |
parents | a4908ad8c78e |
children | 2e1fdac115af |
line wrap: on
line source
#include "testApp.h" #define SLIDER_GUI_WIDTH 256 #define NUM_PARAMS 10 extern Grid theGridView; extern PresetManager presetManager; extern EventLogger eventLogger; extern Frequencer frequencer; const vector<string> parameterNames; const string sliderParamNames[10] = {"Transpose", "1/4 note","1/6 note","1/7 note","1/8 note","Waveform", "Filter Type","Filter Freq", "Envelope","FM amt"}; //const vector<const string> v(ra[0],ra[1]); //DeviceID3523537000 //-------------------------------------------------------------- void testApp::setup(){ paused = true; ofBackground( 0, 0, 0 ); ofEnableAlphaBlending(); //ofEnableSmoothing(); // open an outgoing connection to HOST:PORT sender.setup( HOST, PORT ); ofSetFrameRate(30); // reciever lastMoveTime = ofGetSystemTimeMicros(); prevTouchX = 0; prevTouchY = 0; xLocked = false; yLocked = false; numActiveTouches = 0; touch0.setCoord(17./7., 2./3.); touch1.setCoord(10,20); prevTouch0.setCoord(1,2); prevTouch1.setCoord(10,20); prevDist = 10; slowFactor = 0.98; // the 5 harmonics for the frequencer freqIndexes.push_back(0); freqIndexes.push_back(4); freqIndexes.push_back(6); freqIndexes.push_back(7); freqIndexes.push_back(8); ofxiPhoneSetOrientation( OFXIPHONE_ORIENTATION_PORTRAIT ); // do this before setting up all the other objects // initialise the interfaces theGridView.init(); setupSliderGui(); sliderGUI->setVisible(true); // initial slider vals for(int i=0; i<10;i++){ sliderVals.push_back(64); } // initialise PD int ticksPerBuffer = 8; // 8 * 64 = buffer len of 512 // setup the app core core.setup(2, 1, 44100, ticksPerBuffer); // setup OF sound stream ofSoundStreamSetup(2, 1, this, 44100, ofxPd::blockSize()*ticksPerBuffer, 3); // set up iOS gui stuff bottomTabViewController = [[BottomTabViewController alloc] initWithNibName:@"BottomTabViewController" bundle:nil]; [ofxiPhoneGetGLParentView() addSubview:bottomTabViewController.view]; [bottomTabViewController setAppRef:(id)this]; [bottomTabViewController show:(id)this]; bottomTabViewController.view.frame = CGRectMake(0,getHeight()-44,getWidth(),44); ///// topButtonViewController = [[TopButtonViewController alloc] initWithNibName:@"TopButtonViewController" bundle:nil]; [ofxiPhoneGetGLParentView() addSubview:topButtonViewController.view]; [topButtonViewController setAppRef:(id)this]; [topButtonViewController show:(id)this]; topButtonViewController.view.frame = CGRectMake(0,0,getWidth(),44); usernameAlertViewController = [[UsernameAlertViewController alloc] init]; /* sliderViewController = [[SliderViewController alloc] initWithNibName:@"SLiderViewController" bundle:nil]; [ofxiPhoneGetGLParentView() addSubview:sliderViewController.view]; [sliderViewController setAppRef:(id)this]; [sliderViewController show:(id)this]; sliderViewController.view.frame = CGRectMake(0,getHeight()-43 - 363,getWidth(),44); */ // initialise user logging stuff presetManager.startupLoadAll(); eventLogger.init(); whichInterfaceShowing = BOTH; // GO paused = false; } //-------------------------------------------------------------- void testApp::exit(){ presetManager.exitAndSaveAll(); eventLogger.exitAndSave(); core.exit(); // are these handled automatically? //[introViewController release]; //[topButtonViewController release]; //[bottomTabViewController release]; delete sliderGUI; cout << "exit done \n"; } //-------------------------------------------------------------- #pragma mark GUI //-- float testApp::getWidth(){ // depends on orientation return ofGetWidth(); } float testApp::getHeight(){ // depends on orientation return ofGetHeight(); } #pragma mark GUI //////////////////////////// // These functions called from iOS toolbars //-------------------------------------------------------------- void testApp::lockSequencerPressed(bool locked){ theGridView.shiftCentreToSnapped(); xLocked = locked; eventLogger.logEvent(SEQ_LOCKED); } //-------------------------------------------------------------- void testApp::lockSynthPressed(bool locked){ theGridView.shiftCentreToSnapped(); yLocked = locked; eventLogger.logEvent(SYNTH_LOCKED); } //-------------------------------------------------------------- void testApp::seqStartStop(bool go){ if(!go){ //stop core.pd.startMessage(); core.pd.addFloat(0); core.pd.finishMessage("fromOF", "seqStartStop"); eventLogger.logEvent(PAUSE_PRESSED); }else { // play //stopSequencer(); core.pd.startMessage(); core.pd.addFloat(1); core.pd.finishMessage("fromOF", "seqStartStop"); eventLogger.logEvent(PLAY_PRESSED); } } //-------------------------------------------------------------- void testApp::showQuestionnaire(){ // stop updating / drawing // if(eventLogger.questionnaireCompleted) return; paused = true; //stopSequencer core.pd.startMessage(); core.pd.addFloat(0); core.pd.finishMessage("fromOF", "seqStartStop"); questionnaireViewController = [[QuestionnaireViewController alloc] initWithNibName:@"QuestionnaireViewController" bundle:nil]; [ofxiPhoneGetGLParentView() addSubview:questionnaireViewController.view]; [questionnaireViewController setAppRef:(id)this]; [questionnaireViewController show:(id)this]; whichInterfaceShowing = QUESTIONNAIRE; } //-------------------------------------------------------------- void testApp::questionnaireHidden(vector<int> answers){ // send answers to server as json eventLogger.questionnaireAnswersObtained(answers); // set "we've done questionnaire" to true in event logger paused = false; //startSequencer (TODO what about the toggle ? ?) core.pd.startMessage(); core.pd.addFloat(1); core.pd.finishMessage("fromOF", "seqStartStop"); whichInterfaceShowing = BOTH; // tell bottomtabviewcontroller } //-------------------------------------------------------------- void testApp::showIntro(){ paused = true; cout << "SHOW INTRO\n"; introViewController = [[IntroViewController alloc] initWithNibName:@"IntroViewController" bundle:nil]; [ofxiPhoneGetGLParentView() addSubview:introViewController.view]; [introViewController setAppRef:(id)this]; [introViewController show:(id)this]; whichInterfaceShowing = INTRO; } //-------------------------------------------------------------- void testApp::introHidden(bool OK){ if(OK){ paused = false; eventLogger.consentGiven = true; whichInterfaceShowing = BOTH; // show username prompt [usernameAlertViewController showUserNamePrompt]; } // no unOK } //-------------------------------------------------------------- // called from BottomTabViewController iOS segmented thing void testApp::interfaceSelected(int which){ switch (which){ case 0: whichInterfaceShowing = SLIDERS; sliderGUI->setVisible(true); // set the slider values to stuff got from zoomer sliderVals = theGridView.getParams(); setAllGUISliders(sliderVals); break; case 1: whichInterfaceShowing = BOTH; sliderGUI->setVisible(true); // set the slider values to stuff got from zoomer sliderVals = theGridView.getParams(); setAllGUISliders(sliderVals); break; case 2: sliderGUI->setVisible(false); whichInterfaceShowing = ZOOMER; break; } eventLogger.logEvent(SWAP_VIEW,TwoVector(),0.0, which); } //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::setupSliderGui(){ float xInit = OFX_UI_GLOBAL_WIDGET_SPACING; float length = SLIDER_GUI_WIDTH - (OFX_UI_GLOBAL_WIDGET_SPACING*2); //float dim = 42; // make this iphone size...? int height = 480; int width = 320; float dim = (height-10.0*OFX_UI_GLOBAL_WIDGET_SPACING)/10.0; // LEFT GUI sliderGUI = new ofxUICanvas(0,100,SLIDER_GUI_WIDTH,getHeight()); // Uh.. loop this for(int i = 1; i<=10;i++){ ofxUISlider *slider; slider = (ofxUISlider *)sliderGUI->addWidgetDown(new ofxUISlider(length,dim,0.0,127,64,sliderParamNames[i-1])); slider->setDrawPadding(true); if(i <= 5){ slider->setColorFill(ofColor(0,0,255)); slider->setColorFillHighlight(ofColor(0,0,255)); }else{ slider->setColorFill(ofColor(255,0,0)); slider->setColorFillHighlight(ofColor(255,0,0)); } sliders.push_back(slider); } ofAddListener(sliderGUI->newGUIEvent, this, &testApp::sliderGUIEvent); } //-------------------------------------------------------------- void testApp::sliderGUIEvent(ofxUIEventArgs &e){ if(whichInterfaceShowing == ZOOMER){ cout << "GUI ERROR"; return; } // "normal" parameter changes for(int i = 1; i<=10;i++){ if(e.widget->getName() == sliderParamNames[i-1]) { //cout << "param change: " << p; ofxUISlider *slider = (ofxUISlider *) e.widget; sliderMoved(i-1,slider->getScaledValue()); // internal array 0 indexed } } } //-------------------------------------------------------------- void testApp::sliderMoved(int which, float value){ // an update caused by slider view being touched sliderVals[which] = (int)value; theGridView.setParams(sliderVals); sendParametersToPD(); eventLogger.logEvent(CHANGE_SLIDER, TwoVector(),0.0,which , value); } //-------------------------------------------------------------- void testApp::setAllGUISliders(vector<int> vals){ // an update caused by zoomer view being moved for(int i = 0; i<NUM_PARAMS;i++){ sliders[i]->setValue(vals[i]); sliderVals[i] = vals[i]; } } //-------------------------------------------------------------- void testApp::randomise(){ // pick random settings for all params for(int i=0; i < NUM_PARAMS ; i++){ sliderVals[i] = ofRandom(0, 127); } // send to grid, sliders and PD theGridView.setParams(sliderVals); setAllGUISliders(sliderVals); sendParametersToPD(); eventLogger.logEvent(RANDOMISE, theGridView.getCoord() ,0.0); } //-------------------------------------------------------------- void testApp::sendParametersToPD(){ // frequencer stuff to get 16 steps vector<double> vals; vals.push_back((sliderVals[0]+32)*8.); // DC offset for(int i=1; i<5;i++){ vals.push_back((sliderVals[i] - 64)*2.); } vector<double> steps = frequencer.freqMagEdit(freqIndexes, vals); // send a list using the List object List seqSteps; seqSteps.addSymbol("seqSteps"); for(int i=0; i < 16; i++){ seqSteps.addFloat(round(steps[i])); // rounding here?? } core.pd.sendList("fromOF", seqSteps); sendOscShape(sliderVals[5]); sendFiltType(sliderVals[6]); sendFiltFreq(sliderVals[7]); sendEnvShape(sliderVals[8]); sendModFreq(sliderVals[9]); } //-------------------------------------------------------------- #pragma mark STANDARD OF FUNCTIONS //-------------------------------------------------------------- void testApp::update(){ //we do a heartbeat on iOS as the phone will shut down the network connection to save power //this keeps the network alive as it thinks it is being used. if(paused) return; if( ofGetFrameNum() % 120 == 0 ){ ofxOscMessage m; m.setAddress( "/misc/heartbeat" ); m.addIntArg( ofGetFrameNum() ); sender.sendMessage( m ); } // continiue to move at velocity, unless snapped if (numActiveTouches == 0){ // no touches, use momentum if(moveVel.norm() > 0.3){ if(theGridView.snapped){ // stop it, send snap event moveVel.setCoord(0.0,0.0); }else{ theGridView.move(moveVel); moveVel = moveVel*slowFactor; } // and get new parameter values setAllGUISliders(theGridView.getParams()); sendParametersToPD(); }else if(moveVel.norm() > 0.01){ // and less than 0.3 // stop it moveVel.setCoord(0.0,0.0); setAllGUISliders(theGridView.getParams()); sendParametersToPD(); eventLogger.logEvent(SCROLL_STOPPED, theGridView.getCoord() ); }else{ // stopped - do nothing } } // continiue to zoom at velocity if (numActiveTouches < 2 && abs(zoomVel)>0.001){ theGridView.zoom(zoomVel + 1.0); // +1 because zoomVel factor is + or - , wheras zoom is a multiplier near 1 zoomVel = zoomVel*slowFactor; } } //-------------------------------------------------------------- void testApp::sendOSCParams(){ vector<int> params = theGridView.getParams(); // FILTER HERE? NEED FLOATS... vector<int>::iterator iter = params.begin(); ofxOscMessage m; m.setAddress( "p" ); for(;iter < params.end();iter++){ m.addFloatArg( *iter ); } sender.sendMessage( m ); } //-------------------------------------------------------------- void testApp::draw(){ if(paused) return; switch (whichInterfaceShowing){ case SLIDERS: break; case ZOOMER: theGridView.draw(); break; case BOTH: theGridView.draw(); break; case INTRO: break; case QUESTIONNAIRE: break; } } //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ // TODO check if in gui area!!! if(whichInterfaceShowing == SLIDERS){ return; }else if (whichInterfaceShowing == BOTH && touch.x < (SLIDER_GUI_WIDTH+10)){ return; }// otherwise we're good to let the zoomer handle touch numActiveTouches++; // absolute position doesn't matter // which one? if(touch.id == 0){ touch0.setCoord(touch.x,touch.y); prevTouch0 = touch0; }else if(touch.id == 1){ touch1.setCoord(touch.x,touch.y); prevTouch1 = touch1; } if(numActiveTouches == 1){ moveVel.setCoord(0.0, 0.0); prevMove.setCoord(0.0, 0.0); prevMove2.setCoord(0.0, 0.0); }else if(numActiveTouches == 2){ zoomVel = 0.0; prevZoom = 0.0; prevZoom2 = 0.0; double dist = touch1.distanceTo(touch0); prevDist = dist; } } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ // TODO check if in gui area!!! if(whichInterfaceShowing == SLIDERS){ return; }else if (whichInterfaceShowing == BOTH && touch.x < (SLIDER_GUI_WIDTH+10)){ return; }// otherwise we're good to let the zoomer handle touch // check if in other gui area if(touch.x > getWidth()-200 && touch.y < 300){ return; } // which one? keep track of each touch point if(touch.id == 0){ touch0.setCoord(touch.x,touch.y); }else if(touch.id == 1){ touch1.setCoord(touch.x,touch.y); } if(numActiveTouches == 1){ handleScroll(); }else if(numActiveTouches == 2){ handleZoom(); } prevTouch0 = touch0; } //-------------------------------------------------------------- void testApp::handleScroll(){ TwoVector move = touch0 - prevTouch0; if(yLocked){ move.y = 0.0; } if(xLocked){ move.x = 0.0; } // check time since last move - if unsigned int moveTime = ofGetSystemTimeMicros(); if(moveTime - lastMoveTime > 100000){ moveVel = TwoVector(); // zero }else{ moveVel = (move*0.3 + prevMove*0.34 + prevMove2*0.38); // use the time } lastMoveTime = moveTime; prevMove2 = prevMove; prevMove = move; theGridView.move(move); // and get new parameter values setAllGUISliders(theGridView.getParams()); sendParametersToPD(); } //-------------------------------------------------------------- void testApp::handleZoom(){ // work out change in difference double dist = touch1.distanceTo(touch0); double zoomFactor = prevDist/dist; //TODO check for sensible maximums, e.g. spurious touch data if(zoomFactor > 2.0 || zoomFactor < 0.5){ cout << "Zoom too much!!!!" << zoomFactor; zoomFactor = 1.0; } zoomVel = (zoomFactor-1)*0.3 + prevZoom*0.34 + prevZoom2*0.38; prevZoom2 = prevZoom; prevZoom = (zoomFactor-1); theGridView.zoom(zoomFactor); prevDist = dist; } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ if(numActiveTouches > 0) numActiveTouches--; // dirty // TODO check if in gui area!!! if(whichInterfaceShowing == SLIDERS){ return; }else if (whichInterfaceShowing == BOTH && touch.x < 256){ return; }// otherwise we're good to let the zoomer handle touch // which one? if(touch.id == 0){ // tricky situation - we tried to zoom but may have left non-move finger on prevTouch0.setCoord(touch.x,touch.y); }else if(touch.id == 1){ prevTouch1.setCoord(0,0); } if(numActiveTouches == 0){ // check time since last move // check time since last move - if unsigned int moveTime = ofGetSystemTimeMicros(); if(moveTime - lastMoveTime > 100000){ moveVel = TwoVector(); // zero }else{ moveVel = (move*0.3 + prevMove*0.34 + prevMove2*0.38); // use the time } lastMoveTime = moveTime; } } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ // preset? /* ballses everything for some reason TwoVector centre = TwoVector(getWidth()*0.5,getHeight()*0.5); // if near centre if((touch.x < centre.x+10) && (touch.x > centre.x-10) && (touch.y < centre.y+10) && (touch.y > centre.y-10)){ numActiveTouches = 0; // dirty presetManager.showNameDialog(); } */ } //-------------------------------------------------------------- void testApp::lostFocus(){ } //-------------------------------------------------------------- void testApp::gotFocus(){ } //-------------------------------------------------------------- void testApp::gotMemoryWarning(){ } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ /* cout << "orientation: " << newOrientation; if(newOrientation == 4){ ofxiPhoneSetOrientation( OF_ORIENTATION_DEFAULT ); }else if(newOrientation == 3){ ofxiPhoneSetOrientation( OF_ORIENTATION_90_LEFT ); }else if(newOrientation == 3){ ofxiPhoneSetOrientation( OF_ORIENTATION_90_LEFT ); } [ofxiPhoneGetGLView() updateDimensions]; */ } //-------------------------------------------------------------- void testApp::touchCancelled(ofTouchEventArgs& args){ } //--------------------------------------------------------------- // AUDIO STUFF //--------------------------------------------------------------- #pragma mark AUDIO STREAMS //-------------------------------------------------------------- void testApp::audioReceived(float * input, int bufferSize, int nChannels) { core.audioReceived(input, bufferSize, nChannels); } void testApp::audioRequested(float * output, int bufferSize, int nChannels) { core.audioRequested(output, bufferSize, nChannels); } //--------------------------------------------------------------- #pragma mark UTILITIES // 5hz cut off const double fB[3] = {0.049489956268677, 0.098979912537354, 0.049489956268677}; const double fA[3] = {1.000000000000000, -1.279632424997809, 0.477592250072517}; // 1hz cut off //const double fB[3] = {0.002550535158536, 0.005101070317073, 0.002550535158536}; //const double fA[3] = {1.000000000000000, -1.852146485395936, 0.862348626030081}; //a(1)*y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb)- a(2)*y(n-1) - ... - a(na+1)*y(n-na) //--------------------------------------------------------------- vector<float> testApp::vectorFilter(vector<float> newVec){ static vector<float> x0(10,0); static vector<float> x1(10,0); static vector<float> x2(10,0); static vector<float> y0(10,0); static vector<float> y1(10,0); static vector<float> y2(10,0); x0 = newVec; // this low passes a bunch of params values all at once int sz = newVec.size(); for(int i=0; i<sz; i++){ y0[i] = fB[0]*x0[i] + fB[1]*x1[i] + fB[2]*x2[i] - fA[1]*y1[i] - fA[2]*y2[i]; } // shift x2 = x1; x1 = x0; y2 = y1; y1 = y0; return y0; } float ctrlSmoother(float newsamp){ static float x1,x2,y1,y2; float x0, y0; x0 = newsamp; y0 = fB[0]*x0 + fB[1]*x1 + fB[2]*x2 - fA[1]*y1 - fA[2]*y2; // shift x2 = x1; x1 = x0; y2 = y1; y1 = y0; return y0; } //--------------------------------------------------------------- void testApp::sendOscShape(int ctrlin){ static int numpoints = 5; static int numcontrols = 5; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[5] = {"pWidth" , "sqVol", "sawVol", "sineVol", "FMAmt"}; float values[5][5] = {{0.5, 0., 0., 1., 1.}, // 0 {0.5, 0., 0., 1., 0.}, // 32 {0.5, 0., 1., 0., 0.}, // 64 {0.5, 1., 1., 0., 0.}, // 96 {0.01,1., 1., 0., 0.}}; // 127 float fidx = (numpoints-1)*ctrlin/128.; int idx = floor(fidx); float frac = fidx - idx; for(int i=0; i < numcontrols; i++){ ctrlout[i] = (1 - frac)*values[idx][i] + (frac)*values[idx+1][i]; // send to PD List toPD; toPD.addSymbol(ctrlName[i]); toPD.addFloat(ctrlout[i]); // rounding here?? core.pd.sendList("fromOF", toPD); //cout << ctrlName[i] << "sending" << ctrlout[i] << "\n"; } } //--------------------------------------------------------------- void testApp::sendFiltType(int ctrlin){ static int numpoints = 3; static int numcontrols = 4; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[4] = {"lpLev" , "bpLev", "hpLev", "reson"}; float values[3][4] = {{2., 0., 0., 1.}, // 0 {0., 10., 0., 10.}, // 64 {0., 0., 1., 1.}}; // 127 float fidx = (numpoints-1)*ctrlin/128.; int idx = floor(fidx); float frac = fidx - idx; for(int i=0; i < numcontrols; i++){ ctrlout[i] = (1 - frac)*values[idx][i] + (frac)*values[idx+1][i]; // send to PD List toPD; toPD.addSymbol(ctrlName[i]); toPD.addFloat(ctrlout[i]); // rounding here?? core.pd.sendList("fromOF", toPD); //cout << ctrlName[i] << "sending" << ctrlout[i] << "\n"; } } //--------------------------------------------------------------- void testApp::sendFiltFreq(int ctrlin){ // smooth this float fin = ctrlin; float fout; fout = (int)ctrlSmoother(fin); List toPD; toPD.addSymbol("filtFreq"); toPD.addFloat(fout); core.pd.sendList("fromOF", toPD); } //--------------------------------------------------------------- void testApp::sendEnvShape(int ctrlin){ static int numpoints = 5; static int numcontrols = 3; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[3] = {"attack" , "decay", "sustain"}; float values[5][3] = {{0., 0., 0.}, // 0 {0., 0.5, 0.}, // 32 {0.0, 1., 0.8}, // 64 {0.99, 0.3, 0.}, // 96 {0.3, 0.1, 0.}}; // 127 float fidx = (numpoints-1)*ctrlin/128.; int idx = floor(fidx); float frac = fidx - idx; for(int i=0; i < numcontrols; i++){ ctrlout[i] = (1 - frac)*values[idx][i] + (frac)*values[idx+1][i]; // send to PD List toPD; toPD.addSymbol(ctrlName[i]); toPD.addFloat(ctrlout[i]); // rounding here?? core.pd.sendList("fromOF", toPD); //cout << ctrlName[i] << "sending" << ctrlout[i] << "\n"; } } //--------------------------------------------------------------- void testApp::sendModFreq(int ctrlin){ float fm = ctrlin/127.; List toPD; toPD.addSymbol("FMFreq"); toPD.addFloat(fm); // rounding here?? core.pd.sendList("fromOF", toPD); } //---------------------------------------------------------------