Analyzing data from an mp3 player and mapping it to LEDS?

Hi, I'm super new at working with arduinos (and frankly, any sort of code), and I've taken on a project for a digital art class that may be out of my depth, but I'm super determined to finish it.
Essentially what I'm aiming to do is to send audio from an MP3 player to my arduino through a headphone jack, use some sort of FFT library to do audio analysis on the audio, and then map sections of the high, low and midrange frequencies from the audio analysis to individual LEDs on a NeoPixel ring to visually represent music in color.
I have someone helping me with the FFT coding and mapping to LEDs already, so I'm good on that for now, I think (possibly not, though, but we'll see).
For whatever reason, though, I can't figure out how a) properly hook up the headphone jack to my arduino, and b) read data through it from a music player (any kind; laptop, mp3 player, iphone, etc.) for analyzing purposes.
Before someone says that it'd just be easier on me to use an mp3 shield or something: I'm aware of that possibility, but I can't do that for two reasons- I'm operating on a college student budget and the NeoPixel LEDs were a dent in my budget already, and part of the purpose of the project is that because this is an art piece, I'm attaching the NeoPixel LEDs to a set of headphones; the audio is going from the mp3 player into both the arduino AND the headphones through a headphone cord splitter. It's an artistic vision. I'm an art student out of my depth in code stuff but I'm trying really hard.
Basically I'm having trouble with what's arguably one of the simpler elements of the project, and I feel silly about this, but can someone help me figure out how to get audio input from an MP3 player onto an arduino?

Since the Arduino can't handle the negative half of the AC audio waveform, you need to bias the input to 2.5V, and then "block" that bias from the MP3 player. That just requires 2 equal-value resistors and a capacitor.

Look at the parts in the box in [u]this circuit[/u]. The two equal-value 100k resistors create a voltage divider to bias the ADC input at 2.5V. The 10uF capacitor blocks the DC (allowing the AC signal through) and isolates the 2.5V bias. (You can ignore the 47nF capacitor.)

You'll probably need to keep the volume up rather "loud" to take maximum advantage of the full 5V voltage swing. A line-level signal or loud headphone-level signal will be around 1V. Tthat should be enough to "analyze". But it means you'll probably need a volume control somewhere after the signal is split to the Arduino to allow.

alright, thank you very much! I've managed to get it working since then, but I didn't know about the capacitor thing so I'll fix that so I don't damage my circuit or anything.
I've gotten the LEDs responding to audio volume at this point, actually (basic stuff; more volume = more LEDs lit and such) and I'm trying to find a good library for doing the FFT work. Most of the ones I'm finding don't seem to have the breadth of functionality I'm looking for, but that might be me misunderstanding their functions. The one I'm looking at right now is this one: ArduinoFFT - Open Music Labs Wiki
but I'm worried it's not drawing from a full audio spectrum, only part of it? I'm not sure what the bins are actually collecting data from; is it the entire audio spectrum dumped into 256 bins, or is it just the first 256 samples, or what? Is there a better library I could be using?
Also (and this might just be a very silly question because I'm new), where is the audio input's data being stored? I mean before I send it to the LEDs as an output. Is it stored on the arduino or on my computer somewhere? Or do I need to specify where it gets put?

Anyway, thank you for helping.

The OpenMusicLabs FFT library works very well. You will clearly need to do some reading to learn how the data are sampled and how the FFT works, though.

The entire audio spectrum cannot be analyzed by the Arduino unless you use special tricks. Using standard analog sampling functions you are limited to collecting audio data at a rate of about 9.6 kHz, which limits the upper audio frequency to about 4.8 kHz. Higher frequencies SHOULD NOT be present if you want to make sense of the FFT results. You will probably need an input filter to remove the high frequencies.

If you collect 256 audio samples, then music amplitudes for the frequencies between 0 Hz and 4.8 kHz are divided up linearly into the 256 bins.

Several web sites describe the special tricks to cover the entire audio range, so google for example "arduino audio spectrum analysis" to learn more.

I think I'm starting to understand how the FFT works... I've been researching it for like two weeks as it is and my professor managed to explain it mostly. At this point I'm trying to figure out how to map the array of data to specific LEDs. I'm working with a 24 LED NeoPixel ring; I'm hoping to map individual bins of the FFT to the RGB values of each individual LED.
Because of my level of coding proficiency, I'm basically working off of and modifying the FFT code from the examples the open music labs library came with. Right now it's printing the array to the serial port. How do I map specific bins in that array to specific LEDs? Also how do I know which bins are the high, low and mid frequencies? If this is a very silly question that I can figure out on my own, just nobody answer before the 3rd of December when this is due and I'll probably sort through it somehow?
Anyway, thank you all for the help so far.

The example program posted by OpenMusicLabs for testing the FFT is not very useful. Here is one I wrote for testing that may help you think about the relationship between the input frequencies, and the output frequency bin index.

The example generates two pure tones with different amplitudes. The FFT decomposes the input signal correctly, except for an amplitude factor of two due to the symmetry of the transform about 0 frequency. Of course, the meaning of “frequency” depends on the audio sample rate, which is not defined for this example.

/*
 fft_test_sine
 example sketch for testing the fft library.
 This generates a simple sine wave data set
 of frequency f, transforms it, calculates 
 and prints the amplitude of the transform.
 */

// do #defines BEFORE #includes
#define LIN_OUT 1 // use the lin output function
#define FFT_N 32 // set to 32 point fft

#include <FFT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
}

void loop() {
  int i,k;
  float f1=2,f2=5;  //two input frequencies
  for (i = 0 ; i < 32 ; i++) { // create 32 samples
    k=1000*sin(2*PI*f1*i/32.)+500.*sin(2*PI*f2*i/32.); //amplitudes 1000 and 500
    fft_input[2*i] = k; // put real data into even bins
    fft_input[2*i+1] = 0; // set odd bins to 0
  }
  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
  // print the frequency index and amplitudes
  for (i=0; i<16; i++) {
    Serial.print(i);
    Serial.print(" ");
    Serial.println(fft_lin_out[i]);
  }
  Serial.println("Done");
  while(1); //hang here
}

Oh! That’s really useful, thank you.
I’ve got the library working now; I messed around and modified the code in one of the examples and managed to successfully frankenstein it together with the FastLED library. It’s doing what I want now, sort of. It maps the FFT data to the red values of the LEDs, at least. The only problem is that it’s not doing it in time with the music? It’s not responding to the music that’s coming into the analog input, at least. It’s responding to FFT data, certainly, but what I think is happening is that either it’s still got whatever data was produced by the last song I played into it and it’s drawing from that, or it’s taking whatever FFT data is coming into the analog in at the moment the code is uploaded to the arduino and just repeats that over and over somehow? I’m not especially well versed in this so I’m bad at diagnosing the problem

What I want to be happening is that it does the FFT audio analysis in real time, and then maps the data to the LEDs in realtime as well. I have no idea what to do at this point to fix them problem I’m having though, so I’m gonna upload my code and see what someone who understands this better makes of it:

//example sketch modified from FFT library's examples
//example: fft_adc_serial
//butchered and frankensteined together 
//by yours truly


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

#include <FFT.h> // include the library
#include <FastLED.h> //includes FastLED library

#define LED_PIN     6 //pin attached to Neopixels
#define NUM_LEDS    24 //number of lights per Neopixel
#define BRIGHTNESS  64 //can't figure out if this even changes anything to alter
#define LED_TYPE    WS2812 //type of LED
#define COLOR_ORDER RGB //these are pretty obv
CRGB leds[NUM_LEDS]; ///this is just important idk what it does

#define UPDATES_PER_SECOND 100  //how many times the LEDs refresh color per second

void setup() {
  FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS); //this is copied from FastLED's example codes
  //it's in all of them so I figure it's necessary. It looks necessary. 
  //I will readily admit my lack of comprehension to retain honesty.
  
  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() {
  
 
    cli();  // UDRE interrupt slows this way down on arduino1.
    for (int i = 0 ; i < 128 ; i += 2) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 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();
      
    int numLedsToLight = 24;
  
    for (int i = 0 ; i < 24 ; i++) { 
     int val = fft_log_out[i];
     int redval = map(val, 0,300, 0,50);
       
      FastLED.clear();
      for(int led = 0; led < 24; led++){
      leds[i].setRGB(redval,30, 30);
      }
      FastLED.show();
    }
    Serial.println("start");
     for (byte i = 0 ; i < FFT_N/2 ; i++) { 
      Serial.println(fft_log_out[i]);
     }
}

What it’s doing right now is it’s mapping the FFT data to the red values of the LEDs (and printing it to the serial port so I can see what kind of numerical data I’m getting out). I have no idea what part of the code to change to make it realtime instead of… whatever it’s presently doing.

I don’t know what the calls in your LED library do, but unless you have a 24x24 array of LEDs, this code is probably not correct. Check the loop nesting among other things.

    for (int i = 0 ; i < 24 ; i++) { 
     int val = fft_log_out[i];
     int redval = map(val, 0,300, 0,50);
       
      FastLED.clear();
      for(int led = 0; led < 24; led++){
      leds[i].setRGB(redval,30, 30);
      }
      FastLED.show();
    }

In any case, this accesses only the first 24 of 32 amplitude values output by the FFT.