X-Git-Url: https://git.sesse.net/?p=pitch;a=blobdiff_plain;f=glpitch.cpp;h=a168d79c5c4d3083bd4bf7766d2c9e46f6455a8c;hp=90c47b8502715ec95bda0f2a7e73a97c819dc26d;hb=abee20b74fec255942d42656047e371979ef0fcf;hpb=f5029e9edd2cff89ae9e0ff3d836d871c7c61f95 diff --git a/glpitch.cpp b/glpitch.cpp index 90c47b8..a168d79 100644 --- a/glpitch.cpp +++ b/glpitch.cpp @@ -9,15 +9,50 @@ #define MIN_X -40 #define MAX_X 5 -double find_pos(double freq) +double find_linear_pos(double freq) { return 12.0 * log2(freq / BASE_PITCH) - 3.0; } +#if COMPRESS_PITCH_DISPLAY +// bend the scale a bit to get more precision around the interesting points +double magnifying_glass(double x) +{ + double sigma = PITCH_COMPRESSION_SIGMA; + double div = 1.0 / sqrt(2.0 * sigma * sigma); + return + erf((x - find_linear_pos(notes[0].freq)) * div) + + erf((x - find_linear_pos(notes[1].freq)) * div) + + erf((x - find_linear_pos(notes[2].freq)) * div) + + erf((x - find_linear_pos(notes[3].freq)) * div) + + erf((x - find_linear_pos(notes[4].freq)) * div) + + erf((x - find_linear_pos(notes[5].freq)) * div); +} + +// like nonlinear_func, but f(MIN_X) = MIN_X and f(MAX_X) = MAX_X +double normalized_magnifying_glass(double x) +{ + double y = magnifying_glass(x); + double min_y = magnifying_glass(MIN_X); + double max_y = magnifying_glass(MAX_X); + return (y - min_y) * (MAX_X - MIN_X) / (max_y - min_y) + MIN_X; +} +#endif /* COMPRESS_PITCH_DISPLAY */ + +double find_display_pos(double freq) +{ + double linear_pos = find_linear_pos(freq); +#if COMPRESS_PITCH_DISPLAY + return normalized_magnifying_glass(linear_pos); +#else + return linear_pos; +#endif +} + int main(void) { PitchDetector pd(SAMPLE_RATE, FFT_LENGTH, PAD_FACTOR, OVERLAP); - int fd = get_dsp_fd(SAMPLE_RATE, FFT_LENGTH, OVERLAP); + snd_pcm_t *pcm = get_dsp_handle(SAMPLE_RATE); SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -25,10 +60,24 @@ int main(void) glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); for ( ;; ) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_KEYUP: + if (event.key.keysym.sym == SDLK_ESCAPE) { + exit(0); + } + break; + case SDL_QUIT: + exit(0); + } + } + short buf[FFT_LENGTH / PAD_FACTOR / OVERLAP]; - read_chunk(fd, buf, FFT_LENGTH / PAD_FACTOR / OVERLAP); + read_chunk(pcm, buf, FFT_LENGTH / PAD_FACTOR / OVERLAP); std::pair peak = pd.detect_pitch(buf); glMatrixMode(GL_PROJECTION); @@ -49,23 +98,30 @@ int main(void) glVertex2f(MAX_X, 0.0f); glEnd(); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); + if (peak.second - log10(FFT_LENGTH) >= 0.0) { + double peak_pos = find_display_pos(peak.first); + double strength = peak.second / 40.0f; - double peak_pos = find_pos(peak.first); + glEnable(GL_POLYGON_SMOOTH); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glEnable(GL_POLYGON_SMOOTH); - glBegin(GL_QUADS); - glColor4f(0.0, 1.0f, 0.0f, 0.2f); - glVertex2f(peak_pos - 0.1, 0.0f); - glVertex2f(peak_pos - 0.1, 1.0f); - glVertex2f(peak_pos + 0.1, 1.0f); - glVertex2f(peak_pos + 0.1, 0.0f); - glEnd(); + glBegin(GL_QUADS); + glColor4f(0.0f, strength, 1.0 - strength, 0.2f); + glVertex2f(peak_pos - 0.1, 0.0f); + glVertex2f(peak_pos - 0.1, 1.0f); + glVertex2f(peak_pos + 0.1, 1.0f); + glVertex2f(peak_pos + 0.1, 0.0f); + glEnd(); + + glDisable(GL_POLYGON_SMOOTH); + } glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_LINES); for (int i = 0; i < 6; ++i) { - double pos = find_pos(notes[i].freq); + double pos = find_display_pos(notes[i].freq); glVertex2f(pos, 0.0f); glVertex2f(pos, 1.0f); }