FastLED Sound Visualization not functioning as intended

I am trying to merge a known-working Arduino Sketch with a FastLED demoreel that features button switching to change animations.

I have gotten most parts working except for the propagation feature of the sound amplitude through the LED strip. Here is my code (sound will show up on the first LED but it does not propagate along the strip for some reason).

#include "FastLED.h"
#include "JC_Button.h"  // Button library. Includes press, long press, double press detection.

// Pushbutton pin definition
const int buttonPin = 5; // Digital pin used for debounced pushbutton

// int buttonState = 0;
// int lastButtonState = 0;
Button myBtn(buttonPin, true, true, 50); // Declare the button

#define DATA_PIN 6
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
#define NUM_LEDS 149
CRGB leds[NUM_LEDS];

#define FRAMES_PER_SECOND  120

/* Output pin definitions */
#define ANALOG_PIN_L 1 // Left audio channel
#define ANALOG_PIN_R 0 // Right audio channel
#define REFRESH_POT_PIN 2 // Left pot
#define SENSITIVITY_POT_PIN 3 // Right pot
#define STROBE_PIN 12 // Strobe pin 
#define RESET_PIN 13 // Reset Pin

/* Sensitivity variables, refresh variables, and start/end points */
#define REFRESH_DIVISOR 80. // Higher = range of refresh values is lower
#define SENSITIVITY_DIVISOR 100. // Higher = range of sensitivity values on pot is lower
#define LEFT_START_POINT ((NUM_LEDS / 2)) // Starting LED for left side
#define LEFT_END_POINT 1 // Generally the end of the left side is the first LED
#define RIGHT_START_POINT ((NUM_LEDS / 2) + 1) // Starting LED for the right side
#define RIGHT_END_POINT (NUM_LEDS - 1) // Generally the end of the right side is the last LED
#define LED_STACK_SIZE (NUM_LEDS / 2) // How many LED's in each stack
#define MAX_AMPLITUDE 4700 // Maximum possible amplitude value
#define MAX_AMPLITUDE_MULTIPLIER 380
#define MIN_AMPLITUDE 545 // Lowest possible amplitude value (Higher number causes there to be more blank LED's)
#define MIN_AMPLITUDE_MULTIPLIER 200
#define SENSITIVITY_MULTIPLIER 200 // Higher = range of sensitivity values on pot is lower
uint8_t max_bright = 64;

int refresh_rate; // Refresh rate of the animation
int refresh_counter = 0; // Looping variable for refresh loop
int sensitivity; // Sensitivity value
int max_amplitude;
int start_hue = 0;

/* Represents the left and right LED color values.
 * In the case of an odd number of LED's, you need to adjust these
 * values and the values of RIGHT_START_POINT, LEFT_START_POINT, etc.
 */

int left_LED_stack[NUM_LEDS / 2] = {0};
int right_LED_stack[NUM_LEDS / 2] = {0};

// Set color value to full saturation and value. Set the hue to 0
CHSV color(0, 255, 255);

// Read in and sum amplitudes for the 7 frequency bands
int get_freq_sum(int pin) {

  int i;
  int spectrum_values[7];
  int spectrum_total = 0;

  //get readings from chip, sum freq values
  for (i = 0; i < 7; i++) {
    digitalWrite(STROBE_PIN, LOW);
    delayMicroseconds(30); // to allow the output to settle

    spectrum_values[i] = analogRead(pin);
    spectrum_total += spectrum_values[i];
    
    // strobe to the next frequency
    digitalWrite(STROBE_PIN, HIGH); 
   
  }
  return spectrum_total;
}

/* Sets led 'position' to 'value' and converts the value to an HSV value.
 */
void set_LED_color(int position, int value) {
  // If lower than min amplitude, set to min amplitude
  if(value <= MIN_AMPLITUDE) {
    value = MIN_AMPLITUDE;
  }
  
  // Subtract min amplitude so lowest value is 0
  value -= MIN_AMPLITUDE;
  
  float max = (max_amplitude - MIN_AMPLITUDE);
  if(value > max) value = max;
  float ratio = ((float)(value / max));
  if(ratio == 0) {
    color.val = 0;
  } else {
    color.val = 255;
  }
  color.saturation = 255;
  color.hue = start_hue + ((ratio * 255) * 2);
  leds[position] = color;
}

/*  Push a new LED color value onto the beginning of the stack.
 *  The last LED color value is discarded. This is the primary 
 *  function relating to the propagation behavior.
 */
void push_stack(int stack[], int value) {
  int i;
  for(i = (LED_STACK_SIZE - 1); i >= 0; --i) {
    stack[i] = stack[i - 1];
  }
  stack[0] = value;
}

void setup() {
  Serial.begin(57600);
  delay(3000); // 3 second delay for recovery
  
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

  // set master brightness control
  FastLED.setBrightness(max_bright);

  // Set pin modes
  pinMode(ANALOG_PIN_L, INPUT);
  pinMode(ANALOG_PIN_R, INPUT);
  pinMode(STROBE_PIN, OUTPUT);
  pinMode(RESET_PIN, OUTPUT);
  digitalWrite(RESET_PIN, LOW);
  digitalWrite(STROBE_PIN, HIGH); 
}

// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = {soundReactive_A4, confetti };

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
  
void loop()
{
  // Call the current pattern function once, updating the 'leds' array
  gPatterns[gCurrentPatternNumber]();

  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 

  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow

    readbutton(); // Button press increases the ledMode up to last contiguous mode and then starts over at 0.
}

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
  gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

void confetti() 
{
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds, NUM_LEDS, map(analogRead(3), 0, 1023, 5, 100));
  int pos = random16(NUM_LEDS);
  leds[pos] += CHSV(50, 5, 200);
  FastLED.delay(map(analogRead(2), 0, 1023, 5, 100));
}

void soundReactive_A4() {
  
  // Set local loop variables
  int amp_sum_L = 0;
  int amp_sum_R = 0;
  int i; // Loop var
  int stack_loop = 0;

  // Reset EQ7 chip
  digitalWrite(RESET_PIN, HIGH);
  digitalWrite(RESET_PIN, LOW);

  // Get the sum of the amplitudes of all 7 frequency bands
  amp_sum_L = get_freq_sum(ANALOG_PIN_L);
  amp_sum_R = get_freq_sum(ANALOG_PIN_R);

  /*  SENSITIVITY_DIVISOR lowers the range of the possible pot values
   *  If the value is higher than the max or lower than the min,
   *  set it to the max or min respectively.
   */
  sensitivity = (analogRead(SENSITIVITY_POT_PIN) / SENSITIVITY_DIVISOR) * SENSITIVITY_MULTIPLIER;
  max_amplitude = MAX_AMPLITUDE - (((1023 - analogRead(SENSITIVITY_POT_PIN)) / SENSITIVITY_DIVISOR) * MAX_AMPLITUDE_MULTIPLIER);

  // REFRESH_DIVISOR lowers the range of possible pot values
  refresh_rate = analogRead(REFRESH_POT_PIN) / REFRESH_DIVISOR;

  // Run this code based on the refresh rate
  if(refresh_counter >= refresh_rate) {

    // Start by resetting the refresh counter
    refresh_counter = 0;

    /*  Push the new values onto the stack of LED's for each side
     *  This moves each LED value up the strip by 1 LED and drops the
     *  last value in the stack. This is the code that effects the propagation
     */
    push_stack(left_LED_stack, amp_sum_L);
    push_stack(right_LED_stack, amp_sum_R);

    /*  Set the LED values based on the left and right stacks
     *  This is a reverse loop because the left side LED's travel toward
     *  LED 0.
     */
    for(i = LEFT_START_POINT; i >= LEFT_END_POINT; --i) {
      set_LED_color(i, left_LED_stack[stack_loop]);
      ++stack_loop;
    }

    // Reset and reuse stack_loop var
    stack_loop = 0;

    /*  LED's on the right travel towards the last LED in the strand 
     *  so the loop increments positively
     */ 
    for(i = RIGHT_START_POINT; i <= RIGHT_END_POINT; ++i) {
      set_LED_color(i, right_LED_stack[stack_loop]);
      ++stack_loop;
    }

    leds[0] = left_LED_stack[0];

    // Show the new LED values
    FastLED.show();
  }

  // Increase the refresh counter
  ++refresh_counter;
}

void readbutton() { // Read the button and increase the mode
  myBtn.read();
  if(myBtn.wasReleased()) {
    nextPattern();
  }
} // readbutton()

Here is the known-working version of the sound-visualization, it correctly propagates: audiolux-one/A4.ino at master · audioluxdevices/audiolux-one · GitHub

Any clues where I went amiss?

I see that you copied a lot of crappy code as a starting point.

int get_freq_sum(int pin) {

There is no reason for pin to be an int. There is no analog pin 14587 or -5489. So, the proper type would be byte.

  int spectrum_values[7];

This array is never actually used.

void set_LED_color(int position, int value) {

You don't have enough LEDs for position to need to be an int.

  leds[position] = color;

It would be good practice to make sure that position holds a legal value BEFORE using it as an array index.

  pinMode(ANALOG_PIN_L, INPUT);
  pinMode(ANALOG_PIN_R, INPUT);

Diddling with the digital nature of the pin you use as an analog point is pointless.

    for(i = LEFT_START_POINT; i >= LEFT_END_POINT; --i) {
      set_LED_color(i, left_LED_stack[stack_loop]);
      ++stack_loop;
    }

    // Reset and reuse stack_loop var
    stack_loop = 0;

Why do you set stack_loop to 0 before the second for loop, but not before the first for loop? What IS the value of stack_loop when the first for loop starts?

I'm guessing that somewhere you are writing outside the bounds of an array. There are many places that you do not check the validity of an index before writing to an array.

Paul,
These are helpful pointers however I am not clear which comments are related to the known-working code which you are calling "crappy" and the latter attempt to merge this code with the button demo reel code which I posted before.

I am a novice coder so fixing up the original A4 code which was created by a volunteer at our non-profit is a stretch for my abilities, until I have developed more proficiency. I am willing to learn but it would be more helpful for us if we can focus comments on the code I pasted into this thread and not on fixing the A4 code because it is working as intended when it is stand-alone.

PaulS: Out of the 6 quoted code snippets, which ones are most likely to be breaking the functionality of the attempted merge? Thank you for your help.

PaulS: Out of the 6 quoted code snippets, which ones are most likely to be breaking the functionality of the attempted merge? Thank you for your help.

I'd place a bet on #4.