timing/sync issue with analogRead

Hello everyone!

I have an Arduino nano I'd like to incorporate in an audio processing unit, utilizing the well worn HT8950 "robot voice" IC. It's a toy/karaoke type effect, with a ring mod style "robot" voice and something they call "tremelo" which is more than just amplitude modulation. Whatever it is, it's a lovely mangler.
Besides those two modes, it also has "up" and "down" controls that adjust the pitch, in eight different steps. You can wire up momentary push buttons to two dedicated pins and cycle through the steps, or it has three digital address pins for switching, giving 8 combinations: 000, 010, 100, 110, 001, 011, 101, 111. I've used CMOS ICs to make a clock and divider to achieve an automated switching function, moving through the pitches in sequence at a rate determined by the clock. I would like to do this with an Arduino instead, though.

What I want is a potentiometer or encoder that controls the rate at which the device cycles through those steps. To experiment and get visual confirmation, I've tried making 3 LEDS blink, one at a base rate, the others at double and quadruple that rate, to mimic the digital switching, using analogRead and a 10k pot to adjust the rate.
It works as predicted with one problem: if I adjust the rate with the pot, the LEDs get out of sync. When I first turn it on, they are in sync, at least to the human eye. But after adjusting the pot up and down they blink with some kind of latency or delay between themselves, blinking at the correct rates relative to each other but no longer turning on and off in sync.

Is this a normal issue? Perhaps I'm searching with the wrong terms.

Here is my sketch so far. Thanks for your time y'all!

const int ledAPin = 4;
const int ledBPin = 5;
const int ledCPin = 6;

int ledAState = LOW;
int ledBState = LOW;
int ledCState = LOW;

unsigned long previousMillisA = 0;
unsigned long previousMillisB = 0;
unsigned long previousMillisC = 0;

int bpmPot = A0;

void setup() 
{
  pinMode(ledAPin, OUTPUT);
  pinMode(ledBPin, OUTPUT);
  pinMode(ledCPin, OUTPUT);
} 

void loop()
{
  unsigned long currentMillisA = millis();
  unsigned long currentMillisB = millis();
  unsigned long currentMillisC = millis();
  
  int potValue = analogRead(bpmPot);
  int rateValue;
  rateValue = map(potValue, 0, 1023, 20, 3000);
  int intervalA = rateValue;
  int intervalB = rateValue*2;
  int intervalC = rateValue*4;
  
// if A statement
  if (currentMillisA - previousMillisA >= intervalA) 
    {
      previousMillisA = currentMillisA; // save the last time you blinked the LED
      if (ledAState == LOW) // if the LED is off turn it on and vice-versa 
        {
        ledAState = HIGH;
        }else{
        ledAState = LOW;
        } 
      digitalWrite(ledAPin, ledAState);
    } 

// if B statement  
  if (currentMillisB - previousMillisB >= intervalB) 
    {
      previousMillisB = currentMillisB;
      if (ledBState == LOW)
        {
          ledBState = HIGH;
          }else{
          ledBState = LOW;
        }
      digitalWrite(ledBPin, ledBState);    
    } 

  
// if C statement
  if (currentMillisC - previousMillisC >= intervalC)
    {
      previousMillisC = currentMillisC;
      if (ledCState == LOW)
        {
          ledCState = HIGH;
          }else{
          ledCState = LOW;
        }
      digitalWrite(ledCPin, ledCState);
    }    
}

You are right, there is no provision in your program for synchronization of the LEDs. I recommend adding it by updating all three previousMillisX variables whenever the analog reading changes (with a dead band of course).

Another way is to access the bits of a counter:

const int ledAPin = 4;
const int ledBPin = 5;
const int ledCPin = 6;

unsigned long previousMillisA = 0;
unsigned int counter;
int bpmPot = A0;

void setup()
{
  pinMode(ledAPin, OUTPUT);
  pinMode(ledBPin, OUTPUT);
  pinMode(ledCPin, OUTPUT);
}

void loop()
{
  unsigned long currentMillisA = millis();

  int potValue = analogRead(bpmPot);
  int rateValue;
  rateValue = map(potValue, 0, 1023, 20, 3000);
  int intervalA = rateValue;

  // if A statement
  if (currentMillisA - previousMillisA >= intervalA)
  {
    previousMillisA = currentMillisA; // save the last time you blinked the LED
    
    counter++;
    digitalWrite(ledAPin, counter & 1);
    digitalWrite(ledBPin, counter & 2);
    digitalWrite(ledCPin, counter & 4);
  }
}

(untested)

updating all three previousMillisX variables whenever the analog reading changes

I can find my way around analog circuitry but I'm new to any kind of programming, so forgive me.

If the analog reading changes during the space between intervalX (which is inevitable), then the LEDs will get out of sync because the reading will change for say, LED A and LED C before LED B has a chance to respond to the new analog reading? Is that what's happening?

I'm not sure where to go from here. Precision isn't important, if the digitalWrite outputs can get in sync to each other in less a second or two, that's totally acceptable.

How do I go about doing what you say, updating the previousMillisX variables whenever the analog reading changes? Is it another IF condition? Add previousPotValue = potValue at the end of the loop, then, IF potValue != previousPotValue previousMilliX = millis? Like I said, precision isn't the game here. Am I even in the right neighborhood? Thanks for the help.

Yes, you would keep a previous pot value in another variable and test it against the current pot value (but analog readings bounce around so you need also a dead band)

Did you get a chance to test the code I posted?

I guess I didn't see the example you attached until after I posted. Thank you, it works perfectly! I wasn't expecting such a quick and easy solution, I don't have the time now to dive into understanding it and what led me astray in my thinking for the original idea. I need to cook my wife dinner now, I'll respond further later or tomorrow, thank you so much for your time, and thanks for that example, it's spot on!