Simple guitar tuner

Dependencies:   mbed

Committer:
adurand
Date:
Mon Oct 24 23:03:27 2011 +0000
Revision:
0:490e67fb09c2
Child:
1:ae7d0cf78b3e

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
adurand 0:490e67fb09c2 1 //////////////////////////////////////////
adurand 0:490e67fb09c2 2 // //
adurand 0:490e67fb09c2 3 // Guitar Tuner via Goertzel's Algorithm //
adurand 0:490e67fb09c2 4 // Created by: Andrew Durand //
adurand 0:490e67fb09c2 5 // //
adurand 0:490e67fb09c2 6 //////////////////////////////////////////
adurand 0:490e67fb09c2 7
adurand 0:490e67fb09c2 8 #include "mbed.h"
adurand 0:490e67fb09c2 9 #include "adc.h"
adurand 0:490e67fb09c2 10 #include "NokiaLCD.h"
adurand 0:490e67fb09c2 11
adurand 0:490e67fb09c2 12 #define PI 3.1415
adurand 0:490e67fb09c2 13 #define SAMPLE_RATE 24000
adurand 0:490e67fb09c2 14
adurand 0:490e67fb09c2 15 DigitalOut led_low(LED1);
adurand 0:490e67fb09c2 16 DigitalOut led_ok(LED2);
adurand 0:490e67fb09c2 17 DigitalOut led_high(LED4);
adurand 0:490e67fb09c2 18 InterruptIn button1(p12);
adurand 0:490e67fb09c2 19
adurand 0:490e67fb09c2 20 //LCD and Other Random Variables
adurand 0:490e67fb09c2 21 NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::LCD6610); // mosi, sclk, cs, rst, type
adurand 0:490e67fb09c2 22 int string_select = 0;
adurand 0:490e67fb09c2 23 float high, high1, high2, high3, high4, high5, high6, high7, high8, in_tune, in_tune1, in_tune2, in_tune3,
adurand 0:490e67fb09c2 24 low, low1, low2, low3, low4, low5, low6, low7, low8, note;
adurand 0:490e67fb09c2 25 char* key;
adurand 0:490e67fb09c2 26 int Counter = 0;
adurand 0:490e67fb09c2 27 int Buffer[6000];
adurand 0:490e67fb09c2 28
adurand 0:490e67fb09c2 29 float goertzelFilter(int samples[], float freq, int N) {
adurand 0:490e67fb09c2 30 float s_prev = 0.0;
adurand 0:490e67fb09c2 31 float s_prev2 = 0.0;
adurand 0:490e67fb09c2 32 float coeff,normalizedfreq,power,s,k;
adurand 0:490e67fb09c2 33 int i;
adurand 0:490e67fb09c2 34 normalizedfreq = freq / SAMPLE_RATE;
adurand 0:490e67fb09c2 35 coeff = 2*cos(2*PI*normalizedfreq);
adurand 0:490e67fb09c2 36 for (i=0; i<N; i++) {
adurand 0:490e67fb09c2 37 s = samples[i] + coeff * s_prev - s_prev2;
adurand 0:490e67fb09c2 38 s_prev2 = s_prev;
adurand 0:490e67fb09c2 39 s_prev = s;
adurand 0:490e67fb09c2 40 }
adurand 0:490e67fb09c2 41 power = s_prev2*s_prev2+s_prev*s_prev-coeff*s_prev*s_prev2;
adurand 0:490e67fb09c2 42 return power;
adurand 0:490e67fb09c2 43 }
adurand 0:490e67fb09c2 44
adurand 0:490e67fb09c2 45 ADC adc(SAMPLE_RATE, 1);
adurand 0:490e67fb09c2 46
adurand 0:490e67fb09c2 47 void sample_audio(int chan, uint32_t value) {
adurand 0:490e67fb09c2 48 Buffer[Counter] = adc.read(p20);
adurand 0:490e67fb09c2 49 Counter += 1;
adurand 0:490e67fb09c2 50 }
adurand 0:490e67fb09c2 51
adurand 0:490e67fb09c2 52 void button1_pressed() {
adurand 0:490e67fb09c2 53 string_select++;
adurand 0:490e67fb09c2 54 if (string_select > 5) string_select = 0;
adurand 0:490e67fb09c2 55 }
adurand 0:490e67fb09c2 56
adurand 0:490e67fb09c2 57 int main() {
adurand 0:490e67fb09c2 58 //Interupt for Switching Strings
adurand 0:490e67fb09c2 59 button1.mode(PullDown);
adurand 0:490e67fb09c2 60 button1.rise(&button1_pressed);
adurand 0:490e67fb09c2 61
adurand 0:490e67fb09c2 62 //Setup LCD
adurand 0:490e67fb09c2 63 lcd.background(0xF0000F);
adurand 0:490e67fb09c2 64 lcd.cls();
adurand 0:490e67fb09c2 65
adurand 0:490e67fb09c2 66 while (1) {
adurand 0:490e67fb09c2 67
adurand 0:490e67fb09c2 68 switch (string_select) {
adurand 0:490e67fb09c2 69 case 0:
adurand 0:490e67fb09c2 70 note = 82;
adurand 0:490e67fb09c2 71 key= "E2";
adurand 0:490e67fb09c2 72 break;
adurand 0:490e67fb09c2 73 case 1:
adurand 0:490e67fb09c2 74 note = 110;
adurand 0:490e67fb09c2 75 key= "A2";
adurand 0:490e67fb09c2 76 break;
adurand 0:490e67fb09c2 77 case 2:
adurand 0:490e67fb09c2 78 note = 147;
adurand 0:490e67fb09c2 79 key= "D3";
adurand 0:490e67fb09c2 80 break;
adurand 0:490e67fb09c2 81 case 3:
adurand 0:490e67fb09c2 82 note = 196;
adurand 0:490e67fb09c2 83 key= "G3";
adurand 0:490e67fb09c2 84 break;
adurand 0:490e67fb09c2 85 case 4:
adurand 0:490e67fb09c2 86 note = 247;
adurand 0:490e67fb09c2 87 key= "B3";
adurand 0:490e67fb09c2 88 break;
adurand 0:490e67fb09c2 89 case 5:
adurand 0:490e67fb09c2 90 note = 330;
adurand 0:490e67fb09c2 91 key= "E4";
adurand 0:490e67fb09c2 92 break;
adurand 0:490e67fb09c2 93 }
adurand 0:490e67fb09c2 94
adurand 0:490e67fb09c2 95 //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford
adurand 0:490e67fb09c2 96 adc.append(sample_audio);
adurand 0:490e67fb09c2 97 adc.startmode(0,0);
adurand 0:490e67fb09c2 98 adc.burst(1);
adurand 0:490e67fb09c2 99 adc.setup(p20,1);
adurand 0:490e67fb09c2 100
adurand 0:490e67fb09c2 101 //start the interrupt and wait for about 4096 samples
adurand 0:490e67fb09c2 102 adc.interrupt_state(p20,1);
adurand 0:490e67fb09c2 103 wait(.2);
adurand 0:490e67fb09c2 104
adurand 0:490e67fb09c2 105 //Finsh up - Unset pin 20
adurand 0:490e67fb09c2 106 adc.interrupt_state(p20,0);
adurand 0:490e67fb09c2 107 adc.setup(p20,0);
adurand 0:490e67fb09c2 108 int actual_rate = adc.actual_sample_rate();
adurand 0:490e67fb09c2 109
adurand 0:490e67fb09c2 110 //for debugging tell the terminal sample rate and how many samples we took
adurand 0:490e67fb09c2 111 printf("Requested max sample rate is %u, actual max sample rate is %u.\n",
adurand 0:490e67fb09c2 112 SAMPLE_RATE, actual_rate);
adurand 0:490e67fb09c2 113 printf("We did %i samples\n",Counter);
adurand 0:490e67fb09c2 114
adurand 0:490e67fb09c2 115 high1 = goertzelFilter(Buffer, (note+18), Counter);
adurand 0:490e67fb09c2 116 high2 = goertzelFilter(Buffer, (note+16), Counter);
adurand 0:490e67fb09c2 117 high3 = goertzelFilter(Buffer, (note+14), Counter);
adurand 0:490e67fb09c2 118 high4 = goertzelFilter(Buffer, (note+12), Counter);
adurand 0:490e67fb09c2 119 high5 = goertzelFilter(Buffer, (note+10), Counter);
adurand 0:490e67fb09c2 120 high6 = goertzelFilter(Buffer, (note+8), Counter);
adurand 0:490e67fb09c2 121 high7 = goertzelFilter(Buffer, (note+6), Counter);
adurand 0:490e67fb09c2 122 high8 = goertzelFilter(Buffer, (note+4), Counter);
adurand 0:490e67fb09c2 123 in_tune1 = goertzelFilter(Buffer, (note+0.5), Counter);
adurand 0:490e67fb09c2 124 in_tune2 = goertzelFilter(Buffer, note, Counter);
adurand 0:490e67fb09c2 125 in_tune3 = goertzelFilter(Buffer, (note-0.5), Counter);
adurand 0:490e67fb09c2 126 low1 = goertzelFilter(Buffer, (note-4), Counter);
adurand 0:490e67fb09c2 127 low2 = goertzelFilter(Buffer, (note-6), Counter);
adurand 0:490e67fb09c2 128 low3 = goertzelFilter(Buffer, (note-8), Counter);
adurand 0:490e67fb09c2 129 low4 = goertzelFilter(Buffer, (note-10), Counter);
adurand 0:490e67fb09c2 130 low5 = goertzelFilter(Buffer, (note-12), Counter);
adurand 0:490e67fb09c2 131 low6 = goertzelFilter(Buffer, (note-14), Counter);
adurand 0:490e67fb09c2 132 low7 = goertzelFilter(Buffer, (note-16), Counter);
adurand 0:490e67fb09c2 133 low8 = goertzelFilter(Buffer, (note-18), Counter);
adurand 0:490e67fb09c2 134
adurand 0:490e67fb09c2 135 in_tune = (in_tune1 + in_tune2 + in_tune3)/3;
adurand 0:490e67fb09c2 136 high = (high1 + high2 + high3 + high4 + high5 + high6 + high7 + high8)/8;
adurand 0:490e67fb09c2 137 low = (low1 + low2 + low3 + low4 + low5 + low6 + low7 + low8)/8;
adurand 0:490e67fb09c2 138
adurand 0:490e67fb09c2 139 if ((in_tune > high) && (in_tune > low)) {
adurand 0:490e67fb09c2 140 led_high = 0;
adurand 0:490e67fb09c2 141 led_ok = 1;
adurand 0:490e67fb09c2 142 led_low = 0;
adurand 0:490e67fb09c2 143 } else if (high > in_tune) {
adurand 0:490e67fb09c2 144 led_high = 1;
adurand 0:490e67fb09c2 145 led_ok = 0;
adurand 0:490e67fb09c2 146 led_low = 0;
adurand 0:490e67fb09c2 147 } else if (low > in_tune) {
adurand 0:490e67fb09c2 148 led_high = 0;
adurand 0:490e67fb09c2 149 led_ok = 0;
adurand 0:490e67fb09c2 150 led_low = 1;
adurand 0:490e67fb09c2 151 } else {
adurand 0:490e67fb09c2 152 led_high = 0;
adurand 0:490e67fb09c2 153 led_ok = 0;
adurand 0:490e67fb09c2 154 led_low = 0;
adurand 0:490e67fb09c2 155
adurand 0:490e67fb09c2 156 }
adurand 0:490e67fb09c2 157
adurand 0:490e67fb09c2 158 // Display on the LCD
adurand 0:490e67fb09c2 159 lcd.locate(0,1);
adurand 0:490e67fb09c2 160 lcd.printf("::Guitar Tuner::");
adurand 0:490e67fb09c2 161 lcd.locate(0,3);
adurand 0:490e67fb09c2 162 lcd.printf("Tuning String: %i", (6-string_select));
adurand 0:490e67fb09c2 163 lcd.locate(0,5);
adurand 0:490e67fb09c2 164 lcd.printf("%s at %i Hz",key, (int) note);
adurand 0:490e67fb09c2 165 lcd.locate(5,7);
adurand 0:490e67fb09c2 166 if (led_ok) lcd.printf("In Tune!");
adurand 0:490e67fb09c2 167 else if (led_low) lcd.printf("Too Low ");
adurand 0:490e67fb09c2 168 else if (led_high) lcd.printf("Too High");
adurand 0:490e67fb09c2 169 else lcd.printf("~~~~~");
adurand 0:490e67fb09c2 170
adurand 0:490e67fb09c2 171 Counter = 0;
adurand 0:490e67fb09c2 172
adurand 0:490e67fb09c2 173 }
adurand 0:490e67fb09c2 174
adurand 0:490e67fb09c2 175
adurand 0:490e67fb09c2 176
adurand 0:490e67fb09c2 177 }