Theremin/scales and controller with sensor reading

#include "URMSerial.h"
URMSerial sensor1, sensor2;

byte SENSOR1_RX = 14;
byte SENSOR1_TX = 15;
byte SENSOR2_RX = 16;
byte SENSOR2_TX = 17;

/* The current notes to play, should be mapped to the entire sensing length */
int currentNotes[36];

static int SCALE_LENGTH = 7;
int SENSOR_MAX = 100;
// Multiply sensor readings by this factor in CC mode
float SENSOR_SCALE_FACTOR = 127 / SENSOR_MAX;

static int MODE_CONTROLLER = 0;
static int MODE_NOTES = 1;

// Store previous note and velocity so we don't keep sending the same note
int prevNote, prevVel, prevCont1, prevCont2;

char* noteNames[] = { 
  "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ",
  "G#", "A ", "A#", "B " };

/* These arrays are the semitone intervals between notes in each scale */
int scales[20][7] = { 
  { 
    2,2,1,2,2,2,1   }
  , { 
    2,1,2,2,1,2,2   }
  ,
  {
    2,2,1,2,2,2,1    }
  ,
  {
    2,1,2,2,2,1,2    }
  ,
  {
    1,2,2,2,1,2,2    }
  ,
  {
    2,2,2,1,2,2,1    }
  ,
  {
    2,2,1,2,2,1,2    }
  ,
  {
    2,1,2,2,1,2,2    }
  ,
  {
    1,2,2,1,2,2,2    }
  ,
  {
    2,2,1,2,2,2,1    }
  ,
  {
    2,1,2,2,1,3,1    }
  ,
  {
    2,1,2,2,2,2,1    }
  ,
  {
    2,1,2,2,1,2,2    }
  ,
  {
    2,1,2,2,1,2,2    }
  ,
  {
    2,1,3,1,2,2,1    }
  ,
  {
    2,2,2,2,1,2,1    }
  ,
  {
    2,2,2,1,2,1,2    }
  ,
  {
    2,1,2,1,2,2,2    }
  ,
  {
    1,2,1,2,2,2,2    }
  ,
  {
    2,2,2,2,2,2,2    }
};

char* scaleNames[] = {
  "Major", 
  "Minor", 
  "Ionian Mode",
  "Dorian Mode",
  "Phrygian Mode ",
  "Lydian Mode",
  "Mixolydian",
  "Aeolian Mode",
  "Locrian Mode",
  "Major Scale",
  "Harmonic Minor",
  "Asc. Mel Minor",
  "Des. Mel Minor",
  "Natural Minor",
  "Lydian Dim",
  "Lydian Aug",
  "Lydian b7",
  "Locrian #2",
  "Super Locrian",
  "Whole Tone"};



/*  OPTIONS */
//  Index into the scales[] array (0 - 19)
byte optionScale = 19;
//  in range 0 - 12 (starting at C, ending at B)
byte optionBaseNote = 0;
//  Range (in octaves) (from 1 to ~3)
byte optionRangeInOctaves = 1;
// Start octave, for use by the Octave setting (must be in range -1 to 8)
int optionStartOctave = 3;
// Mode: one of Controller mode, Note mode (or menu mode?).
byte optionMode = 0;
// Controller numbers, from 0 - 127, for each sensor
byte optionControllerNumber1, optionControllerNumber2;

// sensor range  / number of notes. Will be set by makeScale()
float bucketSize;


void setup() {
  Serial.begin(38400); // Sets the baud rate to 9600
  sensor1.begin(SENSOR1_RX,SENSOR1_TX,9600);
  sensor2.begin(SENSOR2_RX,SENSOR2_TX,9600);
}


/* Fills in currentNotes with the midi notes to play
        and bucketSize with the size of the sections each note will play for along the sensor range */
void makeScale(){
  int notesSize = optionRangeInOctaves * SCALE_LENGTH;
  bucketSize = (float)(SENSOR_MAX + 1) / (float)notesSize;
  
  int transposition = (optionStartOctave * 12) + 12;
  // Set transposition up so that optionStartOctave of 0 gets us to note 12
  currentNotes[0] = optionBaseNote + transposition;

  for (int note = 0; note < (notesSize - 1); note++) {
    currentNotes[note + 1] = currentNotes[note] + scales[optionScale][note % SCALE_LENGTH];
  }
}


void loop() {
  //Read Sensors
  int reading1 = getMeasurement(sensor1);
  int reading2 = getMeasurement(sensor2);
  
  //Switch depending on mode
  switch(optionMode){
    //Can't figure out how to switch on static vars :(
    case 0:
      sendControllers(reading1, reading2);
    break;
    case 1:
      sendNote(reading1, reading2);
    break;
  }
}

int getNoteFromScale(int sensorReading){
  int bucket = floor(sensorReading / bucketSize);
  int note = currentNotes[bucket];
  return note;
}

char* getNoteName(int noteNumber) {
  return noteNames[noteNumber % 12];
}

int getOctaveNumber(int noteNumber) {
  return (noteNumber / 12) - 1;
}

int getMeasurement(URMSerial s)
{
  int value; // This value will be populated
  // Request a distance reading from the URM37
  switch(s.requestMeasurementOrTimeout(DISTANCE, value)) // Find out the type of request
  {
  case DISTANCE: // Double check the reading we recieve is of DISTANCE type
    value = min(value, SENSOR_MAX);
  } 
  return value;
}


void sendControllers(int c1, int c2){
  //Scale CCs over entire sensor range
  int controller1 = (float)c1 * SENSOR_SCALE_FACTOR;
  int controller2 = (float)c2 * SENSOR_SCALE_FACTOR;
  
  if(controller1 != prevCont1){
    prevCont1 = controller1;
    sendCC(optionControllerNumber1, controller1);
  }
  
  if(controller2 != prevCont2){
    prevCont2 = controller2;
    sendCC(optionControllerNumber2, controller2);
  }
}

void sendNote(int note, int vel){
  int noteNumber = getNoteFromScale(note);
  
  //Scale velocity over entire sensor range
  int scaledVel = (float)vel * SENSOR_SCALE_FACTOR;
  
  if(noteNumber != prevNote && scaledVel != prevVel){
    //save the inputs so we can turn the 
    //note off when the next ones turned on
    prevNote = noteNumber;
    prevVel = scaledVel;

    noteOff();
    noteOn(note, 127);
  }
}

//Sends a note on event over serial
void noteOn(char noteNo, char vel){
  Serial.print(0x90, BYTE);
  Serial.print(noteNo, BYTE);
  Serial.print(vel, BYTE);
}

//Sends a note on event over serial
void noteOff(){
  Serial.print(0x80, BYTE);
  Serial.print(prevNote, BYTE);
  Serial.print(prevVel, BYTE);
}

// This function sends a Midi CC.
void sendCC(char c_num, char c_val){
  Serial.print(0xB0, BYTE);
  Serial.print(c_num, BYTE);
  Serial.print(c_val, BYTE);
}