]> git.sesse.net Git - audiosync/commitdiff
Change from sine to square triggering.
authorsgunderson@bigfoot.com <>
Thu, 28 Dec 2006 18:55:29 +0000 (19:55 +0100)
committersgunderson@bigfoot.com <>
Thu, 28 Dec 2006 18:55:29 +0000 (19:55 +0100)
estimate-skew.c [deleted file]
estimate-skew.cpp [new file with mode: 0644]

diff --git a/estimate-skew.c b/estimate-skew.c
deleted file mode 100644 (file)
index e8ba75e..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-
-double frac(double x)
-{
-       return x - (int)x;
-}
-
-double filter(double x)
-{
-       static double l = 0.0;
-       l = 0.001 * x + 0.999 * l;
-       return l;
-}
-
-int main(int argc, char **argv)
-{
-       FILE *in1, *in2, *skew;
-
-       // open input1 (reference)
-       if (strcmp(argv[1], "-") == 0) {
-               in1 = stdin;
-       } else {
-               in1 = fopen(argv[1], "rb");
-               if (in1 == NULL) {
-                       perror(argv[1]);
-                       exit(1);
-               }
-       }
-
-       // open input2
-       if (strcmp(argv[2], "-") == 0) {
-               in2 = stdin;
-       } else {
-               in2 = fopen(argv[2], "rb");
-               if (in2 == NULL) {
-                       perror(argv[2]);
-                       exit(1);
-               }
-       }
-
-       // open (estimated) skew
-       if (strcmp(argv[3], "-") == 0) {
-               skew = stderr;
-       } else {
-               skew = fopen(argv[3], "wb");
-               if (skew == NULL) {
-                       perror(argv[3]);
-                       exit(1);
-               }
-       }
-
-       short prev_sample, sample = 0;
-       int in_pos = -1;
-       double p = 0.0;
-       double speed = 1.001;
-
-       while (!feof(in1) && !feof(in2)) {
-               short refs;
-
-               // read sample from reference
-               if (fread(&refs, sizeof(short), 1, in1) != 1) {
-                       exit(0);
-               }
-
-               // read sample from in2 (at current speed)
-               p += speed;
-               while ((int)(ceil(p)) > in_pos) {
-                       prev_sample = sample;
-                       if (fread(&sample, sizeof(short), 1, in2) != 1) {
-                               exit(0);
-                       }
-                       ++in_pos;
-               }
-
-               // linear interpolation (works well since delta_p varies so slowly)
-               double t = frac(p);
-               double intp_sample = prev_sample * (1.0 - t) + sample * t;
-
-               // subtract the two samples and pull it through a filter. we assume
-               // the sines are normalized for now (and that there's no dc skew)
-               double offset = filter(intp_sample - refs);
-               speed += 1e-8 * offset;
-               fwrite(&speed, sizeof(double), 1, skew);
-
-               printf("%f (offset=%f / filt=%f)\n", speed, intp_sample - refs, offset);
-       }
-}
diff --git a/estimate-skew.cpp b/estimate-skew.cpp
new file mode 100644 (file)
index 0000000..f129c49
--- /dev/null
@@ -0,0 +1,199 @@
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+double frac(double x)
+{
+       return x - (int)x;
+}
+
+class FlankDetector
+{
+private:
+       static const unsigned NUM_SAMPLES = 10;
+       static const int MIN_LEVEL = 8192;
+
+       bool status, flag;  // high/low
+       unsigned counter;
+
+public:
+       FlankDetector() : status(false), flag(false), counter(0) {}
+       void update(short x)
+       {
+               if (abs(x) < MIN_LEVEL) {
+                       counter = 0;
+                       return;
+               }
+
+               if (!status) {
+                       // low
+                       if (x >= MIN_LEVEL) {
+                               ++counter;
+                       } else {
+                               counter = 0;
+                       }
+               } else {
+                       // high
+                       if (x <= -MIN_LEVEL) {
+                               ++counter;
+                       } else {
+                               counter = 0;
+                       }
+               }
+
+               if (counter >= NUM_SAMPLES) {
+                       status = !status;
+                       counter = 0;
+                       flag = true;
+               }
+       }
+
+       bool check_flag()
+       {
+               bool ret = flag;
+               flag = false;
+               return ret;
+       }
+
+       bool get_status() const
+       {
+               return status;
+       }
+};
+
+class InterpolatingReader
+{
+private:
+       FILE *f;
+       double speed;
+       double p;
+       int in_pos;
+       short prev_sample;
+
+public:
+       InterpolatingReader(FILE *f) : f(f), speed(1.0), p(0.0), in_pos(-1) {}
+
+       void update_speed(double speed)
+       {
+               this->speed = speed;
+       }
+
+       double read_sample()
+       {
+               short sample;
+
+               p += speed;
+               while ((int)(ceil(p)) > in_pos) {
+                       prev_sample = sample;
+                       if (fread(&sample, sizeof(short), 1, f) != 1) {
+                               exit(0);
+                       }
+                       ++in_pos;
+               }
+
+               // linear interpolation (works OK since delta_p varies so slowly)
+               double t = frac(p);
+               return prev_sample * (1.0 - t) + sample * t;
+       }
+};
+
+double filter(double x)
+{
+       static double l = 1.0;
+       l = 0.01 * x + 0.99 * l;
+       return l;
+}
+
+int main(int argc, char **argv)
+{
+       FILE *in1, *in2, *skew;
+
+       // open input1 (reference)
+       if (strcmp(argv[1], "-") == 0) {
+               in1 = stdin;
+       } else {
+               in1 = fopen(argv[1], "rb");
+               if (in1 == NULL) {
+                       perror(argv[1]);
+                       exit(1);
+               }
+       }
+
+       // open input2
+       if (strcmp(argv[2], "-") == 0) {
+               in2 = stdin;
+       } else {
+               in2 = fopen(argv[2], "rb");
+               if (in2 == NULL) {
+                       perror(argv[2]);
+                       exit(1);
+               }
+       }
+
+       // open (estimated) skew
+       if (strcmp(argv[3], "-") == 0) {
+               skew = stderr;
+       } else {
+               skew = fopen(argv[3], "wb");
+               if (skew == NULL) {
+                       perror(argv[3]);
+                       exit(1);
+               }
+       }
+
+       FlankDetector f1, f2;
+
+       // initial sync, reference
+       do {
+               short s;
+               if (fread(&s, sizeof(short), 1, in1) != 1) {
+                       exit(0);
+               }
+
+               f1.update(s);
+       } while (!f1.check_flag() || !f1.get_status());
+       
+       // initial sync, input
+       do {
+               short s;
+               if (fread(&s, sizeof(short), 1, in2) != 1) {
+                       exit(0);
+               }
+
+               f2.update(s);
+       } while (!f2.check_flag() || !f2.get_status());
+
+       double speed = 1.000;
+
+       InterpolatingReader intp(in2);
+       intp.update_speed(speed);  // test to see if we can resync OK
+
+       while (!feof(in1) && !feof(in2)) {
+               short refs;
+
+               // read reference until the next triggering
+               unsigned num_ref = 0;
+               while (!feof(in1) && !f1.check_flag()) {
+                       if (fread(&refs, sizeof(short), 1, in1) != 1) {
+                               exit(0);
+                       }
+                       f1.update(refs);
+                       ++num_ref;
+               }
+
+               // same here
+               unsigned num_inp = 0;
+               while (!feof(in2) && !f2.check_flag()) {
+                       double s = intp.read_sample();
+                       f2.update((short)s);
+                       ++num_inp;
+               }
+
+               double ns = filter(speed * double(num_inp) / double(num_ref));
+               printf("%u vs. %u -- ratio %f, speed %f, filtered speed %f\n", num_inp, num_ref,
+                       double(num_inp) / double(num_ref), speed * double(num_inp) / double(num_ref), ns);
+               speed = ns;
+               intp.update_speed(ns);
+       }
+}