Advertisement
charlieslick

charlesMIDI.ccp

Aug 25th, 2014
285
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.67 KB | None | 0 0
  1. #include "charlesMIDI.h"
  2. #include <arduino.h>
  3.  
  4. // general word constructor
  5. MidiWord::MidiWord(){
  6.   command = nullByte;
  7.   pitch = nullByte;
  8.   velocity = nullByte;
  9. }
  10.  
  11. // word constructor with parameters
  12. MidiWord::MidiWord(byte inCommand, byte inPitch, byte inVelocity){
  13.   command = inCommand;
  14.   pitch = inPitch;
  15.   velocity = inVelocity;
  16. }
  17.  
  18. byte MidiWord::setAll(byte inCommand, byte inPitch, byte inVelocity){
  19.   command = inCommand;
  20.   pitch = inPitch;
  21.   velocity = inVelocity;
  22. }
  23.  
  24. // check the serial que for next midi word
  25. void MidiWord::getWord(){
  26.   byte incomingByte = nullByte;
  27.   command = nullByte;
  28.   pitch = nullByte;
  29.   velocity = nullByte;
  30.   boolean fullWord = false;
  31.  
  32.  //check to see if the serial is available
  33.  if(!Serial.available()){
  34.    return;
  35.  }
  36.  
  37.  incomingByte = Serial.read();
  38.  while(!fullWord){
  39.    if(incomingByte > 0x7F && incomingByte < 0xF0){
  40.      command = incomingByte;
  41.    }
  42.    while(!Serial.available()){
  43.    }
  44.    incomingByte = Serial.read();
  45.    if(incomingByte > 0x7F){
  46.      continue;
  47.    }
  48.    else{
  49.      pitch = incomingByte;
  50.    }
  51.    while(!Serial.available()){
  52.    }
  53.    incomingByte = Serial.read();
  54.    if(incomingByte > 0x7F){
  55.      continue;
  56.    }
  57.    else{
  58.      velocity = incomingByte;
  59.      fullWord = true;
  60.      return;
  61.    }
  62.  
  63.  }
  64.    // noteOn between 0x90 and 0x9F, note off 0x80 and 0x8F
  65.   if(incomingByte >= 0x80 && incomingByte <= 0x9F){
  66.     command = incomingByte;
  67.       while(!Serial.available()){
  68.         //delay(1);
  69.       }
  70.     pitch = Serial.read();
  71.       while(!Serial.available()){
  72.        // delay(1);
  73.       }
  74.     velocity = Serial.read();
  75.   }
  76.   return;
  77. }
  78.  
  79. /*
  80. // check the serial que for next midi word
  81. void MidiWord::getWord(){
  82.   byte incomingByte = nullByte;
  83.   command = nullByte;
  84.   pitch = nullByte;
  85.   velocity = nullByte;
  86.  //check to see if the serial is available
  87.  if(Serial.available() > 0){
  88.     incomingByte = Serial.read();
  89.  }
  90.  else{
  91.    return;
  92.  }
  93.    // noteOn between 0x90 and 0x9F, note off 0x80 and 0x8F
  94.   if(incomingByte >= 0x80 && incomingByte <= 0x9F){
  95.     command = incomingByte;
  96.       while(!Serial.available()){
  97.         //delay(1);
  98.       }
  99.     pitch = Serial.read();
  100.       while(!Serial.available()){
  101.        // delay(1);
  102.       }
  103.     velocity = Serial.read();
  104.   }
  105.   return;
  106. }
  107. */
  108.  
  109. byte MidiWord::getCommand() const{
  110.   return command;
  111. }
  112.  
  113. byte MidiWord::getPitch() const{
  114.   return pitch;
  115. }
  116.  
  117. byte MidiWord::getVelocity() const{
  118.   return velocity;  
  119. }
  120.  
  121. boolean MidiWord::isEqual(MidiWord inWord) const{
  122.   if(command == inWord.getCommand() && pitch == inWord.getPitch() && velocity == inWord.getVelocity()){
  123.     //digitalWrite(ledPin, flipState(digitalRead(ledPin)));
  124.     return true;
  125.   }
  126.   else{
  127.     //digitalWrite(ledPin, flipState(digitalRead(ledPin)));
  128.     return false;
  129.    
  130.   }
  131. }
  132.  
  133. // send the midi note out on specific channel.
  134. void MidiWord::writeWord(byte sdChannel) const{
  135.   //a way to say "don't send
  136.   if(sdChannel > 0x0f){
  137.     return;
  138.   }
  139.   if(command > 0x00){
  140.   //digitalWrite(ledPin, flipState(digitalRead(ledPin)));
  141.   //Serial.write(command);
  142.   //Serial.write(pitch);
  143.   //Serial.write(velocity);
  144.  
  145.   Serial.write(command + sdChannel);
  146.   Serial.write(pitch);
  147.   Serial.write(velocity);
  148.   }
  149.   else{
  150.     return;
  151.   }
  152. }
  153.  
  154. MidiChannel::MidiChannel(){
  155.    //channel = 0x00;
  156.    currentPitch = nullByte;
  157.    playState = false;
  158.    startTime = millis();
  159. }
  160.  
  161. /*
  162. MidiChannel::MidiChannel(byte selectChannel){
  163.    channel = selectChannel;
  164.    currentPitch = nullByte;
  165.    playState = false;
  166.    startTime = millis();
  167. }
  168.  
  169.  
  170. byte MidiChannel::getMChannel() const{
  171.   return channel;
  172. }
  173. */
  174.  
  175. byte MidiChannel::getCurrentPitch() const{
  176.   return currentPitch;
  177. }
  178.  
  179. boolean MidiChannel::getPlayState() const{
  180.   return playState;
  181.  }
  182.  
  183. unsigned long MidiChannel::getStartTime() const{
  184.   return startTime;
  185. }
  186. /*
  187. void MidiChannel::setMChannel(byte inChannel){
  188.   channel = inChannel;
  189. }
  190. */
  191.  
  192. void MidiChannel::setCurrentPitch(const byte inCurrentPitch){
  193.   currentPitch = inCurrentPitch;
  194. }
  195.  
  196. void MidiChannel::setPlayState(const boolean inState){
  197.   playState = inState;
  198. }
  199.  
  200. void MidiChannel::setStartTime(){
  201.   startTime = millis();
  202. }
  203.  
  204. MCArray::MCArray(){
  205. }
  206.  
  207.  
  208. // use an algorithm to find which note should be played next
  209. // killnote is in case all channels are in use.
  210. byte MCArray::nextNotePlayPitch(MidiWord& killNote, byte numberOfChannels) const{
  211.  
  212.   // check if all notes are being played
  213.   for(int i = 0x00; i < numberOfChannels; i++){
  214.     if (midiArray[i].getPlayState() == false){
  215.       return i;
  216.     }
  217.   }
  218.  
  219.   // check play times
  220.   byte dropChannel = 0x00;
  221.   byte maxPitch = midiArray[0x00].getCurrentPitch();
  222.   killNote.setAll(noteOff, midiArray[0x00].getCurrentPitch(), nullByte);
  223.   for(int i = 0x01; i < numberOfChannels; i++){
  224.     if(maxPitch < midiArray[i].getCurrentPitch()){
  225.       dropChannel = i;
  226.       maxPitch = midiArray[i].getCurrentPitch();
  227.       killNote.setAll(noteOff, midiArray[i].getCurrentPitch(), maxVelocity);
  228.     }
  229.   }
  230.   return dropChannel;
  231. }
  232.  
  233. // use an algorithem to find which note should be played next
  234. // killnote is in case all channels are in use.
  235. byte MCArray::nextNotePlayTime(MidiWord& killNote, byte numberOfChannels) const{
  236.  
  237.   // check if all notes are being played
  238.   for(int i = 0x00; i < numberOfChannels; i++){
  239.     if (midiArray[i].getPlayState() == false){
  240.       return i;
  241.     }
  242.   }
  243.  
  244.   // check play times
  245.   byte dropChannel = 0x00;
  246.   unsigned long lowTime = midiArray[0x00].getStartTime();
  247.   killNote.setAll(noteOff, midiArray[0x00].getCurrentPitch(), nullByte);
  248.   for(int i = 0x01; i < numberOfChannels; i++){
  249.     if(lowTime > midiArray[i].getStartTime()){
  250.       dropChannel = i;
  251.       lowTime = midiArray[i].getStartTime();
  252.       killNote.setAll(noteOff, midiArray[i].getCurrentPitch(), maxVelocity);
  253.     }
  254.   }
  255.   return dropChannel;
  256. }
  257.  
  258. // check the channels with current status on and match pitch to determine note send off.
  259. byte MCArray::noteOffMatch(const byte inPitch) const{
  260.   for(int i = 0x00; i < TOTAL_CHANNELS; i++){
  261.     if(midiArray[i].getCurrentPitch() == inPitch){
  262.       return i;
  263.     }
  264.   }
  265.   // incase the note has already been turned off
  266.   return 0xFF;
  267.  
  268. }
  269. void MCArray::updateStatus(const MidiWord& currentMessage, byte messageChannel){
  270.   if(currentMessage.getCommand() == noteOn){
  271.     midiArray[messageChannel].setCurrentPitch(currentMessage.getPitch());
  272.     midiArray[messageChannel].setPlayState(true);
  273.     midiArray[messageChannel].setStartTime();
  274.   }
  275.  
  276.   if(currentMessage.getCommand() == noteOff){
  277.     midiArray[messageChannel].setCurrentPitch(nullByte);
  278.     midiArray[messageChannel].setPlayState(false);
  279.   }
  280. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement