#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);
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<double, double> peak = pd.detect_pitch(buf);
glMatrixMode(GL_PROJECTION);
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);
}