Pro mini clone, FFT, & Neopixels.. Memory leak?

Attached is a copy of my Christmas hat .ino. Things went well until I combined the code clips from my stand alone FFT Neopixels.ino and my xmas hat Neopixels .ino. It produces a very specific program error, as if the “pix5” is being overwritten outside the audio while loop.
The program first time through the loop works as intended, subsequent iterations through the loop the audio code works as intended except for the neopixel related to “pix5”. There are 16 pixels spread out over the hat. After the first time through the main loop, pix5 according to the serial terminal has values much higher than the 255 the setColor(); in the Neopixel library supports. Due to the Mic preamp setup, and the way i had to hack the pro mini for Aref access, setting the FFT library to LINOUT8 (8 bit scaled output) will barely light the neopixels. LINOUT gives the best results for displaying what our ears pickup. Aref was using a 4.096V precision Vref module from Adafruit for Aref, mic Vcc, and input biasing. It all worked well UNTIL I combined that code with the neopixel demo codes.
Something broke something inside my program and I cant seem to isolate the problem. I tried the pix# variables as word and byte, and as local and global variables. They all produce the same results. Neopixel library disables interrupts while its constructing its output stream, but I believe re-enables them once the output stream is finished because of the use of delay() in the neopixel demo code…
The mic doesn’t have a low-pass filter on it, but the FFT code is the same for the stand alone version. So how is it that only one variable in the whole program seems to be getting overwritten after the neopixel demos run and returns to the audio code?

#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#include <avr/wdt.h>
#define LIN_OUT 1
#define FFT_N 128 // set to 64 point fft
#include <FFT.h> // include the library

#define NUMPIXELS  16
#define PIN 10
#define debug 9
#define DEBUG 4
#define debug_active true
boolean debugFFT, debugfft = false;
byte p,m,j;
int k;
word bins = 0;
word  Time = 0;
#define decay        1
#define noise_floor 32
#define looptime 20
unsigned long prevTime,currTime = 0;
const word  spekTime = 2660;
const byte chaseTime = 80;
volatile byte scale = 6;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  //#if defined (__AVR_ATmega328__)
  
  ADCSRA = 0xf6; // set the adc to free running mode (f6 = 9.6kHz bandwidth)
  ADMUX = 0; // use Aref & ADC0(Pc0)  ATMEGA328
  DIDR0 = 0x1F; // disable digital inputs for A0:A5 on ATMEGA328(pg 251 datasheet)
  pinMode(PIN, OUTPUT);
  pinMode(debug, INPUT);
  pinMode(DEBUG, INPUT);
  pinMode(5,OUTPUT);
  digitalWrite(5,HIGH);
  pixels.begin();
  pixels.show();
  Serial.begin(115200);
  interrupts();
}

void loop() {
  Time = spekTime;
  TIMSK0 = 0x0; // turn off timer0 for lower jitter
  spectrum_vis();
  TIMSK0 = 0x1;
  // Some example procedures showing how to display to the pixels:
  colorWipe(pixels.Color(255, 0, 0), chaseTime); // Red
  colorWipe(pixels.Color(0, 255, 0), chaseTime); // Green
  colorWipe(pixels.Color(0, 0, 255), chaseTime); // Blue
  colorWipe(pixels.Color(192,192,192),chaseTime); //white
  pixels.clear();
  pixels.show(); 
   
  Time = spekTime;  
  TIMSK0 = 0x0; // turn off timer0 for lower jitter
  spectrum_vis();
  TIMSK0 = 0x1;
  
  // Send a theater pixel chase in...
  theaterChase(pixels.Color(127, 127, 127), chaseTime); // White
  theaterChase(pixels.Color(127, 0, 0), chaseTime); // Red
  theaterChase(pixels.Color(0, 0, 127), chaseTime); // Blue
  theaterChase(pixels.Color(255,64,8), chaseTime); // gold
  theaterChase(pixels.Color(255,64,8), chaseTime); // gold
  pixels.clear();
  pixels.show();
  
  Time = spekTime;  
  TIMSK0 = 0x0; // turn off timer0 for lower jitter
  spectrum_vis();
  TIMSK0 = 0x1;
  
  rainbow(25);
  rainbowCycle(10);
  theaterChaseRainbow(75);
  pixels.clear();
  pixels.show();
  
}



void spectrum_vis(){
  DIDR0 = 0x1F; // disable digital inputs for A0:A5 on ATMEGA328(pg 251 datasheet)
  byte  pix1, pix2, pix3, pix4, pix5, pix6 = 0;
  while (1) { // reduces jitter
    Time --;
    
    //PORTD ^= (1<<PD5);  //XOR toggle for loop time measure
    if(Time == 0) break;    
    if (debug_active == true) {
      debugFFT = PINB & B10; //just read the damned pin already!
      debugfft = PINB & B1;
    }
    cli();
    for (int i = 0 ; i < FFT_N * 2 ; i += 2) { // save 256 samples
      while (!(ADCSRA & 0x10)) {}; // wait for adc to be ready
      ADCSRA = 0xf6; //  start adc sample @0xf5 38.4kHz || 0xf6 = 19.2kHz (9.6kHz Nyquist)
      m = ADCL ; // fetch adc data
      j = ADCH;
      k = (j << 8) | m; // form into an int (ignore 2LSB)
      k -= 0x200; // form into a signed int DC offset 619 count(0x26b)
      k <<= scale; // form into a 16b signed int
      fft_input[i] = k ; // put real data into even bins
      fft_input[i + 1] = 0; // set odd bins to 0
    }
    if (debug_active == true) {
      if (debugFFT == false && debugfft == false) {
        for (int r = 0; r < FFT_N >> 1; r += 2) {
          Serial.println(fft_input[r]); 
        }
      }
    }

    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_lin(); // take the output of the fft
    sei();
    bins = 0;
    for (p = FFT_N >> 1; p > (FFT_N >> 2) + 1; p--) {
      bins = fft_lin_out[p];
      if (bins > pix5) {
        pix5 = bins << 1;
        if(pix5>255) pix5 = 255;
      }
    }
    for (p = FFT_N >> 2; p > (FFT_N >> 3) + 1; p--) {
      bins = fft_lin_out[p];
      if (bins > pix4) {
        pix4 = bins << 1;
      }
    }
    for (p = FFT_N >> 3; p > (FFT_N >> 5) + 1; p--) {
      bins = fft_lin_out[p];
      if (bins > pix3) {
        pix3 = bins;
      }
    }
    //for (p = FFT_N >> 4; p > (FFT_N >> 5) + 1; p--) {
    bins = fft_lin_out[1];
    if (bins > pix2) {
      pix2 = bins;
    }

    bins = fft_lin_out[0];
    if (bins > pix1) {
      pix1 = bins >> 1;
    }

    bins = 0;
    if (pix5 > 128) pix5 -= decay << 2;
    if (pix5 > 64) pix5 -= decay << 1;
    if (pix5 > decay) pix5 -= decay;
    if (pix5 < noise_floor) pix5 = 0;

    if (pix4 > 128) pix4 -= decay << 3;
    if (pix4 > 64) pix4 -= decay << 1;
    if (pix4 > decay) pix4 -= decay;
    if (pix4 < noise_floor) pix4 = 0;

    if (pix3 > 192) pix3 -= decay << 4;
    if (pix3 > 64) pix3 -= decay << 2;
    if (pix3 > decay) pix3 -= decay;
    if (pix3 < noise_floor) pix3 = 0;

    if (pix2 > 128) pix2 -= decay << 4;
    if (pix2 > 64) pix2 -= decay << 2;
    if (pix2 > decay) pix2 -= decay;
    if (pix2 < noise_floor) pix2 = 0;

    if (pix1 > 128) pix1 -= decay << 4;
    if (pix1 > 64) pix1 -= decay << 2;
    if (pix1 > decay) pix1 -= decay;
    if (pix1 < noise_floor) pix1 = 0;

    pixels.setPixelColor(4, pixels.Color((pix5 >> 1), 0, pix5));
    pixels.setPixelColor(3, pixels.Color(0, pix4, pix4));
    pixels.setPixelColor(2, pixels.Color( 0, pix3, 0));
    pixels.setPixelColor(1, pixels.Color(pix2, (pix2 >> 1), 0));
    pixels.setPixelColor(0, pixels.Color(pix1, 0, 0));

    delay(looptime);
    pixels.show();  // very important!

FFTneoPixels.ino (13.6 KB)

#define FFT_N 128 // set to 64 point fft

128 != 64

#define debug 9
#define DEBUG 4

Not very creative, eh? Do not do crap like this. You CAN use longer, meaningful names.

boolean debugFFT, debugfft = false;

Or this. Names that differ only in case are extremely difficult to keep straight.

yeah.... Aware of the silly naming convention. Was under pressure to get wifes xmas hat done before xmas. Init tried for a 64 point FFT but not enough separation in lower bins for display, 256 used more memory than i needed, 128 point was just right.

Apologies for the NON-proper naming convention, wasn't meant for the public yet or at all really. Was just a last minute that got out of hand a bit with integrating FFT into an xmas hat. Would have been nice to track down this bug but ran out of time.