Help Understanding FFT Analysis and analogRead()? Here's the deal, I'm attempting to learn how to use an FFT (Fast Fourier Transformation) Library for sound analysis (link is here). My issue is that this comes with included C++ code to show users how to use the FFT library. There are three examples, but I'll show this one because it's closest to the application I have planned for it:

/*
fft_adc_serial.pde
guest openmusiclabs.com 7.7.14
example sketch for testing the fft library.
it takes in data on ADC0 (Analog0) and processes them
with the fft. the data is sent out over the serial
port at 115.2kb.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft

#include &lt;FFT.h&gt; // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while(1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i &lt; 512 ; i += 2) { // save 256 samples
      while(!(ADCSRA &amp; 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j &lt;&lt; 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k &lt;&lt;= 6; // 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
     }
    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_log(); // take the output of the fft
    sei();
    Serial.println("start");
    for (byte i = 0 ; i &lt; FFT_N/2 ; i++) { 
      Serial.println(fft_log_out[i]); // send out the data
    }
  }
}


Now, with that said, I have a very general grasp of the idea that those lines referencing some variable called ADMUX and ADCSRA have to do with the analogRead() method and that the ADCH and ADCL refer to another two components that are combined to provide the returned integer that analogRead() spits out. What I don't understand whatsoever are those seemingly random strings of characters that these are being set equal to. For example, what does 0x40 or 0x01 or 0xe5 even refer to in the setup() method (if nothing else maybe somebody could point me in the right direction for this, because that part I really am entirely clueless about). And furthermore, why manipulate these directly in the first place, because if you reference the source code for analogRead() they look awfully similar. Thanks for any help in advance!
Nick Gammon already gave a very fine answer about the meaning of the
mysterious numbers you were wondering about. Here I am trying to answer
only your last question:


  why manipulate these directly in the first place, because if you
  reference the source code for analogRead() they look awfully similar.


One of the reasons is, as Dave X said in a comment, to get a higher
sample rate. Assuming this is an Arduino Uno or similar (ATmega328P @
16 MHz), the Arduino core normally configures the ADC prescaler to 128.
This gives a conversion time of 104 µs (equal to 13 × prescaler ÷
F_CPU), and a maximum sample rate of about 9.6 kHz. This is fine for
telephone quality audio, but insufficient for hi-fi applications. This
example code sets the prescaler to 32 for a conversion time of 26 µs and
a maximum sample rate around 38 kHz. According to Atmel, the ADC should
work fine with this kind of sample rate, except that you should not
expect to get the full resolution.

The main reason, however, is not to get a fast sample rate, but rather
to get a consistent sample rate. The problem with analogRead() is
that it is a blocking function. If you look at its source code you
will see a busy wait like this:

// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));


This means that the CPU is not doing anything useful while waiting for
the ADC to finish the conversion. If you do analogRead() in a loop,
the CPU will wait for the ADC, then the ADC will be idle while the CPU
completes the loop and so on. The conversion period is then the time
required by the ADC plus the time taken by the CPU to loop. And the
CPU time is hard to predict because it can be influenced by interrupts
and by conditional branches inside the loop.

This code, in contrast, configures the ADC to work in free running
mode. In this mode, the ADC starts a new conversion as soon as the
previous one is done. This way you get a steady sample rate while the
ADC and the CPU work in parallel. In the loop you see these lines:

while(!(ADCSRA &amp; 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc


The comments are a bit misleading. The first line (which I would rather
write loop_until_bit_is_set(ADCSRA, ADIF);) waits for a flags that is
set when the current conversion is done and the data register updated.
The next line does not restart the ADC (it restarted itself, as it is in
free running mode): it only clears the flag so that it can be
meaningfully tested on the next iteration.

Now, I have a few comments on this code that are not directly related to
your question, but may be useful if you are going to build your program
on this basis.

First, it should be noticed that the whole ADC-reading loop is done with
interrupts disabled. This is not normally needed, as the free running
mode gives you a steady sampling even if the CPU timing is somewhat
jittery. The only valid reason I see for disabling interrupts is if
one of your ISRs takes so long to execute that you may miss one sample.
This could very well be the case with such a high sampling frequency.
But still, there is no point in keeping the interrupts disabled during
the FFT processing. And there is no point in turning off Timer 0 if you
are disabling interrupts anyway.

My second point is about the three lines starting with byte m = ADCL;.
Those are meant to read the ADC data register in the proper order: low
byte first. However, the C compiler is well aware of the proper way to
do read a 16-bit I/O register (see “Accessing 16-bit Registers” in the
datasheet chapter about Timer 1). Thus, these three lines can be
simplified to just int k = ADC;.

My last point is that having the CPU left adjust the result (k &lt;&lt;= 6)
takes some time, as it is implemented as a loop. There is no point in
doing this when the ADC can do it for free: you just have to set the
ADLAR bit when configuring ADMUX in setup(). Then the 5 lines starting
with byte m = ADCL; would be reduced to

int k = ADC - 0x8000;  // ADC reading as a 16 bit signed int