SpectrumAnalyzer fft.available() is always false

s4l4x

Member
Hi, I'm new to audio programming on the teensy and was trying to get the SpectrumAnalyzer example file to work, but fft.available() is always false. Do I need external memory for it to work? Am I missing something? Thank you!

Code:
// LED Audio Spectrum Analyzer Display
//
// Creates an impressive LED light show to music input
//   using Teensy 3.1 with the OctoWS2811 adaptor board
//   http://www.pjrc.com/store/teensy31.html
//   http://www.pjrc.com/store/octo28_adaptor.html
//
// Line Level Audio Input connects to analog pin A3
//   Recommended input circuit:
//   http://www.pjrc.com/teensy/gui/?info=AudioInputAnalog
//
// This example code is in the public domain.

#include <OctoWS2811.h>
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <Adafruit_NeoTrellis.h>

// The display size and color to use
const unsigned int matrix_width = 60;
const unsigned int matrix_height = 32;
const unsigned int myColor = 0x400020;

// These parameters adjust the vertical thresholds
const float maxLevel = 0.5;      // 1.0 = max, lower is more "sensitive"
const float dynamicRange = 40.0; // total range to display, in decibels
const float linearBlend = 0.3;   // useful range is 0 to 0.7

// OctoWS2811 objects
constexpr int LEDS_PER_STRIP = 375;
DMAMEM int displayMemory[LEDS_PER_STRIP * 6];
int drawingMemory[LEDS_PER_STRIP * 6];
const int config = WS2811_RGB | WS2811_800kHz;
OctoWS2811 leds(LEDS_PER_STRIP, displayMemory, drawingMemory, config);


// Audio library objects
AudioInputAnalog adc1(A3); // xy=99,55
AudioAnalyzeFFT1024 fft;   // xy=265,75
AudioConnection patchCord1(adc1, fft);

// This array holds the volume level (0 to 1.0) for each
// vertical pixel to turn on.  Computed in setup() using
// the 3 parameters above.
float thresholdVertical[matrix_height];

// This array specifies how many of the FFT frequency bin
// to use for each horizontal pixel.  Because humans hear
// in octaves and FFT bins are linear, the low frequencies
// use a small number of bins, higher frequencies use more.
int frequencyBinsHorizontal[matrix_width] = {
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
    3, 3, 3, 3, 4, 4, 4, 4, 4, 5,
    5, 5, 6, 6, 6, 7, 7, 7, 8, 8,
    9, 9, 10, 10, 11, 12, 12, 13, 14, 15,
    15, 16, 17, 18, 19, 20, 22, 23, 24, 25};

// Run once from setup, the compute the vertical levels
void computeVerticalLevels()
{
  unsigned int y;
  float n, logLevel, linearLevel;

  for (y = 0; y < matrix_height; y++)
  {
    n = (float)y / (float)(matrix_height - 1);
    logLevel = pow10f(n * -1.0 * (dynamicRange / 20.0));
    linearLevel = 1.0 - n;
    linearLevel = linearLevel * linearBlend;
    logLevel = logLevel * (1.0 - linearBlend);
    thresholdVertical[y] = (logLevel + linearLevel) * maxLevel;
  }
}

// Run setup once
void setup()
{
  Serial.begin(38400);
  Serial.println("# Setup");

  // the audio library needs to be given memory to start working
  AudioMemory(12);
  Serial.println("AudioMemory");

  // compute the vertical thresholds before starting
  computeVerticalLevels();
  Serial.println("computeVerticalLevels");

  // turn on the display
  leds.begin();
  leds.show();
  Serial.println("leds");
}

// A simple xy() function to turn display matrix coordinates
// into the index numbers OctoWS2811 requires.  If your LEDs
// are arranged differently, edit this code...
unsigned int xy(unsigned int x, unsigned int y)
{
  if ((y & 1) == 0)
  {
    // even numbered rows (0, 2, 4...) are left to right
    return y * matrix_width + x;
  }
  else
  {
    // odd numbered rows (1, 3, 5...) are right to left
    return y * matrix_width + matrix_width - 1 - x;
  }
}

// Run repetitively
void loop()
{
  unsigned int x, y, freqBin;
  float level;

  if (fft.available())
  {
    Serial.println("FFT OK");
    // freqBin counts which FFT frequency data has been used,
    // starting at low frequency
    freqBin = 0;

    for (x = 0; x < matrix_width; x++)
    {
      // get the volume for each horizontal pixel position
      level = fft.read(freqBin, freqBin + frequencyBinsHorizontal[x] - 1);

      // uncomment to see the spectrum in Arduino's Serial Monitor
      // Serial.print(level);
      // Serial.print("  ");

      for (y = 0; y < matrix_height; y++)
      {
        // for each vertical pixel, check if above the threshold
        // and turn the LED on or off
        if (level >= thresholdVertical[y])
        {
          leds.setPixel(xy(x, y), myColor);
        }
        else
        {
          leds.setPixel(xy(x, y), 0x000000);
        }
      }
      // increment the frequency bin count, so we display
      // low to higher frequency from left to right
      freqBin = freqBin + frequencyBinsHorizontal[x];
    }
    // after all pixels set, show them all at the same instant
    leds.show();
    // Serial.println();
  }
  
    leds.setPixel(LEDS_PER_STRIP * 1, 0x00ff00);
    leds.show();
}
 
Try to get the FFT function to respond with the correct settings. The audio signal should be on A2, it even works without the audio shield. If there is something wrong with it let the experts clarify it for us, but so far I haven't seen sparks come out of teensy 4.1 jejeje

Try this simple example:

Code:
#include <Audio.h>

AudioInputAnalog     adc1;   //A2    
AudioAnalyzeFFT1024  fft1024_2;
AudioOutputI2S       i2s2;  
AudioConnection      patchCord3(adc1, fft1024_2);      

#define NUM_BINS     380
double Datos[NUM_BINS];
double Bin_inicial =   1;
double escalaFFT   =   1.2; 
double FRuido      =   0; 
double TOP         =  60;

void setup() {
 AudioMemory(30);
 fft1024_2.windowFunction(AudioWindowHanning1024);
 //fft1024_2.windowFunction(NULL);
}

void loop() {
   if (fft1024_2.available()) 
   {
    for (int i=Bin_inicial; i<NUM_BINS; i++)
    {
      Datos[i] = (1000*escalaFFT*fft1024_2.read(i))-FRuido*escalaFFT;
      if (Datos[i] >= TOP) Datos[i] = TOP;
      Serial.println(Datos[i]);
    }
   }
}

Connect the audio output of the PC speakers to your teensy with a 3.5 jack and immediately play a multimedia file on the PC. Remember to connect GND of the audio signal to GND of the teensy. Once you have a response from the FFT function, it will be up to you to manage to pass the signal from the selected bins to your addressable LED array.

You should see something like this in the serial plotter
 

Attachments

  • FFT test01.jpg
    FFT test01.jpg
    233.4 KB · Views: 46
Back
Top