Using an Arduino controller to display sound

Home / Cool Gear / Using an Arduino controller to display sound

I have been experimenting with Arduinos for sound visualization. One of my favorite sketches is by Andrew Tuline whose FastLED code makes frequency display possible. FHT, or Fast Hartley Transform, analyzes an incoming audio signal, does a whole boatload of math, then spits out data, to a string of Neopixels in this case. Here’s a quickie video where the synthesizer is modulating a sinewave up and down along with the resulting action on the LED strip.

The schematic for the whole mess is pretty simple. A tiny microphone for $7.00 off Ebay, senses the sound and sends it to the Arduino, which spits out a serial stream which goes to the Neopixels.
The code is here:

/* 09 17 15 works great.
 *  Fast Hartley Transform

By: Andrew Tuline
Date: Oct, 2014

This is an implementation of the FHT library with FastLED
The FHT library is available at
The example I started off with was:

Note: If you are using a microphone powered by the 3.3V signal, such as the Sparkfun MEMS microphone, then connect 3.3V to the AREF pin.
Also make sure you uncomment analogReference(EXTERNAL);  in Setup().

Test with:

#define qsubd(x, b) ((x>b)?wavebright:0)                     // A digital unsigned subtraction macro. if result <0, then => 0. Otherwise, take on fixed value.
#define qsuba(x, b) ((x>b)?x-b:0)                            // Unsigned subtraction macro. if result <0, then => 0.

#define wavebright 128                                        // qsubd result will be this value if subtraction is >0.

#include "FastLED.h"                                          // FastLED library. Preferably the latest copy of FastLED 2.1.

#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."

// Fixed definitions cannot change on the fly.
#define LED_DT 12                                             // Data pin to connect to the strip.
#define LED_CK 11                                             // Clock pin for APA102 or WS2801
#define COLOR_ORDER GRB                                       // It's GRB for WS2812
#define LED_TYPE WS2812B                                       // What kind of strip are you using (APA102, WS2801 or WS2812B)
#define NUM_LEDS 29                                        // Number of LED's.

// Initialize changeable global variables.
uint8_t max_bright = 255;                                     // Overall brightness definition. It can be changed on the fly.

struct CRGB leds[NUM_LEDS];                                   // Initialize our LED array.

#define LOG_OUT 1

#define FHT_N 256                                             // Set to 256 point fht.
#define inputPin A5
//#define potPin A4

#include <FHT.h>                                              // FHT library

uint8_t hueinc = 0;                                               // A hue increment value to make it rotate a bit.
uint8_t micmult = 25;
uint8_t fadetime = 900;
uint8_t noiseval = 25;                                        // Increase this to reduce sensitivity. 30 seems best for quiet

void setup() {
  analogReference(EXTERNAL);                                  // Connect 3.3V to AREF pin for any microphones using 3.3V
  Serial.begin(9600);                                        // use the serial port

  set_max_power_in_volts_and_milliamps(5, 500);               // FastLED Power management set at 5V, 500mA.

void loop() {
//    noiseval = map(analogRead(potPin), 0, 1023, 16, 48);          // Adjust sensitivity of cutoff.

  Serial.println(LEDS.getFPS(),DEC);          // Display frames per second on the serial monitor.
      Serial.println(" ");          // Display frames per second on the serial monitor.
   Serial.println(analogRead(inputPin));       // print as an ASCII-encoded decimal         */


void fhtsound() {
 // hueinc++;                                                   // A cute little hue incrementer.
  GetFHT();                                                   // Let's take FHT_N samples and crunch 'em.

  for (int i= 0; i < NUM_LEDS; i++) {                         // Run through the LED array.
    int tmp = qsuba(fht_log_out[2*i+2], noiseval);           // Get the sample and subtract the 'quiet' normalized values, but don't go < 0.
    if (tmp > (leds[i].r + leds[i].g + leds[i].b)/2)            // Refresh an LED only when the intensity is low
        leds[i] = CHSV((i*4)+tmp*micmult,255, tmp*micmult);  // Note how we really cranked up the tmp value to get BRIGHT LED's. Also increment the hue for fun.
    leds[i].nscale8(fadetime);                                     // Let's fade the whole thing over time as well.
} // fhtsound()

void GetFHT() {
  for (int i = 0 ; i < FHT_N ; i++) fht_input[i] = analogRead(inputPin);

  fht_window();                                               // Window the data for better frequency response.
  fht_reorder();                                              // Reorder the data before doing the fht.
  fht_run();                                                  // Process the data in the fht.
} // GetFHT()

That’s all there is to it. The serious number crunching happens with the “fht” libraries. You can copy/paste the code into your Arduino IDE, and it’ll run just fine, but you’ll need to go get the FAST LED library first.

Since I repeatedly would connect LED strips to the controller so often, but mostly in the same configuration, I decided to solder a 9-pin connector to the LEDs and and use another 9-pin to connect them to the Arduino. Then I put the whole thing into a lasercut box.
Here you can see that it all barely fits inside, but the mic is mounted, the big capacitor and a resistor soldered to the internal 9-pin.
If you’d like to cut a box on your laser cutter, download this pdf and import it into Inkscape or AI.



Related Posts
Recent Posts
August 2020
Don’t forget to check out the LINKS
I have put together all my favorite synthesizer links for your time-slaughtering pleasure. Go click it!