Arduino pitch detection in realtime (using autocorrelation and peak detection)

I think your code now looks something like the following. I made the buffer 1000 samples which seems to help reduce the noise (as it should), but slows down the autocorrelation rate (also expected). Using a function generator on my cell phone and going between 320 Hz and 350 Hz sine wave, I got the plot below. The microphone had to be very close to the phone's speaker. There's some noise in the measurement and a few outliers, but generally it seems to do pretty well.

// Arduino Pitch Detection on A0 with autocorrelation and peak detection
// Original author(s): akellyirl, revised by robtillaart and MrMark

#define E1 329.63
#define B2 246.94
#define G3 196.00
#define D4 146.83
#define A5 110.00
#define E6 82.41

float sampleFrequency;
float frequencyRange = 10;
volatile int interruptCount = 0;
const int arraySize = 1000;
volatile byte rawData[arraySize];
long currentSum, previousSum, nextSum ;
int threshold = 0;
float frequency = 0;
byte pdState = 0;

void setup() {
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
  TIMSK1 = 0;
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS10);
  TIMSK1 |= (1 << OCIE1A);

  ADCSRA = 0;
  ADCSRB = 0;
  ADMUX |= (1 << REFS0);
  ADMUX |= (1 << ADLAR);
  ADCSRA |= (1 << ADPS1);
  ADCSRA |= (1 << ADATE);
  ADCSRA |= (1 << ADEN);
  ADCSRA |= (1 << ADSC);

  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
}

ISR(TIMER1_COMPA_vect) {
  // Collect analog signal
  rawData[interruptCount] = ADCH;
  interruptCount ++;
}

void readData(float baseFreq) {
  int OCRvalue = 2 * (16000000 / (baseFreq - frequencyRange)) / arraySize - 1;
  OCR1A = OCRvalue;
  sampleFrequency = 16000000 / (OCRvalue + 1) ;
  interrupts();
  while (interruptCount != arraySize); // wait for data
  noInterrupts();
  interruptCount = 0;
}

void findFrequency() {
  // Calculate mean to remove DC offset
  long meanSum = 0;
  for (int j = 0; j < arraySize; j++) {
    meanSum += rawData[j];
  }
  char mean = meanSum / arraySize;
  // Autocorrelation
  currentSum = 0;
  pdState = 0;
  int period = 0;
  for (int i = 0; i < arraySize && (pdState != 3); i++) {
    // Autocorrelation
    previousSum = currentSum;
    currentSum = 0;
    for (int k = 0; k < arraySize - i; k++) currentSum += (rawData[k] - mean) * (rawData[k + i] - mean);
    // Peak detection
    if (pdState == 0) {
      threshold = currentSum / 2;
      pdState = 1;
    }
    else if (pdState == 1 && (currentSum > threshold) && (currentSum - previousSum) > 0) {
      pdState = 2;
    }
    else if (pdState == 2 && (currentSum - previousSum) <= 0) {
      // quadratic interpolation
      nextSum = 0 ;
      for (int k = 0; k < arraySize - i + 1; k++) nextSum += (rawData[k] - mean) * (rawData[k + i + 1] - mean);
      float interpolationValue = 0.5 * (nextSum - previousSum) / (2 * currentSum - previousSum - nextSum);
      period = i + interpolationValue;
      pdState = 3;
    }
  }

  // Frequency identified in Hz
  if (threshold > 100) {
    frequency = sampleFrequency / period;
    if (frequency < 400) {
      Serial.println(frequency);
    }
  }
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  readData(D4);
  digitalWrite(LED_BUILTIN, LOW);
  findFrequency();
}