Music Visualizer

Dependencies:   mbed SDFileSystem NeoStrip PinDetect

Committer:
makkoli98
Date:
Thu Apr 30 02:40:20 2020 +0000
Revision:
7:c2ef4232feb4
Parent:
5:b6f462ece58f
Child:
8:fa37292cf52c
Play/pause, skip, and back only work in sd card mode

Who changed what in which revision?

UserRevisionLine numberNew contents of line
spatel465 0:adce77867281 1 #include "mbed.h"
spatel465 0:adce77867281 2 #include "PinDetect.h"
spatel465 0:adce77867281 3 #include "NeoStrip.h"
spatel465 0:adce77867281 4 #include "SDFileSystem.h"
spatel465 0:adce77867281 5 #include "wave_player.h"
spatel465 0:adce77867281 6 #include "rtos.h"
spatel465 0:adce77867281 7 #include <string>
spatel465 0:adce77867281 8 #include <vector>
spatel465 0:adce77867281 9
spatel465 0:adce77867281 10 # define MAX_FILE 30
spatel465 0:adce77867281 11
spatel465 0:adce77867281 12 #define N 40
spatel465 0:adce77867281 13 NeoStrip strip(p21, N);
spatel465 0:adce77867281 14
spatel465 0:adce77867281 15 //BusOut myleds(LED1,LED2,LED3,LED4);
spatel465 0:adce77867281 16 DigitalOut myled(LED1);
spatel465 0:adce77867281 17
spatel465 0:adce77867281 18 DigitalIn b2(p29, PullUp);
spatel465 0:adce77867281 19 Serial pc(USBTX, USBRX);
spatel465 0:adce77867281 20 SDFileSystem sd(p5, p6, p7, p8, "sd");
spatel465 0:adce77867281 21 Ticker sampletick;
spatel465 0:adce77867281 22 AnalogOut speaker(p18); // Speaker (pin)
spatel465 0:adce77867281 23 wave_player waver(&speaker);
spatel465 0:adce77867281 24 Serial bt(p28, p27); // Bluetooth
spatel465 0:adce77867281 25 DigitalOut mute(p29); // mute pin (low for shutdown)
spatel465 0:adce77867281 26
spatel465 0:adce77867281 27 PwmOut spk(p24);
spatel465 0:adce77867281 28
spatel465 0:adce77867281 29 Thread thread1;
spatel465 0:adce77867281 30 Thread thread2;
spatel465 0:adce77867281 31 Thread thread3;
spatel465 0:adce77867281 32 Mutex sd_mtx;
makkoli98 4:6fbdec5bc602 33 volatile int src = 1; // 0 for Mic, 1 for SD card
spatel465 0:adce77867281 34
spatel465 0:adce77867281 35 vector<string> filenames; // list of files in sd card
spatel465 0:adce77867281 36 volatile int cur_song = 1;
spatel465 0:adce77867281 37
spatel465 0:adce77867281 38 void read_file_names(char *dir) {
spatel465 0:adce77867281 39 DIR *dp;
spatel465 0:adce77867281 40 struct dirent *dirp;
spatel465 0:adce77867281 41 dp = opendir(dir);
spatel465 0:adce77867281 42 while ((dirp = readdir(dp)) != NULL) {
spatel465 0:adce77867281 43 filenames.push_back(string(dirp->d_name));
spatel465 0:adce77867281 44 }
spatel465 0:adce77867281 45 closedir(dp);
spatel465 0:adce77867281 46 }
spatel465 0:adce77867281 47
spatel465 0:adce77867281 48 class microphone
spatel465 0:adce77867281 49 {
spatel465 0:adce77867281 50 public :
spatel465 0:adce77867281 51 microphone(PinName pin);
spatel465 0:adce77867281 52 float read();
spatel465 0:adce77867281 53 operator float ();
spatel465 0:adce77867281 54 private :
spatel465 0:adce77867281 55 AnalogIn _pin;
spatel465 0:adce77867281 56 };
spatel465 0:adce77867281 57 microphone::microphone (PinName pin):
spatel465 0:adce77867281 58 _pin(pin)
spatel465 0:adce77867281 59 {
spatel465 0:adce77867281 60 }
spatel465 0:adce77867281 61 float microphone::read()
spatel465 0:adce77867281 62 {
spatel465 0:adce77867281 63 return _pin.read();
spatel465 0:adce77867281 64 }
spatel465 0:adce77867281 65 inline microphone::operator float ()
spatel465 0:adce77867281 66 {
spatel465 0:adce77867281 67 return _pin.read();
spatel465 0:adce77867281 68 }
spatel465 0:adce77867281 69
spatel465 0:adce77867281 70 microphone mymicrophone(p16);
spatel465 0:adce77867281 71
spatel465 0:adce77867281 72 uint8_t r = (uint8_t)0;
spatel465 0:adce77867281 73 uint8_t g = (uint8_t)128;
spatel465 0:adce77867281 74 uint8_t b = (uint8_t)0;
spatel465 0:adce77867281 75
spatel465 0:adce77867281 76 int red, green, blue;
spatel465 0:adce77867281 77
spatel465 0:adce77867281 78 // fancy function to make rainbow colors on LEDs
spatel465 0:adce77867281 79 int hueToRGB(float h)
spatel465 0:adce77867281 80 {
spatel465 0:adce77867281 81 float r, g, b;
spatel465 0:adce77867281 82 if (h > 360)
spatel465 0:adce77867281 83 h -= 360;
spatel465 0:adce77867281 84 if (h < 0)
spatel465 0:adce77867281 85 h += 360;
spatel465 0:adce77867281 86 int i = (int)(h / 60.0);
spatel465 0:adce77867281 87 float f = (h / 60.0) - i;
spatel465 0:adce77867281 88 float q = 1 - f;
spatel465 0:adce77867281 89
spatel465 0:adce77867281 90 switch (i % 6)
spatel465 0:adce77867281 91 {
spatel465 0:adce77867281 92 case 0: r = 1; g = f; b = 0; break;
spatel465 0:adce77867281 93 case 1: r = q; g = 1; b = 0; break;
spatel465 0:adce77867281 94 case 2: r = 0; g = 1; b = f; break;
spatel465 0:adce77867281 95 case 3: r = 0; g = q; b = 1; break;
spatel465 0:adce77867281 96 case 4: r = f; g = 0; b = 1; break;
spatel465 0:adce77867281 97 case 5: r = 1; g = 0; b = q; break;
spatel465 0:adce77867281 98 default: r = 0; g = 0; b = 0; break;
spatel465 0:adce77867281 99 }
spatel465 0:adce77867281 100
spatel465 0:adce77867281 101 // scale to integers and return the packed value
spatel465 0:adce77867281 102 uint8_t R = (uint8_t)(r * 255);
spatel465 0:adce77867281 103 uint8_t G = (uint8_t)(g * 255);
spatel465 0:adce77867281 104 uint8_t B = (uint8_t)(b * 255);
spatel465 0:adce77867281 105
spatel465 0:adce77867281 106 return (R << 16) | (G << 8) | B;
spatel465 0:adce77867281 107 }
spatel465 0:adce77867281 108
spatel465 0:adce77867281 109 // convert float values to LED otuput for soundtest array
spatel465 0:adce77867281 110 void float2LED(float value){
spatel465 0:adce77867281 111 float fnumLED = abs((value - 0.5)/3.3)*100; // can mess with this scaling for better LED output
spatel465 0:adce77867281 112 int numLED = (int)fnumLED;
spatel465 0:adce77867281 113 if (numLED > 8) numLED = 8;
spatel465 0:adce77867281 114
spatel465 0:adce77867281 115 static float dh = 360.0 / 5;
spatel465 0:adce77867281 116 static float x = 0;
spatel465 0:adce77867281 117
spatel465 0:adce77867281 118 for(int i = 0; i < numLED; i++){
spatel465 0:adce77867281 119 int c = hueToRGB((dh * i) - x);
spatel465 0:adce77867281 120 strip.setPixel(i, c);
spatel465 0:adce77867281 121 strip.setPixel(i + 8, c);
spatel465 0:adce77867281 122 strip.setPixel(i + 16, c);
spatel465 0:adce77867281 123 strip.setPixel(i + 24, c);
spatel465 0:adce77867281 124 strip.setPixel(i + 32, c);
spatel465 0:adce77867281 125 }
spatel465 0:adce77867281 126 for(int i = numLED; i < 8; i++){
spatel465 0:adce77867281 127 strip.setPixel(i, 0x000000);
spatel465 0:adce77867281 128 strip.setPixel(i + 8, 0x000000);
spatel465 0:adce77867281 129 strip.setPixel(i + 16, 0x000000);
spatel465 0:adce77867281 130 strip.setPixel(i + 24, 0x000000);
spatel465 0:adce77867281 131 strip.setPixel(i + 32, 0x000000);
spatel465 0:adce77867281 132
spatel465 0:adce77867281 133 // old setup for 5 rows of 8 LEDs
spatel465 0:adce77867281 134 //strip.setPixel(i + i * 7, 0x000000);
spatel465 0:adce77867281 135 // strip.setPixel(i + 1 + i * 7, 0x000000);
spatel465 0:adce77867281 136 // strip.setPixel(i + 2 + i * 7, 0x000000);
spatel465 0:adce77867281 137 // strip.setPixel(i + 3 + i * 7, 0x000000);
spatel465 0:adce77867281 138 // strip.setPixel(i + 4 + i * 7, 0x000000);
spatel465 0:adce77867281 139 // strip.setPixel(i + 5 + i * 7, 0x000000);
spatel465 0:adce77867281 140 // strip.setPixel(i + 6 + i * 7, 0x000000);
spatel465 0:adce77867281 141 // strip.setPixel(i + 7 + i * 7, 0x000000);
spatel465 0:adce77867281 142 }
spatel465 0:adce77867281 143 x += 1;
spatel465 0:adce77867281 144 if (x > 360)
spatel465 0:adce77867281 145 x = 0;
spatel465 0:adce77867281 146 }
spatel465 0:adce77867281 147
spatel465 0:adce77867281 148 // same thing but for the mic
spatel465 0:adce77867281 149 void mic2LED(int mic){
spatel465 0:adce77867281 150 static float dh = 360.0 / 5;
spatel465 0:adce77867281 151 static float x = 0;
spatel465 0:adce77867281 152
spatel465 0:adce77867281 153 int numLED = 0;
spatel465 0:adce77867281 154 if(mic == 0) numLED = 0;
spatel465 0:adce77867281 155 else if(mic == 1) numLED = 1;
spatel465 0:adce77867281 156 else if(mic == 2) numLED = 2;
spatel465 0:adce77867281 157 else if(mic == 3) numLED = 3;
spatel465 0:adce77867281 158 else if(mic == 4) numLED = 4;
spatel465 0:adce77867281 159 else numLED = 5;
spatel465 0:adce77867281 160
spatel465 0:adce77867281 161 for(int i = 0; i < numLED; i++){
spatel465 0:adce77867281 162 int c = hueToRGB((dh * i) - x);
spatel465 0:adce77867281 163 strip.setPixel(i, c);
spatel465 0:adce77867281 164 strip.setPixel(i + 8, c);
spatel465 0:adce77867281 165 strip.setPixel(i + 16, c);
spatel465 0:adce77867281 166 strip.setPixel(i + 24, c);
spatel465 0:adce77867281 167 strip.setPixel(i + 32, c);
spatel465 0:adce77867281 168 }
spatel465 0:adce77867281 169 for(int i = numLED; i < 8; i++){
spatel465 0:adce77867281 170 strip.setPixel(i, 0x000000);
spatel465 0:adce77867281 171 strip.setPixel(i + 8, 0x000000);
spatel465 0:adce77867281 172 strip.setPixel(i + 16, 0x000000);
spatel465 0:adce77867281 173 strip.setPixel(i + 24, 0x000000);
spatel465 0:adce77867281 174 strip.setPixel(i + 32, 0x000000);
spatel465 0:adce77867281 175 }
spatel465 0:adce77867281 176 x += 1;
spatel465 0:adce77867281 177 if (x > 360)
spatel465 0:adce77867281 178 x = 0;
spatel465 0:adce77867281 179 }
spatel465 0:adce77867281 180
spatel465 0:adce77867281 181
spatel465 0:adce77867281 182 void sound_thread() {
spatel465 0:adce77867281 183 FILE *wave_file;
spatel465 0:adce77867281 184 printf("\n\n\nHello, wave world!\n");
spatel465 0:adce77867281 185 string songstr = "/sd/songs/" + filenames[cur_song];
spatel465 0:adce77867281 186 printf("%s", songstr.c_str());
spatel465 0:adce77867281 187 wave_file=fopen(songstr.c_str(),"r");
spatel465 0:adce77867281 188 printf("file opened\n");
spatel465 0:adce77867281 189 waver.play(wave_file);
spatel465 0:adce77867281 190 fclose(wave_file);
spatel465 0:adce77867281 191 Thread::yield();
spatel465 0:adce77867281 192 }
spatel465 0:adce77867281 193
spatel465 0:adce77867281 194
spatel465 0:adce77867281 195
spatel465 0:adce77867281 196 unsigned short max_range = 0xFFFF;
spatel465 0:adce77867281 197 // function that calls above functions
spatel465 0:adce77867281 198 void patternSound(){
spatel465 0:adce77867281 199 //for(int i = 0; i < 60; i++){
spatel465 0:adce77867281 200 float sample;
spatel465 0:adce77867281 201 float average = 0.67/3.3;//initial DC bias level
spatel465 0:adce77867281 202
spatel465 0:adce77867281 203 int buffer[20];
spatel465 0:adce77867281 204
spatel465 0:adce77867281 205 while(1){
spatel465 0:adce77867281 206 if (src) {
spatel465 0:adce77867281 207 // this part works for DAC PCM output //
spatel465 0:adce77867281 208 float test = (float)waver.dac_data/max_range;
spatel465 0:adce77867281 209 pc.printf("--%f", abs((test - 0.5)/3.3));
spatel465 0:adce77867281 210 float2LED(test);
spatel465 0:adce77867281 211 strip.write();
spatel465 0:adce77867281 212 }
spatel465 0:adce77867281 213 //------------------------------------//
spatel465 0:adce77867281 214 else {
spatel465 0:adce77867281 215 //microphone setup //
spatel465 0:adce77867281 216 int centervalue;
spatel465 0:adce77867281 217 for(int i = 0; i < 20; i++){
spatel465 0:adce77867281 218 sample = mymicrophone;
spatel465 0:adce77867281 219 //subtract 0.67V DC bias - but it varies quite a bit after loud or long sounds
spatel465 0:adce77867281 220 average = 0.9999*average + 0.0001*sample;//try to slowly auto adjust the DC bias level
spatel465 0:adce77867281 221 speaker = 0.5 +((sample - average)*33.0);//scale up to 0.0 to 1.0 for speaker output
spatel465 0:adce77867281 222
spatel465 0:adce77867281 223 int micvalue = int(abs((sample - average)*300.0));
spatel465 0:adce77867281 224 //pc.printf("-%d-", micvalue); //scale to around 15 for LEDs
spatel465 0:adce77867281 225
spatel465 0:adce77867281 226 if(i == 1){
spatel465 0:adce77867281 227 centervalue = micvalue;
spatel465 0:adce77867281 228 }
spatel465 0:adce77867281 229 buffer[i] = micvalue;
spatel465 0:adce77867281 230 if(i > 10){
spatel465 0:adce77867281 231 if(micvalue == buffer[1] && micvalue == buffer[2] && micvalue == buffer[3] &&
spatel465 0:adce77867281 232 micvalue == buffer[4] && micvalue == buffer[5] && micvalue == buffer[6] &&
spatel465 0:adce77867281 233 micvalue == buffer[7] && micvalue == buffer[8] && micvalue == buffer[9]){
spatel465 0:adce77867281 234 centervalue = buffer[1];
spatel465 0:adce77867281 235 //pc.printf("-%d-", centervalue);
spatel465 0:adce77867281 236 }
spatel465 0:adce77867281 237 }
spatel465 0:adce77867281 238 int offset = micvalue-centervalue;
spatel465 0:adce77867281 239 //pc.printf(" %d ", offset);
spatel465 0:adce77867281 240 //myleds = micvalue;
spatel465 0:adce77867281 241 mic2LED(2+offset);
spatel465 0:adce77867281 242 wait(1.0/4000.0);
spatel465 0:adce77867281 243 }
spatel465 0:adce77867281 244 ////////////////////////////////////////////////////////
spatel465 0:adce77867281 245 strip.write();
spatel465 0:adce77867281 246 Thread::wait(10);
spatel465 0:adce77867281 247 }
spatel465 0:adce77867281 248 }
spatel465 0:adce77867281 249 }
spatel465 0:adce77867281 250
spatel465 0:adce77867281 251 void bt_thread() {
spatel465 0:adce77867281 252 char bnum = 0;
spatel465 0:adce77867281 253 char bhit = 0;
spatel465 0:adce77867281 254 while(1) {
spatel465 0:adce77867281 255 if (bt.readable()) {
spatel465 0:adce77867281 256 if (bt.getc()=='!') {
spatel465 0:adce77867281 257 if (bt.getc()=='B') { //button data
spatel465 0:adce77867281 258 bnum = bt.getc(); //button number
spatel465 0:adce77867281 259 bhit = bt.getc(); //1 = hit, 0 = release
spatel465 0:adce77867281 260 if (bhit == '1') {
spatel465 0:adce77867281 261 switch (bnum) {
spatel465 0:adce77867281 262 case '1': // Button 1 for play/pause
makkoli98 7:c2ef4232feb4 263 if (src) {
makkoli98 7:c2ef4232feb4 264 if (waver.get_play_state() == 1) {
makkoli98 7:c2ef4232feb4 265 waver.set_play_state(0);
makkoli98 7:c2ef4232feb4 266 thread2.terminate();
makkoli98 7:c2ef4232feb4 267 mute = 0;
makkoli98 7:c2ef4232feb4 268 } else if (waver.get_play_state() == 0) {
makkoli98 7:c2ef4232feb4 269 waver.set_play_state(1);
makkoli98 7:c2ef4232feb4 270 thread2.start(sound_thread);
makkoli98 7:c2ef4232feb4 271 mute = 1;
makkoli98 7:c2ef4232feb4 272 }
spatel465 0:adce77867281 273 }
spatel465 0:adce77867281 274 break;
spatel465 0:adce77867281 275 case '2': // Button 2 for mute/unmute
spatel465 0:adce77867281 276 mute = !mute;
spatel465 0:adce77867281 277 break;
spatel465 0:adce77867281 278 case '3': // Button 3 to switch between mic/sd
spatel465 0:adce77867281 279 if (sd_mtx.trylock()) {
spatel465 0:adce77867281 280 sd_mtx.lock();
spatel465 0:adce77867281 281 src = src ? 0 : 1;
spatel465 0:adce77867281 282 if (src) {
makkoli98 5:b6f462ece58f 283 waver.set_play_state(1);
spatel465 0:adce77867281 284 thread2.start(sound_thread);
makkoli98 1:2e32808bfc2b 285 mute = 1;
spatel465 0:adce77867281 286 } else {
spatel465 0:adce77867281 287 waver.set_play_state(0);
spatel465 0:adce77867281 288 while (thread2.get_state() == Thread::Running) {
spatel465 0:adce77867281 289 Thread::yield();
spatel465 0:adce77867281 290 }
spatel465 0:adce77867281 291 thread2.terminate();
makkoli98 1:2e32808bfc2b 292 mute = 0;
spatel465 0:adce77867281 293 }
spatel465 0:adce77867281 294 sd_mtx.unlock();
spatel465 0:adce77867281 295 Thread::wait(100);
spatel465 0:adce77867281 296 }
spatel465 0:adce77867281 297 break;
spatel465 0:adce77867281 298 case '7': // Left arrow for previous
makkoli98 7:c2ef4232feb4 299 if (sd_mtx.trylock() && src) {
spatel465 0:adce77867281 300 sd_mtx.lock();
spatel465 0:adce77867281 301 waver.set_play_state(0);
spatel465 0:adce77867281 302 if (cur_song > 0) {
spatel465 0:adce77867281 303 --cur_song;
spatel465 0:adce77867281 304 }
spatel465 0:adce77867281 305 while (thread2.get_state() == Thread::Running) {
spatel465 0:adce77867281 306 Thread::yield();
spatel465 0:adce77867281 307 }
spatel465 0:adce77867281 308 thread2.terminate();
spatel465 0:adce77867281 309 thread2.start(sound_thread);
spatel465 0:adce77867281 310 waver.set_play_state(1);
spatel465 0:adce77867281 311 sd_mtx.unlock();
spatel465 0:adce77867281 312 }
spatel465 0:adce77867281 313 break;
spatel465 0:adce77867281 314 case '8': // Right arrow for skip
makkoli98 7:c2ef4232feb4 315 if (sd_mtx.trylock() && src) {
spatel465 0:adce77867281 316 sd_mtx.lock();
spatel465 0:adce77867281 317 waver.set_play_state(0);
spatel465 0:adce77867281 318 if (cur_song < filenames.size() - 1) {
spatel465 0:adce77867281 319 ++cur_song;
spatel465 0:adce77867281 320 }
spatel465 0:adce77867281 321 while (thread2.get_state() == Thread::Running) {
spatel465 0:adce77867281 322 Thread::yield();
spatel465 0:adce77867281 323 }
spatel465 0:adce77867281 324 thread2.terminate();
spatel465 0:adce77867281 325 thread2.start(sound_thread);
spatel465 0:adce77867281 326 waver.set_play_state(1);
spatel465 0:adce77867281 327 sd_mtx.unlock();
spatel465 0:adce77867281 328 }
spatel465 0:adce77867281 329 break;
spatel465 0:adce77867281 330 default:
spatel465 0:adce77867281 331 break;
spatel465 0:adce77867281 332 }
spatel465 0:adce77867281 333 }
spatel465 0:adce77867281 334 }
spatel465 0:adce77867281 335 }
spatel465 0:adce77867281 336 }
spatel465 0:adce77867281 337 Thread::wait(100);
spatel465 0:adce77867281 338 }
spatel465 0:adce77867281 339 }
spatel465 0:adce77867281 340
spatel465 0:adce77867281 341 int main() {
spatel465 0:adce77867281 342 read_file_names("/sd/songs");
spatel465 0:adce77867281 343
spatel465 0:adce77867281 344 strip.setBrightness(0.05);
spatel465 0:adce77867281 345
spatel465 0:adce77867281 346 mute = 1;
spatel465 0:adce77867281 347
spatel465 0:adce77867281 348 thread1.start(bt_thread);
spatel465 0:adce77867281 349 thread2.start(sound_thread);
spatel465 0:adce77867281 350 thread3.start(patternSound);
spatel465 0:adce77867281 351
spatel465 0:adce77867281 352 while(1){
spatel465 0:adce77867281 353 myled = !myled;
spatel465 0:adce77867281 354 Thread::wait(100);
spatel465 0:adce77867281 355 }
spatel465 0:adce77867281 356 }
spatel465 0:adce77867281 357