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
 
Back
Top