My Goal

Have Arduino read audio output from a TRS stereo audio cable (coming from a computer, smartphone, etc.). As motivation for this use-case, once some audio data (depending on the sample rate) have been stored in a buffer, the Arduino will perform an FFT on the buffered data. The power contained in the FFT is mapped to the red, green, and blue frequency-bands of visible light to determine the color of an LED strip.

My Set-up

The obvious first step was to connect a Right-Angle 3.5mm Stereo Plug to Pigtail Cable to the Arduino. As is commonplace, this cable has a Tip, Ring, and Sleeve connector; Adafruit labels the black wire as ground (sleeve). They further label the red wire as "left channel live" (tip) and the white wire as "right channel live" (ring), if I can trust Wikipedia:

Stereo sockets commonly provide two such NC contacts, one for the tip (left channel live) and one for the ring or collar (right channel live).

My Question

So, I've plugged the red wire into the A0 pin and the white wire into the A1 pin. However, I'm unsure of how to sample the actual audio signal from these analog pins.

I don't believe the analogRead() function solves the whole problem - it only converts a voltage reading at the pin into a value between 0 and 1023. Presumably, if I knew the bit rate (i.e., sample rate) & of each packet in the transmitted audio signal, I'd be able to construct signal from that. Is it possible to extract the original audio's waveform from a simple voltage signal? If not, what approach would enable the Arduino to read audio data from an audio cable?

Note: For those wondering, I have indeed heeded the advice from this Electronics SE answer to attach a DC-blocking/DC-bias circuit to the signal source before driving it into an analog pin on the Arduino.

  • While not impossible, an ATmega based Arduino is a relatively non-optimal choice for this project. With three output colors, you can probably do more optimal mapping than an FFT - it sort of sounds like you're trying to imitate an old op-amp "color organ" Jul 4 '17 at 22:28
  • @ChrisStratton I've never heard of an op-amp color organ. Three output channels*, so that could be any number of colors depending on the intensity of each channel. Could expand on what makes the Arduino non-optimal (what should I do to make it better)? Processing power / resource constraints are hard to fix for any microcontroller. Jul 4 '17 at 22:35
  • 2
    The ATmega has a very slow, limited resolution ADC, little memory, and slow processing compared to even cheaper modern alternative MCUs. You really should spend some time researching color organs. You have only 3 color controls, so if you are going to do color mixing, you are going to need to define some algorithm to map frequency components to color mixes. It will probably be easiest to play with that on a PC, reading audio files and running it through your evolving algorithm until you are showing satisfactorily pretty colors on the screen. Only then worry about the MCU. Jul 4 '17 at 22:38
  • @ChrisStratton I see where you're going with color organs. It seems like a color organ takes the average the power over three selected frequency sub-bands in the acoustic range & dim a red, blue, or green light based on those average powers. I'm doing the same thing, except for an RGB LED strip has a R, G, and B channel. So simply, if I supply three PWM signals generated according to those average powers, the R, G, and B channels mix at the LED and produce some other color (for instance, bright white if all channels are provided with the same PWM signal). Jul 5 '17 at 18:04
  • @dda - please don't make edits which decrease the quality of a post. The original version was superior to yours, and so has been restored. Jul 6 '17 at 5:23

The middle path

Build the simple op-amp (or whatever) 70s-era color organ, but without all the LEDs. Then basically feed the organ's LED-driving lines into the Arduino's ADCs. Sampling that pre-processed/summarized data, you can define a wide variety of RGB interactions without complicated math or an EE background. The timing requirements will be well-within the Arduino's reach, unlike computing FFTs or other "difficult" processes. Besides, old/new hybrids are cool!


Simply, YES: it is possible to reconstruct the waveform from the sampled signal. There are entire 400 level college courses on this subject, in fact, but it is rather simple to implement. However, you should study the FFT algorithm you plan to use a little more closely, as it actually requires a discreet time (sampled) input.

Some background: The audio signal you are getting from the TRS cable is continuous, but was recreated from discreet samples (unless your using a tape deck) by using reconstruction theory. The basic idea is this: you take a continuous train of discreet values (the sample points of the sound you want to make), then you multiply each one by a sinusoidal rectangle function (called a sinc, if you want to look it up), which basically takes your discrete values and makes them analog. The frequencies of the sampled signal will probably be 44.1 or 96kHz, although the signal you actually get is analog.

Now, the FFT! The FFT itself is a discrete time function, meaning that it is designed to use sampled data (for instance, of vector of values read from analogread() once every T seconds, where T=1/f, f being your sampling frequency). I should warn you, unless you're planning on using a library someone else already made, the FFT is a complicated beast! It's not impossible to use--in fact once you understand it, it's really quite beautiful--just be aware there is a lot of circle-based math and opaque optimization.

So, again in short, yes, you can reconstruct a signal from its sample, but you don't need to!

Note: there may be more information on what you're trying to do on the Signal processing SE as well.

Hope that helps!


In response to the comments, I very much agree that most lower level arduinos (assuming uno or similar) is not the ideal chip. However, there is a way around your sampling problem. Whether your processor can handle the higher sampling rate is questionable, but we'll address that momentarily.

Q: How to get a higher sample rate out a 10kHz max ADC. A: Double up. Or triple up, or quadrupile up, etc. The basic idea is, if you have one ADC reading channel 1 of a signal nT seconds (T being period = 1/10kHz and n being a discrete set of integers = 0,1,2,3...), then you can have a second ADC reading the signal every nT+(T/2) seconds. Then, you populate your data vector as DATA=[ADC1(0*T),ADC2(0*T+T/2),ADC1(1*T),ADC2(1*T+T/2),...] and so on. This effectively doubles your sampling rate. If you want to sample at ~40Hz, you use 4 ADC channels. The real question is how high do you need to go. By Nyqist's Theorem, you need a sampling freequency >= to twice of the highest frequency you expect to be present in your signal. In most recorded sounds this never above 18kHz. So, you do this with 4 ADC channels offset from each other by a quarter period, and you have a high enough sample rate.

Q: What if I can't process the data with an FFT that fast? A: Never fear! Discrete time filters and power integration are here! (okay, that was a bit corny). A much less processor intensive method of frequency band power estimation would be to implement band-pass filters in your software (which can work with very little overhead processor-wise) and then average the power output of each filter.

Again, hope this addition helps! But as another commenter pointed out, what you want to due may be much easier with a different chip. And as I will point out, moving the filtering and power integration to external op-amp circuits would be an equally simpler option, eliminating the entire sampling problem!

  • The real problem at hand is: how do I sample the analog audio signal at the analog pin at 44.1 or 96 kHz? Because the ADC has a maximum sampling frequency of 10 kHz. At the moment, the key seems to be something called an "interrupt call" on a timer (this page seems to explain that, but I haven't wrapped my head around what it's doing yet). I'm having trouble identifying where the sample rate is being scaled up, though... Jul 5 '17 at 18:30
  • @VladislavMartin - you can do slightly better, but an ATmega is neither intended nor able to sample high fidelity audio. You'll have to pick a different part if you really want to do that. Jul 6 '17 at 1:05
  • No. The ATmega's ADC is multiplexed. Using multiple channels doesn't make it faster, because it's not 4 ADC's, it's 1 ADC dividing its capabilities to cover 4 inputs in turn. That idea only works on parts that have multiple ADC's - but many of those are already fast enough for Audio when using just one. Jul 6 '17 at 4:46
  • @ChrisStratton Are you sure it's not able to sample audio? I'm writing up an answer that uses Timer1 for interrupt handling to effectively increase the ADC's sample rate. According to Atmel doc, this is perfectly acceptable: "Recommended maximum ADC clock frequency is limited by the internal DAC in the conversion circuitry. For optimum performance, the ADC clock should not exceed 200kHz. However, frequencies up to 1MHz do not reduce the ADC resolution significantly." Jul 7 '17 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.