Teensy synth crashes while playing

dirky

Member
Hi,
i have made my first teensy project followed a tutorial from Notes and Volts. After i added a Line out to the Audioshield i am finaly able to play it via a Midi-interface from my DAW. Unfortunatly it crashes quite often. Its usualy when i change notes while the Sequencer is still playing. Only fix is to unplug it.
I am powering Teensy via USB from my Computer.
Is there a way to make it responde more stable while editing notes on the fly?
Here s a link to the Code :
Thanks for reply
 
I can't see anything obviously wrong with it, I'm curious about why it has so many connections between the audio board and the Teensy, also your note handling routine isn't that great which might be causing it to crash, really you need a better way to handle on/off notes and only play free ones etc. Also it uses velocity to control the volume of the oscillators, it's novel, but I've never seen anyone do that before. Usually you use velocity to modify the envelope intensity of the VCF or VCA and simply use a level mixer for each VCO output. Also move checkSwitches to the main loop insetad on inside the checkMux.

Here is a simple 6 note, noteOn/Off routine that also checks for notes free etc. Maybe you can adapt it.

C++:
#define NO_OF_VOICES 6

struct VoiceAndNote {
  int note;
  int velocity;
  long timeOn;
};

struct VoiceAndNote voices[NO_OF_VOICES] = {
  { -1, -1, 0 },
  { -1, -1, 0 },
  { -1, -1, 0 },
  { -1, -1, 0 },
  { -1, -1, 0 },
  { -1, -1, 0 }
};

boolean voiceOn[NO_OF_VOICES] = { false, false, false, false, false, false };
int prevNote = 0;  //Initialised to middle value
bool notes[88] = { 0 }, initial_loop = 1;
int8_t noteOrder[40] = { 0 }, orderIndx = { 0 };

void DinHandleNoteOn(byte channel, byte note, byte velocity) {

    //Check for out of range notes
    if (note < 0 || note > 127) return;
    switch (getVoiceNo(-1)) {
      case 1:
        voices[0].note = note;
        voices[0].velocity = velocity;
        voices[0].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[0] = true;
        break;
      case 2:
        voices[1].note = note;
        voices[1].velocity = velocity;
        voices[1].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[1] = true;
        break;
      case 3:
        voices[2].note = note;
        voices[2].velocity = velocity;
        voices[2].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[2] = true;
        break;
      case 4:
        voices[3].note = note;
        voices[3].velocity = velocity;
        voices[3].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[3] = true;
        break;
      case 5:
        voices[4].note = note;
        voices[4].velocity = velocity;
        voices[4].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[4] = true;
        break;
      case 6:
        voices[5].note = note;
        voices[5].velocity = velocity;
        voices[5].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[5] = true;
        break;
    }
}

void DinHandleNoteOff(byte channel, byte note, byte velocity) {
    switch (getVoiceNo(note)) {
      case 1:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[0].note = -1;
        voiceOn[0] = false;
        break;
      case 2:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[1].note = -1;
        voiceOn[1] = false;
        break;
      case 3:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[2].note = -1;
        voiceOn[2] = false;
        break;
      case 4:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[3].note = -1;
        voiceOn[3] = false;
        break;
      case 5:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[4].note = -1;
        voiceOn[4] = false;
        break;
      case 6:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[5].note = -1;
        voiceOn[5] = false;
        break;
    }
}

int getVoiceNo(int note) {
  voiceToReturn = -1;       //Initialise to 'null'
  earliestTime = millis();  //Initialise to now
  if (note == -1) {
    //NoteOn() - Get the oldest free voice (recent voices may be still on release stage)
    for (int i = 0; i < NO_OF_VOICES; i++) {
      if (voices[I].note == -1) {
        if (voices[I].timeOn < earliestTime) {
          earliestTime = voices[I].timeOn;
          voiceToReturn = i;
        }
      }
    }
    if (voiceToReturn == -1) {
      //No free voices, need to steal oldest sounding voice
      earliestTime = millis();  //Reinitialise
      for (int i = 0; i < NO_OF_VOICES; i++) {
        if (voices[I].timeOn < earliestTime) {
          earliestTime = voices[I].timeOn;
          voiceToReturn = i;
        }
      }
    }
    return voiceToReturn + 1;
  } else {
    //NoteOff() - Get voice number from note
    for (int i = 0; i < NO_OF_VOICES; i++) {
      if (voices[I].note == note) {
        return i + 1;
      }
    }
  }
  //Shouldn't get here, return voice 1
  return 1;
}
 
Last edited:
When you post code, can you do it between code tags using the </> button.
This preserves indenting which makes your code more readable and therefore more likely to get a response.
I have posted your code below so you can see the difference.
It is also usual to ask that a complete program is provided so that the error/problem can be replicated and then hopefully solved.

Code:
#define NO_OF_VOICES 6

struct VoiceAndNote {
    int note;
    int velocity;
    long timeOn;
};

struct VoiceAndNote voices[NO_OF_VOICES] = {
{ -1, -1, 0 },
{ -1, -1, 0 },
{ -1, -1, 0 },
{ -1, -1, 0 },
{ -1, -1, 0 },
{ -1, -1, 0 }
};

boolean voiceOn[NO_OF_VOICES] = { false, false, false, false, false, false };
int prevNote = 0; //Initialised to middle value
bool notes[88] = { 0 }, initial_loop = 1;
int8_t noteOrder[40] = { 0 }, orderIndx = { 0 };

void DinHandleNoteOn(byte channel, byte note, byte velocity) {

    //Check for out of range notes
    if (note < 0 || note > 127) return;
    switch (getVoiceNo(-1)) {
    case 1:
        voices[0].note = note;
        voices[0].velocity = velocity;
        voices[0].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[0] = true;
        break;
    case 2:
        voices[1].note = note;
        voices[1].velocity = velocity;
        voices[1].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[1] = true;
        break;
    case 3:
        voices[2].note = note;
        voices[2].velocity = velocity;
        voices[2].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[2] = true;
        break;
    case 4:
        voices[3].note = note;
        voices[3].velocity = velocity;
        voices[3].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[3] = true;
        break;
    case 5:
        voices[4].note = note;
        voices[4].velocity = velocity;
        voices[4].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[4] = true;
        break;
    case 6:
        voices[5].note = note;
        voices[5].velocity = velocity;
        voices[5].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[5] = true;
        break;
    }
}

void DinHandleNoteOff(byte channel, byte note, byte velocity) {
    switch (getVoiceNo(note)) {
    case 1:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[0].note = -1;
        voiceOn[0] = false;
        break;
    case 2:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[1].note = -1;
        voiceOn[1] = false;
        break;
    case 3:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[2].note = -1;
        voiceOn[2] = false;
        break;
    case 4:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[3].note = -1;
        voiceOn[3] = false;
        break;
    case 5:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[4].note = -1;
        voiceOn[4] = false;
        break;
    case 6:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[5].note = -1;
        voiceOn[5] = false;
        break;
    }
}

int getVoiceNo(int note) {
    voiceToReturn = -1; //Initialise to 'null'
    earliestTime = millis(); //Initialise to now
    if (note == -1) {
        //NoteOn() - Get the oldest free voice (recent voices may be still on release stage)
        for (int i = 0; i < NO_OF_VOICES; i++) {
            if (voices.note == -1) {
                if (voices.timeOn < earliestTime) {
                    earliestTime = voices.timeOn;
                    voiceToReturn = i;
                }
            }
        }
        if (voiceToReturn == -1) {
            //No free voices, need to steal oldest sounding voice
            earliestTime = millis(); //Reinitialise
            for (int i = 0; i < NO_OF_VOICES; i++) {
                if (voices.timeOn < earliestTime) {
                    earliestTime = voices.timeOn;
                    voiceToReturn = i;
                }
            }
        }
        return voiceToReturn + 1;
    }
    else {
        //NoteOff() - Get voice number from note
        for (int i = 0; i < NO_OF_VOICES; i++) {
            if (voices.note == note) {
                return i + 1;
            }
        }
    }
    //Shouldn't get here, return voice 1
    return 1;
}
 
When you post code, can you do it between code tags using the </> button.
This preserves indenting which makes your code more readable and therefore more likely to get a response.
I have posted your code below so you can see the difference.
It is also usual to ask that a complete program is provided so that the error/problem can be replicated and then hopefully solved.

Code:
#define NO_OF_VOICES 6

struct VoiceAndNote {
    int note;
    int velocity;
    long timeOn;
};

struct VoiceAndNote voices[NO_OF_VOICES] = {
{ -1, -1, 0 },
{ -1, -1, 0 },
{ -1, -1, 0 },
{ -1, -1, 0 },
{ -1, -1, 0 },
{ -1, -1, 0 }
};

boolean voiceOn[NO_OF_VOICES] = { false, false, false, false, false, false };
int prevNote = 0; //Initialised to middle value
bool notes[88] = { 0 }, initial_loop = 1;
int8_t noteOrder[40] = { 0 }, orderIndx = { 0 };

void DinHandleNoteOn(byte channel, byte note, byte velocity) {

    //Check for out of range notes
    if (note < 0 || note > 127) return;
    switch (getVoiceNo(-1)) {
    case 1:
        voices[0].note = note;
        voices[0].velocity = velocity;
        voices[0].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[0] = true;
        break;
    case 2:
        voices[1].note = note;
        voices[1].velocity = velocity;
        voices[1].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[1] = true;
        break;
    case 3:
        voices[2].note = note;
        voices[2].velocity = velocity;
        voices[2].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[2] = true;
        break;
    case 4:
        voices[3].note = note;
        voices[3].velocity = velocity;
        voices[3].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[3] = true;
        break;
    case 5:
        voices[4].note = note;
        voices[4].velocity = velocity;
        voices[4].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[4] = true;
        break;
    case 6:
        voices[5].note = note;
        voices[5].velocity = velocity;
        voices[5].timeOn = millis();
        MIDI.sendNoteOn(note, velocity, 1);
        voiceOn[5] = true;
        break;
    }
}

void DinHandleNoteOff(byte channel, byte note, byte velocity) {
    switch (getVoiceNo(note)) {
    case 1:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[0].note = -1;
        voiceOn[0] = false;
        break;
    case 2:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[1].note = -1;
        voiceOn[1] = false;
        break;
    case 3:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[2].note = -1;
        voiceOn[2] = false;
        break;
    case 4:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[3].note = -1;
        voiceOn[3] = false;
        break;
    case 5:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[4].note = -1;
        voiceOn[4] = false;
        break;
    case 6:
        MIDI.sendNoteOff(note, velocity, 1);
        voices[5].note = -1;
        voiceOn[5] = false;
        break;
    }
}

int getVoiceNo(int note) {
    voiceToReturn = -1; //Initialise to 'null'
    earliestTime = millis(); //Initialise to now
    if (note == -1) {
        //NoteOn() - Get the oldest free voice (recent voices may be still on release stage)
        for (int i = 0; i < NO_OF_VOICES; i++) {
            if (voices.note == -1) {
                if (voices.timeOn < earliestTime) {
                    earliestTime = voices.timeOn;
                    voiceToReturn = i;
                }
            }
        }
        if (voiceToReturn == -1) {
            //No free voices, need to steal oldest sounding voice
            earliestTime = millis(); //Reinitialise
            for (int i = 0; i < NO_OF_VOICES; i++) {
                if (voices.timeOn < earliestTime) {
                    earliestTime = voices.timeOn;
                    voiceToReturn = i;
                }
            }
        }
        return voiceToReturn + 1;
    }
    else {
        //NoteOff() - Get voice number from note
        for (int i = 0; i < NO_OF_VOICES; i++) {
            if (voices.note == note) {
                return i + 1;
            }
        }
    }
    //Shouldn't get here, return voice 1
    return 1;
}

I have updated my post, first time posting code
 
Have a look at noteFreqs[note + octave1] - there are quite a few instances where I think you could go out of bounds i.e. >127 which would have unpredictable results. You need to constrain the note+octave to keep it in bounds.

I do it with something like :
// Wraps a MIDI note to the range 0–127 in a musical way
inline byte wrapMidiNote(int note)
{
while (note > 127)
note -= 12;
while (note < 0)
note += 12;
return note;
}

cheers Paul
 
Back
Top