Mercurial > hg > soniczoomios
changeset 0:307e5fb699fb
First commit.
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Mon, 19 Nov 2012 12:56:47 +0000 |
parents | |
children | 23efe1f0cd8a |
files | 2dvector.h 2dvector.mm eventLogger.h eventLogger.mm grid.cpp grid.h main.mm presetManager.h presetManager.mm testApp.h testApp.mm |
diffstat | 11 files changed, 1675 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/2dvector.h Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,35 @@ +/* + * 2dvector.h + * simplespring + * + * Created by Robert Tubb on 01/06/2011. + * Copyright 2011 __MyCompanyName__. All rights reserved. + * + */ +#ifndef _2DVECTORH +#define _2DVECTORH + +class TwoVector{ +public: + double x, y; + TwoVector(); + TwoVector(double ax, double ay); + +// public methods + double norm(); + void setCoord(double ax, double ay); + TwoVector minus(TwoVector otherPoint); + TwoVector operator-(TwoVector otherPoint); + TwoVector operator+(TwoVector otherPoint); + + TwoVector operator*(TwoVector otherPoint); + TwoVector operator*(double scalar); // scalar is right operand + + //TwoVector operator=(TwoVector otherPoint); + + double distanceTo(TwoVector otherPoint); + + +}; + +#endif // #ifndef _2DVECTORH \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/2dvector.mm Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,79 @@ +/* + * 2dvector.cpp + * simplespring + * + * Created by Robert Tubb on 01/06/2011. + * Copyright 2011 __MyCompanyName__. All rights reserved. + * + */ + +#include "2dvector.h" +#include <iostream> + +TwoVector::TwoVector(){ + x = 0.0; + y = 0.0; + //cout << "def constr set vector to zeros" << endl; +} + +TwoVector::TwoVector(double ax, double ay){ + x = ax; + y = ay; + //cout << "spec constr set vector to " << ax << "," << ay << endl; +} + +double TwoVector::norm(){ + double norm; + norm = sqrt(x * x + y * y); + return norm; + +} + +void TwoVector::setCoord(double ax, double ay){ + x = ax; + y = ay; + +} + +TwoVector TwoVector::minus(TwoVector otherPoint){ + TwoVector diff; + diff.setCoord(x - otherPoint.x, y - otherPoint.y); + return diff; +} + +TwoVector TwoVector::operator-(TwoVector otherPoint){ + TwoVector diff; + diff.setCoord(x - otherPoint.x, y - otherPoint.y); + return diff; +} + +TwoVector TwoVector::operator*(TwoVector otherPoint){ // if multiplying two vectors - elementwise + TwoVector diff; + diff.setCoord(x * otherPoint.x, y * otherPoint.y); + return diff; +} + +TwoVector TwoVector::operator*(double scalar){ // if multiplying two vectors - elementwise + TwoVector diff; + diff.setCoord(x * scalar, y * scalar); + return diff; +} + +TwoVector TwoVector::operator+(TwoVector otherPoint){ + TwoVector diff; + diff.setCoord(otherPoint.x + x, otherPoint.y + y); + return diff; +} +/* +TwoVector TwoVector::operator=(TwoVector otherPoint){ + TwoVector result; + result.setCoord(otherPoint.x, otherPoint.y); + return result; +} +*/ +double TwoVector::distanceTo(TwoVector otherPoint){ + TwoVector diff; + diff.setCoord(otherPoint.x - x, otherPoint.y - y); + return diff.norm(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eventLogger.h Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,27 @@ +// +// eventLogger.h +// oscSenderExample +// +// Created by Robert Tubb on 05/11/2012. +// +// +// This class handle everything to do with loggin user actions, +// uploading logs to server, and storing locally if not uploaded + +#ifndef __oscSenderExample__eventLogger__ +#define __oscSenderExample__eventLogger__ + +#include <iostream> + + +class EventLogger{ +public: + // what we need... + /* + time, type, value + */ + +}; + + +#endif /* defined(__oscSenderExample__eventLogger__) */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eventLogger.mm Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,9 @@ +// +// eventLogger.mm +// oscSenderExample +// +// Created by Robert Tubb on 05/11/2012. +// +// + +#include "eventLogger.h"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grid.cpp Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,793 @@ +// +// grid.cpp +// oscSenderExample +// +// Created by Robert Tubb on 03/10/2012. +// +// +#include "ofMain.h" +#include "grid.h" +//#include "presetManager.h" + +#include <sstream> + +//extern PresetManager presetManager; + +//-------------------------------------------------------------- +Grid::Grid(){ + +} +//-------------------------------------------------------------- +//-------------------------------------------------------------- +Grid::~Grid(){ + +} +void Grid::init(){ + maxValue = pow(32.0,7.0)-1; + minValue = 60; // number of 1-size divisions at smallest scale + maxZoom = false; + minZoom = false; + paramsPerDim = 5; + paramBitDepth = 7; + codeLength = pow(2.0,paramsPerDim); + + pixSize.setCoord(ofGetWidth(), ofGetHeight()); + + //set scale and position to mid way + scale = pow(32.0,6.0); + + + size.setCoord(pixSize.x*scale, pixSize.y*scale); + centre.setCoord(maxValue/2 , maxValue/2); + topLeft.setCoord(centre.x - size.x/2, centre.y - size.y/2); + + + makeCode(); + + // set a starting param value, find coord that does it. + vector<int> params(paramsPerDim*2); + for(int i = 0;i<2*paramsPerDim;i++){ + midiCC[i] = 64; + params[i] = 64; + } + TwoVector coord = calculateCoordFromParams(params); + setCoord(coord); + + viewWasChanged(); + + + +} + +template <typename T> int sgn(T val) { + return (T(0) < val) - (val < T(0)); +} + +void Grid::makeCode(){ + + ////////////////////////////////~~~,,,,,,,,......... + ////////// gray code generation + ////// + /// + // TODO 5bit specific + // transition sequence.... what a palaver! only need to do once though. + int trans[] = {0,1,2,3,0,4,2,1,0,3,2,1,0,4,2,3,0,1,2,3,0,4,2,1,0,3,2,1,0,4,2,3}; + + + int code[codeLength][paramsPerDim]; // start with normal array + + + + for(int j=0; j<paramsPerDim; j++){ + code[0][j] = 0; + } + + for(int i=0; i < codeLength-1; i++){ // TODO went off end?? + transSeq.push_back(trans[i]); // member vector + for(int j=0; j<paramsPerDim; j++){ + + if (j == abs(trans[i])){ + code[i+1][j] = !code[i][j]; + }else{ + code[i+1][j] = code[i][j]; + } + } + + } + + for(int i=0; i < codeLength; i++){ // fill vector + + vcode.push_back(vector<bool>()); + + for(int j=0; j<paramsPerDim; j++){ + vcode[i].push_back(code[i][j]); + } + } + + // now try with iterators to print... + vector< vector<bool> >::iterator cit; + //vector<bool>::iterator bit; + vector<bool>::iterator bit; + int i = 0; + for(cit=vcode.begin(); cit!=vcode.end() ; cit++){ // fill vector + i++; + cout << i << " = "; + bit = (*cit).begin(); + for(bit=(*cit).begin(); bit!=(*cit).end() ; bit++){ + + cout << *bit; + } + cout << "\n"; + + } + /* + // codeToInt unit test + vector<bool> aCode = vcode[12]; + int result = grayToInt(aCode); + cout << "GRAY TO INT : " << result << "\n"; + + cout << "-------------------------------\n"; + + // base32toFloat unit test + + vector<int> test32 = coordTobase32(869437.0); + double cresult = base32toCoord(test32); + cout << "base32toCoord : " << cresult << "\n"; + + cout << "-------------------------------\n"; + + + + // midiToGray unit test + + vector<vector<bool> > incodes(paramBitDepth, vector<bool>(paramsPerDim)); + for(int i=0;i<7;i++){ + incodes[i] = vcode[i+5]; + } + + vector<int> midiTest; + midiTest = grayToMidi(incodes); + vector<vector<bool> > outcodes = midiToGray(midiTest); + + vector< vector<bool> >::iterator cit1; + //vector<bool>::iterator bit; + vector<bool>::iterator bit1; + cout << "midiToGray Unit test\n"; + for(int i=0;i<paramBitDepth;i++){ // fill vector + + for(int j=0;j<paramsPerDim;j++){ + + cout << (incodes[i][j] == outcodes[i][j]) << ","; + } + cout << "\n"; + + } + cout << "-------------------------------\n"; + + + // whole process unit test(?) + + TwoVector inCoord(888999777,777666555); + vector<int> checkParam; + checkParam = calculateParamsFromCoord(inCoord); + for(int i=0; i<2*paramsPerDim;i++){ + cout << checkParam[i] << "_"; + } + TwoVector outCoord = calculateCoordFromParams(checkParam); + cout << "Unit TEst coord = " << outCoord.x << "," << outCoord.y << "\n"; +*/ + +} +//-------------------------------------------------------------- +void Grid::draw(){ // draw lines + // TODO too friggin long + + //scale++; + // nice loopy thing + int power = 0; + + // these get big! + double divsr; + double yl,xl; + double gridSize = 0; + + double firstLineXPos, lastLineXPos,firstLineYPos, lastLineYPos, remleft, xoffset, yoffset = 0.0; + double xstart, xfinish, ystart,yfinish; + // these don't + int xpos, ypos = 0; + + float alpha; + bool done = false; + float markpow = 32.0; // power that denotes next grid markings + int lineWidth = 0; + int colCycle = 0; + + // get all the preset points within this view + //presetManager.getPresetsInRange(topLeft, topLeft+size); + + // loop thru powers of (base?) to determine which should be shown as grids + while (!done){ + gridSize = pow(markpow,power); + + colCycle = power % 7; + + divsr = size.x / gridSize; + + // if (divisor i.e. number of lines is less than 1000 + if( divsr >= 1 && divsr < 1000){ + + // calculate transparency + float visCont = log10(divsr); // 0 if only 1 line, 3 if 1000 lines + alpha = 90*(3 - visCont); + ofSetLineWidth(lineWidth); + + // cycle colors for different scales + if(colCycle == 0){ + ofSetColor(255,255,255,alpha); + }else if(colCycle == 1){ + ofSetColor(255,0,0,alpha); + }else if(colCycle == 2){ + ofSetColor(0,0,255,alpha); + }else if(colCycle == 3){ + ofSetColor(0,255,0,alpha); + }else if(colCycle == 4){ + ofSetColor(255,0,255,alpha); + }else if(colCycle == 5){ + ofSetColor(0,255,255,alpha); + }else if(colCycle == 6){ + ofSetColor(255,255,0,alpha); + }else if(colCycle == 7){ + ofSetColor(255,255,255,alpha); + }else{ + cout << "err colour messed up\n"; + } + + + // draw level numbers associated with each color. This would not be true if markpow wasnt 2^d + ////////-------///////// + /* + temp << "THIS LEVEL = " << (int)pow(2.0,power) << " "; + string s = temp.str(); + ofDrawBitmapString( s, 10, line ); + line+=30; + temp.str(""); + *////////-------///////// + + // draw presets at this level + // fill in smallest squares if they contain a preset + // how to do this efficiently? + + + if(topLeft.x < 0.0){ + firstLineXPos = 0.0; + xoffset = firstLineXPos - topLeft.x; + xstart = xoffset/scale; + }else{ + firstLineXPos = topLeft.x; + // kinda float version of % operator + remleft = ceil(firstLineXPos/gridSize); + xoffset = (remleft * gridSize) - topLeft.x; + xstart = 0; + } + if(topLeft.x + size.x > maxValue){ + lastLineXPos = maxValue+1 - topLeft.x; + + + }else{ + lastLineXPos = size.x; + + } + xfinish = lastLineXPos/scale; + + //////////------------------------ + // same for y + + if(topLeft.y < 0.0){ + firstLineYPos = 0.0; + yoffset = firstLineYPos - topLeft.y; + ystart = yoffset/scale; + }else{ + firstLineYPos = topLeft.y; + // kinda float version of % operator + remleft = ceil(firstLineYPos/gridSize); + yoffset = (remleft * gridSize) - topLeft.y; + ystart = 0; + } + if(topLeft.y + size.y > maxValue){ + lastLineYPos = maxValue+1 - topLeft.y; + + }else{ + lastLineYPos = size.y; + + } + yfinish = lastLineYPos/scale; + // ------------------------------------------- + // now draw + for(xl = xoffset; xl <= (lastLineXPos); xl+= gridSize){ + + xpos = xl/scale; + ofLine(xpos, ystart, xpos, yfinish); + + } + + for(yl = yoffset; yl <= (lastLineYPos); yl+= gridSize){ + + ypos = yl/scale; + ofLine(xstart, ypos, xfinish, ypos); + } + + + }else if (divsr < 1){ + // ignore... + done = true; + } + + power++; + } + //cout << "draw done" << "\n"; + //displayInfo(); + + ////////-------///////// + + ////////-------///////// + + // draw centre cross hairs + ofSetColor(255, 0, 0); + ofNoFill(); + ofLine(pixSize.x/2-20, pixSize.y/2, pixSize.x/2+20, pixSize.y/2); + ofLine(pixSize.x/2, pixSize.y/2-20, pixSize.x/2, pixSize.y/2+20); + ofEllipse(pixSize.x/2, pixSize.y/2, 20, 20); + ofFill(); + ////////-------//////// + /* + ostringstream temp; + temp << "Centre x = " << centre.x << "\n y = " << centre.y << " "; + string s = temp.str(); + ofDrawBitmapString( s, pixSize.x/2+10, pixSize.y/2+10 ); + */ +} +//----------------------------------------------------------------------- +void Grid::displayInfo(){ + + // display some "useful information" + + ofSetColor(255,255,255,255); + + ostringstream temp; + int line = 10; // text output pos + + + ////////-------///////// + temp << "scale = " << scale << " "; + string s = temp.str(); + ofDrawBitmapString( s, 10, line ); + line+=30; + temp.str(""); + ////////-------///////// + temp << "Top Left = " << topLeft.x << "," << topLeft.y << " "; + s = temp.str(); + ofDrawBitmapString( s, 10, line ); + line+=60; + temp.str(""); + + ////////-------///////// + temp << "View Size = " << size.x << "," << size.y << " "; + s = temp.str(); + ofDrawBitmapString( s, 10, line ); + line+=60; + temp.str(""); + + ////////-------///////// + + for(int i=0;i<10;i++){ // TODO 5bit specific + temp << midiCC[i] << " "; + s = temp.str(); + ofDrawBitmapString( s, 10, line ); + line+=20; + temp.str(""); + } +} + //-------------------------------------------------------------- +void Grid::update(){ // ? + // "update" bit of a crap name - all we do here is calculate the dimension params from the x,y position + + vector<int> params = calculateParamsFromCoord(centre); + for(int i = 0;i<2*paramsPerDim;i++){ + midiCC[i] = params[i]; + } + +} +//-------------------------------------------------------------- +void Grid::move(int moveX, int moveY){ + // numspacing, pixelspacing stay the same + + // convert pixels to surf units + TwoVector moveS; + moveS.setCoord(moveX * scale, moveY * scale); + + topLeft = topLeft - moveS; // - because moving to the right means taking away from offset + centre = centre - moveS; + + viewWasChanged(); +} +//-------------------------------------------------------------- +void Grid::zoom(float factor){ + if(maxZoom && factor > 1.0){ + return; + + } + if(factor < 1.0){ + maxZoom = false; + } + if(minZoom && factor < 1.0){ + return; + + } + if(factor > 1.0){ + minZoom = false; + } + scale = scale*factor; // simple eh? + + // update view size using centre + // and scale... + size.x = size.x*factor; // zooming in, size gets SMALLER (view less) + size.y = size.y*factor; + + viewWasChanged(); + +} +//-------------------------------------------------------------- +void Grid::viewWasChanged(){ + checkLimits(); + // and calculate new params? + + +} + +//-------------------------------------------------------------- +void Grid::checkLimits(){ + // check for maximum zoom level + // TODO: DODGY + + if(size.x > maxValue*2.0){ + cout << "maxZoom\n"; + maxZoom = true; + size.x = maxValue*2.0; + // need to also set y size back to + } + if(size.y > maxValue*2.0){ + cout << "maxZoom\n"; + maxZoom = true; + size.y = maxValue*2.0; + } + + if(size.x < minValue){ + cout << "min Zoom\n"; + minZoom = true; + size.x = minValue; + // need to also set y size back to + } + if(size.y < minValue){ + minZoom = true; + cout << "min Zoom\n"; + size.y = minValue; + } + + scale = size.x/pixSize.x; + size.y = scale * pixSize.y; + + topLeft.x = centre.x - size.x/2; + topLeft.y = centre.y - size.y/2; + // check for negatives + + // allow centre to be at limits + if((topLeft.x + size.x*0.5) < 0.0){ + cout << "left Wall\n"; + topLeft.x = 0.0 - size.x*0.5; + centre.x = 0.0; + } + + if(topLeft.y + size.y*0.5 < 0.0) { + cout << "top Wall\n"; + topLeft.y = 0.0 - size.y*0.5; + centre.y = 0.0; + } + + // does topleft refer to lines or view? + + // check max + if(topLeft.x + size.x/2 > maxValue){ + cout << "right Wall\n"; + topLeft.x = maxValue - size.x/2; + centre.x = maxValue; + } + if(topLeft.y + size.y/2 > maxValue) { + cout << "bottom Wall\n"; + topLeft.y = maxValue - size.y/2; + centre.y = maxValue; + } + +} +//-------------------------------------------------------------- +void Grid::checkConsistencies(){ + // debug function to check all the parameters are consistent maybe + +} +//-------------------------------------------------------------- +void Grid::setCoord(TwoVector coord){ + + centre = coord; + viewWasChanged(); +} +//-------------------------------------------------------------- +TwoVector Grid::getCoord(){ + + return centre; +} +//-------------------------------------------------------------- +vector<int> Grid::getParams(){ + // return a vector with midiCCs in + // should we store params somewhere and use this as a low computation get ? + vector<int> params(2*paramsPerDim,0); + // + for(int i = 0;i<2*paramsPerDim;i++){ + params[i] = midiCC[i]; + } + return params; +} +//-------------------------------------------------------------- +void Grid::setParams(vector<int> params){ + // input midiCCs, and go to the appropriate coordinate + + for(int i = 0;i<2*paramsPerDim;i++){ + midiCC[i] = 64; + } + TwoVector coord = calculateCoordFromParams(params); + setCoord(coord); + + viewWasChanged(); + +} +//-------------------------------------------------------------- +TwoVector Grid::calculateCoordFromParams(vector<int> params){ + + vector<int> ccValueX(paramsPerDim); + vector<int> ccValueY(paramsPerDim); + for(int i=0;i<paramsPerDim;i++){ + ccValueX[i] = params[i]; + ccValueY[i] = params[i+paramsPerDim]; + } + vector<vector <bool> > codesX = midiToGray(ccValueX); + vector<vector <bool> > codesY = midiToGray(ccValueY); + + vector<int> base32X = codesToBase32(codesX); + vector<int> base32Y = codesToBase32(codesY); + + TwoVector result; + result.x = base32toCoord(base32X); + result.y = base32toCoord(base32Y); + return result; +} + +//-------------------------------------------------------------- +vector<int> Grid::calculateParamsFromCoord(TwoVector coord){ + // some arrays in reverse order of power from normal numbers! 1,2,4, + + // centre to base 32 + if (coord.x > maxValue || coord.y > maxValue){ + cout << "calculateParams Error: centre double value is too large" << "\n"; + vector<int> empty; + return empty; + } + + //-------------------------- + // X + vector<int> base32x = coordTobase32(coord.x); // 7 numbers from 0 to 31 + vector<vector <bool> > grayCodesX; + + int size = base32x.size(); + for(int i=0;i<size;i++){ + grayCodesX.push_back(intToGray(base32x[i])); + } + + vector<int> result; + result = grayToMidi(grayCodesX); + //-------------------------- + // AND FOR Y + vector<int> base32y = coordTobase32(coord.y); + vector<vector <bool> > grayCodesY; + + size = base32y.size(); + for(int i=0;i<size;i++){ + grayCodesY.push_back(intToGray(base32y[i])); + } + + vector<int> resultY; + resultY = grayToMidi(grayCodesY); + + // concatenate + result.insert( result.end(), resultY.begin(), resultY.end() ); + return result; +} +//------------------------------------------------------------------- + +// for 1 dimension!!! i.e. call this twice +vector<int> Grid::grayToMidi(vector<vector <bool> > grayCodes){ + + // gray to midi CC values + // loop thru the scales to build up a CC number per dimension + int midiCCresult[paramsPerDim]; // TODO dims specific + for(int i=0;i<paramsPerDim;i++){ + midiCCresult[i] = 0; + } + + int bin = 1; + bin = bin << grayCodes.size()-1; + + int midP = 0; + + vector<vector <bool> >::iterator piter = grayCodes.begin(); + for(;piter < grayCodes.end();piter++){ // each lesser power of 2 + midP = 0; // reset + vector<bool>::iterator diter = (*piter).begin(); + for(; diter <= (*piter).end();diter++){ // each one is different dimension + int ig = int(*diter); // convert binary to int + //cout << "ig: " << ig; + midiCCresult[midP] += ig*bin; // mult by power of two + midP++; + } + bin = bin >> 1; // next power of 2 down + + } + + // put in vector + vector<int> result; + for(int i=0;i<paramsPerDim;i++){ + result.push_back(midiCCresult[i]); + } + + return result; + + +} + + +//-------------------------------------------------------------- + +vector<bool> Grid::intToGray(int num, int dimToTravel){ + + // dimToTravel - this is the dimension that we want the walk to traverse, i.e. the last non zero digit of the code + // so swap it for 3 to produce correct orientation + + // just use look up table... until it gets huuuge. + vector<bool> grayCode = vcode[num]; + grayCode[3] = vcode[num][dimToTravel]; + grayCode[dimToTravel] = vcode[num][3]; + return grayCode; +} +//-------------------------------------------------------------- +vector<int> Grid::walkDiff(vector<bool> left, vector<bool> right){ + // horrible + vector<int> result(2,0); + + int size = left.size(); + for(int i = 0; i < size; i++){ + if(left[i] && !right[i]){ // 1 - 0 + // dim + result[0] = i; + result[1] = 1; + }else if(!left[i] && right[i]){ // 0 - 1 + result[0] = i; + result[1] = -1; + }else{ // equal do nothing + + + } + } + + return result; +} + +//-------------------------------------------------------------- +/* +breaks down float into a base 32 number (2^D) +each of these is converted to gray code +this is then converted to 10 parameters, where each 32-digit becomes separate power of 2 + so "zoom" grid 32-patches are converted to 2-scales. 1,2,4,8,16,32,64,(128?) biggest number is 32^7 +*/ +vector<int> Grid::coordTobase32(double value){ + //double base = 32.0; + if(value < 0.0){ + cout << "coordTobase32 error: input value is negative\n"; + value = 0.0; + }else if(value > maxValue){ + cout << "coordTobase32 error: input value too big!\n"; + } + double rem, divdr = 0.0; + int digit32; + + // what power of 32 to start at? + int maxpow = 7; // midi cc specific + vector<int> result; + + rem = value; + for(;maxpow >=0;maxpow--){ + // repeatedly get digit and remainder. This is exactly what we're doing in draw !?... could put all this in one place? + divdr = pow((double)codeLength,(double)maxpow); + digit32 = floor(rem/divdr); + rem = rem - digit32*divdr; + result.push_back(digit32); // array, biggest index is smallest power + } + // at this point rem should be fractional... use for interp? + + return result; +} +//-------------------------------------------------------------- + +// WHY HERE XCODE? +vector<int> Grid::codesToBase32(vector<vector<bool> > inCodes){ + vector<int> result; + for(int i=0;i<paramBitDepth;i++){ + result.push_back(grayToInt(inCodes[i])); + } + return result; +} +//-------------------------------------------------------------- + +int Grid::grayToInt(vector<bool> incode){ + // look for match in table + + int s = vcode.size(); + + for(int i=0; i<s;i++){ // fill vector + if(vcode[i] == incode){ + return i; + } + + } + cout << "grayToInt error: no matching code found!"; + return -1; +} +//-------------------------------------------------------------- +double Grid::base32toCoord(vector<int> base32Digs){ + // build up the big float from a base 32 number + double result = 0.0; + + // what power of 32 to start at? + int mpow = base32Digs.size() - 1; // should be 7... + + for(int p=0;p<=mpow;p++){ // biggest index is smallest power + result += ((double)base32Digs[p]) * pow(32.0, (double)mpow-p); + + } + return result; + +} +//-------------------------------------------------------------- +// for 1 dimension - takes in 5 cc params and outputs 7 codes +vector<vector <bool> > Grid::midiToGray(vector<int> ccValue){ + int pow2 = 1 << (paramBitDepth-1); + + vector<int> aCode(paramsPerDim); + vector<vector<int> > theXCodes(paramBitDepth,aCode); + + // build up binary gray code representations from the bits of the midi ccs + + vector<vector<bool> > theCodes(paramBitDepth, vector<bool>(paramsPerDim)); + + // x + for(int p=0;p<paramBitDepth;p++){ + + for(int i=0;i<paramsPerDim;i++){ + + bool bit = (pow2 == (ccValue[i] & pow2)); + theCodes[p][i] = bit; + } + pow2 = pow2 >> 1; + + } + return theCodes; +} +//-------------------------------------------------------------- +//-------------------------------------------------------------- +//-------------------------------------------------------------- \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/grid.h Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,80 @@ +// +// grid.h +// oscSenderExample +// +// Created by Robert Tubb on 03/10/2012. +// +// This is the view onto the zoomable movable grid + +#ifndef __oscSenderExample__grid__ +#define __oscSenderExample__grid__ + +#include <iostream> +#include "2dvector.h" +using namespace std; + +class Grid { +private: + double scale; // surface units per pixel + + double maxValue; // width of entire space + double minValue; // smallest zoom + TwoVector topLeft; // top left corner of view, surface coords + TwoVector bottomRight; + TwoVector size; // size of view, surface coords + TwoVector pixSize; // size of view pixels (ie screen size!) + TwoVector centre; + bool maxZoom, minZoom; + int cubeWidth; // side of hypercube. 2 for binary coding. + int paramsPerDim; // no of parameters per dimension ( + int codeLength; // the 1d size of the code, determines max extent of single tile, related to params per dim + int paramBitDepth; // number of bits for the parameter control data - i.e. always 7 for midi CC + vector< vector<bool> > vcode; // + vector<int> icode; + vector<int> transSeq; + int midiCC[10]; // the actual params SHOULD BE INITED FROM 2*paramsPerDim + +// private functions + + void makeCode(); + void checkLimits(); + void viewWasChanged(); + void checkConsistencies(); + + vector<int> calculateParamsFromCoord(TwoVector coord); + TwoVector calculateCoordFromParams(vector<int> params); + + vector<bool> intToGray(int num, int dimToTravel=3); + vector<int> coordTobase32(double coord); + vector<int> grayToMidi(vector<vector <bool> > grayCodes); + + // the inverse stuff + int grayToInt(vector<bool>); + double base32toCoord(vector<int>); + vector<vector <bool> > midiToGray(vector<int>); + vector<int> codesToBase32(vector<vector<bool> >); + + vector<int> walkDiff(vector<bool> left, vector<bool> right); // not used... not worth it! + + void displayInfo(); + + void setCoord(TwoVector coord); +public: + Grid(); + ~Grid(); + void init(); + void move(int moveX, int moveY); // shift view by pixels + void zoom(float factor); + + void draw(); // draw lines + void update(); // change according to zoom + + vector<int> getParams(); + TwoVector getCoord(); + // the inverse stuff + void setParams(vector<int>); + + +}; + +#endif /* defined(__oscSenderExample__grid__) */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.mm Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,9 @@ +#include "ofMain.h" +#include "testApp.h" + +Grid theGridView; // global because it saves PAIN + +int main(){ + ofSetupOpenGL(1024,768, OF_FULLSCREEN); // <-------- setup the GL context + ofRunApp(new testApp); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/presetManager.h Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,53 @@ +// +// presetManager.h +// oscSenderExample +// +// Created by Robert Tubb on 07/11/2012. +// +// + +#ifndef __oscSenderExample__presetManager__ +#define __oscSenderExample__presetManager__ + +#include <iostream> +#include "ofMain.h" +#include "ofxiPhone.h" +#include "ofxiPhoneExtras.h" +#include "2dvector.h" + +//--------------------------------------------------------------------------- +class Preset{ + +public: + int presetID; + string name; + TwoVector coordinates; + Preset(TwoVector acoord, string aname,int aID){ + coordinates = acoord; + name = aname; + presetID = aID; + + }; +}; +//--------------------------------------------------------------------------- +class PresetManager{ +public: + int nextID; + + // names values + // check if already there + // find and return all(?) presets within a certain coordinate range + vector<Preset *> thePresets; // we want vector ? or list? pointers using new? + + int addPreset(TwoVector coord, string name); // returns id or negative error number + TwoVector recallPreset(int presetID); // by name ? id? + TwoVector recallPreset(string name); // by name ? id? + vector<TwoVector > getPresetsInRange(TwoVector min, TwoVector max); + + void startupLoadAll(); // get stuff from XML + void exitAndSaveAll(); // save to XML, delete presets array (?) + + PresetManager(); +}; + +#endif /* defined(__oscSenderExample__presetManager__) */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/presetManager.mm Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,61 @@ +// +// presetManager.mm +// oscSenderExample +// +// Created by Robert Tubb on 07/11/2012. +// +// + +#include "presetManager.h" + +//--------------------------------------------------------------------------- + +PresetManager presetManager; +//--------------------------------------------------------------------------- + + +PresetManager::PresetManager(){ + nextID = 0; + +} +//--------------------------------------------------------------------------- + +int PresetManager::addPreset(TwoVector coord, string name){ + // check for same name + vector<Preset *>::iterator iter; + for(iter = thePresets.begin(); iter < thePresets.end(); iter++){ + if ((*iter)->name == name){ + cout << " Preset by that name exists\n"; + + // use exceptions! + return -1; + } + } + if(name == ""){ + cout << "Please name preset\n"; + return -2; + + } + // check for same coords (!?!) + thePresets.push_back(new Preset(coord, name,nextID)); + + // if ok + return nextID++; +} +//--------------------------------------------------------------------------- +vector<TwoVector > getPresetsInRange(TwoVector min, TwoVector max){ + //return all the coordinates. oh and names (displayed at certain scales?). +} +//--------------------------------------------------------------------------- +void startupLoadAll(){ + // get stuff from XML +} +//--------------------------------------------------------------------------- +void exitAndSaveAll(){ + +} +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testApp.h Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,84 @@ +#pragma once + +#include "ofMain.h" +#include "ofxiPhone.h" +#include "ofxiPhoneExtras.h" +#include "ofxOsc.h" +#include "grid.h" +#include "2dvector.h" +#include "ofxUI.h" +#include "eventLogger.h" +#define HOST "169.254.1.1" +#define PORT 12345 + +class testApp : public ofxiPhoneApp { + + public: + + + int prevTouchX; + int prevTouchY; + double prevDist; + // not many so dont bother with vectors/arrays? + TwoVector touch0; + TwoVector touch1; + TwoVector prevTouch0; + TwoVector prevTouch1; + + bool xLocked, yLocked; + + + TwoVector moveVel; // velocity at which we were moving the grid + + vector <ofxUISlider *> sliders; + + double slowFactor; + double zoomVel; // do the same + double prevZoom, prevZoom2; + TwoVector prevMove, prevMove2; + + vector<int> sliderVals; + + int numActiveTouches; + + ofxiPhoneKeyboard * keyboard; + // + + void setup(); + void update(); + void draw(); + void exit(); + + void touchDown(ofTouchEventArgs &touch); + void touchMoved(ofTouchEventArgs &touch); + void touchUp(ofTouchEventArgs &touch); + void touchDoubleTap(ofTouchEventArgs &touch); + void touchCancelled(ofTouchEventArgs &touch); + + vector<float> vectorFilter(vector<float> newVec); + + void lostFocus(); + void gotFocus(); + void gotMemoryWarning(); + void deviceOrientationChanged(int newOrientation); + + ofxOscSender sender; + void sendOSCParams(); + + // stardard GUI - knbs and sliders - hides zoomer + bool standardGUIShowing; + void standardGUIEvent(ofxUIEventArgs &e); + void setupStandardGui(); + ofxUICanvas *standardGUI; + + // zoom gui - the swap view button and save preset button + void zoomGUIEvent(ofxUIEventArgs &e); + void setupZoomGui(); + + void updateSliderValue(int which, float value); + void setGUISliders(vector<int> vals); + + ofxUICanvas *zoomGUI; + +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testApp.mm Mon Nov 19 12:56:47 2012 +0000 @@ -0,0 +1,445 @@ +#include "testApp.h" +#include "grid.h" +#include "presetManager.h" + +extern Grid theGridView; +extern PresetManager presetManager; +//-------------------------------------------------------------- +void testApp::setup(){ + ofSetOrientation(OF_ORIENTATION_90_LEFT); + + ofBackground( 0, 0, 0 ); + ofEnableAlphaBlending(); + + // open an outgoing connection to HOST:PORT + sender.setup( HOST, PORT ); + ofSetFrameRate(40); + // reciever + + + prevTouchX = 0; + prevTouchY = 0; + + xLocked = false; + yLocked = false; + + numActiveTouches = 0; + touch0.setCoord(1,2); + touch1.setCoord(10,20); + prevTouch0.setCoord(1,2); + prevTouch1.setCoord(10,20); + prevDist = 10; + + theGridView.init(); + + slowFactor = 0.97; + + setupStandardGui(); + standardGUIShowing = false; + standardGUI->setVisible(standardGUIShowing); + + setupZoomGui(); + zoomGUI->setVisible(!standardGUIShowing); + + // initial slider vals + for(int i=0; i<10;i++){ + sliderVals.push_back(64); + } + + keyboard = new ofxiPhoneKeyboard(500,380,320,32); + keyboard->setVisible(false); + keyboard->setBgColor(255, 255, 255, 255); + keyboard->setFontColor(0,0,0, 255); + keyboard->setFontSize(26); + + ofxiPhoneSetOrientation( OF_ORIENTATION_90_RIGHT ); + +} +//-------------------------------------------------------------- +void testApp::setupZoomGui(){ + zoomGUI = new ofxUICanvas(ofGetWidth()-200,0,190,125); + zoomGUI->setTheme(OFX_UI_THEME_HIPSTER); + + ofxUIWidget *bwidge = zoomGUI->addLabelToggle("SWITCH VIEW", false); + + zoomGUI->addLabelButton("SAVE PRESET", false); + + zoomGUI->addLabelToggle("LOCK SEQUENCE (X)", false); + zoomGUI->addLabelToggle("LOCK SYNTH (Y)", false); + + ofAddListener(zoomGUI->newGUIEvent, this, &testApp::zoomGUIEvent); +} +//-------------------------------------------------------------- +void testApp::zoomGUIEvent(ofxUIEventArgs &e){ + + if(e.widget->getName() == "SWITCH VIEW") + { + cout << "change VIEW\n"; + + standardGUI->setVisible(!standardGUIShowing); + standardGUIShowing = !standardGUIShowing; + if(standardGUIShowing){ + // set the slider values to stuff got from zoomer + sliderVals = theGridView.getParams(); + setGUISliders(sliderVals); + } + + }else if(e.widget->getName() == "SAVE PRESET") + { + cout << "SAVE PRESET\n"; + // uh... + // TwoVector preset = theGridView.getCoord(); + // presetManager.savePreset(preset); + // just coordinate or all the dims? + TwoVector preset = theGridView.getCoord(); + + if(!keyboard->isKeyboardShowing()){ + keyboard->openKeyboard(); + keyboard->setVisible(true); + } else{ + keyboard->setVisible(false); + } + // set some kind of modal dialog thing to stop other stuff going on... + // this wont work + presetManager.addPreset(preset,keyboard->getText()); + }else if(e.widget->getName() == "LOCK SEQUENCE (X)") + { + cout << "LOCK SEQUENCE (X)\n"; + // lock + xLocked = !xLocked; + }else if(e.widget->getName() == "LOCK SYNTH (Y)") + { + cout << "LOCK SYNTH (Y)\n"; + // lock + + yLocked = !yLocked; + }else{ + cout << "GUI error : unknown event recieved\n"; + } + +} +//-------------------------------------------------------------- +void testApp::setupStandardGui(){ + float xInit = OFX_UI_GLOBAL_WIDGET_SPACING; + float length = 256-xInit*2; + + + float dim = 42; + + // LEFT GUI + standardGUI = new ofxUICanvas(0,0,length+90,ofGetHeight()-90); + + + + // Uh.. loop this + for(int i = 1; i<=10;i++){ + stringstream ss; + ss << "P" << i; + ofxUISlider *slider; + slider = (ofxUISlider *)standardGUI->addWidgetDown(new ofxUISlider(length,dim,0.0,127,64,ss.str())); + slider->setDrawPadding(true); + slider->setColorFill(ofColor(0,0,255)); + slider->setColorFillHighlight(ofColor(0,0,255)); + sliders.push_back(slider); + } + + ofAddListener(standardGUI->newGUIEvent, this, &testApp::standardGUIEvent); + standardGUI->loadSettings(ofxiPhoneGetDocumentsDirectory() + "guiSettings.xml"); + +} +//-------------------------------------------------------------- +void testApp::standardGUIEvent(ofxUIEventArgs &e){ + if(!standardGUIShowing){ + cout << "GUI ERROR"; + return; + } + // "normal" parameter changes + for(int i = 1; i<=10;i++){ + stringstream ss; + ss << "P" << i; + string p = ss.str(); + + if(e.widget->getName() == p) + { + //cout << "param change: " << p; + ofxUISlider *slider = (ofxUISlider *) e.widget; + updateSliderValue(i-1,slider->getScaledValue()); // internal array 0 indexed + + } + } + + // TODO reflect these changes in zoomer view? Or only when switching? + +} +//-------------------------------------------------------------- +void testApp::updateSliderValue(int which, float value){ + sliderVals[which] = (int)value; + theGridView.setParams(sliderVals); +} +//-------------------------------------------------------------- +void testApp::setGUISliders(vector<int> vals){ + for(int i = 0; i<10;i++){ + // uh shit need to have reference to this lot + sliders[i]->setValue(vals[i]); + } +} +//-------------------------------------------------------------- +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( ofGetFrameNum() % 120 == 0 ){ + ofxOscMessage m; + m.setAddress( "/misc/heartbeat" ); + m.addIntArg( ofGetFrameNum() ); + sender.sendMessage( m ); + } + + // continiue to move at velocity + if (numActiveTouches == 0 && moveVel.norm() > 0.01){ + theGridView.move(moveVel.x,moveVel.y); + moveVel = moveVel*slowFactor; + } + // 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; + } + + // we need this? + theGridView.update(); + vector<int> params = theGridView.getParams(); // FILTER HERE? NEED FLOATS... + setGUISliders(params); + // sendOSCParams(); + +} +//-------------------------------------------------------------- +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 (standardGUIShowing){ + ofSetColor(57, 57, 57,200); + ofRect(0,0,ofGetWidth(),ofGetHeight()); + } + theGridView.draw(); + + ofSetColor(20, 160, 240, 255); + ofDrawBitmapString("text entered = "+ keyboard->getText() , 2, 70); +} + +//-------------------------------------------------------------- +void testApp::exit(){ + delete standardGUI; + delete zoomGUI; +} + +//-------------------------------------------------------------- +void testApp::touchDown(ofTouchEventArgs &touch){ + if(standardGUIShowing){ + // check if in GUI area + if(touch.x < 256) return; + } + + 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){ + if(standardGUIShowing){ + // check if in GUI area + if(touch.x < 256) return; + } + + // + // which one? + if(touch.id == 0){ + touch0.setCoord(touch.x,touch.y); + + }else if(touch.id == 1){ + + touch1.setCoord(touch.x,touch.y); + } + + + //cout << "touch id " << touch.id << "\n"; + //cout << "active touches " << numActiveTouches << "\n"; + + + if(numActiveTouches == 1){ + // TODO: when num touches goes down to 1 after zoom prevTouch can be hugely different! + + TwoVector move = touch0 - prevTouch0; + moveVel = move*0.3 + prevMove*0.34 + prevMove2*0.38; // broke? + prevMove2 = prevMove; + prevMove = move; + + theGridView.move(move.x,move.y); + + + + }else if(numActiveTouches == 2){ + // work out change in difference + double dist = touch1.distanceTo(touch0); + double zoomFactor = prevDist/dist; + + cout << "Zoom: " << zoomFactor << "\n"; + //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; + // TODO: when num touches goes down to 1 after zoom prevTouch can be hugely different! + // also if try to move with other finger after zoom , this is touch1 :( + // prevTouch0 = ??? + + } + prevTouch0 = touch0; + + +} + +//-------------------------------------------------------------- +void testApp::touchUp(ofTouchEventArgs &touch){ + if(standardGUIShowing){ + // check if in GUI area + if(touch.x < 256) + if(numActiveTouches > 0) numActiveTouches--; // dirty + return; + } + + numActiveTouches--; + // 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); + } + +} + +//-------------------------------------------------------------- +void testApp::touchDoubleTap(ofTouchEventArgs &touch){ + // preset? + +} + +//-------------------------------------------------------------- +void testApp::lostFocus(){ + +} + +//-------------------------------------------------------------- +void testApp::gotFocus(){ + +} + +//-------------------------------------------------------------- +void testApp::gotMemoryWarning(){ + +} + +//-------------------------------------------------------------- +void testApp::deviceOrientationChanged(int newOrientation){ + cout << "orientation: " << newOrientation; + keyboard->updateOrientation(); // takes ages , only applies to text box + if(newOrientation == 4){ + ofxiPhoneSetOrientation( OF_ORIENTATION_90_RIGHT ); + }else if(newOrientation == 3){ + ofxiPhoneSetOrientation( OF_ORIENTATION_90_LEFT ); + } + +} + + +//-------------------------------------------------------------- +void testApp::touchCancelled(ofTouchEventArgs& args){ + +} + +// 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; +} \ No newline at end of file