/*
// Combining the PJRC audio library http://www.pjrc.com/teensy/td_libs_Audio.html and
fastLED libraries https://github.com/FastLED/FastLED
as well as some code from Owen.
*/
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <FastLED.h>
#define LED_COUNT 393
#define BIN_LENGTH 7 // 8 averages for frequency range
#define DATA_PIN 2
#define CLK_PIN 4
//-------------- Standard audio stuff ----------------------------------------------
const int myInput = AUDIO_INPUT_LINEIN;
AudioInputI2S audioInput; // audio shield: mic or line-in
AudioAnalyzeFFT256 myFFT(20); //Number of FFT reads per analysis?
AudioOutputI2S audioOutput; // audio shield: headphones & line-out
AudioConnection c1(audioInput, 0, audioOutput, 0);
AudioConnection c2(audioInput, 0, myFFT, 0);
AudioConnection c3(audioInput, 1, audioOutput, 1);
AudioControlSGTL5000 audioShield;
//--------------LED array structuring------------------------------------------------
struct CRGB leds[LED_COUNT];
int ledsX[LED_COUNT][3]; //-ARRAY FOR COPYING WHATS IN THE LED STRIP CURRENTLY (FOR CELL-AUTOMATA, MARCH, ETC)
//-------------Funkboxing attributes-------------------------------------------------
int BOTTOM_INDEX = 0;
int TOP_INDEX = int(LED_COUNT/2);
int EVENODD = LED_COUNT%2;
//---LED FX VARS
int idex = 0; //-LED INDEX (0 to LED_COUNT-1
int ihue = 0; //-HUE (0-255)
int ibright = 0; //-BRIGHTNESS (0-255)
int isat = 0; //-SATURATION (0-255)
int bouncedirection = 0; //-SWITCH FOR COLOR BOUNCE (0-1)
float tcount = 0.0; //-INC VAR FOR SIN LOOPS
int lcount = 0; //-ANOTHER COUNTING VAR
int thisdelay = 20; //-FX LOOPS DELAY VAR
int thisstep = 10; //-FX LOOPS DELAY VAR
int thishue = 0; //-FX LOOPS DELAY VAR
int thissat = 255; //-FX LOOPS DELAY VAR
//--------------fcknaround attributes-------------------------------------
int hue;
int hueCounter;
int modeZero;
int modeOne;
int hueCalc;
//--------------Owens Audio attributes--------------------------------------
double MAX_SIZE = 200.0; // Max range of averaged freq bands
int max_bright = 255;
int count = 0; // No of fft rounds analysed yeah?
//int c = 0; //not needed?
//int audio = 0; //not needed?
int iterations = 10000;
const int half = 1;
int ampRounding = 64; // Rounds the 8 freq bands to 0 - 64
unsigned long time;
IntervalTimer smpltimer;
/* -------------------------------------------- Effects ------------------------------------------------
/*------------------------------------#
#----- FASTSPI2 EFFECTS EXAMPLES -----#
#-------------- v0.51 ----------------#
#------------ teldredge --------------#
#-------- www.funkboxing.com ---------#
#------ teldredge1979@gmail.com ------#
#-------------------------------------#
*/
void ems_lightsONE() { //Multiple Cylon's
//Two points (antiPodal) getting dimmer on either side spinning around.
idex++;
if (idex >= LED_COUNT) {idex = 0;}
int idexR = idex;
int idexB = antipodal_index(idexR);
int iL1 = adjacent_cw(idexR);
int iL2 = adjacent_cw(iL1);
int iL3 = adjacent_cw(iL2);
int iL4 = adjacent_cw(iL3);
int iL5 = adjacent_cw(iL4);
int iR1 = adjacent_ccw(idexR);
int iR2 = adjacent_ccw(iR1);
int iR3 = adjacent_ccw(iR2);
int iR4 = adjacent_ccw(iR3);
int iR5 = adjacent_ccw(iR4);
int iL1AP = adjacent_cw(idexB);
int iL2AP = adjacent_cw(iL1AP);
int iL3AP = adjacent_cw(iL2AP);
int iL4AP = adjacent_cw(iL3AP);
int iL5AP = adjacent_cw(iL4AP);
int iR1AP = adjacent_ccw(idexB);
int iR2AP = adjacent_ccw(iR1AP);
int iR3AP = adjacent_ccw(iR2AP);
int iR4AP = adjacent_ccw(iR3AP);
int iR5AP = adjacent_ccw(iR4AP);
for(int i = 0; i < LED_COUNT; i++ ) {
if (i == idexR) {leds[i] = CHSV(hue, thissat, 255);}
else if (i == idexB) {leds[i] = CHSV(hue, thissat, 255);}
else if (i == iL1) {leds[i] = CHSV(hue, thissat, 150);}
else if (i == iL2) {leds[i] = CHSV(hue, thissat, 110);}
else if (i == iL3) {leds[i] = CHSV(hue, thissat, 80);}
else if (i == iL4) {leds[i] = CHSV(hue, thissat, 50);}
else if (i == iL5) {leds[i] = CHSV(hue, thissat, 20);}
else if (i == iR1) {leds[i] = CHSV(hue, thissat, 150);}
else if (i == iR2) {leds[i] = CHSV(hue, thissat, 110);}
else if (i == iR3) {leds[i] = CHSV(hue, thissat, 80);}
else if (i == iR4) {leds[i] = CHSV(hue, thissat, 50);}
else if (i == iR5) {leds[i] = CHSV(hue, thissat, 20);}
else if (i == iL1AP) {leds[i] = CHSV(hue, thissat, 150);}
else if (i == iL2AP) {leds[i] = CHSV(hue, thissat, 110);}
else if (i == iL3AP) {leds[i] = CHSV(hue, thissat, 80);}
else if (i == iL4AP) {leds[i] = CHSV(hue, thissat, 50);}
else if (i == iL5AP) {leds[i] = CHSV(hue, thissat, 20);}
else if (i == iR1AP) {leds[i] = CHSV(hue, thissat, 150);}
else if (i == iR2AP) {leds[i] = CHSV(hue, thissat, 110);}
else if (i == iR3AP) {leds[i] = CHSV(hue, thissat, 80);}
else if (i == iR4AP) {leds[i] = CHSV(hue, thissat, 50);}
else if (i == iR5AP) {leds[i] = CHSV(hue, thissat, 20);}
else {leds[i] = CHSV(0, 0, 0);}
}
LEDS.show();
}
//----------------------------------------------------------------------------------
void color_bounceFADE() { //Single Cylon Bounce
if (bouncedirection == 0) {
idex = idex + 1;
if (idex == LED_COUNT) {
bouncedirection = 1;
idex = idex - 1;
}
}
if (bouncedirection == 1) {
idex = idex - 1;
if (idex == 0) {
bouncedirection = 0;
}
}
int iL1 = adjacent_cw(idex);
int iL2 = adjacent_cw(iL1);
int iL3 = adjacent_cw(iL2);
int iL4 = adjacent_cw(iL3);
int iL5 = adjacent_cw(iL4);
// Arrays be easier yeah?
int iR1 = adjacent_ccw(idex);
int iR2 = adjacent_ccw(iR1);
int iR3 = adjacent_ccw(iR2);
int iR4 = adjacent_ccw(iR3);
int iR5 = adjacent_ccw(iR4);
for(int i = 0; i < LED_COUNT; i++ ) {
if (i == idex) {leds[i] = CHSV(hue, thissat, 255);}
else if (i == iL1) {leds[i] = CHSV(hue, thissat, 150);}
else if (i == iL2) {leds[i] = CHSV(hue, thissat, 110);}
else if (i == iL3) {leds[i] = CHSV(hue, thissat, 80);}
else if (i == iL4) {leds[i] = CHSV(hue, thissat, 50);}
else if (i == iL5) {leds[i] = CHSV(hue, thissat, 20);}
else if (i == iR1) {leds[i] = CHSV(hue, thissat, 150);}
else if (i == iR2) {leds[i] = CHSV(hue, thissat, 110);}
else if (i == iR3) {leds[i] = CHSV(hue, thissat, 80);}
else if (i == iR4) {leds[i] = CHSV(hue, thissat, 50);}
else if (i == iR5) {leds[i] = CHSV(hue, thissat, 20);}
else {leds[i] = CHSV(0, 0, 0);}
}
LEDS.show();
// delay(thisdelay);
}
//-----------------Funkboxing--- UTILITY FXNS --------------------------------------
//
//
//---SET THE COLOR OF A SINGLE RGB LED
void set_color_led(int adex, int cred, int cgrn, int cblu) {
leds[adex].setRGB( cred, cgrn, cblu);
}
//---FIND INDEX OF HORIZONAL OPPOSITE LED
int horizontal_index(int i) {
//-ONLY WORKS WITH INDEX < TOPINDEX
if (i == BOTTOM_INDEX) {return BOTTOM_INDEX;}
if (i == TOP_INDEX && EVENODD == 1) {return TOP_INDEX + 1;}
if (i == TOP_INDEX && EVENODD == 0) {return TOP_INDEX;}
return LED_COUNT - i;
}
//---FIND INDEX OF ANTIPODAL OPPOSITE LED
int antipodal_index(int i) {
int iN = i + TOP_INDEX;
if (i >= TOP_INDEX) {iN = ( i + TOP_INDEX ) % LED_COUNT; }
return iN;
}
//---FIND ADJACENT INDEX CLOCKWISE
int adjacent_cw(int i) {
int r;
if (i < LED_COUNT - 1) {r = i + 1;}
else {r = 0;}
return r;
}
//---FIND ADJACENT INDEX COUNTER-CLOCKWISE
int adjacent_ccw(int i) {
int r;
if (i > 0) {r = i - 1;}
else {r = LED_COUNT - 1;}
return r;
}
//copys led array...
void copy_led_array(){
for(int i = 0; i < LED_COUNT; i++ ) {
ledsX[i][0] = leds[i].r;
ledsX[i][1] = leds[i].g;
ledsX[i][2] = leds[i].b;
}
}
//--------------------Owens Utility Functions------------------------------
//
//Creates an upper bound for the amplitute and scales bands differently
// multiplies rest by four.
int scale_doof(double val, int f_band){
if(f_band > 1) { //keeps bands 0, 1 as they are (Bass dominates)
val = val*4;
}
if (val > MAX_SIZE) { //Scales value to a maximum
val = MAX_SIZE;
}
return (val/MAX_SIZE)*ampRounding; //Rounds values to 64
}
//Turns em all off
void zero_leds(void) {
int i;
for(i = 0; i < LED_COUNT; i++) {
leds[i].setRGB(0,0,0);
}
}
//----Work in progress. converts scaled freq bands to hue modifiers
//
int set_doof(int scale, int mode, int f_band) {
if (mode == 0) {
Serial.print("modeZero: ");
Serial.println(modeZero);
modeZero+= scale;
}
else if (mode == 1) {
modeOne+= scale;
// Serial.print("modeOne: ");
// Serial.println(modeOne);
}
/*DEBUGGGG
Serial.print("-------");
Serial.print("Scale: ");
Serial.println(scale);
Serial.println("-------");
Serial.print("mode: ");
Serial.println(mode);
Serial.println("-------");
Serial.print("f_band: ");
Serial.println(f_band);
Serial.println("-------");
}
*///
/* ------------------ Hue Fader ----------------
if (hue > 54)
{hueCounter = 1;}
if (hue < 10)
{hueCounter = 0;}
if(hueCounter == 0)
{hue++;}
if(hueCounter ==1)
{hue--;}
---------------------------------------------------*/
}
//--------------------------
//Main function. Uses above to convert to hue modifiers and then displays pretty lights
//--------------------------
void update_audio(double fft[]) {
int i, j, scaled;
int mode = 0;
for(i = 0; i < BIN_LENGTH; i++) {
scaled = scale_doof(fft[i], i);
if(i > 3){
mode = 1;
}
set_doof(scaled, mode, i);
}
count++;
hue = hueCalc;
// LEDS.show();
// zero_leds();
}
void setup() {
//--Audio Setup -----
AudioMemory(12);
audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(1.5);
Serial.begin(115200);
//--Timer Setup ------
smpltimer.begin(smpltimerisr, 1000000); //seconds = Value/1000000
//--LED Setup ----------
LEDS.setBrightness(max_bright);
LEDS.addLeds<NEOPIXEL,DATA_PIN>(leds, LED_COUNT); //Change to multistrip style.
}
void loop() {
if (myFFT.available()) {
// each time new FFT data is available
// print it all to the Arduino Serial Monitor
Serial.println(count);
int i, sum, avCounter, total;
sum, avCounter, total = 0;
double averages[BIN_LENGTH]; // array of 8 freq bands
int divider = 8;
Serial.print("FFT: ");
for (i=0; i<64; i++) { // take the first 64 of 128 frequency bins and average 8 bins to get the 8 different frequency values
total+= myFFT.output[i];
Serial.print(myFFT.output[i]);
Serial.print(" ");
if(i % divider == 0){
averages[avCounter] = total/divider;
total = 0;
avCounter++;
}
}
update_audio(averages);
// Serial.print("Zero:Final ");
// Serial.println(modeZero);
hueCalc = modeZero - modeOne;
// Serial.print("hueCalc: ");
// Serial.println(hueCalc);
}
ems_lightsONE();
//Resets
modeZero = 0;
modeOne = 0;
}
void smpltimerisr(void){
Serial.print("Count: ");
Serial.println(count);
count = 0;
}