Music Visualizer


It'll have music. It'll have lights. It'll be great.

You are viewing an older revision! See the latest version

music visualizer

Team Members

Section A - Joo Won Lee

Section B - Shlok Patel

Description

Schematic

https://os.mbed.com/media/uploads/spatel465/circuit-3-.png

Parts Needed

  • One Mbed LPC1768

200

  • Five 8-LED WS2812b WRGB LED Strips

200

  • Sparkfun MicroSD Breakout Board

200

  • Adafruit SPW 2430 MEMS Microphone

200

  • Adafruit Bluefruit LE UART Friend

200

  • Sparkfun TPA2005D1 Class D Audio Amp

200

  • PCB Mount Speaker

200

  • DC Barrel Jack

200

  • 5V/2A AC to DC Power Adapter

200

  • 330Ω Resistor (Orange - Orange - Brown - Gold)

https://os.mbed.com/media/uploads/spatel465/resi.jpg

  • Smartphone with Adafruit Bluefruit Connect App

200

  • (Optional) 10k Potentiometer

200

Wiring

WS2812b WRGB LED Strips

These LED Strips are chained together, with the output end of one strip connected to the input side of the next strip. Additionally, a 330Ω Resistor is placed in series between mbed p21 and LED strip DIN to prevent any issues from voltage spikes.

mbedLED Strips
GNDGND
P21DIN
VOUT (3.3v)VCC
GNDGND

MicroSD Breakout

mbedMicroSD Breakout
p8CS
p5DI
VOUT (3.3v)VCC
p7SCK
GNDGND
p6DO
CD

MEMS Microphone

mbedMEMS10uf decoupling capacitor
GNDGND-
VU (5v)Vin+
p16DC

Adafruit BLE Friend

mbedAdafruit BLEDC Barrel Jack
GNDGND-
VIN (3.3-16V)+
ncRTS
GNDCTS
p27 (Serial RX)TXO
p28 (Serial TX)RXI

Class D Audio Amp + Speaker

mbedTPA2005D1DC Barrel JackSpeaker
GNDPWR -, IN --
PWR ++
p18IN +
OUT ++
OUT --
p29S

Demo Setup

https://os.mbed.com/media/uploads/spatel465/mbed_setup.jpg

Code

main.cpp

#include "mbed.h"
#include "PinDetect.h"
#include "NeoStrip.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include "rtos.h"
#include <string>
#include <vector>

# define MAX_FILE 30

#define N 40
NeoStrip strip(p21, N);

//BusOut myleds(LED1,LED2,LED3,LED4);
DigitalOut myled(LED1);

DigitalIn b2(p29, PullUp);
Serial pc(USBTX, USBRX);
SDFileSystem sd(p5, p6, p7, p8, "sd");
Ticker sampletick;
AnalogOut speaker(p18);                  // Speaker (pin)
wave_player waver(&speaker);
Serial bt(p28, p27);      // Bluetooth
DigitalOut mute(p29);          // mute pin (low for shutdown)

PwmOut spk(p24);

Thread thread1;
Thread thread2;
Thread thread3;
Mutex sd_mtx;
volatile int src = 0;  // 0 for Mic, 1 for SD card

vector<string> filenames;               // list of files in sd card
volatile int cur_song = 1;

void read_file_names(char *dir) {
    DIR *dp;
    struct dirent *dirp;
    dp = opendir(dir);
    while ((dirp = readdir(dp)) != NULL) {
        filenames.push_back(string(dirp->d_name));
    }
    closedir(dp);
}

class microphone
{
public :
    microphone(PinName pin);
    float read();
    operator float ();
private :
    AnalogIn _pin;
};
microphone::microphone (PinName pin):
    _pin(pin)
{
}
float microphone::read()
{
    return _pin.read();
}
inline microphone::operator float ()
{
    return _pin.read();
}
 
microphone mymicrophone(p16);

uint8_t r = (uint8_t)0;
uint8_t g = (uint8_t)128;
uint8_t b = (uint8_t)0;

int red, green, blue;
 
// fancy function to make rainbow colors on LEDs
int hueToRGB(float h)
{
    float r, g, b;
    if (h > 360)
        h -= 360;
    if (h < 0)
        h += 360;
    int i = (int)(h / 60.0);
    float f = (h / 60.0) - i;
    float q = 1 - f;
    
    switch (i % 6)
    {
        case 0: r = 1; g = f; b = 0; break;
        case 1: r = q; g = 1; b = 0; break;
        case 2: r = 0; g = 1; b = f; break;
        case 3: r = 0; g = q; b = 1; break;
        case 4: r = f; g = 0; b = 1; break;
        case 5: r = 1; g = 0; b = q; break;
        default: r = 0; g = 0; b = 0; break;
    }
    
    // scale to integers and return the packed value
    uint8_t R = (uint8_t)(r * 255);
    uint8_t G = (uint8_t)(g * 255);
    uint8_t B = (uint8_t)(b * 255);

    return (R << 16) | (G << 8) | B;
}

// convert float values to LED otuput for soundtest array
void float2LED(float value){
    float fnumLED = abs((value - 0.5)/3.3)*100; // can mess with this scaling for better LED output
    int numLED = (int)fnumLED;
    if (numLED > 8) numLED = 8;
    
    static float dh = 360.0 / 5;
    static float x = 0;
    
    for(int i = 0; i < numLED; i++){
        int c = hueToRGB((dh * i) - x);
        strip.setPixel(i, c);
        strip.setPixel(i + 8, c);
        strip.setPixel(i + 16, c);
        strip.setPixel(i + 24, c);
        strip.setPixel(i + 32, c);
        }
    for(int i = numLED; i < 8; i++){
        strip.setPixel(i, 0x000000);
        strip.setPixel(i + 8, 0x000000);
        strip.setPixel(i + 16, 0x000000);
        strip.setPixel(i + 24, 0x000000);
        strip.setPixel(i + 32, 0x000000);
        
        // old setup for 5 rows of 8 LEDs
        //strip.setPixel(i + i * 7, 0x000000);
//        strip.setPixel(i + 1 + i * 7, 0x000000);
//        strip.setPixel(i + 2 + i * 7, 0x000000);
//        strip.setPixel(i + 3 + i * 7, 0x000000);
//        strip.setPixel(i + 4 + i * 7, 0x000000);
//        strip.setPixel(i + 5 + i * 7, 0x000000);
//        strip.setPixel(i + 6 + i * 7, 0x000000);
//        strip.setPixel(i + 7 + i * 7, 0x000000);
        }
    x += 1;
    if (x > 360)
        x = 0;
}

// same thing but for the mic
void mic2LED(int mic){
    static float dh = 360.0 / 5;
    static float x = 0;
    
    int numLED = 0;
    if(mic == 0) numLED = 0;
    else if(mic == 1) numLED = 1;
    else if(mic == 2) numLED = 2;
    else if(mic == 3) numLED = 3;
    else if(mic == 4) numLED = 4;
    else numLED = 5;
    
    for(int i = 0; i < numLED; i++){
        int c = hueToRGB((dh * i) - x);
        strip.setPixel(i, c);
        strip.setPixel(i + 8, c);
        strip.setPixel(i + 16, c);
        strip.setPixel(i + 24, c);
        strip.setPixel(i + 32, c);
        }
    for(int i = numLED; i < 8; i++){
        strip.setPixel(i, 0x000000);
        strip.setPixel(i + 8, 0x000000);
        strip.setPixel(i + 16, 0x000000);
        strip.setPixel(i + 24, 0x000000);
        strip.setPixel(i + 32, 0x000000);
        }
    x += 1;
    if (x > 360)
        x = 0; 
}

 
void sound_thread() {
    FILE *wave_file;
    printf("\n\n\nHello, wave world!\n");
    string songstr = "/sd/songs/" + filenames[cur_song];
    printf("%s", songstr.c_str());
    wave_file=fopen(songstr.c_str(),"r");
    printf("file opened\n");
    waver.play(wave_file);
    fclose(wave_file);
    Thread::yield();
}
    

    
unsigned short max_range = 0xFFFF;
// function that calls above functions
void patternSound(){
    //for(int i = 0; i < 60; i++){
        float sample;
        float average = 0.67/3.3;//initial DC bias level
        
        int buffer[20];
        
        while(1){
            if (src) {
            // this part works for DAC PCM output //
            float test = (float)waver.dac_data/max_range;
            pc.printf("--%f", abs((test - 0.5)/3.3));
            float2LED(test);
            strip.write();
            }
            //------------------------------------//
            else {
            //microphone setup //
            int centervalue;
            for(int i = 0; i < 20; i++){
                sample = mymicrophone;
                //subtract 0.67V DC bias - but it varies quite a bit after loud or long sounds
                average = 0.9999*average + 0.0001*sample;//try to slowly auto adjust the DC bias level
                speaker = 0.5 +((sample - average)*33.0);//scale up to 0.0 to 1.0 for speaker output
                
                int micvalue = int(abs((sample - average)*300.0));
                //pc.printf("-%d-", micvalue); //scale to around 15 for LEDs
                
                if(i == 1){
                    centervalue = micvalue;
                }
                buffer[i] = micvalue;
                if(i > 10){
                    if(micvalue == buffer[1] && micvalue == buffer[2] && micvalue == buffer[3] &&
                        micvalue == buffer[4] && micvalue == buffer[5] && micvalue == buffer[6] && 
                        micvalue == buffer[7] && micvalue == buffer[8] && micvalue == buffer[9]){
                              centervalue = buffer[1];
                              //pc.printf("-%d-", centervalue);
                              }
                    }
                int offset = micvalue-centervalue;
                //pc.printf(" %d ", offset);
                //myleds = micvalue;
                mic2LED(2+offset);
                wait(1.0/4000.0);
                }
               ////////////////////////////////////////////////////////
            strip.write();
            Thread::wait(10);
            }
        }
}

void bt_thread() {
    char bnum = 0;
    char bhit = 0;
    while(1) {
        if (bt.readable()) {
            if (bt.getc()=='!') {
                if (bt.getc()=='B') { //button data
                    bnum = bt.getc(); //button number
                    bhit = bt.getc(); //1 = hit, 0 = release
                    if (bhit == '1') {
                        switch (bnum) {
                            case '1':   // Button 1 for play/pause
                                if (waver.get_play_state() == 1) {
                                    waver.set_play_state(0);
                                } else if (waver.get_play_state() == 0) {
                                    waver.set_play_state(1);
                                    thread2.start(sound_thread);
                                }
                                printf("%d\n\r", waver.get_play_state());
                                break;
                            case '2':   // Button 2 for mute/unmute
                                mute = !mute;
                                break;
                            case '3':   // Button 3 to switch between mic/sd
                                if (sd_mtx.trylock()) {
                                    sd_mtx.lock();
                                    src = src ? 0 : 1;
                                    if (src) {
                                        thread2.start(sound_thread);
                                    } else {
                                        waver.set_play_state(0);
                                        while (thread2.get_state() == Thread::Running) {
                                            Thread::yield();
                                        }
                                        thread2.terminate();
                                    }
                                    sd_mtx.unlock();
                                    Thread::wait(100);
                                }
                                break;
                            case '7':   // Left arrow for previous
                                if (sd_mtx.trylock()) {
                                    sd_mtx.lock();
                                    waver.set_play_state(0);
                                    if (cur_song > 0) {
                                        --cur_song;
                                    }
                                    while (thread2.get_state() == Thread::Running) {
                                        Thread::yield();
                                    }
                                    thread2.terminate();
                                    thread2.start(sound_thread);
                                    waver.set_play_state(1);
                                    sd_mtx.unlock();
                                }
                                break;
                            case '8':   // Right arrow for skip
                                if (sd_mtx.trylock()) {
                                    sd_mtx.lock();
                                    waver.set_play_state(0);
                                    if (cur_song < filenames.size() - 1) {
                                        ++cur_song;
                                    }
                                    while (thread2.get_state() == Thread::Running) {
                                        Thread::yield();
                                    }
                                    thread2.terminate();
                                    thread2.start(sound_thread);
                                    waver.set_play_state(1);
                                    sd_mtx.unlock();
                                }
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
        Thread::wait(100);
    }
}

int main() {
    read_file_names("/sd/songs");

    strip.setBrightness(0.05);
    
    mute = 1;
        
    thread1.start(bt_thread);
    thread2.start(sound_thread);
    thread3.start(patternSound);
    
    while(1){
        myled = !myled;
        Thread::wait(100);
    }
}

working LED code

#include "mbed.h"
#include <string>
#include "PinDetect.h"
#include "NeoStrip.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include "rtos.h"

# define MAX_FILE 30

#define N 40
NeoStrip strip(p21, N);

BusOut myleds(LED1,LED2,LED3,LED4);

DigitalIn b2(p29, PullUp);
Serial pc(USBTX, USBRX);
SDFileSystem sd(p5, p6, p7, p8, "sd");
Ticker sampletick;
AnalogOut speaker(p18);                  // Speaker (pin)
wave_player waver(&speaker);

PwmOut spk(p24);

Thread thread1;
Thread thread2;
Thread thread3;
Thread thread4;

class microphone
{
public :
    microphone(PinName pin);
    float read();
    operator float ();
private :
    AnalogIn _pin;
};
microphone::microphone (PinName pin):
    _pin(pin)
{
}
float microphone::read()
{
    return _pin.read();
}
inline microphone::operator float ()
{
    return _pin.read();
}
 
microphone mymicrophone(p16);

uint8_t r = (uint8_t)0;
uint8_t g = (uint8_t)128;
uint8_t b = (uint8_t)0;

int red, green, blue;
 
// fancy function to make rainbow colors on LEDs
int hueToRGB(float h)
{
    float r, g, b;
    if (h > 360)
        h -= 360;
    if (h < 0)
        h += 360;
    int i = (int)(h / 60.0);
    float f = (h / 60.0) - i;
    float q = 1 - f;
    
    switch (i % 6)
    {
        case 0: r = 1; g = f; b = 0; break;
        case 1: r = q; g = 1; b = 0; break;
        case 2: r = 0; g = 1; b = f; break;
        case 3: r = 0; g = q; b = 1; break;
        case 4: r = f; g = 0; b = 1; break;
        case 5: r = 1; g = 0; b = q; break;
        default: r = 0; g = 0; b = 0; break;
    }
    
    // scale to integers and return the packed value
    uint8_t R = (uint8_t)(r * 255);
    uint8_t G = (uint8_t)(g * 255);
    uint8_t B = (uint8_t)(b * 255);

    return (R << 16) | (G << 8) | B;
}

// convert float values to LED otuput for soundtest array
void float2LED(float value){
    float fnumLED = abs((value - 0.5)/3.3)*100; // can mess with this scaling for better LED output
    int numLED = (int)fnumLED;
    if (numLED > 8) numLED = 8;
    
    static float dh = 360.0 / 5;
    static float x = 0;
    
    for(int i = 0; i < numLED; i++){
        int c = hueToRGB((dh * i) - x);
        strip.setPixel(i, c);
        strip.setPixel(i + 8, c);
        strip.setPixel(i + 16, c);
        strip.setPixel(i + 24, c);
        strip.setPixel(i + 32, c);
        }
    for(int i = numLED; i < 8; i++){
        strip.setPixel(i, 0x000000);
        strip.setPixel(i + 8, 0x000000);
        strip.setPixel(i + 16, 0x000000);
        strip.setPixel(i + 24, 0x000000);
        strip.setPixel(i + 32, 0x000000);
        
        // old setup for 5 rows of 8 LEDs
        //strip.setPixel(i + i * 7, 0x000000);
//        strip.setPixel(i + 1 + i * 7, 0x000000);
//        strip.setPixel(i + 2 + i * 7, 0x000000);
//        strip.setPixel(i + 3 + i * 7, 0x000000);
//        strip.setPixel(i + 4 + i * 7, 0x000000);
//        strip.setPixel(i + 5 + i * 7, 0x000000);
//        strip.setPixel(i + 6 + i * 7, 0x000000);
//        strip.setPixel(i + 7 + i * 7, 0x000000);
        }
    x += 1;
    if (x > 360)
        x = 0;
}

// same thing but for the mic
void mic2LED(int mic){
    static float dh = 360.0 / 5;
    static float x = 0;
    
    int numLED = 0;
    if(mic == 0) numLED = 0;
    else if(mic == 1) numLED = 1;
    else if(mic == 2) numLED = 2;
    else if(mic == 3) numLED = 3;
    else if(mic == 4) numLED = 4;
    else numLED = 5;
    
    for(int i = 0; i < numLED; i++){
        int c = hueToRGB((dh * i) - x);
        strip.setPixel(i, c);
        strip.setPixel(i + 8, c);
        strip.setPixel(i + 16, c);
        strip.setPixel(i + 24, c);
        strip.setPixel(i + 32, c);
        }
    for(int i = numLED; i < 8; i++){
        strip.setPixel(i, 0x000000);
        strip.setPixel(i + 8, 0x000000);
        strip.setPixel(i + 16, 0x000000);
        strip.setPixel(i + 24, 0x000000);
        strip.setPixel(i + 32, 0x000000);
        }
    x += 1;
    if (x > 360)
        x = 0; 
}

 
void sound_thread() {
        while(1){
            FILE *wave_file;
            printf("\n\n\nHello, wave world!\n");
            wave_file=fopen("/sd/runningmono.wav","r");
            printf("file opened\n");
            waver.play(wave_file);
            fclose(wave_file);
            Thread::yield();
        }
    }
    

    
unsigned short max_range = 0xFFFF;
// function that calls above functions
void patternSound(){
    //for(int i = 0; i < 60; i++){
        float sample;
        float average = 0.67/3.3;//initial DC bias level
        
        int buffer[20];
        while(1){
            
            // this part works for DAC PCM output //
            float test = (float)waver.dac_data/max_range;
            pc.printf("--%f", abs((test - 0.5)/3.3));
            float2LED(test);
            //------------------------------------//
            
            //microphone setup //
             //int centervalue;
//            for(int i = 0; i < 20; i++){
//                sample = mymicrophone;
//                //subtract 0.67V DC bias - but it varies quite a bit after loud or long sounds
//                average = 0.9999*average + 0.0001*sample;//try to slowly auto adjust the DC bias level
//                speaker = 0.5 +((sample - average)*33.0);//scale up to 0.0 to 1.0 for speaker output
//                
//                int micvalue = int(abs((sample - average)*300.0));
//                //pc.printf("-%d-", micvalue); //scale to around 15 for LEDs
//                
//                if(i == 1){
//                    centervalue = micvalue;
//                }
//                buffer[i] = micvalue;
//                if(i > 10){
//                    if(micvalue == buffer[1] && micvalue == buffer[2] && micvalue == buffer[3] &&
//                        micvalue == buffer[4] && micvalue == buffer[5] && micvalue == buffer[6] && 
//                        micvalue == buffer[7] && micvalue == buffer[8] && micvalue == buffer[9]){
//                              centervalue = buffer[1];
//                              //pc.printf("-%d-", centervalue);
//                              }
//                    }
//                int offset = micvalue-centervalue;
//                pc.printf(" %d ", offset);
//                myleds = micvalue;
//                mic2LED(2+offset);
//                wait(1.0/4000.0);
//                }
               ////////////////////////////////////////////////////////
            strip.write();
            Thread::wait(10);
        }
}
int main() {

    strip.setBrightness(0.05);
        
    thread1.start(patternSound);
    thread2.start(sound_thread);
    
    while(1){
        Thread::wait(100);
        }
}

All wikipages