Question regarding FFT bins

Status
Not open for further replies.

cYnd

Member
Hi there,

i just started a project where i want to control a LED strip so it reacts to audio. Using the FFT seems to be a good idea for this.
To test my setup i hooked up the MAX4466 to a analog input pin of my Teensy 3.2 aswell as 3.3V and GND.
My idea is to let control the low frequencies the red value, the mid frequencies the green value and the high frequencies the blue value of the LED strip.

However i always get a pretty high value for the low frequencies and nearly no input for the high frequencies (i read that the mic i'm using isn't properly working because it hasn't the 0.6V bias the Teensy is using).

While studying the documentation and the online tool for audio design, i came across one question: the documentationsays that FFT1024 has a resolution of 43Hz. With the read(firstBin, lastBin) i can read a maximum of 512 bins (0, 511)...does that mean that the resolution of the FFT is 43Hz but the bins contains a frequency band of 86Hz? Or is each bin 43Hz though?
For example to read the low frequencies (assuming everything < 172Hz is low frequency) should i use fft1024.read(0, 3) (4 * 43Hz = 172Hz) or fft1024.read(0, 1) (2 * 86Hz = 172Hz)?

This is my code so far, i think it's pretty straight forward:

Code:
.#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <math.h>
#include <LEDStrip.h>
#include <Entropy.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=239,227
AudioAnalyzeFFT1024      fft1024_1;      //xy=482,242
AudioConnection          patchCord1(adc1, fft1024_1);
//GUItool: end automatically generated code

int lowCutoff, midCutoff, highCutoff, maxLEDBrightness, redLED, greenLED, blueLED;
float LEDSwitchThreshold;
LEDStrip led;

void setup() {
  Serial.begin(9600);
  AudioMemory(12);
  fft1024_1.windowFunction(AudioWindowHanning1024);
  lowCutoff = 4;    //0 min
  midCutoff = 48;
  highCutoff = 512; //512 max

  maxLEDBrightness = 140;
  redLED = 0;
  greenLED = 1;
  blueLED = 2;
  LEDSwitchThreshold = 0.4;

  Entropy.Initialize();
  led.initialize(0, 1, 2);
}

void loop() {
  if (!fft1024_1.available()) return;

  int lowBuffer = getNormalizedFrequenzies(lowCutoff, 0) * 140;
  int midBuffer = getNormalizedFrequenzies(midCutoff, lowCutoff) * 140;
  int highBuffer = getNormalizedFrequenzies(highCutoff, midCutoff) * 140;
  if (lowBuffer + midBuffer + highBuffer > 0.0) {
    led.setColor(lowBuffer, midBuffer, highBuffer);
  }

  if ((lowBuffer + midBuffer + highBuffer) > (maxLEDBrightness * 3 * LEDSwitchThreshold)) {
    led.randomizePins();
  }
}

float getNormalizedFrequenzies(int frequenzyCutoff, int loopOffset) {
  float maxValue = 0.0;
  float sum = 0.0;
  for (int i = 0 + loopOffset; i < frequenzyCutoff; i++) {
    float buffer = fft1024_1.read(i);
    if (!buffer) return 0.0;
    if (buffer > maxValue) {
      maxValue = buffer;
    }
    sum += buffer;
  }

  float normalizedValue = (log(sum / (frequenzyCutoff - loopOffset) + 1) / log(maxValue + 1));
  return normalizedValue;
}
 
There is an FFT sample IIRC in the Teensy Audio Tutorial that prints out the bin values. If you find that it might help you visualize where the data hits are and what values are coming in, and how to group the bins.

If you don't see it go to the PJRC Audio Tutorial page. Not in a place to look and link just now.

Each of the bins 1-511 will be the expected 43 Hz - IIRC
 
So if each bin contains 43Hz, the maximum frequence which is available will be (43 * 512 = ) 22 016 Hz / 22kHz?

I looked up the example and running this (also setting up the frequencies showed all the way to full 512) reveals that the high frequencies are also much quiter than the lower ones...so i guess i have to consider this and mix my LED colors accordingly :)
 
Keep in mind that human hear in octaves, which are logarithmic, not FFT bins which are a linear scale.

Half of all the FFT bins are the top octave, and another 1/4 of them are the next octave down... both of which are barely heard by ordinary people.
 
Oh and what i totally forgot: the mics maximum frequency is 20kHz - so i guess i just can cutoff every frequency above that and get more reliable results.

Thanks paul for the hint but do you think i should consider human hearing capabilities when i try to get three signals from the FFT to control my LED colors? When recording with the mic i get the highest values in the low frequency band (bin 0 - 3)
 
Status
Not open for further replies.
Back
Top