Monitoring Audio buffer

Chris Kelly

New member
Hi folks

I have a percussion instrument using the Teensy 4.1 with audioshield revD.

I am very novice with C/C++ and I'm looking for a way to check whether the audio buffer is cleared/empty after each percussion strike. I've been using a peak analyser to check for levels <0.01 to tell me, but was hoping there was a correct way to check if the audio buffer is NULL?

Thanks
 
I think you're more likely to get some help if you can make it a bit clearer what you're doing now, and what you think could be improved on. By far the best way to do that is to post a brief but complete sketch that can be compiled using the Arduino IDE. To post code, please use the </> button and paste your code in the window that pops up, to get a result that looks a bit like this:
C++:
// your code here
void setup()
{
   
}
Ideally reduce the hardware needed to the bare minimum - in particular, whatever you're using to trigger your percussion strikes. Just put code in to "hit the drum" every couple of seconds or so.
 
Thank you for your reply and advice. I found a workaround for the original issue, but I want to try and understand what might have caused it since I am still learning about the Audio Library (and C/C++ in general).

The project uses a piezo-electric sensor for drum hits. The range of input voltages then alter the 'velocity' parameter. This then affects various aspects of the drum sound.

I have an ILI9341 TFT connected using the standard Teensy 4.1 SPI pins. I added a feature which draws a fractal tree for each drum hit. This was originally a recursive function but I soon realised this took too long to complete, which then seemed to affect the length of the drum envelope and altered the sound.

To remedy this I replaced the recursive function and instead split it into stages, to gradually draw one iteration of the fractal after each drum hit. I also split the clearing of the display (tft.fillScreen) by using tft.fillRect multiple times. This was done with the intention of minimising the time spent for each iteration so as not to affect the sound.

The fractal tree is split into 8 stages. I noticed that on the first stage, the audio output is noticeably louder. With a scope on the audio output it seems as though the amplitude and release of the envelope are both increased. For the other 7 stages the envelope returns to normal.
I tried reducing the number of iterations in the function, but still seemed to get this issue every 8 steps i.e/ not necessarily on the 'first' stage, but on multiples of 8.

Here is a simplified version of my code which runs as a complete program and still elicits the same issue. WARNING -The code is badly written, and I've included all 8 stages of the fractal tree function (apologies!)

Code:
#include <Bounce.h>
#include <ILI9341_t3n.h>

////--------------------------------------------------------------------

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

AudioSynthWaveform       waveform1;     
AudioSynthNoiseWhite     transientNoise;
AudioMixer4              transientMixer;
AudioEffectEnvelope      transientEnvelope;
AudioAmplifier           transientAmp;   
AudioMixer4              mainMixer;
AudioAmplifier           FinalAmp;     
AudioOutputI2S           i2s2;         

AudioConnection          patchCord1(waveform1, 0, transientMixer, 1);
AudioConnection          patchCord2(transientNoise, 0, transientMixer, 0);
AudioConnection          patchCord3(transientMixer, transientEnvelope);
AudioConnection          patchCord4(transientEnvelope, transientAmp);
AudioConnection          patchCord5(transientAmp, 0, mainMixer, 0);
AudioConnection          patchCord6(mainMixer, FinalAmp);
AudioConnection          patchCord7(FinalAmp, 0, i2s2, 0);
AudioConnection          patchCord8(FinalAmp, 0, i2s2, 1);
AudioControlSGTL5000     sgtl5000_1;     

//--------------------------------------------------

#warning AUDIO_BLOCK_SAMPLES modified by hand from 128 to 64 in Arduino\hardware\teensy\avr\cores\teensy4

#define CS_PIN    5  //  Touch
#define TFT_DC    9
#define TFT_CS    10
#define TFT_RST   255  // 255 = unused, connected to 3.3V
#define TFT_MOSI  11
#define TFT_SCLK  13
#define TFT_MISO  12
#define TIRQ_PIN  4
#define ILI9341_SPI_CLOCK 60000000u
#define ILI9341_SPI_CLOCK_READ 2000000

ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);

#define LX 320
#define LY 240
#define TRUNK_LENGTH 35.0

const int bit_clock_pin = 21;
const int control_data_pin = 18;
const int din_pin = 7;
const int trig_Pin = 29;
const int manual_Pin = 30;
Bounce trigpushbutton = Bounce(trig_Pin, 10);
Bounce piezopushbutton = Bounce(manual_Pin, 10);

elapsedMillis piezo_input_timer = 0;
elapsedMillis tree_delay_timer = 0;
elapsedMillis transient_milli = 0;

boolean piezo_trigger_flag = false;
boolean piezo_sample_flag = false;

byte    fill_screen_count;
boolean fill_screen_flag;

float   transient_release;
float   transient_attack;
float   transient_noise_mix;
boolean transient_active = false;

float   transient_volume_gain;
float   velocity;
boolean note_active_flag;
                                
int  parametervalues[] =  {0,180,0,30,5,80,50,200,1900,600,10,50,90,2000,20,80,5,0,15,95,25,100,30,0,0,1,30000,0,5,30,0,0,0,150,0,3000,0,6000,0,10000,22,11,23,23,23,23,23,23};                                       

float   trunk_length = TRUNK_LENGTH;
float   branch_length;
float   start_angle;
float   new_clkw_branch_angle;
float   new_anti_branch_angle;
const int maxSize = 256;
float   x_array[maxSize] = {0};
float   x_oldarray[maxSize] = {0};
float   y_array[maxSize] = {0};
float   y_oldarray[maxSize] = {0};
float   angle_array[maxSize] = {0};
float   angle_oldarray[maxSize] = {0};
float   x_element;
float   y_element;
float   angle_element;
int     count;
long int random_number;
byte    max_iterations;
float   random_length_multiplier;
boolean tree_animation_flag;
byte    tree_drum_count;
boolean tree_advance_flag;

//----------------------- ------------------------ -------------------------- -----------------------------------//

void setup() {
 
  Serial.begin(115200);
  AudioMemory(128);
  sgtl5000_1.enable();
  sgtl5000_1.lineOutLevel (13,0) ;
  pinMode(trig_Pin, INPUT);
  pinMode(manual_Pin, INPUT);
  pinMode(TFT_CS, OUTPUT);
  pinMode(TFT_SCLK, OUTPUT);
      
  pinMode(A0, INPUT_DISABLE);
  pinMode(A1, INPUT_DISABLE);
  pinMode(A2, INPUT_DISABLE);
  pinMode(A3, INPUT_DISABLE);
  pinMode(A8, INPUT_DISABLE);
  pinMode(A10, INPUT_DISABLE);
  pinMode(A11, INPUT_DISABLE);
  pinMode(A12, INPUT_DISABLE);
  pinMode(A13, INPUT_DISABLE);
  pinMode(A14, INPUT_DISABLE);
  pinMode(A15, INPUT_DISABLE);
  pinMode(A16, INPUT_DISABLE);
  pinMode(A17, INPUT_DISABLE);
 
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  tft.setRotation(3);

  transientEnvelope.decay(0.0);
  transientEnvelope.sustain(1.0);
  transientAmp.gain(1.25);
  transientEnvelope.hold(1.0);
 
  max_iterations = 7;
  tree_drum_count = max_iterations;
      
}

void begin(uint32_t spi_clock = ILI9341_SPICLOCK, uint32_t spi_clock_read = ILI9341_SPICLOCK_READ);

// ----------------------------------------------------------------------------- //


void loop() {

//--------------------------------------------------------------------------------
//                          SCREEN WIPE / FILL CODE
//--------------------------------------------------------------------------------

  if (fill_screen_flag == true && transient_milli > transient_release)
  {
    switch (fill_screen_count)
     {
        case(0):
        tft.fillRect(0, 0, LX, LY/3, ILI9341_BLACK);
        fill_screen_count++;
        break;
    
        case(1):
        tft.fillRect(0, LY/3, LX, LY/3, ILI9341_BLACK);
        fill_screen_count++;
        break;
    
        case(2):
        tft.fillRect(0, 2*LY/3, LX, LY/3, ILI9341_BLACK);
        fill_screen_count++;
        break;

        case(3):
        fill_screen_count = 0;
        fill_screen_flag = false;
        break;
      }
  }

//--------------------------------------------------------------------------------
//                          TRIGGER DETECTION
//--------------------------------------------------------------------------------

  if (piezopushbutton.update())
  {
    if (piezopushbutton.risingEdge()) 
    {
      piezo_trigger_flag = true;
      piezo_sample_flag = false;
      piezo_input_timer = 0;
    }
  }

  if (piezo_trigger_flag == true && piezo_input_timer >= 2 && piezo_sample_flag == false)  // Adding 2ms delay to reach peak piezo voltage before sampling
  {
    velocity = analogRead(A0) * 0.00125;
    piezo_sample_flag = true;
    note_active_flag = true;
  }

  if (note_active_flag == false && piezo_trigger_flag == true && piezo_sample_flag == true)
  {
    note_active_flag = true;
  }
 
  if (note_active_flag == true)
  {
     transient_active = true;             
     waveform1.begin(0.7, 180, WAVEFORM_SINE);         
     transientEnvelope.noteOn();
     transient_milli = 0;
     note_active_flag = false;
     piezo_trigger_flag = false;
     if (fill_screen_flag == false && tree_delay_timer > 50)
      {
         tree_delay_timer = 0;
         tree_animation_flag = true;
         tree_advance_flag = true;
         tree_drum_count++;
         if (tree_drum_count > max_iterations)
         {
            tree_drum_count = 0;
         }             
      }
  } 
 
  if (transient_milli > transient_release)
  {
    transientEnvelope.noteOff();
    transient_active = false;
  }

  transient_volume_gain = analogRead(A12)*0.00098 - 0.1;
  if (transient_volume_gain <= 0.0)
  {
    transient_volume_gain = 0.0;
  }
  transientEnvelope.attack(0.5 / velocity);
  transientNoise.amplitude(0.3 * velocity);
  transientMixer.gain (0 , 0.7 * (0.5 + (0.5*velocity)));
  transientMixer.gain (1 , (0.3) * (0.5 + (0.5*velocity)));
  transientEnvelope.release(5);
  mainMixer.gain (0,transient_volume_gain);
  FinalAmp.gain(2.5);

//--------------------------------------------------------------------------------
//                          FRACTAL TREE CODE
//--------------------------------------------------------------------------------
 
if (tree_animation_flag == true &&  note_active_flag == false && tree_advance_flag == true)
{ 
  switch (tree_drum_count)
  {
    
    // ------------------------------- DRAWING TREE TRUNK ---------------------------- //

    case(0):

    branch_length = TRUNK_LENGTH * velocity * 0.001 * (1000 - parametervalues[1]); 
    tft.drawLine(LX/2, 0, LX/2, branch_length, ILI9341_WHITE);
    x_oldarray[0] = LX/2;
    x_oldarray[1] = LX/2;
    y_oldarray[0] = branch_length;
    y_oldarray[1] = branch_length;
    start_angle = parametervalues[11] * 0.002;
    angle_oldarray[0] = start_angle;
    angle_oldarray[1] = 0 - start_angle;
    tree_advance_flag = false;
    break;

    // ------------------------------- FIRST ITERATION ---------------------------- //

    case(1): 
          
    for (int i = 0 ; i < 4; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        angle_element = angle_oldarray[0]; 
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
                    
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                  
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        angle_element = angle_oldarray[1];         
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
              
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
              
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
              
        branch_length /= random_length_multiplier;
        
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        
        }
    }
    
    for (int i = 0; i < 4; i++)
    {     
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
    tree_advance_flag = false;
    break;

    // ------------------------------- SECOND ITERATION ---------------------------- //

    case(2):
    
    for (int i = 0 ; i < 8; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);           
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                  
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
              
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
              
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
              
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        }
    }

    for (int i = 0; i < 8; i++)
    {     
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
    
    tree_advance_flag = false;
    break;

    // ------------------------------- THIRD ITERATION ---------------------------- //

    case(3):
    
    for (int i = 0 ; i < 16; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);             
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                  
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
              
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
              
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
              
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        
        }
      }
      
      for (int i = 0; i < 16; i++)
      {     
          x_oldarray[i] = x_array[i];
          x_array[i] = 0;
          y_oldarray[i] = y_array[i];
          y_array[i] = 0;
          angle_oldarray[i] = angle_array[i];
          angle_array[i] = 0;
      }

      tree_advance_flag = false;
      break;

    // ------------------------------- FOURTH ITERATION ---------------------------- //
      
      case(4):
      
      for (int i = 0 ; i < 32; i++)
      {
        if (x_oldarray[i] != 0.0)
        {
          random_number = random(0, 50 + parametervalues[14]);
          new_clkw_branch_angle = random_number * 0.01;
          angle_element = angle_oldarray[i] + new_clkw_branch_angle;
          
          for (count = 0 ; count < maxSize; count++)
          {
            if (angle_array[count] == 0)
            {
              angle_array[count] = angle_element;
              count = 0;
              break;
            }
          }
          branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);           
          random_number = random(1 + parametervalues[12],100);
          random_length_multiplier = random_number * 0.01;
          branch_length *= random_length_multiplier;
          y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
            
          for (count = 0 ; count < maxSize; count++)
          {
            if (y_array[count] == 0)
            {
              y_array[count] = y_element;
              count = 0;
              break;
            }
          }
            
          x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
            
          for (count = 0 ; count < maxSize; count++)
          {
            if (x_array[count] == 0)
            {
              x_array[count] = x_element;
              count = 0;
              break;
            }
          }
                  
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
              
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
              
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
              
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        
        }
    }
      
   for (int i = 0; i < 32; i++)
    {     
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }

    tree_advance_flag = false;
    break;

    // ------------------------------- FIFTH ITERATION ---------------------------- //
    
    case(5):
    
    for (int i = 0 ; i < 64; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);             
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                  
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
              
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
              
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
              
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        
        }
    }
    
    for (int i = 0; i < 64; i++)
    {     
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
    tree_advance_flag = false;
    break;

    // ------------------------------- SIXTH ITERATION ---------------------------- //
    
    case(6):
    
    for (int i = 0 ; i < 128; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                  
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
              
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
          
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
              
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
              
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
              
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        
        }
    }

    for (int i = 0; i < 128; i++)
    {     
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
    
    tree_advance_flag = false;
    break;
    
    // ------------------------------- CLEARING ARRAYS ---------------------------- //     
    
    case(7):
    
    for (int i = 0; i < maxSize ; i++)
      {     
        x_oldarray[i] = 0;
        x_array[i] = 0;
        y_oldarray[i] = 0;
        y_array[i] = 0;
        angle_oldarray[i] = 0;
        angle_array[i] = 0;
      }
    
    tree_advance_flag = false;
    fill_screen_flag = true;
    break;
      
    }
                  
}
    
}     
// END OF LOOP

Also note that I did manually alter the AUDIO_BLOCK_SAMPLES from 128 to 64. I changed this back to see if this was a factor but it didn't resolve the issue.

Thanks

Chris
 
So ... I don't have a piezo sensor, so I can't usefully compile and try your sketch. If you can simulate the piezo in a way that reproduces the issue, that would be helpful. I also don't happen to have the ILI9341_t3n library installed - ILI9341_t3 is included with Teensyduino, and allows the sketch to compile for me. Obviously that might either mask the issue, or make it impossible to fix...

I can't 100% follow your code, but I can make a couple of observations:
  • you've split the screen clearing, but it still looks as if it might take about 7ms to do each section...
  • ...so trying to read the piezo after 2ms may be doomed to failure, sometimes
  • I can't see anywhere that transient_release is set to anything other than its default value of 0.0 (which is a float, so not very appropriate for comparison with an integer number of milliseconds, but unlikely to be a major issue)
  • a bunch of changes to gains and envelope settings are made unconditionally around lines 235 onwards; that doesn't look quite right, compared to the rest of the code
Since you say you have an oscilloscope, I'd suggest you connect it to some spare pins and output changes / pulses at "points of interest" - you'll be able to choose those better than I can. The initial trigger point and the point of determining the hit velocity are a couple of obvious candidates, as well as long-running TFT writes like the subdivided screen clear. The more channels you have the easier that will be, but even a couple will often help you home in on any oddities. You could even alter the audio at key points, but do bear in mind any gain changes etc. you make will only take place on the next audio update; these run every 2.9ms or so with the default 128-sample blocks, or twice as often if you edit it down to 64. You may well find you can get way with blocks as small as 16 samples, if you need that for debugging.
 
Thank you for your suggestions - much appreciated. You've given me a lot of ideas to investigate. I'll do as you suggest and scope a spare pin to monitor the key points in the code.
 
Hi h4yn0nnym0u5e

I've made further investigations and made the following changes to the code:-

- Replaced the piezo trigger with a simple trigpushbutton.risingEdge() check on an input pin, triggered with a 3.3V input ('trig_pin') to eliminate any chance of this being the cause.
- added a digitalWrite instruction to a spare pin ('BLUE_LED' pin) which is positioned at the start of the trigger code to help me monitor when the envelope noteOn command gets called.
- Subdivided the fillScreen code into 10 separate stages (to try and further reduce any unnecessary delays) just to see if this helps.

I had one scope monitoring the BLUE LED pin and another monitoring the audio output. I was able to test the delay times between the BLUE_LED signal and the audio output. The code was then running through 8 stages of the drawing function with switch/case:

case (0) -> setup and draw a short vertical line
case (1) to case (6) -> drawing an increasing number of lines as the fractal progresses
case (7) -> set all arrays to zero, and initiate the screen clearing code.

cases (1) to (6) all show a 7ms delay between the fallingEdge of the BLUE_LED indicator and the start of the audio
case (0) has a much shorter delay - approx 2ms
case (7) had too much noise on the signals to see what the delay time was.
However it is always case (0) which causes the discernable audio issue, since the audio is louder, as though the amplitude of the envelope is larger. Since the envelope starts earlier than the others, this always manifests in a louder sound.

Since the first case has the simplest code (and only draws one line), I decided to insert a dummy case at the start, and the list of cases is now case(0) to case (8). I expected both case (0) and case (1) to then show the shortest delays, but it turned out that only case (0) showed a 2ms delay, and then new case (1) now has the same 7ms delay as the others.

This means that there is something going on after the screen clearing code [case (8)] which is causing the next iteration [case (0)] to always have a shorter delay.

I've posted the updated code below, along with some pictures from the scope (Yellow trace = LED PIN and Blue trace = AUDIO)

20260515_173243 - case 0.jpg

case(0) showing the 2ms delay

20260515_173417 - cases 1-6.jpg

case (1) to (6) are all similar with 7-8ms delay

20260515_173513 - case 7.jpg

case (7) has same delay but there is noise on the LED signal (voltage jitter from TFT activity)

20260515_173541 - case 8.jpg

case (8) with the stuttering while the screen is cleared.

I'm a bit lost as to why there would be a delay at all between the rising edge of the BLUE_LED digitalWrite() command and the envelope.noteOn() command. There is no delay setting on the envelope before my attack phase.

Maybe if I could understand what is causing this delay, I might be able to find a way to maintain a consistent 7ms delay for each iteration?

Any insights would be helpful.

Thanks again

Chris



Code:
#include <Bounce.h>
#include <ILI9341_t3n.h>

////--------------------------------------------------------------------

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

AudioSynthWaveform       waveform1;    
AudioSynthNoiseWhite     transientNoise;
AudioMixer4              transientMixer;
AudioEffectEnvelope      transientEnvelope;
AudioAmplifier           transientAmp;  
AudioMixer4              mainMixer;
AudioAmplifier           FinalAmp;    
AudioOutputI2S           i2s2;        

AudioConnection          patchCord1(waveform1, 0, transientMixer, 1);
AudioConnection          patchCord2(transientNoise, 0, transientMixer, 0);
AudioConnection          patchCord3(transientMixer, transientEnvelope);
AudioConnection          patchCord4(transientEnvelope, transientAmp);
AudioConnection          patchCord5(transientAmp, 0, mainMixer, 0);
AudioConnection          patchCord6(mainMixer, FinalAmp);
AudioConnection          patchCord7(FinalAmp, 0, i2s2, 0);
AudioConnection          patchCord8(FinalAmp, 0, i2s2, 1);
AudioControlSGTL5000     sgtl5000_1;    

//--------------------------------------------------

#warning AUDIO_BLOCK_SAMPLES modified by hand from 128 to 64 in Arduino\hardware\teensy\avr\cores\teensy4

#define CS_PIN    5  //  Touch
#define TFT_DC    9
#define TFT_CS    10
#define TFT_RST   255  // 255 = unused, connected to 3.3V
#define TFT_MOSI  11
#define TFT_SCLK  13
#define TFT_MISO  12
#define TIRQ_PIN  4

#define BLUE_LED 34
#define TEST_PIN  22

#define ILI9341_SPI_CLOCK 60000000u
#define ILI9341_SPI_CLOCK_READ 2000000

ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);

#define LX 320
#define LY 240
#define TRUNK_LENGTH 35.0

const int bit_clock_pin = 21;
const int control_data_pin = 18;
const int din_pin = 7;
const int trig_Pin = 29;
const int manual_Pin = 30;
Bounce trigpushbutton = Bounce(trig_Pin, 10);
Bounce piezopushbutton = Bounce(manual_Pin, 10);

elapsedMillis piezo_input_timer = 0;
elapsedMillis tree_delay_timer = 0;
elapsedMillis transient_milli = 0;

boolean piezo_trigger_flag = false;
boolean piezo_sample_flag = false;

byte    fill_screen_count;
boolean fill_screen_flag;

float   transient_release;
float   transient_attack;
float   transient_noise_mix;
boolean transient_active = false;

float   transient_volume_gain;
float   velocity;
boolean note_active_flag;
                               
int  parametervalues[] =  {0,180,0,30,5,80,50,200,1900,600,10,50,90,2000,20,80,5,0,15,95,25,100,30,0,0,1,30000,0,5,30,0,0,0,150,0,3000,0,6000,0,10000,22,11,23,23,23,23,23,23};                                      

float   trunk_length = TRUNK_LENGTH;
float   branch_length;
float   start_angle;
float   new_clkw_branch_angle;
float   new_anti_branch_angle;
const int maxSize = 256;
float   x_array[maxSize] = {0};
float   x_oldarray[maxSize] = {0};
float   y_array[maxSize] = {0};
float   y_oldarray[maxSize] = {0};
float   angle_array[maxSize] = {0};
float   angle_oldarray[maxSize] = {0};
float   x_element;
float   y_element;
float   angle_element;
int     count;
long int random_number;
byte    max_iterations;
float   random_length_multiplier;
boolean tree_animation_flag = false;
byte    tree_drum_count;
boolean tree_advance_flag = false;;
boolean start_animation_flag = false;

//----------------------- ------------------------ -------------------------- -----------------------------------//

void setup() {
 
  Serial.begin(115200);
  AudioMemory(128);
  sgtl5000_1.enable();
  sgtl5000_1.lineOutLevel (13,0) ;
  pinMode(trig_Pin, INPUT);
  pinMode(manual_Pin, INPUT);
  pinMode(TFT_CS, OUTPUT);
  pinMode(TFT_SCLK, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);
  pinMode(TEST_PIN, OUTPUT);
     
  pinMode(A0, INPUT_DISABLE);
  pinMode(A1, INPUT_DISABLE);
  pinMode(A2, INPUT_DISABLE);
  pinMode(A3, INPUT_DISABLE);
  pinMode(A8, INPUT_DISABLE);
  pinMode(A10, INPUT_DISABLE);
  pinMode(A11, INPUT_DISABLE);
  pinMode(A12, INPUT_DISABLE);
  pinMode(A13, INPUT_DISABLE);
  pinMode(A14, INPUT_DISABLE);
  pinMode(A15, INPUT_DISABLE);
  pinMode(A16, INPUT_DISABLE);
  pinMode(A17, INPUT_DISABLE);
 
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  tft.setRotation(3);

  transientEnvelope.decay(0.0);
  transientEnvelope.sustain(1.0);
  transientAmp.gain(1.25);
  transientEnvelope.hold(1.0);
 
  max_iterations = 8;
  tree_drum_count = max_iterations;
     
}

void begin(uint32_t spi_clock = ILI9341_SPICLOCK, uint32_t spi_clock_read = ILI9341_SPICLOCK_READ);

// ----------------------------------------------------------------------------- //


void loop() {

//--------------------------------------------------------------------------------
//                          SCREEN WIPE / FILL CODE
//--------------------------------------------------------------------------------

  if (fill_screen_flag == true && transient_milli > transient_release)
  {
    switch (fill_screen_count)
     {
        digitalWrite(BLUE_LED, 0);
        case(0):
        tft.fillRect(0, 0, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
   
        case(1):
        tft.fillRect(0, LY/10, LX, 2*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
   
        case(2):
        tft.fillRect(0, 2*LY/3, LX, 3*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;

        case(3):
        tft.fillRect(0, 3*LY/10, LX, 4*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
   
        case(4):
        tft.fillRect(0, 4*LY/10, LX, 5*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
   
        case(5):
        tft.fillRect(0, 5*LY/10, LX, 6*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
        case(6):
        tft.fillRect(0, 6*LY/10, LX, 7*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
   
        case(7):
        tft.fillRect(0, 7*LY/10, LX, 8*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
   
        case(8):
        tft.fillRect(0, 8*LY/10, LX, 9*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;

        case(9):
        tft.fillRect(0, 9*LY/10, LX, 10*LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;

        case(10):
        fill_screen_count = 0;
        fill_screen_flag = false;
        break;
      }
  }

//--------------------------------------------------------------------------------
//                          TRIGGER DETECTION
//--------------------------------------------------------------------------------

  /*
  if (piezopushbutton.update())
  {
   
    if (piezopushbutton.risingEdge())
    {
      piezo_trigger_flag = true;
      piezo_sample_flag = false;
      piezo_input_timer = 0;
    }
  }

  if (piezo_trigger_flag == true && piezo_input_timer >= 2 && piezo_sample_flag == false)  // Adding 2ms delay to reach peak piezo voltage
  {
    velocity = analogRead(A0) * 0.00125;
    piezo_sample_flag = true;
   
  }

  if (note_active_flag == false && piezo_trigger_flag == true && piezo_sample_flag == true)
  {
    note_active_flag = true;
  }
 
  */

  if (trigpushbutton.update()){
    if(trigpushbutton.risingEdge()){
      note_active_flag = true;
      velocity = 0.25;
    }
  }
 
  if (note_active_flag == true)
  {
     digitalWrite(BLUE_LED, 1);
     transient_active = true;            
     waveform1.begin(0.7, 180, WAVEFORM_SINE);        
     transientEnvelope.noteOn();
     transient_milli = 0;
     note_active_flag = false;
     piezo_trigger_flag = false;
     start_animation_flag = true;
     piezo_sample_flag = false;
   
  }

  if (transient_milli > 1)
  {
    transientEnvelope.noteOff();
  }

 
  if (transient_milli > transient_release)
  {
        transient_active = false;
        digitalWrite(BLUE_LED, 0);
        digitalWrite(TEST_PIN, 0);
        if (fill_screen_flag == false && start_animation_flag == true)
        {
           tree_animation_flag = true;
           tree_advance_flag = true;
           start_animation_flag = false;
           tree_drum_count++;
           if (tree_drum_count > max_iterations)
           {
              tree_drum_count = 0;
           }            
        }
  }

  transient_volume_gain = analogRead(A12)*0.00098 - 0.1;
  if (transient_volume_gain <= 0.0)
  {
    transient_volume_gain = 0.0;
  }
  transientEnvelope.attack(0.5 / velocity);
  transientNoise.amplitude(0.3 * velocity);
  transientMixer.gain (0 , 0.7 * (0.5 + (0.5*velocity)));
  transientMixer.gain (1 , (0.3) * (0.5 + (0.5*velocity)));
  transientEnvelope.release(5);
  mainMixer.gain (0,transient_volume_gain);
  FinalAmp.gain(2.5);

//--------------------------------------------------------------------------------
//                          FRACTAL TREE CODE
//--------------------------------------------------------------------------------
 
if (tree_animation_flag == true &&  note_active_flag == false && tree_advance_flag == true)
{
  switch (tree_drum_count)
  {
    case(0):
    tree_advance_flag = false;
    break;
       
    case(1):
    branch_length = TRUNK_LENGTH * velocity * 0.001 * (1000 - parametervalues[1]);
    tft.drawLine(LX/2, 0, LX/2, branch_length, ILI9341_WHITE);
    x_oldarray[0] = LX/2;
    x_oldarray[1] = LX/2;
    y_oldarray[0] = branch_length;
    y_oldarray[1] = branch_length;
    start_angle = parametervalues[11] * 0.002;
    angle_oldarray[0] = start_angle;
    angle_oldarray[1] = 0 - start_angle;
    tree_advance_flag = false;
    break;

    case(2):          
    for (int i = 0 ; i < 4; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        angle_element = angle_oldarray[0];
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
                   
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
           
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                 
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                 
        // ------ANTICLOCKWISE BRANCH CODE----------

        angle_element = angle_oldarray[1];        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
             
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
       
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
             
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
             
        branch_length /= random_length_multiplier;
       
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
       
        }
    }
   
    for (int i = 0; i < 4; i++)
    {    
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
    tree_advance_flag = false;
    break;

    case(3):
   
    for (int i = 0 ; i < 8; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);          
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
           
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                 
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                 
        // ------ANTICLOCKWISE BRANCH CODE----------
       
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
             
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
       
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
             
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
             
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        }
    }

    for (int i = 0; i < 8; i++)
    {    
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
   
    tree_advance_flag = false;
    break;

    case(4):
   
    for (int i = 0 ; i < 16; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);            
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
           
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                 
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                 
        // ------ANTICLOCKWISE BRANCH CODE----------
       
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
             
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
       
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
             
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
             
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
       
        }
      }
     
      for (int i = 0; i < 16; i++)
      {    
          x_oldarray[i] = x_array[i];
          x_array[i] = 0;
          y_oldarray[i] = y_array[i];
          y_array[i] = 0;
          angle_oldarray[i] = angle_array[i];
          angle_array[i] = 0;
      }

      tree_advance_flag = false;
      break;

      case(5):
     
      for (int i = 0 ; i < 32; i++)
      {
        if (x_oldarray[i] != 0.0)
        {
          random_number = random(0, 50 + parametervalues[14]);
          new_clkw_branch_angle = random_number * 0.01;
          angle_element = angle_oldarray[i] + new_clkw_branch_angle;
         
          for (count = 0 ; count < maxSize; count++)
          {
            if (angle_array[count] == 0)
            {
              angle_array[count] = angle_element;
              count = 0;
              break;
            }
          }
          branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);          
          random_number = random(1 + parametervalues[12],100);
          random_length_multiplier = random_number * 0.01;
          branch_length *= random_length_multiplier;
          y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
           
          for (count = 0 ; count < maxSize; count++)
          {
            if (y_array[count] == 0)
            {
              y_array[count] = y_element;
              count = 0;
              break;
            }
          }
           
          x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
           
          for (count = 0 ; count < maxSize; count++)
          {
            if (x_array[count] == 0)
            {
              x_array[count] = x_element;
              count = 0;
              break;
            }
          }
                 
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                 
        // ------ANTICLOCKWISE BRANCH CODE----------
       
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
             
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
       
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
             
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
             
        branch_length /= random_length_multiplier;
       
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
       
        }
    }
     
   for (int i = 0; i < 32; i++)
    {    
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }

    tree_advance_flag = false;
    break;

    case(6):
   
    for (int i = 0 ; i < 64; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);            
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
           
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                 
        branch_length /= random_length_multiplier;
       
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                 
        // ------ANTICLOCKWISE BRANCH CODE----------
       
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
             
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
       
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
             
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
             
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
       
        }
    }
   
    for (int i = 0; i < 64; i++)
    {    
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
    tree_advance_flag = false;
    break;

    case(7):
   
    for (int i = 0 ; i < 128; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
       
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
           
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                 
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                 
        // ------ANTICLOCKWISE BRANCH CODE----------
       
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
         
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
             
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
       
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
             
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
       
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
             
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
       
        }
    }

    for (int i = 0; i < 128; i++)
    {    
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
   
    tree_advance_flag = false;
    break;
         
    case(8):
   
    for (int i = 0; i < maxSize ; i++)
      {    
        x_oldarray[i] = 0;
        x_array[i] = 0;
        y_oldarray[i] = 0;
        y_array[i] = 0;
        angle_oldarray[i] = 0;
        angle_array[i] = 0;
      }
   
    tree_advance_flag = false;
    fill_screen_flag = true;
    break;

    }
                 
}
   
}    
// END OF LOOP
 
I've had a play, added some instrumentation pins and fixed a few bugs:
  • the incremental screen clearing was wrong - you had increasing sizes of sub-area (N*LY/10), as well as changing positions. That resulted in longer clearing times than expected some of the time. It's still 4ms per sub-area, which may be a bit long
  • I added an automatic trigger every 1s
  • I didn't change to 64-sample blocks
  • I removed the analogue read of A12, so...
  • ...I didn't particularly hear different volumes of output, but I did have complete failures to trigger
    • those I traced to the extremely short trigger pulses, so noteOn and noteOff were being called entirely inside some audio updates (2.9ms with 128-sample blocks)
    • changing to if (transient_milli > 2) fixes this, though I wouldn't rely on it for production code
  • I put in instrumentation for
    • how fast the loop runs: toggle pin 0 every loop
    • roughly when audio updates occur: toggle pin 1 when the audio queue has data; this is not reliable when loop() is running slowly, you're better off editing AudioStream, but that's complicated!
    • moved your BLUE_LED to show when the envelope noteOn and noteOff happen, specifically in relation to audio updates
    • quite a few Serial.print calls and related code
Because there's no guarantee how fast any given iteration of loop() is going to be, I think it's going to be a huge challenge to get any meaningful trigger and velocity data from one pin read per loop. You may well be better off using the audio adaptor input and an AudioRecordQueue object to get consistently sampled data, and analyse that. Either that, or change things around so you can be 100% sure that loop takes exactly (say) 1ms, every time. Or other methods - I think there's a way to set analogue pin readings at fixed intervals, though I've never used those.

You should also be aware of how your code relates to the audio update speed - anything you do may not get "noticed" by the audio engine for up to 2.9ms (or 1.45ms if you have 64-sample blocks). You'll probably find it works better to set up your envelope to create the transient you want, and let it run to completion, than try to trigger it on and off with a short interval between. If you want fine-grained control, look at using the AudioPlayQueue object to "feed in" a computed envelope, along with an AudioEffectMultiply to use it to modulate the wave or noise source.

Complete code I used is:
C++:
#include <Bounce.h>
#include <ILI9341_t3n.h>

////--------------------------------------------------------------------

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

AudioSynthWaveform       waveform1;   
AudioSynthNoiseWhite     transientNoise;
AudioRecordQueue q;
AudioMixer4              transientMixer;
AudioEffectEnvelope      transientEnvelope;
AudioAmplifier           transientAmp; 
AudioMixer4              mainMixer;
AudioAmplifier           FinalAmp;   
AudioOutputI2S           i2s2;       

AudioConnection          patchCord1(waveform1, 0, transientMixer, 1);
AudioConnection          patchCord2(transientNoise, 0, transientMixer, 0);
AudioConnection     patchCord2b(transientNoise, 0, q, 0);
AudioConnection          patchCord3(transientMixer, transientEnvelope);
AudioConnection          patchCord4(transientEnvelope, transientAmp);
AudioConnection          patchCord5(transientAmp, 0, mainMixer, 0);
AudioConnection          patchCord6(mainMixer, FinalAmp);
AudioConnection          patchCord7(FinalAmp, 0, i2s2, 0);
AudioConnection          patchCord8(FinalAmp, 0, i2s2, 1);
AudioControlSGTL5000     sgtl5000_1;   

//--------------------------------------------------

#warning AUDIO_BLOCK_SAMPLES modified by hand from 128 to 64 in Arduino\hardware\teensy\avr\cores\teensy4

#define CS_PIN    5  //  Touch
#define TFT_DC    9
#define TFT_CS    10
#define TFT_RST   255  // 255 = unused, connected to 3.3V
#define TFT_MOSI  11
#define TFT_SCLK  13
#define TFT_MISO  12
#define TIRQ_PIN  4

#define BLUE_LED 0 // 34
#define Q_PIN 1 // toggle when audio queue has data
#define TEST_PIN  22

#define ILI9341_SPI_CLOCK 60000000u
#define ILI9341_SPI_CLOCK_READ 2000000

ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);

#define LX 320
#define LY 240
#define TRUNK_LENGTH 35.0

const int bit_clock_pin = 21;
const int control_data_pin = 18;
const int din_pin = 7;
const int trig_Pin = 29;
const int manual_Pin = 30;
Bounce trigpushbutton = Bounce(trig_Pin, 10);
Bounce piezopushbutton = Bounce(manual_Pin, 10);

elapsedMillis piezo_input_timer = 0;
elapsedMillis tree_delay_timer = 0;
elapsedMillis transient_milli = 0;

boolean piezo_trigger_flag = false;
boolean piezo_sample_flag = false;

byte    fill_screen_count;
boolean fill_screen_flag;

float   transient_release;
float   transient_attack;
float   transient_noise_mix;
boolean transient_active = false;

float   transient_volume_gain;
float   velocity;
boolean note_active_flag;
                              
int  parametervalues[] =  {0,180,0,30,5,80,50,200,1900,600,10,50,90,2000,20,80,5,0,15,95,25,100,30,0,0,1,30000,0,5,30,0,0,0,150,0,3000,0,6000,0,10000,22,11,23,23,23,23,23,23};                                     

float   trunk_length = TRUNK_LENGTH;
float   branch_length;
float   start_angle;
float   new_clkw_branch_angle;
float   new_anti_branch_angle;
const int maxSize = 256;
float   x_array[maxSize] = {0};
float   x_oldarray[maxSize] = {0};
float   y_array[maxSize] = {0};
float   y_oldarray[maxSize] = {0};
float   angle_array[maxSize] = {0};
float   angle_oldarray[maxSize] = {0};
float   x_element;
float   y_element;
float   angle_element;
int     count;
long int random_number;
byte    max_iterations;
float   random_length_multiplier;
boolean tree_animation_flag = false;
byte    tree_drum_count;
boolean tree_advance_flag = false;;
boolean start_animation_flag = false;

//----------------------- ------------------------ -------------------------- -----------------------------------//
elapsedMillis trig_generator;

void setup() {
 
  Serial.begin(115200);
  AudioMemory(128);
  sgtl5000_1.enable();
  sgtl5000_1.lineOutLevel (13,0) ;
sgtl5000_1.volume(0.5f);
  pinMode(trig_Pin, INPUT);
  pinMode(manual_Pin, INPUT);
  pinMode(TFT_CS, OUTPUT);
  pinMode(TFT_SCLK, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);
  pinMode(TEST_PIN, OUTPUT);
  pinMode(Q_PIN, OUTPUT);
    
  pinMode(A0, INPUT_DISABLE);
  pinMode(A1, INPUT_DISABLE);
  pinMode(A2, INPUT_DISABLE);
  pinMode(A3, INPUT_DISABLE);
  pinMode(A8, INPUT_DISABLE);
  pinMode(A10, INPUT_DISABLE);
  pinMode(A11, INPUT_DISABLE);
  pinMode(A12, INPUT_DISABLE);
  pinMode(A13, INPUT_DISABLE);
  pinMode(A14, INPUT_DISABLE);
  pinMode(A15, INPUT_DISABLE);
  pinMode(A16, INPUT_DISABLE);
  pinMode(A17, INPUT_DISABLE);
 
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  tft.setRotation(3);

  transientEnvelope.decay(0.0);
  transientEnvelope.sustain(1.0);
  transientAmp.gain(1.25);
  transientEnvelope.hold(1.0);

  q.begin();
 
  max_iterations = 8;
  tree_drum_count = max_iterations;
    
}

void begin(uint32_t spi_clock = ILI9341_SPICLOCK, uint32_t spi_clock_read = ILI9341_SPICLOCK_READ);

// ----------------------------------------------------------------------------- //

bool envState = false;
bool test_pin_state, q_pin_state;
elapsedMicros note_on_for;
void loop() {
// show how fast loop is running: 
test_pin_state = !test_pin_state; 
digitalWrite(TEST_PIN, test_pin_state);

// show when audio update has happened, EXCEPT when
// loop runs slowly, when there will be an apparent
// gap (which probably doesn't really happen)
if (q.available())
{
  q_pin_state = !q_pin_state; 
  q.clear();
}
digitalWrite(Q_PIN, q_pin_state);

//--------------------------------------------------------------------------------
//                          SCREEN WIPE / FILL CODE
//--------------------------------------------------------------------------------

  if (fill_screen_flag == true && transient_milli > transient_release)
  {
    switch (fill_screen_count)
     {
        digitalWrite(BLUE_LED, 0); // **** THIS NEVER EXECUTES! ****
        case(0):
        tft.fillRect(0, 0, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
  
        case(1):
        tft.fillRect(0, LY/10, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
  
        case(2):
        tft.fillRect(0, 2*LY/3, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;

        case(3):
        tft.fillRect(0, 3*LY/10, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
  
        case(4):
        tft.fillRect(0, 4*LY/10, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
  
        case(5):
        tft.fillRect(0, 5*LY/10, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
        case(6):
        tft.fillRect(0, 6*LY/10, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
  
        case(7):
        tft.fillRect(0, 7*LY/10, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;
  
        case(8):
        tft.fillRect(0, 8*LY/10, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;

        case(9):
        tft.fillRect(0, 9*LY/10, LX, LY/10, ILI9341_BLACK);
        fill_screen_count++;
        break;

        case(10):
        fill_screen_count = 0;
        fill_screen_flag = false;
        break;
      }
  }

//--------------------------------------------------------------------------------
//                          TRIGGER DETECTION
//--------------------------------------------------------------------------------

  /*
  if (piezopushbutton.update())
  {
  
    if (piezopushbutton.risingEdge())
    {
      piezo_trigger_flag = true;
      piezo_sample_flag = false;
      piezo_input_timer = 0;
    }
  }

  if (piezo_trigger_flag == true && piezo_input_timer >= 2 && piezo_sample_flag == false)  // Adding 2ms delay to reach peak piezo voltage
  {
    velocity = analogRead(A0) * 0.00125;
    piezo_sample_flag = true;
  
  }

  if (note_active_flag == false && piezo_trigger_flag == true && piezo_sample_flag == true)
  {
    note_active_flag = true;
  }
 
  */

//  if (trigpushbutton.update()){
//    if(trigpushbutton.risingEdge()){
bool triggered = false; if (trig_generator > 999) {{ trig_generator = 0; // triggered = true;
 
      note_active_flag = true;
      velocity = 0.25;
    }
  }
 
  if (note_active_flag == true)
  {
     digitalWrite(BLUE_LED, 1);
     transient_active = true;           
     waveform1.begin(0.7, 180, WAVEFORM_SINE);       
     transientEnvelope.noteOn();
note_on_for = 0;     
envState = true;     
triggered = true;
     transient_milli = 0;
     note_active_flag = false;
     piezo_trigger_flag = false;
     start_animation_flag = true;
     piezo_sample_flag = false;
  
  }

  if (transient_milli > 2)
  {
    digitalWrite(BLUE_LED, 0);
    transientEnvelope.noteOff();
if (envState) Serial.printf("%u: noteOff; on for: %uus\n", millis(), (uint32_t) note_on_for);
envState = false;     
  }

 
  if (transient_milli > transient_release)
  {
        transient_active = false;
        //digitalWrite(BLUE_LED, 0);
        //digitalWrite(TEST_PIN, 0);
        if (fill_screen_flag == false && start_animation_flag == true)
        {
           tree_animation_flag = true;
           tree_advance_flag = true;
           start_animation_flag = false;
           tree_drum_count++;
           if (tree_drum_count > max_iterations)
           {
              tree_drum_count = 0;
           }           
        }
  }

  transient_volume_gain = analogRead(A12)*0.00098 - 0.1;
transient_volume_gain = 0.5f;
  if (transient_volume_gain <= 0.0)
  {
    transient_volume_gain = 0.0;
  }
  transientEnvelope.attack(0.5 / velocity);
  transientNoise.amplitude(0.3 * velocity);
  transientMixer.gain (0 , 0.7 * (0.5 + (0.5*velocity)));
  transientMixer.gain (1 , (0.3) * (0.5 + (0.5*velocity)));
  transientEnvelope.release(5);
  mainMixer.gain (0,transient_volume_gain);
  FinalAmp.gain(2.5);
if (triggered) { Serial.printf("%u: trig: volume %.3f; velocity %.3f; env: %s; tree count: %d\n", millis(), transient_volume_gain, velocity, envState?"on":"off", tree_drum_count); triggered = false; }
//--------------------------------------------------------------------------------
//                          FRACTAL TREE CODE
//--------------------------------------------------------------------------------
 
if (tree_animation_flag == true &&  note_active_flag == false && tree_advance_flag == true)
{
  switch (tree_drum_count)
  {
    case(0):
    tree_advance_flag = false;
    break;
      
    case(1):
    branch_length = TRUNK_LENGTH * velocity * 0.001 * (1000 - parametervalues[1]);
    tft.drawLine(LX/2, 0, LX/2, branch_length, ILI9341_WHITE);
    x_oldarray[0] = LX/2;
    x_oldarray[1] = LX/2;
    y_oldarray[0] = branch_length;
    y_oldarray[1] = branch_length;
    start_angle = parametervalues[11] * 0.002;
    angle_oldarray[0] = start_angle;
    angle_oldarray[1] = 0 - start_angle;
    tree_advance_flag = false;
    break;

    case(2):         
    for (int i = 0 ; i < 4; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        angle_element = angle_oldarray[0];
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
                  
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
          
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                
        // ------ANTICLOCKWISE BRANCH CODE----------

        angle_element = angle_oldarray[1];       
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
            
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
      
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
            
        branch_length /= random_length_multiplier;
      
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
      
        }
    }
  
    for (int i = 0; i < 4; i++)
    {   
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
    tree_advance_flag = false;
    break;

    case(3):
  
    for (int i = 0 ; i < 8; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);         
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
          
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                
        // ------ANTICLOCKWISE BRANCH CODE----------
      
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
            
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
      
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
            
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
        }
    }

    for (int i = 0; i < 8; i++)
    {   
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
  
    tree_advance_flag = false;
    break;

    case(4):
  
    for (int i = 0 ; i < 16; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);           
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
          
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                
        // ------ANTICLOCKWISE BRANCH CODE----------
      
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
            
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
      
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
            
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
      
        }
      }
    
      for (int i = 0; i < 16; i++)
      {   
          x_oldarray[i] = x_array[i];
          x_array[i] = 0;
          y_oldarray[i] = y_array[i];
          y_array[i] = 0;
          angle_oldarray[i] = angle_array[i];
          angle_array[i] = 0;
      }

      tree_advance_flag = false;
      break;

      case(5):
    
      for (int i = 0 ; i < 32; i++)
      {
        if (x_oldarray[i] != 0.0)
        {
          random_number = random(0, 50 + parametervalues[14]);
          new_clkw_branch_angle = random_number * 0.01;
          angle_element = angle_oldarray[i] + new_clkw_branch_angle;
        
          for (count = 0 ; count < maxSize; count++)
          {
            if (angle_array[count] == 0)
            {
              angle_array[count] = angle_element;
              count = 0;
              break;
            }
          }
          branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);         
          random_number = random(1 + parametervalues[12],100);
          random_length_multiplier = random_number * 0.01;
          branch_length *= random_length_multiplier;
          y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
          
          for (count = 0 ; count < maxSize; count++)
          {
            if (y_array[count] == 0)
            {
              y_array[count] = y_element;
              count = 0;
              break;
            }
          }
          
          x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
          
          for (count = 0 ; count < maxSize; count++)
          {
            if (x_array[count] == 0)
            {
              x_array[count] = x_element;
              count = 0;
              break;
            }
          }
                
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                
        // ------ANTICLOCKWISE BRANCH CODE----------
      
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
            
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
      
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
            
        branch_length /= random_length_multiplier;
      
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
      
        }
    }
    
   for (int i = 0; i < 32; i++)
    {   
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }

    tree_advance_flag = false;
    break;

    case(6):
  
    for (int i = 0 ; i < 64; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);           
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
          
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                
        branch_length /= random_length_multiplier;
      
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                
        // ------ANTICLOCKWISE BRANCH CODE----------
      
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
            
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
      
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
            
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
      
        }
    }
  
    for (int i = 0; i < 64; i++)
    {   
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
    tree_advance_flag = false;
    break;

    case(7):
  
    for (int i = 0 ; i < 128; i++)
    {
      if (x_oldarray[i] != 0.0)
      {
        random_number = random(0, 50 + parametervalues[14]);
        new_clkw_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] + new_clkw_branch_angle;
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
      
        branch_length = trunk_length * velocity * 0.001 * (1000 - parametervalues[1]);
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
          
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
                
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
                
        // ------ANTICLOCKWISE BRANCH CODE----------
      
        random_number = random(0, 50 + parametervalues[14]);
        new_anti_branch_angle = random_number * 0.01;
        angle_element = angle_oldarray[i] - new_anti_branch_angle;
        
        for (count = 0 ; count < maxSize; count++)
        {
          if (angle_array[count] == 0)
          {
            angle_array[count] = angle_element;
            count = 0;
            break;
          }
        }
            
        random_number = random(1 + parametervalues[12],100);
        random_length_multiplier = random_number * 0.01;
        branch_length *= random_length_multiplier;
      
        y_element = y_oldarray[i] + (branch_length * cos (angle_array[i]) * random_length_multiplier);
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (y_array[count] == 0)
          {
            y_array[count] = y_element;
            count = 0;
            break;
          }
        }
            
        x_element = x_oldarray[i] + (branch_length * sin (angle_array[i]));
      
        for (count = 0 ; count < maxSize; count++)
        {
          if (x_array[count] == 0)
          {
            x_array[count] = x_element;
            count = 0;
            break;
          }
        }
            
        branch_length /= random_length_multiplier;
        tft.drawLine(x_oldarray[i], y_oldarray[i], x_element, y_element, ILI9341_WHITE);
      
        }
    }

    for (int i = 0; i < 128; i++)
    {   
        x_oldarray[i] = x_array[i];
        x_array[i] = 0;
        y_oldarray[i] = y_array[i];
        y_array[i] = 0;
        angle_oldarray[i] = angle_array[i];
        angle_array[i] = 0;
    }
  
    tree_advance_flag = false;
    break;
        
    case(8):
  
    for (int i = 0; i < maxSize ; i++)
      {   
        x_oldarray[i] = 0;
        x_array[i] = 0;
        y_oldarray[i] = 0;
        y_array[i] = 0;
        angle_oldarray[i] = 0;
        angle_array[i] = 0;
      }
  
    tree_advance_flag = false;
    fill_screen_flag = true;
    break;

    }
                
}
  
}   
// END OF LOOP
 
Thank you again for spending time looking into this for me. I would never have thought of some of the ideas you've suggested for checking the code, and I've learned a lot just from seeing the changes you made.

I compiled your code tonight, and using the serial monitor output ("note_on_for"), and it was clear that the tft.fillRect sequence is increasing the duration of the envelope. This duration varied based on the number of stages taken to clear the screen. With fill_screen_count = 20 the duration was around 5000us during the fillscreen, whereas the other stages were taking around 2900us.
By playing around with the number of stages, I ended up being able to keep the note_on_for to around 3000uS. Clearing the screen using fill_screen_count = 10 produced this result.

Despite keeping "note_on_for"consistent, the output still has the problems with the envelope which immediately follows the screen clearance (larger envelope amplitude and shortened time between triggering and audio output).

As a final test, I added an arbitrary delay before the fractal tree code (a 150ms delay)

Code:
if (tree_animation_flag == true &&  note_active_flag == false && tree_advance_flag == true && transientmillis > 150)

and removed all code within the fractal tree switch statement except the flag to fill screen. i.e/ it was just a series of case statements with breaks, except the final case which had the fill_screen_flag = true statement.
So the only interaction with the ILI9341 was to clear the screen.

This still ends up altering the envelope following the screen clearance. Two pictures attached (n.b/ I increased the waveform frequency in each case to make the envelope more pronounced)

20260520_195511.jpg

Normal envelope with approx 4ms delay between digitalWrite(BLUE_LED, 0) and audio output.

20260520_195545.jpg

Envelope triggered after the screen clearance.

I appreciate the help you've provided and I think there is a risk I will end up down a rabbit-hole trying to resolve this! My project is audio-based and everything else works great. The animation/fractal tree was a "nice-to-do" and I think that if I wanted to include it, I might consider just using a second Teensy to handle the ILI9341 interactions.

Thanks again

Chris
 
Managed to resolve this after all!
Instead of using tft.fillScreen, I saved every data point to a huge array and then redraw it all in the background colour.

Wish I'd tried this weeks ago. No loss of timing or envelope oddities.

Anyway - thanks again for offering help and advice.

Cheers

Chris
 
Back
Top