Move the configuration into its own header file.
[pitch] / pitch.cpp
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5
6 #include "config.h"
7 #include "notes.h"
8 #include "linux_audio.h"
9 #include "pitchdetector.h"
10
11 void print_spectrogram(double freq, double amp);
12 void write_sine(int dsp_fd, double freq, unsigned num_samples);
13
14 int main()
15 {
16         PitchDetector pd(SAMPLE_RATE, FFT_LENGTH, PAD_FACTOR, OVERLAP);
17         int fd = get_dsp_fd(SAMPLE_RATE, FFT_LENGTH, OVERLAP);
18         for ( ;; ) {
19                 short buf[FFT_LENGTH / PAD_FACTOR / OVERLAP];
20
21                 read_chunk(fd, buf, FFT_LENGTH / PAD_FACTOR / OVERLAP);
22                 std::pair<double, double> peak = pd.detect_pitch(buf);
23
24                 if (peak.first < 50.0 || peak.second - log10(FFT_LENGTH) < 0.0) {
25 #if TUNING == WELL_TEMPERED_GUITAR
26                         printf("......\n");
27 #else           
28                         printf("............\n");
29 #endif
30                 } else {
31                         print_spectrogram(peak.first, peak.second - log10(FFT_LENGTH));
32                 }
33         }
34 }
35
36 std::string freq_to_tonename(double freq)
37 {
38         std::string notenames[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
39         double half_notes_away = 12.0 * log2(freq / BASE_PITCH) - 3.0;
40         int hnai = int(floor(half_notes_away + 0.5));
41         int octave = (hnai + 48) / 12;
42
43         char buf[256];
44         sprintf(buf, "%s%d + %.2f [%d]", notenames[((hnai % 12) + 12) % 12].c_str(), octave, half_notes_away - hnai, hnai);
45         return buf;
46 }
47
48 #if TUNING == EQUAL_TEMPERAMENT
49 void print_spectrogram(double freq, double amp)
50 {
51         std::string notenames[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
52         double half_notes_away = 12.0 * log2(freq / BASE_PITCH) - 3.0;
53         int hnai = int(floor(half_notes_away + 0.5));
54         int octave = (hnai + 48) / 12;
55
56         for (int i = 0; i < 12; ++i)
57                 if (i == ((hnai % 12) + 12) % 12)
58                         printf("#");
59                 else
60                         printf(".");
61
62         printf(" (%-2s%d %+.2f, %5.2fHz) [%5.2fdB]  [", notenames[((hnai % 12) + 12) % 12].c_str(), octave, half_notes_away - hnai,
63                 freq, amp);
64
65         double off = half_notes_away - hnai;
66         for (int i = -10; i <= 10; ++i) {
67                 if (off >= (i-0.5) * 0.05 && off < (i+0.5) * 0.05) {
68                         printf("#");
69                 } else {
70                         if (i == 0) {
71                                 printf("|");
72                         } else {
73                                 printf("-");
74                         }
75                 }
76         }
77         printf("]\n");
78
79 }
80 #else
81 struct note {
82         char notename[16];
83         double freq;
84 };
85 static note notes[] = {
86         { "E-3", BASE_PITCH/4.0 * (3.0/4.0) },
87         { "A-3", BASE_PITCH/4.0 },
88         { "D-4", BASE_PITCH/4.0 * (4.0/3.0) },
89         { "G-4", BASE_PITCH/4.0 * (4.0/3.0)*(4.0/3.0) },
90         { "B-4", BASE_PITCH * (3.0/4.0)*(3.0/4.0) },
91         { "E-5", BASE_PITCH * (3.0/4.0) }
92 };
93
94 void print_spectrogram(double freq, double amp)
95 {
96         double best_away = 999999999.9;
97         unsigned best_away_ind = 0;
98         
99         for (unsigned i = 0; i < sizeof(notes)/sizeof(note); ++i) {
100                 double half_notes_away = 12.0 * log2(freq / notes[i].freq);
101                 if (fabs(half_notes_away) < fabs(best_away)) {
102                         best_away = half_notes_away;
103                         best_away_ind = i;
104                 }
105         }
106         
107         for (unsigned i = 0; i < sizeof(notes)/sizeof(note); ++i)
108                 if (i == best_away_ind)
109                         printf("#");
110                 else
111                         printf(".");
112
113         printf(" (%s %+.2f, %5.2fHz) [%5.2fdB]  [", notes[best_away_ind].notename, best_away, freq, amp);
114
115         // coarse tuning
116         for (int i = -10; i <= 10; ++i) {
117                 if (best_away >= (i-0.5) * 0.05 && best_away < (i+0.5) * 0.05) {
118                         printf("#");
119                 } else {
120                         if (i == 0) {
121                                 printf("|");
122                         } else {
123                                 printf("-");
124                         }
125                 }
126         }
127         printf("]  [");
128         
129         // fine tuning
130         for (int i = -10; i <= 10; ++i) {
131                 if (best_away >= (i-0.5) * 0.01 && best_away < (i+0.5) * 0.01) {
132                         printf("#");
133                 } else {
134                         if (i == 0) {
135                                 printf("|");
136                         } else {
137                                 printf("-");
138                         }
139                 }
140         }
141         printf("]\n");
142 }
143 #endif