Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Sound Reactive demoreel100 (no longer 100)
- Date: Jan, 2022
- Originally by: Mark Kriegsman
- Modification by: Andrew Tuline
- Running on an Arduino Nano, this sketch demonstrates the ability to add sound reactivity to non-reactive FastLED animations without modifying their code.
- It does so by blending the results of the existing (and unmodified animation) with the results of the sound reactive code prior to calling FastLED.show().
- The concept here is to take away brightness instead of adding it.
- This version has been developed around an Arduino Nano (old bootloader), with a MAX9814 microphone @40db gain.
- I've connected the AREF pin to 3.3V and connected VCC of the microphone to 3.3V as well.
- */
- #include <FastLED.h>
- // --------- Sound --------------
- #define MIC_PIN A5 // Analog port for microphone
- uint8_t squelch = 20; // Anything below this is background noise, so we'll make it '0'.
- int sample; // Current sample.
- float sampleAvg = 0; // Smoothed Average.
- float micLev = 0; // Used to convert returned value to have '0' as minimum.
- int sampleAgc; // Automatic Gain Controlled value.
- int multAgc; // Multiplier for the AGC.
- uint8_t targetAgc = 60; // This is our setPoint at 20% of max for the adjusted output.
- // -------- FastLED --------------
- #define LED_DT 12
- #define COLOR_ORDER GRB
- #define LED_TYPE WS2812
- #define NUM_LEDS 64
- struct CRGB leds[NUM_LEDS];
- uint8_t vals[NUM_LEDS]; // Used for sound reactivity blending.
- void setup() {
- Serial.begin(115200);
- analogReference(EXTERNAL); // Nano or other 5V AVR when using a 3.3V microphone. Also connect AREF pin to 3.3V.
- LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS);
- FastLED.setBrightness(128);
- } // setup()
- // List of patterns to cycle through. Each is defined as a separate function below.
- typedef void (*SimplePatternList[])();
- SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
- uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
- uint8_t gHue = 0; // rotating "base color" used by many of the patterns
- void loop() {
- getSample(); // Sample the microphone.
- agcAvg(); // Calculated the AGC average.
- gPatterns[gCurrentPatternNumber]();
- EVERY_N_MILLISECONDS( 20 ) {
- gHue++; // slowly cycle the "base color" through the rainbow
- }
- EVERY_N_SECONDS( 10 ) {
- nextPattern(); // change patterns periodically
- }
- soundAdjust(); // Insert sound reactive modfications before displaying.
- FastLED.show(); // Display.
- } // loop()
- void soundAdjust() {
- vals[millis() % NUM_LEDS] = sampleAgc; // This requires a high refresh rate.
- for (int i = 0; i < NUM_LEDS; i++) { // Modifying the array prior to FastLED.show().
- leds[i] = blend(CRGB::Black, leds[i], vals[i]); // vals[i] is a uint8_t, which determines the blending between the two colours for the resultant value.
- }
- } // soundAdjust()
- #define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
- void nextPattern() {
- gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
- }
- void rainbow()
- {
- // FastLED's built-in rainbow generator
- fill_rainbow( leds, NUM_LEDS, gHue, 7);
- }
- void rainbowWithGlitter()
- {
- // built-in FastLED rainbow, plus some random sparkly glitter
- rainbow();
- addGlitter(80);
- }
- void addGlitter( fract8 chanceOfGlitter)
- {
- if ( random8() < chanceOfGlitter) {
- leds[ random16(NUM_LEDS) ] += CRGB::White;
- }
- }
- void confetti()
- {
- // random colored speckles that blink in and fade smoothly
- fadeToBlackBy( leds, NUM_LEDS, 10);
- int pos = random16(NUM_LEDS);
- leds[pos] += CHSV( gHue + random8(64), 200, 255);
- }
- void sinelon()
- {
- // a colored dot sweeping back and forth, with fading trails
- fadeToBlackBy( leds, NUM_LEDS, 20);
- int pos = beatsin16( 13, 0, NUM_LEDS - 1 );
- leds[pos] += CHSV( gHue, 255, 192);
- }
- void bpm()
- {
- // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
- uint8_t BeatsPerMinute = 62;
- CRGBPalette16 palette = PartyColors_p;
- uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
- for ( int i = 0; i < NUM_LEDS; i++) { //9948
- leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
- }
- }
- void juggle() {
- // eight colored dots, weaving in and out of sync with each other
- fadeToBlackBy( leds, NUM_LEDS, 20);
- uint8_t dothue = 0;
- for ( int i = 0; i < 8; i++) {
- leds[beatsin16( i + 7, 0, NUM_LEDS - 1 )] |= CHSV(dothue, 200, 255);
- dothue += 32;
- }
- }
- void getSample() {
- int16_t micIn; // Current sample starts with negative values and large values, which is why it's 16 bit signed.
- micIn = analogRead(MIC_PIN); // Poor man's analog read.
- micLev = ((micLev * 31) + micIn) / 32; // Use exponential smoothing over the last 32 samples for automatic centering.
- micIn -= micLev; // Let's center it to 0. This allows us to use ANY microphone without having to worry about offset calculations.
- micIn = abs(micIn); // And get the absolute value of each sample.
- sample = (micIn <= squelch) ? 0 : (sample + micIn) / 2; // Let's filter out the background noise with a ternary operator and more exponential smoothing.
- sampleAvg = ((sampleAvg * 31) + sample) / 32; // Smooth it out over the last 32 samples. This is a non AGC average.
- } // getSample()
- void agcAvg() { // A simple averaging multiplier to automatically adjust sound sensitivity.
- multAgc = (sampleAvg < 1) ? targetAgc : targetAgc / sampleAvg; // Make the multiplier so that sampleAvg * multiplier = setpoint
- sampleAgc = sample * multAgc;
- if (sampleAgc > 255) sampleAgc = 255;
- } // agcAvg()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement