Make an SDL/OpenGL-frontend; might be more intuitive to read, although I'm not sure...
[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 void print_spectrogram(double freq, double amp)
82 {
83         double best_away = 999999999.9;
84         unsigned best_away_ind = 0;
85         
86         for (unsigned i = 0; i < sizeof(notes)/sizeof(note); ++i) {
87                 double half_notes_away = 12.0 * log2(freq / notes[i].freq);
88                 if (fabs(half_notes_away) < fabs(best_away)) {
89                         best_away = half_notes_away;
90                         best_away_ind = i;
91                 }
92         }
93         
94         for (unsigned i = 0; i < sizeof(notes)/sizeof(note); ++i)
95                 if (i == best_away_ind)
96                         printf("#");
97                 else
98                         printf(".");
99
100         printf(" (%s %+.2f, %5.2fHz) [%5.2fdB]  [", notes[best_away_ind].notename, best_away, freq, amp);
101
102         // coarse tuning
103         for (int i = -10; i <= 10; ++i) {
104                 if (best_away >= (i-0.5) * 0.05 && best_away < (i+0.5) * 0.05) {
105                         printf("#");
106                 } else {
107                         if (i == 0) {
108                                 printf("|");
109                         } else {
110                                 printf("-");
111                         }
112                 }
113         }
114         printf("]  [");
115         
116         // fine tuning
117         for (int i = -10; i <= 10; ++i) {
118                 if (best_away >= (i-0.5) * 0.01 && best_away < (i+0.5) * 0.01) {
119                         printf("#");
120                 } else {
121                         if (i == 0) {
122                                 printf("|");
123                         } else {
124                                 printf("-");
125                         }
126                 }
127         }
128         printf("]\n");
129 }
130 #endif