![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Simple guitar tuner
main.cpp@0:490e67fb09c2, 2011-10-24 (annotated)
- Committer:
- adurand
- Date:
- Mon Oct 24 23:03:27 2011 +0000
- Revision:
- 0:490e67fb09c2
- Child:
- 1:ae7d0cf78b3e
Who changed what in which revision?
User | Revision | Line number | New 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 | } |