In glpitch, stretch the x axis a bit so that we have more precision around the intere...
authorsgunderson@bigfoot.com <>
Mon, 19 Jul 2010 23:42:44 +0000 (01:42 +0200)
committersgunderson@bigfoot.com <>
Mon, 19 Jul 2010 23:42:44 +0000 (01:42 +0200)
config.h
glpitch.cpp

index 87f25e9..da6a691 100644 (file)
--- a/config.h
+++ b/config.h
 
 #define TUNING WELL_TEMPERED_GUITAR
 
+// Compress the x scale of the glpitch display in a nonlinear way
+// so that the view is more precise around the reference frequencies.
+#define COMPRESS_PITCH_DISPLAY 1
+
+// Lower is more compressed. Anything over 2-3 is probably going to negate
+// the entire effect.
+#define PITCH_COMPRESSION_SIGMA 1.0
+
 #endif /* !defined(_CONFIG_H) */
index a3c3010..4aea821 100644 (file)
@@ -9,11 +9,46 @@
 #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);
@@ -63,7 +98,7 @@ int main(void)
                glEnd();
 
                if (peak.second - log10(FFT_LENGTH) >= 0.0) {
-                       double peak_pos = find_pos(peak.first);
+                       double peak_pos = find_display_pos(peak.first);
 
                        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
                        glBegin(GL_QUADS);      
@@ -79,7 +114,7 @@ int main(void)
                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);
                }