Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Teensy 4.0 Synthesizer Project - Crashing Issues

  1. #1
    Junior Member
    Join Date
    Mar 2020
    Posts
    1

    Teensy 4.0 Synthesizer Project - Crashing Issues

    This is my first time playing with a Teensy and I am attempting to build a synthesizer using the Teensy 4.0 and the audioshield. I've harvested the keyboard from an old Yamaha synth and am reading the key matrix into the Teensy using a 74hc165 shift register. The keyboard has 2 separate matrix's (one for each half) each with 4 columns(output) and 6 rows(input). Ive built a basic program for reading the input from the shift register and playing the associated note for each key, i currently have it configured to be able to play 8 notes at the same time. Everything seems to work fine if I play slowly but if I smash down a few keys at the same time or just play very fast the Teensy crashes and makes a loud buzzing until I reset it. Ive tried reading the shift register using the SPI library and now using the shiftIn() function, both give me the same results. Hoping that someone with more experience might know where I've gone all wrong
    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #include <SPI.h>
    
    // GUItool: begin automatically generated code
    
    AudioSynthWaveform   sine6; 
    AudioSynthWaveform   sine7; 
    AudioSynthWaveform   sine8; 
    AudioSynthWaveform   sine3; 
    AudioSynthWaveform   sine4; 
    AudioSynthWaveform   sine5; 
    AudioSynthWaveform   sine1;   
    AudioSynthWaveform   sine2; 
    AudioSynthWaveform *waves[8] = {
      &sine1, &sine2, &sine3,
      &sine4, &sine5, &sine6, &sine7, &sine8,  
    };
    
    AudioEffectEnvelope      envelope8; 
    AudioEffectEnvelope      envelope7; 
    AudioEffectEnvelope      envelope5; 
    AudioEffectEnvelope      envelope6; 
    AudioEffectEnvelope      envelope4; 
    AudioEffectEnvelope      envelope3; 
    AudioEffectEnvelope      envelope1;   
    AudioEffectEnvelope      envelope2; 
    AudioEffectEnvelope *envs[8] = {
      &envelope1, &envelope2, &envelope3,
      &envelope4, &envelope5, &envelope6, &envelope7, &envelope8
    };
    
    AudioMixer4              mixer2; //xy=548.75,280.75
    AudioMixer4              mixer1;         //xy=549.75,214.75
    AudioMixer4              mixer3; //xy=686.75,248.75
    AudioOutputI2S           i2s1;           //xy=844.9998779296875,249.22219848632812
    AudioConnection          patchCord1(sine6, envelope6);
    AudioConnection          patchCord2(sine7, envelope7);
    AudioConnection          patchCord3(sine8, envelope8);
    AudioConnection          patchCord4(sine3, envelope3);
    AudioConnection          patchCord5(sine4, envelope4);
    AudioConnection          patchCord6(sine5, envelope5);
    AudioConnection          patchCord7(sine1, envelope1);
    AudioConnection          patchCord8(sine2, envelope2);
    AudioConnection          patchCord9(envelope8, 0, mixer2, 3);
    AudioConnection          patchCord10(envelope7, 0, mixer2, 2);
    AudioConnection          patchCord11(envelope5, 0, mixer2, 0);
    AudioConnection          patchCord12(envelope6, 0, mixer2, 1);
    AudioConnection          patchCord13(envelope4, 0, mixer1, 3);
    AudioConnection          patchCord14(envelope3, 0, mixer1, 2);
    AudioConnection          patchCord15(envelope1, 0, mixer1, 0);
    AudioConnection          patchCord16(envelope2, 0, mixer1, 1);
    AudioConnection          patchCord17(mixer2, 0, mixer3, 1);
    AudioConnection          patchCord18(mixer1, 0, mixer3, 0);
    AudioConnection          patchCord19(mixer3, 0, i2s1, 0);
    AudioConnection          patchCord20(mixer3, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=607.1111450195312,489
    // GUItool: end automatically generated code
     
    const int sh_ld = 0; //shift/load
    const int key_out[4] = {10,12,28,33}; // keyboard output pins
    const int clk = 1;
    const int shift_in = 11;
    
    float vol = .1;
    
    byte last_shift_1[4]; // holds previous shift register data
    byte shift_data_1[4]; // holds current shift register data
    byte last_shift_2[4]; // holds previous shift register data
    byte shift_data_2[4]; // holds current shift register data
    
    int voice = 0; // the audio object being used, 8 existint key_state1 = 0;
    
    byte current_key; // used to hold the current bit read
    byte last_key; // used to hold the last bit read
    
    int right_side =25; // right side which starts at key 25
    byte note_tracking[49]; //tracks which note is currently being played
      
    float notes[49] = {65.41, 69.30, 73.42, 77.78, 82.41, 87.31, 92.50, 98.00, 103.83, 110.00, 116.54, 123.47, 130.81, 138.59, 146.83, 155.56, 164.81,  
    174.61, 185.00, 196.00, 207.65, 220.00, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 
    493.88, 523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77, 1046.50};
    
    
    void setup(){
      Serial.begin(9600);
       
      AudioMemory(24);
      sgtl5000_1.enable();
      sgtl5000_1.volume(.3);
      AudioProcessorUsageMaxReset();
      AudioMemoryUsageMaxReset();
      
      pinMode(sh_ld, OUTPUT);//set pin modes
      pinMode(key_out[0], OUTPUT);
      pinMode(key_out[1], OUTPUT);
      pinMode(key_out[2], OUTPUT);
      pinMode(key_out[3], OUTPUT);
      pinMode(clk, OUTPUT);
      pinMode(shift_in,INPUT);
    
      // set 
      digitalWrite(sh_ld, HIGH);//set to shift
      digitalWrite(key_out[0], LOW); //set output pins low
      digitalWrite(key_out[1], LOW);
      digitalWrite(key_out[2], LOW);
      digitalWrite(key_out[3], LOW);
      digitalWrite(clk, LOW);
      
    
       // set envelope parameters, for pleasing sound :-)
      for (int i=0; i<8; i++) {
        envs[i]->attack(9.2);
        envs[i]->hold(2.1);
        envs[i]->decay(31.4);
        envs[i]->sustain(0.6);
        envs[i]->release(84.5);
      }
      for (int i=0;i<49;i++){ // initialize all key = not pressed
        note_tracking[i] = 0;
      }
      for (int i=0;i<4;i++){ // set last shift arrays to zero
        last_shift_1[i] = 0;
      }
      for (int i=0;i<4;i++){ // set last shift arrays to zero
        last_shift_2[i] = 0;
      }
     
    }
    void loop(){
      
      while(voice < 8)
      {
        for(int row=0;row<4;row++)
        {
          int oct = (row * 6); //6 keys per output
          digitalWrite(key_out[row], HIGH);//set output line high 
          delayMicroseconds(500);
          
          shift_data_1[row] = read_keys_1(); // first shift register
          shift_data_2[row] = (read_keys_2() >> 1); // second shift register
                           
          for(int column=0;column<6;column++) //right side of keyboard
          {
            int note = (oct + right_side + column); // starting at beginning of right side and going through each key
            current_key = bitRead(shift_data_1[row], column);
            last_key = bitRead(last_shift_1[row], column);
            
            if ((current_key == 1) && (last_key == 0)){                            // key pressed
              AudioNoInterrupts();
              waves[voice]->begin(vol,notes[note],WAVEFORM_SINE);// play note
              envs[voice]->noteOn();
              AudioInterrupts();
              note_tracking[note] = voice; // keeps track of the voice being used for this sound
              //Serial.print(voice);
              voice ++;
              
            }
            if ((current_key == 0) && (last_key == 1)){                            // key released
              envs[note_tracking[note]]->noteOff(); 
              //Serial.print(note_tracking[note]);             
            }
          }
          
          for(int column=0;column<6;column++) //left side of keyboard
          {
            int note = (oct + column); //current note, starting at left side and gong through each key
            current_key = bitRead(shift_data_2[row], column);
            last_key = bitRead(last_shift_2[row], column);
            
            if ((current_key == 1) && (last_key == 0)){                            // key pressed
              AudioNoInterrupts();
              waves[voice]->begin(vol,notes[note],WAVEFORM_SINE);// play note
              envs[voice]->noteOn();
              AudioInterrupts();
              note_tracking[note] = voice; // keeps track of the voice being used for this sound
              Serial.print(voice);
              voice ++;
              
            }
            if ((current_key == 0) && (last_key == 1)){                            // key released
              envs[note_tracking[note]]->noteOff(); 
              Serial.print(note_tracking[note]);             
            }
          }
          last_shift_1[row] = shift_data_1[row];
          last_shift_2[row] = shift_data_2[row];
          digitalWrite(key_out[row], LOW);
        }
      
      }
      voice = 0;
    }
     
    
    byte read_keys_1 (){
      byte shift_1;
      // Write pulse to load pin
      digitalWrite(sh_ld, LOW);
      delayMicroseconds(500);
      digitalWrite(sh_ld, HIGH);
      delayMicroseconds(500);
      shift_1 = shiftIn(shift_in, clk, MSBFIRST);//shift in data
      return shift_1;
    }
    
    byte read_keys_2 (){
      byte shift_2;
      shift_2 = shiftIn(shift_in, clk, MSBFIRST);//shift in data
      return shift_2;
    }
    Here's the first code using SPI to read the shift register and only reading half of the keyboard, might be a little easier to read.
    Code:
    // GUItool: begin automatically generated code
    
    AudioSynthWaveform   sine6; 
    AudioSynthWaveform   sine7; 
    AudioSynthWaveform   sine8; 
    AudioSynthWaveform   sine3; 
    AudioSynthWaveform   sine4; 
    AudioSynthWaveform   sine5; 
    AudioSynthWaveform   sine1;   
    AudioSynthWaveform   sine2; 
    AudioSynthWaveform *waves[8] = {
      &sine1, &sine2, &sine3,
      &sine4, &sine5, &sine6, &sine7, &sine8,  
    };
    
    AudioEffectEnvelope      envelope8; 
    AudioEffectEnvelope      envelope7; 
    AudioEffectEnvelope      envelope5; 
    AudioEffectEnvelope      envelope6; 
    AudioEffectEnvelope      envelope4; 
    AudioEffectEnvelope      envelope3; 
    AudioEffectEnvelope      envelope1;   
    AudioEffectEnvelope      envelope2; 
    AudioEffectEnvelope *envs[8] = {
      &envelope1, &envelope2, &envelope3,
      &envelope4, &envelope5, &envelope6, &envelope7, &envelope8
    };
    
    AudioMixer4              mixer2; //xy=548.75,280.75
    AudioMixer4              mixer1;         //xy=549.75,214.75
    AudioMixer4              mixer3; //xy=686.75,248.75
    AudioOutputI2S           i2s1;           //xy=844.9998779296875,249.22219848632812
    AudioConnection          patchCord1(sine6, envelope6);
    AudioConnection          patchCord2(sine7, envelope7);
    AudioConnection          patchCord3(sine8, envelope8);
    AudioConnection          patchCord4(sine3, envelope3);
    AudioConnection          patchCord5(sine4, envelope4);
    AudioConnection          patchCord6(sine5, envelope5);
    AudioConnection          patchCord7(sine1, envelope1);
    AudioConnection          patchCord8(sine2, envelope2);
    AudioConnection          patchCord9(envelope8, 0, mixer2, 3);
    AudioConnection          patchCord10(envelope7, 0, mixer2, 2);
    AudioConnection          patchCord11(envelope5, 0, mixer2, 0);
    AudioConnection          patchCord12(envelope6, 0, mixer2, 1);
    AudioConnection          patchCord13(envelope4, 0, mixer1, 3);
    AudioConnection          patchCord14(envelope3, 0, mixer1, 2);
    AudioConnection          patchCord15(envelope1, 0, mixer1, 0);
    AudioConnection          patchCord16(envelope2, 0, mixer1, 1);
    AudioConnection          patchCord17(mixer2, 0, mixer3, 1);
    AudioConnection          patchCord18(mixer1, 0, mixer3, 0);
    AudioConnection          patchCord19(mixer3, 0, i2s1, 0);
    AudioConnection          patchCord20(mixer3, 0, i2s1, 1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=607.1111450195312,489
    // GUItool: end automatically generated code
     
    const int sh_ld = 14; //shift/load
    const int key_out[4] = {18,19,1,0}; // keyboard output pins
    
    byte last_shift[4]; // holds previous shift register data
    byte shift_data[4]; // holds current shift register data
    
    float vol = 0.1;
    int voice = 0; // the audio object being used, 8 existint key_state1 = 0;
    
    byte current_key; // used to hold the current bit read
    byte last_key; // used to hold the last bit read
    
    int first_key =25; // using right side which strts at key 25
    
    byte note_tracking[49];
      
    float notes[49] = {65.41, 69.30, 73.42, 77.78, 82.41, 87.31, 92.50, 98.00, 103.83, 110.00, 116.54, 123.47, 130.81, 138.59, 146.83, 155.56, 164.81,  
    174.61, 185.00, 196.00, 207.65, 220.00, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 
    493.88, 523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77, 1046.50};
    
    SPISettings settingA(1000000, MSBFIRST, SPI_MODE0);//1mhz
    unsigned long last_time = millis();
     
    void setup(){
      Serial.begin(9600);
      SPI.begin();
      
      AudioMemory(8);
      sgtl5000_1.enable();
      sgtl5000_1.volume(.30);
      AudioProcessorUsageMaxReset();
      AudioMemoryUsageMaxReset();
      
      pinMode(sh_ld, OUTPUT);//set pin modes
      pinMode(key_out[0], OUTPUT);
      pinMode(key_out[1], OUTPUT);
      pinMode(key_out[2], OUTPUT);
      pinMode(key_out[3], OUTPUT);
    
      // set 
      digitalWrite(14, HIGH);//set to shift
      digitalWrite(key_out[0], LOW); //set output pins low
      digitalWrite(key_out[1], LOW);
      digitalWrite(key_out[2], LOW);
      digitalWrite(key_out[3], LOW);
    
       // set envelope parameters, for pleasing sound :-)
      for (int i=0; i<8; i++) {
        envs[i]->attack(9.2);
        envs[i]->hold(2.1);
        envs[i]->decay(31.4);
        envs[i]->sustain(0.6);
        envs[i]->release(84.5);
      }
      for (int i=0;i<49;i++){ // initialize all key = not pressed
        note_tracking[i] = 0;
      }
      for (int i=0;i<4;i++){ // set last shift arrays to zero
        last_shift[i] = 0;
      }
     
    }
    void loop(){
      
      
      
      while(voice < 8)
      {
        for(int row=0;row<4;row++)
        {
          int oct = (row * 6); //6 keys per output
          digitalWrite(key_out[row], HIGH);//set output line i high 
          delay(1);
          shift_data[row] = read_keys();
                
          for(int column=0;column<6;column++)
          {
            int note = (oct + first_key + column);
            current_key = bitRead(shift_data[row], column);
            last_key = bitRead(last_shift[row], column);
            
            if ((current_key == 1) && (last_key == 0)){                            // key pressed
              AudioNoInterrupts();
              waves[voice]->begin(vol,notes[note],WAVEFORM_SINE);// play note
              envs[voice]->noteOn();
              AudioInterrupts();
              note_tracking[note] = voice; // keeps track of the voice being used for this sound
              Serial.print(voice);
              voice ++;
              
            }
            if ((current_key == 0) && (last_key == 1)){                            // key released
              envs[note_tracking[note]]->noteOff(); 
              Serial.print(note_tracking[note]);             
            }
            
          }
          last_shift[row] = shift_data[row];
          digitalWrite(key_out[row], LOW);
        }
      
      }
      voice = 0;
    }
     
    
    byte read_keys (){
      byte shift_1;
      SPI.beginTransaction(settingA); // start spi with pre set settings
      digitalWrite(sh_ld, LOW);//set shift reg to load data
      delay(1); //delay 1 ms
      digitalWrite(sh_ld,HIGH);//set shift reg to shift data into teensy 
      shift_1 = SPI.transfer(0x00); // read data transfer
      SPI.endTransaction(); //end spi
      
      if(millis() - last_time >= 5000) {
        Serial.print("Proc = ");
        Serial.print(AudioProcessorUsage());
        Serial.print(" (");    
        Serial.print(AudioProcessorUsageMax());
        Serial.print("),  Mem = ");
        Serial.print(AudioMemoryUsage());
        Serial.print(" (");    
        Serial.print(AudioMemoryUsageMax());
        Serial.println(")");
        last_time = millis();
      }
        
      return shift_1;
    }

  2. #2
    Senior Member
    Join Date
    Feb 2015
    Posts
    217
    My guess is you're reading/writing out of bounds on one of the several arrays that you've got. One recommendation is to #define the array length so you can be sure any code which accesses the array has a proper length available. For example:

    Code:
    #define NUM_VOICES 8
    
    AudioSynthWaveform *waves[NUM_VOICES] = {
    &sine1, &sine2, &sine3,
    &sine4, &sine5, &sine6, &sine7, &sine8,  
    };
    
    AudioEffectEnvelope *envs[NUM_VOICES] = {
    &envelope1, &envelope2, &envelope3,
    &envelope4, &envelope5, &envelope6, &envelope7, &envelope8
    };
    
    ... other code here ...
    
    if ((current_key == 1) && (last_key == 0)){                            // key pressed
        if(voice >= NUM_VOICES) {
            Serial.printf("We just went out of bounds on the voice array!\n");
        } else {
            AudioNoInterrupts();
            waves[voice]->begin(vol,notes[note],WAVEFORM_SINE);// play note
            envs[voice]->noteOn();
            AudioInterrupts();
            note_tracking[note] = voice; // keeps track of the voice being used for this sound
            //Serial.print(voice);
            voice ++;
        }
    }
    Assuming my hunch is right (a big assumption) you would need to check each array in your code until you find the one(s) with out of bounds accesses.

  3. #3
    Junior Member
    Join Date
    Oct 2019
    Posts
    10
    Maybe you got a short circuit in your keyboard matrix when pressing multiple keys? Short circuits crashing the Teensy happened to me once with a faulty pushbutton. But since you said, that your error also occurs, when you are playing fast...
    You could try to scale your program down even further so you can evaluate better.

  4. #4
    I can't find anything in your code that would cause a problem, but when manipulating array it can be tricky. Last week I had three dead keys while polling a 5 octaves Casio keybed. They where dead until I saw they were 8 keys-spaced, then discovered that I update my track table past the end of the table (which for once crashed nothing !)

    My advice : break your code into dedicate functions so you can call them from main loop and test each functionality without the others. it should be easier to track down your bug.
    You also can also add a "debug" for loop that iterate trough your noteTracking table to check that every key answers correctly.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •