Simple guitar tuner

Dependencies:   mbed

Committer:
adurand
Date:
Wed Oct 26 02:01:28 2011 +0000
Revision:
1:ae7d0cf78b3e
Parent:
0:490e67fb09c2

        

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 1:ae7d0cf78b3e 11 #include <math.h>
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 1:ae7d0cf78b3e 23 float high, high1, in_tune, in_tune1, in_tune2, in_tune3,
adurand 1:ae7d0cf78b3e 24 low, low1, note, low_mod, high_mod;
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 1:ae7d0cf78b3e 115 high = 0;
adurand 1:ae7d0cf78b3e 116 low = 0;
adurand 1:ae7d0cf78b3e 117 for (int i=3; i<46; i+=3) {
adurand 1:ae7d0cf78b3e 118 high1 = goertzelFilter(Buffer, (note + i ), Counter);
adurand 1:ae7d0cf78b3e 119 if (high1 > high) high=high1;
adurand 1:ae7d0cf78b3e 120 }
adurand 1:ae7d0cf78b3e 121 for (int i=3; i<46; i+=3) {
adurand 1:ae7d0cf78b3e 122 low1 = goertzelFilter(Buffer, (note - i ), Counter);
adurand 1:ae7d0cf78b3e 123 if (low1 > low) low=low1;
adurand 1:ae7d0cf78b3e 124 }
adurand 1:ae7d0cf78b3e 125 in_tune1 = goertzelFilter(Buffer, (note+1), Counter);
adurand 0:490e67fb09c2 126 in_tune2 = goertzelFilter(Buffer, note, Counter);
adurand 1:ae7d0cf78b3e 127 in_tune3 = goertzelFilter(Buffer, (note-1), Counter);
adurand 1:ae7d0cf78b3e 128
adurand 1:ae7d0cf78b3e 129 if ((in_tune1 > in_tune2) && (in_tune1 > in_tune3)) in_tune = in_tune1;
adurand 1:ae7d0cf78b3e 130 else if ((in_tune2 > in_tune1) && (in_tune2 > in_tune3)) in_tune = in_tune2;
adurand 1:ae7d0cf78b3e 131 else in_tune = in_tune3;
adurand 1:ae7d0cf78b3e 132 // printf("high = %.2f, low = %.2f, in_tune = %.2f", high, low, in_tune);
adurand 1:ae7d0cf78b3e 133 // high_mod = high/in_tune;
adurand 1:ae7d0cf78b3e 134 // low_mod = low/in_tune;
adurand 1:ae7d0cf78b3e 135 // if ((high_mod > .8)&&(low_mod > .8)) {
adurand 1:ae7d0cf78b3e 136 // led_high = 0;
adurand 1:ae7d0cf78b3e 137 // led_ok = 0;
adurand 1:ae7d0cf78b3e 138 // led_low = 0;
adurand 1:ae7d0cf78b3e 139 // }
adurand 0:490e67fb09c2 140 if ((in_tune > high) && (in_tune > low)) {
adurand 0:490e67fb09c2 141 led_high = 0;
adurand 0:490e67fb09c2 142 led_ok = 1;
adurand 0:490e67fb09c2 143 led_low = 0;
adurand 0:490e67fb09c2 144 } else if (high > in_tune) {
adurand 0:490e67fb09c2 145 led_high = 1;
adurand 0:490e67fb09c2 146 led_ok = 0;
adurand 0:490e67fb09c2 147 led_low = 0;
adurand 0:490e67fb09c2 148 } else if (low > in_tune) {
adurand 0:490e67fb09c2 149 led_high = 0;
adurand 0:490e67fb09c2 150 led_ok = 0;
adurand 0:490e67fb09c2 151 led_low = 1;
adurand 0:490e67fb09c2 152 } else {
adurand 0:490e67fb09c2 153 led_high = 0;
adurand 0:490e67fb09c2 154 led_ok = 0;
adurand 0:490e67fb09c2 155 led_low = 0;
adurand 0:490e67fb09c2 156 }
adurand 1:ae7d0cf78b3e 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 1:ae7d0cf78b3e 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 }