Go Down

Topic: FHT noisy output (Read 599 times) previous topic - next topic


Oct 08, 2015, 08:44 pm Last Edit: Oct 09, 2015, 08:56 pm by Crocs
Hi everyone!
I am new to Arduino and am currently stuck.
I am trying to let an RGB LED light up according to the frequencys of a song.
I tried to do this by using a microphone to get the input to the arduino and process it there with FHT.
I am using an Arduino UNO with the FHT library from openmusiclabs.
My problem now is that the output of the FHT is very noisy. The code is the following:
Code: [Select]

#define LOG_OUT 1 // use the log output function
#define FHT_N 128 // set to 128 point fht
#include <FHT.h>

#define MIC_PIN   0

double prevVolts = 100.0;

void setup()

// the loop routine runs over and over again forever:
void loop()
    for (int i = 0 ; i < FHT_N ; i++)   // save 256 samples
      int sample = analogRead(MIC_PIN);
      fht_input[i] = sample; // put real data into bins
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_log(); // take the output of the fht
    for (int curBin = 0; curBin < FHT_N/2; ++curBin)
      if (curBin > 0)

The format of the output looks like that cause i used a program to visualize the output. I put a part of the output from the Serial screen in the attachment. (note that the room was really quiet when I was recording)
I also wanted to add a picture of the Microphone in the attachment but it couldnt upload it. But it basically works like that (at least that's what my teacher told me):
The first part with the microphone itself is just the mic with an amplifier. The second part is to lift the voltage of the audio signal to a positive level (Since a standart audio signal is postive and negative).
My question now is: How can i get a cleaner output that shows the actual frequencys? Or how do i get the actual "strongest" frequency?
I am trying to let the LED light up in a color that represents the strongest frequency (for example blue for a lot of bass).
Thank you very much for your help!
Greetings Crocs

edit: In the end i was able to get a cleaner output by using the fht_mag_lin8() function. I also defined SCALE to 256 for a better resolution.
The output looks now pretty clean. There is only a little bit of noise left, however this tiny bit is not bothering.
Again thanks for all the quick replies!


I've never used that library.

This may not be much help, but try disconnecting the amplifier and ground the Arduino's input.   That will be "silence" so if there's still a lot of noise, you've got a software problem.

Have you plugged the amplifier-output into a power amplifier (or powered computer speakers) to see what kind of sound-signal you're getting?

Your code looks a lot different from this example.    I don't see what's controlling the sample rate in your code or in the example code, but there is a comment in the example that says "wait for the adc to be ready".

It looks like you are reading the mic input in a loop as fast as you can.   Sampled audio is meaningless without knowing the sample rate.      If you don't know what I'm talking about, this tutorial explains how analog audio is digitized.   (It's very basic and it doesn't get into FFT or anything advanced like that.)    


Post a circuit diagram showing how you have connected the microphone (not Fritzing, please).


Oct 09, 2015, 06:11 am Last Edit: Oct 09, 2015, 06:11 am by tmd3
Take a look at the "programming example" linked at the openmusiclabs page.  You'll see that it does a couple of things that your code doesn't do.  It offsets the analog value by half-scale, so that a zero reading becomes -512, ans a full-scale reading become 512.  That sends bipolar data to the FHT routine.  The programming example also left shifts the adjusted analog value by six bits, multiplying by 64, to make the data look like it's 16-bit readings.  Assuming that your input device offsets the analog voltage by half-scale, 2.5V, you can expect to read 512 for each analog value if the microphone output is zero.  

To see what an input value of 512 yields, you can change the analogRead() statement to this:
Code: [Select]
int sample = 512; // analogRead(MIC_PIN);
Try it, and note that the results aren't too different from what you're getting.  The offset voltage gives you a high zeroth term, and the windowing function spreads that value among adjacent bins.

Don't forget that you're displaying the data on a logarithmic scale.  That tends to emphasize low-level values, and de-emphasize higher-level values.  It's purpose is to show low-level components of the signal clearly; otherwise, they'd disappear on a graph.  But, it can fool you into thinking that the low-level components of the output represent meaningful data, when they don't.

I think that what you're seeing is expectable, given that you don't offset the data, and the microphone is picking up only background noise, and you're not scaling the data.  

DVDdoug makes a strong point about sample timing:  with analogRead(), your sample timing is vulnerable to jitter from the Timer0 interrupt.  The programming example uses the ADC in free-running mode, and lets the ADC's hardware clock manage the sample timing.

Go Up