Add calibration support.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 2 May 2013 18:46:37 +0000 (20:46 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 2 May 2013 18:46:37 +0000 (20:46 +0200)
decode.c

index e20c8c9..923913d 100644 (file)
--- a/decode.c
+++ b/decode.c
@@ -8,6 +8,9 @@
 #define LANCZOS_RADIUS 30
 #define BUFSIZE 4096
 #define HYSTERESIS_LIMIT 1000
+#define SAMPLE_RATE 44100
+#define C64_FREQUENCY 985248
+#define TAP_RESOLUTION 8
 
 double sinc(double x)
 {
@@ -98,6 +101,10 @@ int main(int argc, char **argv)
                printf("%d\n", in[i]);
        }
 #endif
+
+       std::vector<float> pulse_lengths;  // in seconds
+
+       // Find the flanks.
        int last_bit = -1;
        double last_upflank = -1;
        int last_max_level = 0;
@@ -105,11 +112,9 @@ int main(int argc, char **argv)
                int bit = (pcm[i] > 0) ? 1 : 0;
                if (bit == 1 && last_bit == 0 && last_max_level > HYSTERESIS_LIMIT) {
                        // up-flank!
-                       double t = find_zerocrossing(pcm, i - 1) * (123156.0/44100.0);
+                       double t = find_zerocrossing(pcm, i - 1) * (1.0 / SAMPLE_RATE);
                        if (last_upflank > 0) {
-//                             fprintf(stderr, "length: %f (0x%x)\n", t - last_upflank, lrintf(t - last_upflank));
-                               int len = lrintf(t - last_upflank);
-                               printf("0x%x\n", len);
+                               pulse_lengths.push_back(t - last_upflank);
                        }
                        last_upflank = t;
                        last_max_level = 0;
@@ -117,4 +122,25 @@ int main(int argc, char **argv)
                last_max_level = std::max(last_max_level, abs(pcm[i]));
                last_bit = bit;
        }
+
+       // Calibrate on the first ~15k pulses (skip a few, just to be sure).
+       float calibration_factor = 1.0f;
+       if (pulse_lengths.size() < 20000) {
+               fprintf(stderr, "Too few pulses, not calibrating!\n");
+       } else {
+               double sum = 0.0;
+               for (int i = 1000; i < 16000; ++i) {
+                       sum += pulse_lengths[i];
+               }
+               double mean_length = C64_FREQUENCY * sum / 15000.0f;
+               calibration_factor = 380.0 / mean_length;
+               fprintf(stderr, "Cycle length: %.2f -> 380.0 (change %+.2f%%)\n",
+                       mean_length, 100.0 * (calibration_factor - 1.0));
+       }
+
+       for (int i = 0; i < pulse_lengths.size(); ++i) {
+               int len = lrintf(pulse_lengths[i] * calibration_factor * C64_FREQUENCY / TAP_RESOLUTION);
+               //fprintf(stderr, "length: %f (0x%x)\n", t - last_upflank, len);
+               printf("0x%x\n", len);
+       }
 }