Watch our video on https://vimeo.com/169865743
Mugic is a magic ball that can react to music and other sound. It can recognize the frequency of each sound waves coming into the microphone, and change color to green to blue to red by low to mid to high pitches.
#include <avr/pgmspace.h>
#include <ffft.h>
#include <math.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#ifdef __AVR_ATmega32U4__
#define ADC_CHANNEL 7
#else
#define ADC_CHANNEL 0
#endif
int voltage;
int16_t Gcolor;
int16_t YColor;
int z;
int h;
float total;
unsigned long time;
uint16_t oldspec[FFT_N];
uint16_t dif[FFT_N];
uint16_t totaldif;
uint16_t averagedif;
uint16_t totalaveragedif;
uint16_t average;
uint16_t averageLow;
uint16_t averageMid;
uint16_t averageHigh;
uint16_t totalLow;
uint16_t totalMid;
uint16_t totalHigh;
uint16_t Low;
uint16_t Mid;
uint16_t High;
int brightness;
boolean record = false;
int16_t capture[FFT_N];
complex_t bfly_buff[FFT_N];
uint16_t spectrum[FFT_N/2];
uint16_t volume[FFT_N/2];
volatile byte samplePos = 0;
static const uint8_t PROGMEM
noise[64]={ 1,2,3,2,3,3,2,1,2,3,2,3,2,3,3,4,
2,1,2,1,3,2,3,2,1,2,3,1,2,3,4,4,
3,2,2,2,2,2,2,1,3,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,4 },
eq[64]={
255, 175,218,225,220,198,147, 99, 68, 47, 33, 22, 14, 8, 4, 2,
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, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, 6, NEO_GRB + NEO_KHZ800);
void setup() {
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// End of trinket special code
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(9, OUTPUT);
//pinMode(6, OUTPUT);
ADMUX = ADC_CHANNEL;
ADCSRA = _BV(ADEN) |
_BV(ADSC) |
_BV(ADATE) |
_BV(ADIE) |
_BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
ADCSRB = 0;
DIDR0 = 1 << ADC_CHANNEL;
TIMSK0 = 0;
strip.begin();
//firstColor(765);
strip.show(); // Initialize all pixels to 'off'
sei();
}
void loop() {
sampling();
setColor(YColor);
//Serial.println(YColor);
analogWrite(9, voltage);
}
void sampling() {
uint8_t i, x, L, *data, nBins, binNum, weighting, currentMax, currentMaxPo, currentMax2, currentMaxPo2, currentMax3, currentMaxPo3;
uint16_t minLvl, maxLvl;
int level, y, sum;
while(ADCSRA & _BV(ADIE));
fft_input(capture, bfly_buff);
samplePos = 0;
ADCSRA |= _BV(ADIE);
fft_execute(bfly_buff);
fft_output(bfly_buff, spectrum);
// Remove noise and apply EQ levels
for(x=0; x<FFT_N/2; x++) {
volume[x] = spectrum[x];
L = pgm_read_byte(&noise[x]);
spectrum[x] = (spectrum[x] <= L) ? 0 : // if (...) then S[] = 0; else,
(((spectrum[x] - L) * (256L - pgm_read_byte(&eq[x]))) >> 8); //256L means 256, >>8 = 256的倍数
}
for(int i = 0; i < 64; i++){
total += volume[i];
if(i <= 10) {
totalLow += volume[i];
}
else if (i <= 40) {
totalMid += volume[i];
}
else if (i <= 64) {
totalHigh += volume[i];
}
}
averageLow = totalLow / 10;
averageMid = totalMid / 30;
averageHigh = totalHigh / 24;
average = total / 64;
//Serial.println("A");
//Serial.println(average);
/*Serial.print(averageLow);
Serial.print(" ");
Serial.print(averageMid);
Serial.print(" ");
Serial.println(averageHigh);
*/
if(average > 2) {
record = true;
}
while(record) {
z++;
Low += averageLow;
Mid += averageMid;
High += averageHigh;
//Serial.println("A");
if(z >= 5){
YColor = WheelPos(Low, Mid, High);
Serial.print(Low);
Serial.print(" ");
Serial.print(Mid);
Serial.print(" ");
Serial.println(High);
h++;
record = false;
z = 0;
}
}
totalLow = 0;
totalMid = 0;
totalHigh = 0;
total = 0;
Low = 0;
Mid = 0;
High = 0;
for(int c; c < 64; c++) {
if(volume[c] > currentMax) {
currentMax = volume[c];
currentMaxPo = c;
voltage = currentMax;
}
//Serial.println(currentMax);
}
maping();
}
void maping() {
voltage = map(voltage, 0, 100, 400, 500);
}
ISR(ADC_vect) {
static const int16_t noiseThreshold = 4;
int16_t sample = ADC;
capture[samplePos] =
((sample > (512-noiseThreshold)) &&
(sample < (512+noiseThreshold))) ? 0 :
sample - 512;
if(++samplePos >= FFT_N) ADCSRA &= ~_BV(ADIE);
}
void fadeOut() {
//delay(1000000);
for(int j=brightness; j>=0; j -= 2) {
strip.setBrightness(j);
//
strip.show();
}
h = 0;
brightness = 0;
//
}
void firstColor(uint16_t color) {
uint16_t i, j;
for(j=0; j<254; j += 2) {
strip.setBrightness(j);
for(int i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(color));
}
//delay(0);
strip.show();
}
Gcolor = color;
//delay(10000);
}
void setColor(uint16_t color){
uint16_t j;
if(color > Gcolor)
for(uint16_t j=Gcolor; j < color; j++) {
for(int i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(j));
}
strip.show();
}
if(color < Gcolor) {
for(uint16_t j=Gcolor; j > color; j--) {
for(int i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(j));
}
strip.show();
}
}
Gcolor = color;
}
uint16_t WheelPos(uint16_t low, uint16_t mid, uint16_t high) {
uint16_t color;
int greenSpecs;
int lowColor = low - mid;
int midColor = mid - low;
if (lowColor > 20) {
greenSpecs = map(mid, 10, 100, 0, 255);
color = map(low, 30, 200, 255, 510);
}
else if (lowColor <= 20 || midColor > 0) {
greenSpecs = map(low, 10, 100, 0, 255);
color = map(mid, 0, 100, 510, 1040);
Serial.println(color);
return color - greenSpecs;
}
}
uint32_t Wheel(uint16_t WheelPos) {
//WheelPos = 255 - WheelPos;
if(WheelPos < 255) { // 0-255
return strip.Color(0, 255, WheelPos);
}
if(WheelPos < 510) { // 255-510 -> 0-255
WheelPos -= 255;
return strip.Color(0, 255-WheelPos, 255);
}
if(WheelPos < 765) { // 510-765 -> 0-255
WheelPos -= 510;
return strip.Color(WheelPos, 0, 255-WheelPos);
}
if(WheelPos < 1020) {
WheelPos -= 765; // 765-1020 -> 0-255
return strip.Color(255, 255-WheelPos, 0);
}
WheelPos -= 1020; // 765-1020 -> 0-255
return strip.Color(255-WheelPos, 0, 0);
}
No comments:
Post a Comment