Components and supplies
Capacitor 10 µF
Arduino UNO
LED
Resistor 100k ohm
Project description
Code
arduino_beat_detector.ino
arduino
It detects beats on audio line level signal and blink an LED
1// Arduino Beat Detector By Damian Peckett 2015 2// License: Public Domain. 3 4// Our Global Sample Rate, 5000hz 5#define SAMPLEPERIODUS 200 6 7// defines for setting and clearing register bits 8#ifndef cbi 9#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 10#endif 11#ifndef sbi 12#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 13#endif 14 15void setup() { 16 // Set ADC to 77khz, max for 10bit 17 sbi(ADCSRA,ADPS2); 18 cbi(ADCSRA,ADPS1); 19 cbi(ADCSRA,ADPS0); 20 21 //The pin with the LED 22 pinMode(2, OUTPUT); 23} 24 25// 20 - 200hz Single Pole Bandpass IIR Filter 26float bassFilter(float sample) { 27 static float xv[3] = {0,0,0}, yv[3] = {0,0,0}; 28 xv[0] = xv[1]; xv[1] = xv[2]; 29 xv[2] = (sample) / 3.f; // change here to values close to 2, to adapt for stronger or weeker sources of line level audio 30 31 32 yv[0] = yv[1]; yv[1] = yv[2]; 33 yv[2] = (xv[2] - xv[0]) 34 + (-0.7960060012f * yv[0]) + (1.7903124146f * yv[1]); 35 return yv[2]; 36} 37 38// 10hz Single Pole Lowpass IIR Filter 39float envelopeFilter(float sample) { //10hz low pass 40 static float xv[2] = {0,0}, yv[2] = {0,0}; 41 xv[0] = xv[1]; 42 xv[1] = sample / 50.f; 43 yv[0] = yv[1]; 44 yv[1] = (xv[0] + xv[1]) + (0.9875119299f * yv[0]); 45 return yv[1]; 46} 47 48// 1.7 - 3.0hz Single Pole Bandpass IIR Filter 49float beatFilter(float sample) { 50 static float xv[3] = {0,0,0}, yv[3] = {0,0,0}; 51 xv[0] = xv[1]; xv[1] = xv[2]; 52 xv[2] = sample / 2.7f; 53 yv[0] = yv[1]; yv[1] = yv[2]; 54 yv[2] = (xv[2] - xv[0]) 55 + (-0.7169861741f * yv[0]) + (1.4453653501f * yv[1]); 56 return yv[2]; 57} 58 59void loop() { 60 unsigned long time = micros(); // Used to track rate 61 float sample, value, envelope, beat, thresh; 62 unsigned char i; 63 64 for(i = 0;;++i){ 65 // Read ADC and center so +-512 66 sample = (float)analogRead(0)-503.f; 67 68 // Filter only bass component 69 value = bassFilter(sample); 70 71 // Take signal amplitude and filter 72 if(value < 0)value=-value; 73 envelope = envelopeFilter(value); 74 75 // Every 200 samples (25hz) filter the envelope 76 if(i == 200) { 77 // Filter out repeating bass sounds 100 - 180bpm 78 beat = beatFilter(envelope); 79 80 // Threshold it based on potentiometer on AN1 81 thresh = 0.02f * (float)analogRead(1); 82 83 // If we are above threshold, light up LED 84 if(beat > thresh) digitalWrite(2, HIGH); 85 else digitalWrite(2, LOW); 86 87 //Reset sample counter 88 i = 0; 89 } 90 91 // Consume excess clock cycles, to keep at 5000 hz 92 for(unsigned long up = time+SAMPLEPERIODUS; time > 20 && time < up; time = micros()); 93 } 94} 95
arduino_beat_detector.ino
arduino
It detects beats on audio line level signal and blink an LED
1// Arduino Beat Detector By Damian Peckett 2015 2// License: Public 3 Domain. 4 5// Our Global Sample Rate, 5000hz 6#define SAMPLEPERIODUS 200 7 8// 9 defines for setting and clearing register bits 10#ifndef cbi 11#define cbi(sfr, 12 bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 13#endif 14#ifndef sbi 15#define sbi(sfr, 16 bit) (_SFR_BYTE(sfr) |= _BV(bit)) 17#endif 18 19void setup() { 20 // Set 21 ADC to 77khz, max for 10bit 22 sbi(ADCSRA,ADPS2); 23 cbi(ADCSRA,ADPS1); 24 25 cbi(ADCSRA,ADPS0); 26 27 //The pin with the LED 28 pinMode(2, OUTPUT); 29} 30 31// 32 20 - 200hz Single Pole Bandpass IIR Filter 33float bassFilter(float sample) { 34 35 static float xv[3] = {0,0,0}, yv[3] = {0,0,0}; 36 xv[0] = xv[1]; xv[1] = 37 xv[2]; 38 xv[2] = (sample) / 3.f; // change here to values close to 2, to adapt 39 for stronger or weeker sources of line level audio 40 41 42 yv[0] = 43 yv[1]; yv[1] = yv[2]; 44 yv[2] = (xv[2] - xv[0]) 45 + (-0.7960060012f 46 * yv[0]) + (1.7903124146f * yv[1]); 47 return yv[2]; 48} 49 50// 10hz Single 51 Pole Lowpass IIR Filter 52float envelopeFilter(float sample) { //10hz low pass 53 54 static float xv[2] = {0,0}, yv[2] = {0,0}; 55 xv[0] = xv[1]; 56 xv[1] 57 = sample / 50.f; 58 yv[0] = yv[1]; 59 yv[1] = (xv[0] + xv[1]) + (0.9875119299f 60 * yv[0]); 61 return yv[1]; 62} 63 64// 1.7 - 3.0hz Single Pole Bandpass IIR 65 Filter 66float beatFilter(float sample) { 67 static float xv[3] = {0,0,0}, 68 yv[3] = {0,0,0}; 69 xv[0] = xv[1]; xv[1] = xv[2]; 70 xv[2] = sample / 2.7f; 71 72 yv[0] = yv[1]; yv[1] = yv[2]; 73 yv[2] = (xv[2] - xv[0]) 74 + (-0.7169861741f 75 * yv[0]) + (1.4453653501f * yv[1]); 76 return yv[2]; 77} 78 79void loop() 80 { 81 unsigned long time = micros(); // Used to track rate 82 float sample, 83 value, envelope, beat, thresh; 84 unsigned char i; 85 86 for(i = 0;;++i){ 87 88 // Read ADC and center so +-512 89 sample = (float)analogRead(0)-503.f; 90 91 92 // Filter only bass component 93 value = bassFilter(sample); 94 95 96 // Take signal amplitude and filter 97 if(value < 0)value=-value; 98 99 envelope = envelopeFilter(value); 100 101 // Every 200 samples (25hz) 102 filter the envelope 103 if(i == 200) { 104 // Filter out 105 repeating bass sounds 100 - 180bpm 106 beat = beatFilter(envelope); 107 108 109 // Threshold it based on potentiometer on AN1 110 thresh 111 = 0.02f * (float)analogRead(1); 112 113 // If we are above threshold, 114 light up LED 115 if(beat > thresh) digitalWrite(2, HIGH); 116 else 117 digitalWrite(2, LOW); 118 119 //Reset sample counter 120 i 121 = 0; 122 } 123 124 // Consume excess clock cycles, to keep at 5000 125 hz 126 for(unsigned long up = time+SAMPLEPERIODUS; time > 20 && time < up; 127 time = micros()); 128 } 129} 130
Downloadable files
Biasing audio signal (line level) to Arduino analog input 0
Biasing audio signal (line level) to Arduino analog input 0
Comments
Only logged in users can leave comments
mamifero
0 Followers
•0 Projects
+1
Work attribution
0