forked from RossMcIlvaine/Cool_Tuner_Arduino_SegFaults
-
Notifications
You must be signed in to change notification settings - Fork 1
/
frequency_test_v2.ino
113 lines (98 loc) · 3.19 KB
/
frequency_test_v2.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "arduinoFFT.h"
#define SAMPLES 128 //SAMPLES-pt FFT. Must be a base 2 number. Max 128 for Arduino Uno.
#define SAMPLING_FREQUENCY 2048 //Ts = Based on Nyquist, must be 2 times the highest expected frequency.
#define log2(x) log(x)/log(2)
arduinoFFT FFT = arduinoFFT();
unsigned int samplingPeriod;
unsigned long microSeconds;
double vReal[SAMPLES]; //create vector of size SAMPLES to hold real values
double vImag[SAMPLES]; //create vector of size SAMPLES to hold imaginary values
String notes[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
void setLed(int cents);
void setup()
{
Serial.begin(115200); //Baud rate for the Serial Monitor
samplingPeriod = round(1000000*(1.0/SAMPLING_FREQUENCY)); //Period in microseconds
pinMode(2, OUTPUT);
pinMode(4, OUTPUT);
pinMode(6, OUTPUT);
pinMode(8, OUTPUT);
pinMode(10, OUTPUT);
}
void loop()
{
/*Sample SAMPLES times*/
for(int i=0; i<SAMPLES; i++)
{
microSeconds = micros(); //Returns the number of microseconds since the Arduino board began running the current script.
vReal[i] = analogRead(0); //Reads the value from analog pin 0 (A0), quantize it and save it as a real term.
vImag[i] = 0; //Makes imaginary term 0 always
/*remaining wait time between samples if necessary*/
while(micros() < (microSeconds + samplingPeriod))
{
//do nothing
}
}
/*Perform FFT on samples*/
FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
/*Find peak frequency and print peak*/
double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);
int midi_num = round(12.0 * log2(peak/440.0) + 69.0);
double expected_freq = pow(2.0, (midi_num - 69.0)/12.0) * 440.0;
double cents = 1200*log2(peak / expected_freq);
Serial.println(notes[midi_num%12] + " (" + cents + ")"); //Print out the most dominant frequency.
setLed(cents);
}
void setLed(int cents)
{
if (cents > 25)
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(6, LOW);
digitalWrite(8, LOW);
digitalWrite(10, HIGH);
}
else if (cents > 12 && cents <= 25)
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(6, LOW);
digitalWrite(8, HIGH);
digitalWrite(10, LOW);
}
else if (cents > 0 && cents <= 12)
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(6, HIGH);
digitalWrite(8, LOW);
digitalWrite(10, LOW);
}
else if (cents > -12 && cents <= 0)
{
digitalWrite(2, LOW);
digitalWrite(4, HIGH);
digitalWrite(6, LOW);
digitalWrite(8, LOW);
digitalWrite(10, LOW);
}
else if (cents > -25 && cents <= -12)
{
digitalWrite(2, HIGH);
digitalWrite(4, LOW);
digitalWrite(6, LOW);
digitalWrite(8, LOW);
digitalWrite(10, LOW);
}
else {
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(6, LOW);
digitalWrite(8, LOW);
digitalWrite(10, LOW);
}
return;
}