ksumrall
07-05-2016, 04:23 AM
Hello,
I'm working on a light to music project and stuck getting a reliable spectrum.
I'm using a Teensy 3.1 and an Adafruit AGC Electrit Microphone (https://www.adafruit.com/product/1713).
I'm running the teensy through USB for now so that I can use the serial monitor ro view results.
My code is as follows:
// FFT Test
//
// Compute a 1024 point Fast Fourier Transform (spectrum analysis)
// on audio connected to an adafruit AGC Electret Microphone MAX9814
// https://www.adafruit.com/product/1713
//
// The 512 bins are calculated into 32 bins.
//
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#define debug
const unsigned int matrix_width = 32;
const unsigned int matrix_height = 256;
// These parameters adjust the vertical thresholds
const float maxLevel = 0.4; // 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
// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
AudioInputAnalog adc1(A2);
AudioAnalyzeFFT1024 myFFT;
AudioConnection patchCord1(adc1, myFFT);
// This array specifies how many of the FFT frequency bins 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.
const int lowerFFTBins[] = {0,1,2,3,4,5,6,8,10,12,15,18,22,27,32,38,45,53,63, 74,87,102,119,138,160,186,216,250,289,334,385,444} ;
const int upperFFTBins[] = {0,1,2,3,4,5,7,9,11,14,17,21,26,31,37,44,52,62,73, 86,101,118,137,159,185,215,249,288,333,384,443,511 };
float thresholdVertical[matrix_height];
float thresholdVert[matrix_height];
void setup() {
analogReadAveraging(4);
AudioMemory(12);
// compute the vertical thresholds before starting
computeVerticalLevels();
for(unsigned int j = 0; j < matrix_height; j++) {
thresholdVert[j] = thresholdVertical[matrix_height-j-1];
}
myFFT.windowFunction(AudioWindowHanning1024);
}
void loop() {
float level;
int maxY;
if (myFFT.available()) {
#ifdef debug
Serial.print("FFT: ");
#else
Serial.write(255);
#endif
float bar[60];
int index = 2;
for (int x = 0; x < matrix_width; x++) {
level = myFFT.read(lowerFFTBins[x], upperFFTBins[x]);
maxY = 0;
for(int y = 0; y < matrix_height; y++){
if(level >= thresholdVert[y]){
maxY = y;
}
}
#ifdef debug
Serial.print(maxY);
Serial.print(" ");
#else
Serial.write(maxY);
#endif
}
#ifdef debug
Serial.println();
#endif
delay(20);
}
}
// 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;
}
}
The results look good for all but the first two bands. The first two bands seem to latch on to the maximum value experienced...
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Those first two bands keep latching onto the max value experienced. What's interesting is that I do see them show lower values as there is sound being calculated, but when it goes quiet, they appear in their 'latched' state.
I remember seeing some example code of Paul's where he skipped the first two bins. That makes me wonder if I should do the same and move on with just 30 bins.
*EDIT*
The scale of the values is 0 - 255
I have seen through the course of one song a the first two bins reading 248 and 196 respectively during silence. While the song is playing, the first bins seem to show properly fluctuating levels.
I'm working on a light to music project and stuck getting a reliable spectrum.
I'm using a Teensy 3.1 and an Adafruit AGC Electrit Microphone (https://www.adafruit.com/product/1713).
I'm running the teensy through USB for now so that I can use the serial monitor ro view results.
My code is as follows:
// FFT Test
//
// Compute a 1024 point Fast Fourier Transform (spectrum analysis)
// on audio connected to an adafruit AGC Electret Microphone MAX9814
// https://www.adafruit.com/product/1713
//
// The 512 bins are calculated into 32 bins.
//
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#define debug
const unsigned int matrix_width = 32;
const unsigned int matrix_height = 256;
// These parameters adjust the vertical thresholds
const float maxLevel = 0.4; // 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
// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
AudioInputAnalog adc1(A2);
AudioAnalyzeFFT1024 myFFT;
AudioConnection patchCord1(adc1, myFFT);
// This array specifies how many of the FFT frequency bins 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.
const int lowerFFTBins[] = {0,1,2,3,4,5,6,8,10,12,15,18,22,27,32,38,45,53,63, 74,87,102,119,138,160,186,216,250,289,334,385,444} ;
const int upperFFTBins[] = {0,1,2,3,4,5,7,9,11,14,17,21,26,31,37,44,52,62,73, 86,101,118,137,159,185,215,249,288,333,384,443,511 };
float thresholdVertical[matrix_height];
float thresholdVert[matrix_height];
void setup() {
analogReadAveraging(4);
AudioMemory(12);
// compute the vertical thresholds before starting
computeVerticalLevels();
for(unsigned int j = 0; j < matrix_height; j++) {
thresholdVert[j] = thresholdVertical[matrix_height-j-1];
}
myFFT.windowFunction(AudioWindowHanning1024);
}
void loop() {
float level;
int maxY;
if (myFFT.available()) {
#ifdef debug
Serial.print("FFT: ");
#else
Serial.write(255);
#endif
float bar[60];
int index = 2;
for (int x = 0; x < matrix_width; x++) {
level = myFFT.read(lowerFFTBins[x], upperFFTBins[x]);
maxY = 0;
for(int y = 0; y < matrix_height; y++){
if(level >= thresholdVert[y]){
maxY = y;
}
}
#ifdef debug
Serial.print(maxY);
Serial.print(" ");
#else
Serial.write(maxY);
#endif
}
#ifdef debug
Serial.println();
#endif
delay(20);
}
}
// 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;
}
}
The results look good for all but the first two bands. The first two bands seem to latch on to the maximum value experienced...
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Those first two bands keep latching onto the max value experienced. What's interesting is that I do see them show lower values as there is sound being calculated, but when it goes quiet, they appear in their 'latched' state.
I remember seeing some example code of Paul's where he skipped the first two bins. That makes me wonder if I should do the same and move on with just 30 bins.
*EDIT*
The scale of the values is 0 - 255
I have seen through the course of one song a the first two bins reading 248 and 196 respectively during silence. While the song is playing, the first bins seem to show properly fluctuating levels.