├── LICENSE ├── README.md └── src └── LED_Visualizer.ino /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Devon Crawford 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Create a realtime LED audio waveform based on the pitch and volume with Arduino 3 | ### Watch the video 4 | The entire process was filmed here: https://youtu.be/lU1GVVU9gLU 5 | 6 | ## Requirements 7 | - Frequency to voltage converter such as Math Encounters Blog: http://mathscinotes.com/2014/03/a-simple-frequency-to-voltage-converter/ 8 | - WS2812B LED strip: https://goo.gl/YoFYP5 9 | - Arduino: https://goo.gl/Ah6GGG 10 | 11 | ## How it works 12 | 13 | Every 1 ms, the frequency(pitch) of the audio is read into the arduino, and the volume is read from the amplified audio signal. 14 | The pitch is then mapped to rgb colors, and the volume represents the brightness. The combination of these values give us unique rgb 15 | colors for a single LED. Since we have an array of LEDs we can shift all of them to the right before we update the first LED. 16 | This creates a "memory" effect to display a real time portion of the audio waveform. 17 | 18 | ## Note 19 | This code assumes you have a frequency to voltage converter, which operates between 1 - 3 volts during regular music frequencies (roughly 20 | 100 - 600hz). Take note to define the correct data pins if you try to build and use this code for your own builds. 21 | -------------------------------------------------------------------------------- /src/LED_Visualizer.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * LED Music Visualizer 3 | * by Devon Crawford 4 | * using the FastLED library: http://fastled.io/ 5 | * April 22, 2018 6 | * Watch the video: https://youtu.be/lU1GVVU9gLU 7 | */ 8 | #include "FastLED.h" 9 | 10 | #define NUM_LEDS 300 // How many leds in your strip? 11 | #define updateLEDS 8 // How many do you want to update every millisecond? 12 | #define COLOR_SHIFT 180000 // Time for colours to shift to a new spectrum (in ms) 13 | CRGB leds[NUM_LEDS]; // Define the array of leds 14 | 15 | // Define the digital I/O PINS.. 16 | #define DATA_PIN 6 // led data transfer 17 | #define PITCH_PIN 0 // pitch input from frequency to voltage converter 18 | #define BRIGHT_PIN 4 // brightness input from amplified audio signal 19 | 20 | // Don't touch these, internal color variation variables 21 | unsigned long setTime = COLOR_SHIFT; 22 | int shiftC = 0; 23 | int mulC = 2; 24 | 25 | // Define color structure for rgb 26 | struct color { 27 | int r; 28 | int g; 29 | int b; 30 | }; 31 | typedef struct color Color; 32 | 33 | void setup() { 34 | Serial.begin(9600); 35 | FastLED.addLeds(leds, NUM_LEDS); 36 | pinMode(A0, INPUT); 37 | pinMode(A4, INPUT); 38 | 39 | for(int i = 0; i < NUM_LEDS ; i++) { 40 | leds[i] = CRGB(0,0,0); 41 | } 42 | FastLED.show(); 43 | } 44 | 45 | void loop() { 46 | unsigned long time = millis(); 47 | 48 | // Shift the color spectrum by 200 on set intervals (setTime) 49 | if(time / (double)setTime >= 1) { 50 | setTime = time + COLOR_SHIFT; 51 | Serial.println(setTime); 52 | shiftC += 200; 53 | mulC++; 54 | if(shiftC >= 600) { 55 | shiftC = 0; 56 | } 57 | if(mulC > 3) { 58 | mulC = 2; 59 | } 60 | } 61 | 62 | // Shift all LEDs to the right by updateLEDS number each time 63 | for(int i = NUM_LEDS - 1; i >= updateLEDS; i--) { 64 | leds[i] = leds[i - updateLEDS]; 65 | } 66 | 67 | // Get the pitch and brightness to compute the new color 68 | int newPitch = (analogRead(PITCH_PIN)*2) + shiftC; 69 | Color nc = pitchConv(newPitch, analogRead(BRIGHT_PIN)); 70 | 71 | // Set the left most updateLEDs with the new color 72 | for(int i = 0; i < updateLEDS; i++) { 73 | leds[i] = CRGB(nc.r, nc.g, nc.b); 74 | } 75 | FastLED.show(); 76 | 77 | //printColor(nc); 78 | delay(1); 79 | } 80 | 81 | /** 82 | * Converts the analog brightness reading into a percentage 83 | * 100% brightness is 614.. about 3 volts based on frequency to voltage converter circuit 84 | * The resulting percentage can simply be multiplied on the rgb values when setting our colors, 85 | * for example black is (0,0,0) so when volume is off we get 0v and all colors are black (leds are off) 86 | */ 87 | double convBrightness(int b) { 88 | double c = b / 614.0000; 89 | if( c < 0.2 ) { 90 | c = 0; 91 | } 92 | else if(c > 1) { 93 | c = 1.00; 94 | } 95 | return c; 96 | } 97 | 98 | /** 99 | * Creates a new color from pitch and brightness readings 100 | * int p analogRead(pitch) representing the voltage between 0 and 5 volts 101 | * double b analogRead(brightness) representing volume of music for LED brightness 102 | * returns Color structure with rgb values, which appear synced to the music 103 | */ 104 | Color pitchConv(int p, int b) { 105 | Color c; 106 | double bright = convBrightness(b); 107 | 108 | if(p < 40) { 109 | setColor(&c, 255, 0, 0); 110 | } 111 | else if(p >= 40 && p <= 77) { 112 | int b = (p - 40) * (255/37.0000); 113 | setColor(&c, 255, 0, b); 114 | } 115 | else if(p > 77 && p <= 205) { 116 | int r = 255 - ((p - 78) * 2); 117 | setColor(&c, r, 0, 255); 118 | } 119 | else if(p >= 206 && p <= 238) { 120 | int g = (p - 206) * (255/32.0000); 121 | setColor(&c, 0, g, 255); 122 | } 123 | else if(p <= 239 && p <= 250) { 124 | int r = (p - 239) * (255/11.0000); 125 | setColor(&c, r, 255, 255); 126 | } 127 | else if(p >= 251 && p <= 270) { 128 | setColor(&c, 255, 255, 255); 129 | } 130 | else if(p >= 271 && p <= 398) { 131 | int rb = 255-((p-271)*2); 132 | setColor(&c, rb, 255, rb); 133 | } 134 | else if(p >= 398 && p <= 653) { 135 | setColor(&c, 0, 255-(p-398), (p-398)); 136 | } 137 | else { 138 | setColor(&c, 255, 0, 0); 139 | } 140 | setColor(&c, c.r * bright, c.g * bright, c.b * bright); 141 | return c; 142 | } 143 | 144 | void setColor(Color *c, int r, int g, int b) { 145 | c->r = r; 146 | c->g = g; 147 | c->b = b; 148 | } 149 | 150 | // Prints color structure data 151 | void printColor(Color c) { 152 | Serial.print("( "); 153 | Serial.print(c.r); 154 | Serial.print(", "); 155 | Serial.print(c.g); 156 | Serial.print(", "); 157 | Serial.print(c.b); 158 | Serial.println(" )"); 159 | } 160 | 161 | 162 | --------------------------------------------------------------------------------