Polyphonic USB MIDI Pulse synth works for a few minutes and then stops respondin

Hi all,

I hope you’re safe and healthy. I was looking for some help with a project that I’m working on- a polyphonic USB MIDI pulse synth. The issue is that it works for a few minutes and then seems to stop responding to notes. It continues to show serial communication, and continues to print that it is receiving the correct information in the serial monitor but stops outputting the pulses on the output pin. Any advice would be greatly appreciated. Thanks!

Heres the code:

#include <MIDI.h>
float notes[] = {
  8.1757989156,   // 0
  8.6619572180,   // 1
  9.1770239974,   // 2
  10.3008611535,  // 3
  10.3008611535,  // 4
  10.9133822323,  // 5
  11.5623257097,  // 6
  12.2498573744,  // 7
  12.9782717994,  // 8
  13.7500000000,  // 9
  14.5676175474,  // 10
  15.4338531643,  // 11
  16.3515978313,  // 12
  17.3239144361,  // 13
  18.3540479948,  // 14
  19.4454364826,  // 15
  20.6017223071,  // 16
  21.8267644646,  // 17
  23.1246514195,  // 18
  24.4997147489,  // 19
  25.9565435987,  // 20
  27.5000000000,  // 21
  29.1352350949,  // 22
  30.8677063285,  // 23
  32.7031956626,  // 24
  34.6478288721,  // 25
  36.7080959897,  // 26
  38.8908729653,  // 27
  41.2034446141,  // 28
  43.6535289291,  // 29
  46.2493028390,  // 30
  48.9994294977,  // 31
  51.9130871975,  // 32
  55.0000000000,  // 33
  58.2704701898,  // 34
  61.7354126570,  // 35
  65.4063913251,  // 36
  69.2956577442,  // 37
  73.4161919794,  // 38
  77.7817459305,  // 39
  82.4068892282,  // 40
  87.3070578583,  // 41
  92.4986056779,  // 42
  97.9988589954,  // 43
  103.8261743950,  // 44
  110.0000000000,  // 45
  116.5409403795,  // 46
  123.4708253140,  // 47
  130.8127826503,  // 48
  138.5913154884,  // 49
  146.8323839587,  // 50
  155.5634918610,  // 51
  164.8137784564,  // 52
  174.6141157165,  // 53
  184.9972113558,  // 54
  195.9977179909,  // 55
  207.6523487900,  // 56
  220.0000000000,  // 57
  233.0818807590,  // 58
  246.9416506281,  // 59
  261.6255653006,  // 60
  277.1826309769,  // 61
  293.6647679174,  // 62
  311.1269837221,  // 63
  329.6275569129,  // 64
  349.2282314330,  // 65
  369.9944227116,  // 66
  391.9954359817,  // 67
  415.3046975799,  // 68
  440.0000000000,  // 69
  466.1637615181,  // 70
  493.8833012561,  // 71
  523.2511306012,  // 72
  554.3652619537,  // 73
  587.3295358348,  // 74
  622.2539674442,  // 75
  659.2551138257,  // 76
  698.4564628660,  // 77
  739.9888454233,  // 78
  783.9908719635,  // 79
  830.6093951599,  // 80
  880.0000000000,  // 81
  932.3275230362,  // 82
  987.7666025122,  // 83
  1046.5022612024, // 84
  1108.7305239075, // 85
  1174.6590716696, // 86
  1244.5079348883, // 87
  1318.5102276515, // 88
  1396.9129257320, // 89
  1479.9776908465, // 90
  1567.9817439270, // 91
  1661.2187903198, // 92
  1760.0000000000, // 93
  1864.6550460724, // 94
  1975.5332050245, // 95
  2093.0045224048, // 96
  2217.4610478150, // 97
  2349.3181433393, // 98
  2489.0158697766, // 99
  2637.0204553030, // 100
  2793.8258514640, // 101
  2959.9553816931, // 102
  3135.9634878540, // 103
  3322.4375806396, // 104
  3520.0000000000, // 105
  3729.3100921447, // 106
  3951.0664100490, // 107
  4186.0090448096, // 108
  4434.9220956300, // 109
  4698.6362866785, // 110
  4978.0317395533, // 111
  5274.0409106059, // 112
  5587.6517029281, // 113
  5919.9107633862, // 114
  5919.9107633862, // 115
  6644.8751612791, // 116
  7040.0000000000, // 117
  7458.6201842894, // 118
  7902.1328200980, // 119
  8372.0180896192, // 120
  8869.8441912599, // 121
  9397.2725733570, // 122
  9956.0634791066, // 123
  10548.0818212118, // 124
  11175.3034058561, // 125
  11839.8215267723, // 126
  12543.8539514160 // 127
};

//notes
byte currentNote = 0;

byte voices[6] = {0,0,0,0,0,0};
byte noteVoice[6] = {0,0,0,0,0,0};

byte noteCounter = 0;

//Pulse output pin
int stpPin = 10;

//Are we currently playing a note?
bool playing[6] = {false, false, false, false, false, false};

//unsigned long durations[6] = {0, 0, 0, 0, 0, 0};

unsigned long long currentMillis = 0;
unsigned long long previousMillis[6] = {0, 0, 0, 0, 0, 0};

//Convert a MIDI note to the number of milliseconds to wait between pulses
unsigned long note2milliseconds(byte note) {
  return 1.0 / notes[note] * 100000000000.0;
}

void OnNoteOn(byte channel, byte note, byte velocity) {
    
  long long msNote = note2milliseconds(note);
    
    if(voices[0] == 0){
      noteVoice[0] = note;
      voices[0] = msNote;
      playing[0] = true;
      noteCounter ++;
      previousMillis[0] = currentMillis;
    }
    else if (voices[1] == 0){
      noteVoice[1] = note;
      voices[1] = msNote;
      playing[1] = true;
      noteCounter ++;
      previousMillis[1] = currentMillis;
    }
    else if (voices[2] == 0){
      noteVoice[2] = note;
      voices[2] = msNote;
      playing[2] = true;
      noteCounter ++;
      previousMillis[2] = currentMillis;
    }
    else if (voices[3] == 0){
      noteVoice[3] = note;
      voices[3] = msNote;
      playing[3] = true;
      noteCounter ++;
      previousMillis[3] = currentMillis;
    }
    else if (voices[4] == 0){
      noteVoice[4] = note;
      voices[4] = msNote;
      playing[4] = true;
      noteCounter ++;
      previousMillis[4] = currentMillis;
    }
    else if (voices[5] == 0){
      noteVoice[5] = note;
      voices[5] = msNote;
      playing[5] = true;
      noteCounter ++;
      previousMillis[5] = currentMillis;  
  }
}

void OnNoteOff(byte channel, byte note, byte velocity) {  
   if(currentNote == noteVoice[0]){  
        playing[0] = false;
        noteCounter --;
        noteVoice[0] = 0;

      }
   else if(currentNote == noteVoice[1]){
        playing[1] = false;
        noteCounter --;
        noteVoice[1] = 0;
      }
   else if(currentNote == noteVoice[2]){
        playing[2] = false;
        noteCounter --;
        noteVoice[2] = 0;
      }
    else if(currentNote == noteVoice[3]){
        playing[3] = false;
        noteCounter --;
        noteVoice[3] = 0;
      }
    else if(currentNote == noteVoice[4]){
        playing[4] = false;
        noteCounter --;
        noteVoice[4] = 0;
      }
     else if(currentNote == noteVoice[5]){
       playing[5] = false;
       noteCounter --;
       noteVoice[5] = 0;
    }
}

void setup() {                
  pinMode(stpPin, OUTPUT);     
  digitalWrite(stpPin, LOW);
}

void loop() {
  
  currentMillis = millis();
  
  while(MIDIUSB.available() > 0){
    MIDIEvent e;
    e = MIDIUSB.read();
    //Note Off Shows up in the Serial Monitor as e.type "8"
    if(e.type == 8){
      currentNote = e.m2;
      OnNoteOff(0, e.m2, e.m3);
    } 
    //Note On Shows up in the Serial Monitor as e.type "9"
    else if(e.type == 9){
       OnNoteOn(0, e.m2, e.m3);
       currentNote = e.m2;
       Serial.println("NoteOn Received");
    }
  }  

  
  if(playing[0]) {
    if(currentMillis - previousMillis[0] >= voices[0]){
      digitalWrite(stpPin, HIGH);
      //delayMicroseconds(5);
      digitalWrite(stpPin, LOW);
    }
  }  
  if (playing[1]) {
    if(currentMillis - previousMillis[1] >= voices[1]){
      digitalWrite(stpPin, HIGH);
      //delayMicroseconds(5);
      digitalWrite(stpPin, LOW);
    }
  }  
  if (playing[2]) {
    if(currentMillis - previousMillis[2] >= voices[2]){
      digitalWrite(stpPin, HIGH);
      //delayMicroseconds(5);
      digitalWrite(stpPin, LOW);
    }
  }  
  if (playing[3]) {
    if(currentMillis - previousMillis[3] >= voices[3]){     
      digitalWrite(stpPin, HIGH);
      //delayMicroseconds(5);
      digitalWrite(stpPin, LOW);
    }
  }
  if (playing[4]) {
    if(currentMillis - previousMillis[4] >= voices[4]){
      digitalWrite(stpPin, HIGH);
      //delayMicroseconds(5);
      digitalWrite(stpPin, LOW);
    }
  }
  if (playing[5]) {
    if(currentMillis - previousMillis[5] >= voices[5]){
      digitalWrite(stpPin, HIGH);
      //delayMicroseconds(5);
      digitalWrite(stpPin, LOW);
    }
  }
  if (noteCounter == 0){
  digitalWrite(stpPin, LOW);
  }
}

The issue is that it works for a few minutes and then seems to stop responding to notes. It continues to show serial communication, and continues to print that it is receiving the correct information in the serial monitor but stops outputting the pulses on the output pin.

In that case i suggest you start to send some debug information. particularly what the values of certain variables are within onNoteOn() and specifically 'noteCounter'
There is no check to see if it stays within it's limits, it shouldn't come out of it's limits but what should and what doesn't happen may not be the same.
As a more general idea i think you should have the voices shift down through the array if there are empty voices in lower array slots, so you could create a struct of voice rather than using individual variables, and really you should loop through the voices rather than using individual 'if' statements. It will make the code more transparant and shorter of course.