Mercurial > hg > soniczoomios
view testApp.mm @ 49:178642d134a7 tip
xtra files
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Wed, 01 May 2013 17:34:33 +0100 |
parents | 0d3a993405e4 |
children |
line wrap: on
line source
#include "testApp.h" extern Grid theGridView; extern PresetManager presetManager; extern EventLogger eventLogger; extern Frequencer frequencer; extern Hilbert hilbert; 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]); // really GUI and all that stuff should be somewhere else //-------------------------------------------------------------- void testApp::setup(){ // initilaise initialiseVariables(); initialiseGUIs(); // initialise PD int ticksPerBuffer = 8; // 8 * 64 = buffer len of 512 core.setup(2, 1, 44100, ticksPerBuffer); // send to PD List toPD; toPD.addSymbol("smoothing"); toPD.addFloat(70); // rounding here?? core.pd.sendList("fromOF", toPD); //cout << ctrlName[i] << "sending" << ctrlout[i] << "\n"; // setup OF sound stream ofSoundStreamSetup(2, 1, this, 44100, ofxPd::blockSize()*ticksPerBuffer, 3); tsc = [[TimedSessionController alloc] init]; [tsc setAppRef:(id)this]; //-------------------------------------- // load stuff loadSequences(); // load presets presetManager.startLoadAll(); eventLogger.startLoadAll(); //-------------------------------------- // now do things that will affect the start up state of the app //if(true){ if(eventLogger.questionnaireCompleted){ // then we go into do-what-you-like mode freeUseMode(); randomise(); }else{ // then we're in timed session mode showIntro(); } //freeUseMode(); // GO paused = false; eventLogger.logEvent(APP_STARTED); } //----------------------------------------------------------------------------- //DeviceID3523537000 void testApp::initialiseVariables(){ animatingGrid = false; paused = true; sendMIDIAndOSC = false; allowAnimation = false; ofBackground( 0, 0, 0 ); ofEnableAlphaBlending(); currentSequence = 0; //ofEnableSmoothing(); // open an outgoing connection to HOST:PORT for OSC sender.setup( OSC_HOST, OSC_PORT ); ofSetFrameRate(50); 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; preventingMovePostScroll = false; // 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 ); ofxiPhoneExternalDisplay::mirrorOn(); } //--------------------------------------------------------- void testApp::initialiseGUIs(){ theGridView.init(); //SLIDER //setupSliderGui(); //sliderGUI->setVisible(false); // initial slider vals for(int i=0; i<10;i++){ sliderVals.push_back(64); } // set up iOS gui stuff bottomTabViewController = [[BottomTabViewController alloc] initWithNibName:@"BottomTabViewController" bundle:nil]; [ofxiPhoneGetGLParentView() addSubview:bottomTabViewController.view]; [bottomTabViewController setAppRef:(id)this]; bottomTabViewController.view.frame = CGRectMake(0,getHeight()-44,getWidth(),44); bottomTabViewController.view.hidden = YES; ///// 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); //SLIDER sliderViewController = [[SliderViewController alloc] initWithNibName:@"SliderViewController" bundle:nil]; [ofxiPhoneGetGLParentView() addSubview:sliderViewController.view]; [sliderViewController setAppRef:(id)this]; sliderViewController.view.frame = CGRectMake(0,getHeight()-43 - 278,getWidth(),278); [sliderViewController show:(id)this]; helpViewController = [[HelpViewController alloc] initWithNibName:@"HelpViewController" bundle:nil]; [ofxiPhoneGetGLParentView() addSubview:helpViewController.view]; [helpViewController setAppRef:(id)this]; helpViewController.view.hidden = YES; usernameAlertViewController = [[UsernameAlertViewController alloc] init]; [usernameAlertViewController setAppRef:(id)this]; ////// ///////// setAllGUISliders(theGridView.getParams()); } //-------------------------------------------------------------------------- void testApp::initialiseMIDI(){ ///////////////////////// // MIDI midiChannel = 7; midiOffset = 12; // enables the network midi session between iOS and Mac OSX on a // local wifi network // // in ofxMidi: open the input/outport network ports named "Session 1" // // on OSX: use the Audio MIDI Setup Utility to connect to the iOS device // ofxMidi::enableNetworking(); // list the number of available input & output ports ofxMidiIn::listPorts(); ofxMidiOut::listPorts(); // create and open input ports for(int i = 0; i < ofxMidiIn::getNumPorts(); ++i) { // new object inputs.push_back(new ofxMidiIn); // set this class to receive incoming midi events inputs[i]->addListener(this); // open input port via port number inputs[i]->openPort(i); } // create and open output ports for(int i = 0; i < ofxMidiOut::getNumPorts(); ++i) { // new object outputs.push_back(new ofxMidiOut); // open input port via port number outputs[i]->openPort(i); } // set this class to receieve midi device (dis)connection events ofxMidi::setConnectionListener(this); // END MIDI } //-------------------------------------------------------------- void testApp::exit(){ presetManager.exitAndSaveAll(); eventLogger.exitAndSave(); core.exit(); // are these handled automatically? //[introViewController release]; //[topButtonViewController release]; //[bottomTabViewController release]; // clean up MIDI for(int i = 0; i < inputs.size(); ++i) { inputs[i]->closePort(); inputs[i]->removeListener(this); delete inputs[i]; } for(int i = 0; i < outputs.size(); ++i) { outputs[i]->closePort(); delete outputs[i]; } //SLIDER //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); // TODO whatabout unlock? } //-------------------------------------------------------------- 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; [topButtonViewController pausePressed:(id)this]; //stopSequencer seqStartStop(false); 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, const char* userComments){ // send answers to server as json eventLogger.questionnaireAnswersObtained(answers, userComments); freeUseMode(); } //-------------------------------------------------------------- // shortcut function for testing void testApp::justStart(){ freeUseMode(); } //-------------------------------------------------------------- void testApp::freeUseMode(){ interfaceSelected(1); [bottomTabViewController show:(id)this withSelection:1]; [topButtonViewController enableSmoothSwitch:(id)this]; sendMIDIAndOSC = true; allowAnimation = true; } //-------------------------------------------------------------- void testApp::setInterp(int state){ if(state == 0){ theGridView.setInterpolation(Grid::NO_INTERPOLATION); eventLogger.logEvent(SMOOTHING_OFF); }else if(state == 1){ theGridView.setInterpolation(Grid::INTERPOLATE_GRID); eventLogger.logEvent(SMOOTHING_ON); } // tell sliders and PD setAllGUISliders(theGridView.getParams()); } //-------------------------------------------------------------- void testApp::showIntro(){ cout << "SHOW INTRO\n"; [tsc cancelTimers]; bottomTabViewController.view.hidden = YES; 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){ eventLogger.consentGiven = true; // // clear presets? //presetManager.clearAll(); // show username prompt [usernameAlertViewController showUserNamePrompt]; // reset top buttons [topButtonViewController unlockAll]; randomise(); } // no unOK } //-------------------------------------------------------------- void testApp::startTimedSession(){ [tsc startTimer]; // timer will show alert and set interface } //-------------------------------------------------------------- // called from BottomTabViewController iOS segmented thing, also timed session controller void testApp::interfaceSelected(int which){ if(whichInterfaceShowing == HELP){ // hide the help [helpViewController hide:(id) this]; } switch (which){ case 0: // slider //SLIDER whichInterfaceShowing = SLIDERS; [sliderViewController show:(id)this]; // set the slider values to stuff got from zoomer sliderVals = theGridView.getParams(); setAllGUISliders(sliderVals); break; case 1: // both //SLIDER whichInterfaceShowing = BOTH; [sliderViewController show:(id)this]; // set the slider values to stuff got from zoomer sliderVals = theGridView.getParams(); setAllGUISliders(sliderVals); break; case 2: // zoomer //SLIDER [sliderViewController hide:(id)this]; whichInterfaceShowing = ZOOMER; break; } eventLogger.logEvent(SWAP_VIEW,theGridView.getCoord(),theGridView.getScale(), which); } //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::sliderMoved(int which, float value){ // an update caused by slider view being touched sliderVals[which] = (int)value; theGridView.setParams(sliderVals); sendParametersToPD(); if(sendMIDIAndOSC){ sendMidiParam(which); sendOSCParams(); } eventLogger.logEvent(CHANGE_SLIDER, theGridView.getCoord(),0.0,which , value); } //-------------------------------------------------------------- void testApp::setAllGUISliders(vector<int> vals){ // an update caused by zoomer view being moved // can be called by theGridView or testApp // casues PD and midi to be sent for(int i = 0; i<NUM_PARAMS;i++){ //sliders[i]->setValue(vals[i]); sliderVals[i] = vals[i]; [sliderViewController setSlider:i to:vals[i]]; } sendParametersToPD(); if(sendMIDIAndOSC){ sendMidiParams(); sendOSCParams(); } } //-------------------------------------------------------------- void testApp::randomise(){ // pick random settings for all params // random zoom? no. for(int i=0; i < NUM_PARAMS ; i++){ sliderVals[i] = ofRandom(0, 127); } currentSequence = ofRandom(0, sequences.size()-1); // send to grid, sliders and PD theGridView.setParams(sliderVals); setAllGUISliders(sliderVals); eventLogger.logEvent(RANDOMISE, theGridView.getCoord() ,theGridView.getScale()); } //-------------------------------------------------------------- void testApp::showHelp(){ previousInterface = whichInterfaceShowing; whichInterfaceShowing = HELP; seqStartStop(false); [topButtonViewController pausePressed:(id)this]; helpViewController.view.hidden = NO; eventLogger.logEvent(HELP_PRESSED); } void testApp::helpHidden(){ whichInterfaceShowing = previousInterface; // start seq? } //-------------------------------------------------------------- int testApp::nextSequence(){ currentSequence++; if(currentSequence >= sequences.size()){ currentSequence = 0; } sendParametersToPD(); return currentSequence; } //-------------------------------------------------------------- //-------------------------------------------------------------- #pragma mark sending to pd and midi void testApp::sendParametersToPD(){ static int previousSequence; if(core.patchName == "synth5paramMM.pd"){ // 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); List seqSteps; seqSteps.addSymbol("seqSteps"); for(int i=0; i < 16; i++){ seqSteps.addFloat(round(steps[i])); } core.pd.sendList("fromOF", seqSteps); // send synth params sendOscShape(sliderVals[5]); sendFiltType(sliderVals[6]); sendFiltFreq(sliderVals[7]); sendEnvShape(sliderVals[8]); sendModFreq(sliderVals[9]); }else if (core.patchName == "synth10param.pd"){ // for 10 param synth we get sequence from saved presets // and send 5 extra synth params if(currentSequence != previousSequence){ List seqSteps; seqSteps.addSymbol("seqSteps"); if(currentSequence >= sequences.size() || currentSequence < 0){ cout << "ERROR: not a valid sequence index\n"; for(int i=0; i < 16; i++){ seqSteps.addFloat(50); } }else{ for(int i=0; i < 16; i++){ seqSteps.addFloat(round(sequences[currentSequence][i])); } } core.pd.sendList("fromOF", seqSteps); previousSequence = currentSequence; } /* @"Amp Env",@"Waveform",@"FM amount",@"FM frequency",@"Reverb", @"Filter Type",@"Filter Cut off",@"Filter Resonance",@"Filter Envelope",@"SOMETHING", */ // send synth params sendAmpEnvShape(sliderVals[0]); sendOscShape(sliderVals[1]); sendFMAmt(sliderVals[2]); sendModFreq(sliderVals[3]); sendRevAmt(sliderVals[4]); sendFiltType(sliderVals[5]); sendFiltFreq(sliderVals[6]); sendResonance(sliderVals[7]); sendFiltEnvShape(sliderVals[8]); sendFiltEnvModAmt(sliderVals[9]); //sendUmame(sliderVals[8]); //sendX(sliderVals[2]); //sendX(sliderVals[3]); } /* cout << "SLIDERVALS: "; for(int i=0;i<10;i++){ cout << sliderVals[i] << ","; } cout << '\n'; */ } //-------------------------------------------------------------- void testApp::sendMidiParam(int which){ int midiChannel = 7; int offset = 0; for(int i = 0; i < outputs.size(); ++i) { outputs[i]->sendControlChange(midiChannel, offset+which, sliderVals[which]); } } //-------------------------------------------------------------- void testApp::sendMidiParams(){ for(int i = 0; i< sliderVals.size(); i++){ for(int j = 0; j < outputs.size(); ++j) { outputs[j]->sendControlChange(midiChannel, midiOffset+i, sliderVals[i]); } } } //-------------------------------------------------------------- void testApp::sendOSCParams(){ ofxOscMessage m; m.setAddress( "sonicZoom" ); for(int i = 0; i< sliderVals.size(); i++){ m.addFloatArg(sliderVals[i]); } sender.sendMessage( m ); } //-------------------------------------------------------------- void testApp::setupNewUser(){ // this function is for supervised trials with my ipad eventLogger.newUser(); } //-------------------------------------------------------------- #pragma mark STANDARD OF FUNCTIONS //-------------------------------------------------------------- void testApp::update(){ if(paused) return; if(theGridView.automatedMovementInProgress){ theGridView.update(); return; } if(ofxiPhoneExternalDisplay::isExternalScreenConnected()){ if(!ofxiPhoneExternalDisplay::isMirroring()){ ofxiPhoneExternalDisplay::mirrorOn(); printf("turned on Mirroring!\n"); } } if(animatingGrid){ // theGrid } // continiue to move or zoom at velocity, unless snapped if (numActiveTouches == 0){ // no touches, use momentum // ZOOM MOMENTUM // 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; moveVel.setCoord(0.0,0.0);; // don't move if zooming! Too many events! setAllGUISliders(theGridView.getParams()); } // MOVE MOMENTUM if(moveVel.norm() > 0.3){ if(theGridView.snapped){ // stop it (snap check sends snap event) moveVel.setCoord(0.0,0.0); }else{ theGridView.move(moveVel); moveVel = moveVel*slowFactor; } // and get new parameter values setAllGUISliders(theGridView.getParams()); }else if(moveVel.norm() > 0.01){ // and less than 0.3 // stop it moveVel.setCoord(0.0,0.0); setAllGUISliders(theGridView.getParams()); eventLogger.logEvent(SCROLL_STOPPED, theGridView.getCoord() ); }else{ // stopped - do nothing } } } //-------------------------------------------------------------- void testApp::draw(){ 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){ if(theGridView.automatedMovementInProgress) return; if(whichInterfaceShowing == SLIDERS){ return; } numActiveTouches++; preventingMovePostScroll = false; tapFlag = false; // unless touch 0 if(touch.id == 0){ touch0.setCoord(touch.x,touch.y); prevTouch0 = touch0; // stop zoom zoomVel = 0.0; tapFlag = true; }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){ if(theGridView.automatedMovementInProgress) return; if(whichInterfaceShowing == SLIDERS){ return; } tapFlag = false; // 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){ if(preventingMovePostScroll) return; handleScroll(); }else if(numActiveTouches == 2){ handleZoom(); } prevTouch0 = touch0; } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ if(theGridView.automatedMovementInProgress) return; if(whichInterfaceShowing == SLIDERS){ return; } if(numActiveTouches > 0) numActiveTouches--; // dirty preventingMovePostScroll = false; // TODO check if in gui area!!! //SLIDER if(whichInterfaceShowing == SLIDERS){ return; } if(tapFlag){ cout << "TAP!!\n"; // look for close preset theGridView.tap(TwoVector(touch.x,touch.y)); } tapFlag = false; // 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; }else if (numActiveTouches == 1){ // just zoomed , but now lifted one of the fingers // can be bad if moved so create special mode to stop scroll (special modes bad!) preventingMovePostScroll = true; } } //-------------------------------------------------------------- // handle a finger being dragged 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()); } //-------------------------------------------------------------- // handle pinch movememnt 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; setAllGUISliders(theGridView.getParams()); } //-------------------------------------------------------------- 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; } //--------------------------------------------------------------- //--------------------------------------------------------------- //--------------------------------------------------------------- #pragma mark SYNTH PARAM SENDING TO PD CURVES void testApp::sendOscShape(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } static int numpoints = 5; static int numcontrols = 5; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[4] = {"pWidth" , "sqVol", "sawVol", "sineVol"}; float values[5][4] = {{0.5, 0., 0., 1.}, // 0 {0.5, 0., 0., 1.}, // 32 {0.5, 0., 1., 0.}, // 64 {0.5, 1., 1., 0.}, // 96 {0.01,1., 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::sendFiltType(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } /* static int numpoints = 3; static int numcontrols = 2; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[2] = {"fType","reson"}; float values[3][2] = {{0., 45}, // 0 {0.5, 120}, // 64 {1., 55}}; // 127 */ static int numpoints = 2; static int numcontrols = 1; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[2] = {"fType"}; float values[2][1] = {{0.}, // 0 {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::sendFiltTypeOld(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } 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){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } // 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){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } 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"; } } //--------------------------------------------------------------- // alternative envelopes: seperate for amp and filt void testApp::sendAmpEnvShape(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } 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("aenv"); toPD.addSymbol(ctrlName[i]); toPD.addFloat(ctrlout[i]); // rounding here?? core.pd.sendList("fromOF", toPD); //cout << ctrlName[i] << "sending" << ctrlout[i] << "\n"; } } //--------------------------------------------------------------- void testApp::sendFiltEnvShape(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } 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("fenv"); toPD.addSymbol(ctrlName[i]); toPD.addFloat(ctrlout[i]); // rounding here?? core.pd.sendList("fromOF", toPD); //cout << ctrlName[i] << "sending" << ctrlout[i] << "\n"; } } //--------------------------------------------------------------- void testApp::sendFiltEnvModAmt(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } float amt = ctrlin/127.0; List toPD; toPD.addSymbol("fenv"); toPD.addSymbol("amount"); toPD.addFloat(amt); // rounding here?? core.pd.sendList("fromOF", toPD); } //--------------------------------------------------------------- void testApp::sendModFreq(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } float fm = ctrlin/127.; List toPD; toPD.addSymbol("FMFreq"); toPD.addFloat(fm); // rounding here?? core.pd.sendList("fromOF", toPD); } //--------------------------------------------------------------- //--------------------------------------------------------------- void testApp::sendRevAmt(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } static int numpoints = 5; static int numcontrols = 2; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[3] = {"revDryWet" , "revLength"}; float values[5][3] = {{0., 0.1}, // 0 {0., 0.1}, // 32 {0.3, 30.}, // 64 {0.6, 60.}, // 96 {1., 95.}}; // 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::sendResonance(int ctrlin){ if(ctrlin < 0 || ctrlin > 127){ cout << "ERROR: bad slider value!"; return; } float res = ctrlin; List toPD; toPD.addSymbol("reson"); toPD.addFloat(res); // rounding here?? core.pd.sendList("fromOF", toPD); } //--------------------------------------------------------------------------- void testApp::sendFMAmt(int ctrlin){ static int numpoints = 4; static int numcontrols = 1; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[1] = {"FMAmt"}; float values[4][1] = {{0.}, // 0 {0.}, // {0.3}, // {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::sendDistortion(int ctrlin){ static int numpoints = 5; static int numcontrols = 2; //float values[points][controls] = float ctrlout[numcontrols]; string ctrlName[2] = {"sigGain", "sineGain"}; float values[5][2] = {{0., 0.}, // 0 {0., 0.}, // {20, 0.}, // {45 , 0.}, // {0, 18}}; // 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 saveSequences(){ ofFile sequenceFile(ofxiPhoneGetDocumentsDirectory() + "pilot_sequences.json" ,ofFile::WriteOnly); // the 5 harmonics for the frequencer vector<int> freqIndexes; freqIndexes.push_back(0); freqIndexes.push_back(4); freqIndexes.push_back(6); freqIndexes.push_back(7); freqIndexes.push_back(8); // loop thru all presets int N = presetManager.thePresets.size(); vector<int> sliderVals; Json::Value root; vector<double> vals; for(int i = 0; i< N ; i++){ sliderVals = theGridView.calculateParamsFromCoord(presetManager.thePresets[i].coordinates); 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); for(int j = 0; j<16;j++){ root["sequences"][i][j] = int(steps[j]); } vals.clear(); } //cout << root; sequenceFile << root; } //=-------------------------------------------------------------------- void testApp::loadSequences(){ // read in sequence preset file string jsonFile = ofFilePath::getAbsolutePath(ofToDataPath("pilot_sequences.json")); cout << "SQUENCES FILE: " << jsonFile << "\n"; //string jsonFile = ofxiPhoneGetDocumentsDirectory() + "pilot_sequences.json"; Json::Value root; Json::Reader reader; ifstream theFile(jsonFile.c_str()); stringstream fileText; string line; if(!theFile){ cout<<"can't find sequence file: " << jsonFile.c_str() << "\n"; return; }else{ while(theFile){ theFile >> line; // cout << line << "\n"; // lots? fileText << line; } theFile.close(); } bool parsingSuccessful = reader.parse( fileText.str(), root ); if ( !parsingSuccessful ) { // report to the user the failure and their locations in the document. std::cout << "Failed to parse sequence JSON: \n" << reader.getFormattedErrorMessages(); return; } // now put into variables const Json::Value jseqs = root["sequences"]; int N = jseqs.size(); for(int i=0; i<N; i++){ sequences.push_back(vector<int>()); for(int j=0; j<jseqs[i].size(); j++){ sequences.back().push_back(jseqs[i][j].asInt()); } } // currentSequence currentSequence = ofRandom(0,N-1); } //------------------------------------------------------------------------- //-------------------------------------------------------------- #pragma mark MIDI void testApp::addMessage(string msg) { cout << msg << endl; messages.push_back(msg); while(messages.size() > maxMessages) messages.pop_front(); } //-------------------------------------------------------------- void testApp::newMidiMessage(ofxMidiMessage& msg) { //addMessage(msg.toString()); // look at what it is if(msg.channel == midiChannel && msg.status == MIDI_CONTROL_CHANGE){ int ctl_num = msg.control; int ctl_val = msg.value; if(ctl_num - midiOffset >= 0 && ctl_num - midiOffset < sliderVals.size()){ sliderVals[ctl_num] = (int)ctl_val; theGridView.setParams(sliderVals); } } } //-------------------------------------------------------------- void testApp::midiInputAdded(string name, bool isNetwork) { stringstream msg; msg << "ofxMidi: input added: " << name << " network: " << isNetwork; cout << msg.str(); addMessage(msg.str()); // create and open a new input port ofxMidiIn * newInput = new ofxMidiIn; newInput->openPort(name); newInput->addListener(this); inputs.push_back(newInput); } //-------------------------------------------------------------- void testApp::midiInputRemoved(string name, bool isNetwork) { stringstream msg; msg << "ofxMidi: input removed: " << name << " network: " << isNetwork << endl; cout << msg.str(); addMessage(msg.str()); // close and remove input port vector<ofxMidiIn*>::iterator iter; for(iter = inputs.begin(); iter != inputs.end(); ++iter) { ofxMidiIn * input = (*iter); if(input->getName() == name) { input->closePort(); input->removeListener(this); delete input; inputs.erase(iter); break; } } } //-------------------------------------------------------------- void testApp::midiOutputAdded(string name, bool isNetwork) { stringstream msg; msg << "ofxMidi: output added: " << name << " network: " << isNetwork << endl; cout << msg.str(); addMessage(msg.str()); // create and open new output port ofxMidiOut * newOutput = new ofxMidiOut; newOutput->openPort(name); outputs.push_back(newOutput); } //-------------------------------------------------------------- void testApp::midiOutputRemoved(string name, bool isNetwork) { stringstream msg; msg << "ofxMidi: output removed: " << name << " network: " << isNetwork << endl; cout << msg.str(); addMessage(msg.str()); // close and remove output port vector<ofxMidiOut*>::iterator iter; for(iter = outputs.begin(); iter != outputs.end(); ++iter) { ofxMidiOut * output = (*iter); if(output->getName() == name) { output->closePort(); delete output; outputs.erase(iter); break; } } } //--------------------------------------------------------------