1

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.

Chris Stratton
  • 5,411
  • 20
  • 40

2 Answers2

1

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!

per1234
  • 4,278
  • 2
  • 24
  • 43
dandavis
  • 1,037
  • 9
  • 12
-1

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!

EDIT ADDITION:

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!

user29032
  • 149
  • 5