Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#ifndef PSTR
#define PSTR // Make Arduino Due happy
#endif
AudioInputAnalog adc1;
AudioAnalyzeFFT1024 fft1024;
AudioConnection patchCord1(adc1, fft1024);
#define PIN 2
#define WIDTH 8
#define HEIGHT 5
// MATRIX DECLARATION:
// Parameter 1 = width of NeoPixel matrix
// Parameter 2 = height of matrix
// Parameter 3 = pin number (most are valid)
// Parameter 4 = matrix layout flags, add together as needed:
// NEO_MATRIX_TOP, NEO_MATRIX_BOTTOM, NEO_MATRIX_LEFT, NEO_MATRIX_RIGHT:
// Position of the FIRST LED in the matrix; pick two, e.g.
// NEO_MATRIX_TOP + NEO_MATRIX_LEFT for the top-left corner.
// NEO_MATRIX_ROWS, NEO_MATRIX_COLUMNS: LEDs are arranged in horizontal
// rows or in vertical columns, respectively; pick one or the other.
// NEO_MATRIX_PROGRESSIVE, NEO_MATRIX_ZIGZAG: all rows/columns proceed
// in the same order, or alternate lines reverse direction; pick one.
// See example below for these values in action.
// Parameter 5 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// Example for NeoPixel Shield. In this application we'd like to use it
// as a 5x8 tall matrix, with the USB port positioned at the top of the
// Arduino. When held that way, the first pixel is at the top right, and
// lines are arranged in columns, progressive order. The shield uses
// 800 KHz (v2) pixels that expect GRB color data.
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(WIDTH, HEIGHT, PIN,
NEO_MATRIX_BOTTOM + NEO_MATRIX_LEFT +
NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800);
int fftBins[WIDTH];
float level[WIDTH];
int shown[WIDTH];
int peaks[WIDTH];
float scale = 80.0;
uint32_t dropTimer = millis();
uint32_t peakDropTimer = millis();
void setup() {
matrix.begin();
matrix.setTextWrap(false);
matrix.setBrightness(30);
AudioMemory(12);
getFFTBins();
}
void loop() {
display_fft(50, 1000);
matrix.show();
}
void display_fft(uint32_t levelDecay, uint32_t peakDecay) {
if (fft1024.available()) {
for (int i = 0; i < WIDTH; i++) {
if (i < WIDTH - 1) {
level[i] = fft1024.read(fftBins[i], fftBins[i + 1] - 1);
} else {
level[i] = fft1024.read(fftBins[i], 511);
}
}
int val = 0;
for (int i = 0; i < WIDTH; i++) {
// Serial.print(level[i]);
val = level[i] * scale;
if (val > HEIGHT) val = HEIGHT;
if (val >= shown[i]) {
shown[i] = val;
}
if (val >= peaks[i]) {
peaks[i] = val;
}
// Serial.print(" ");
matrix.drawLine(i, 0, i, HEIGHT - 1, 0);
matrix.drawLine(i, HEIGHT - shown[i], i, HEIGHT, Wheel(180));
matrix.drawPixel(i, HEIGHT - shown[i], Wheel(20));
matrix.drawPixel(i, HEIGHT - peaks[i], Wheel(0));
}
}
if (dropTimer + levelDecay < millis()) {
for (int i = 0; i < WIDTH; i++) {
if (shown[i] > 0) {
shown[i] = shown[i] - 1;
}
dropTimer = millis();
}
}
if (peakDropTimer + peakDecay < millis()) {
for (int i = 0; i < WIDTH; i++) {
if (peaks[i] > 0) {
peaks[i] = peaks[i] - 1;
}
peakDropTimer = millis();
}
}
//Serial.print(" cpu:");
//Serial.println(AudioProcessorUsageMax());
}
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
return matrix.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170) {
WheelPos -= 85;
return matrix.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return matrix.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
void getFFTBins() {
float e, n;
int b, bands, bins, count = 0, d;
while (!Serial && (millis() <= 6000)); // Wait for Serial interface
bands = WIDTH; // Frequency bands; (Adjust to desired value)
bins = 512; // FFT bins; (Adjust to desired value)
e = FindE(bands, bins); // Find calculated E value
if (e) { // If a value was returned continue
Serial.printf("E = %4.4f\n", e); // Print calculated E value
for (b = 0; b < bands; b++) { // Test and print the bins from the calculated E
n = pow(e, b);
d = int(n + 0.5);
Serial.printf( "%4d ", count); // Print low bin
fftBins[b] = count;
count += d - 1;
Serial.printf( "%4d\n", count); // Print high bin
++count;
}
}
else
Serial.println("Error\n"); // Error, something happened
}
float FindE(int bands, int bins) {
float increment = 0.1, eTest, n;
int b, count, d;
for (eTest = 1; eTest < bins; eTest += increment) { // Find E through brute force calculations
count = 0;
for (b = 0; b < bands; b++) { // Calculate full log values
n = pow(eTest, b);
d = int(n + 0.5);
count += d;
}
if (count > bins) { // We calculated over our last bin
eTest -= increment; // Revert back to previous calculation increment
increment /= 10.0; // Get a finer detailed calculation & increment a decimal point lower
}
else if (count == bins) // We found the correct E
return eTest; // Return calculated E
if (increment < 0.0000001) // Ran out of calculations. Return previous E. Last bin will be lower than (bins-1)
return (eTest - increment);
}
return 0; // Return error 0
}