]> git.sesse.net Git - audiosync/blob - estimate-skew.cpp
Move the speed variable out.
[audiosync] / estimate-skew.cpp
1 #include <stdio.h>
2 #include <string.h>
3 #include <math.h>
4 #include <stdlib.h>
5
6 double frac(double x)
7 {
8         return x - (int)x;
9 }
10
11 class FlankDetector
12 {
13 private:
14         static const unsigned NUM_SAMPLES = 10;
15         static const int MIN_LEVEL = 8192;
16
17         bool status, flag;  // high/low
18         unsigned counter;
19
20 public:
21         FlankDetector() : status(false), flag(false), counter(0) {}
22         void update(short x)
23         {
24                 if (abs(x) < MIN_LEVEL) {
25                         counter = 0;
26                         return;
27                 }
28
29                 if (!status) {
30                         // low
31                         if (x >= MIN_LEVEL) {
32                                 ++counter;
33                         } else {
34                                 counter = 0;
35                         }
36                 } else {
37                         // high
38                         if (x <= -MIN_LEVEL) {
39                                 ++counter;
40                         } else {
41                                 counter = 0;
42                         }
43                 }
44
45                 if (counter >= NUM_SAMPLES) {
46                         status = !status;
47                         counter = 0;
48                         flag = true;
49                 }
50         }
51
52         bool check_flag()
53         {
54                 bool ret = flag;
55                 flag = false;
56                 return ret;
57         }
58
59         bool get_status() const
60         {
61                 return status;
62         }
63 };
64
65 class InterpolatingReader
66 {
67 private:
68         FILE *f;
69         double p;
70         int in_pos;
71         short prev_sample;
72
73 public:
74         InterpolatingReader(FILE *f) : f(f), p(0.0), in_pos(-1) {}
75
76         double read_sample(double speed)
77         {
78                 short sample;
79
80                 p += speed;
81                 while ((int)(ceil(p)) > in_pos) {
82                         prev_sample = sample;
83                         if (fread(&sample, sizeof(short), 1, f) != 1) {
84                                 exit(0);
85                         }
86                         ++in_pos;
87                 }
88
89                 // linear interpolation (works OK since delta_p varies so slowly)
90                 double t = frac(p);
91                 return prev_sample * (1.0 - t) + sample * t;
92         }
93 };
94
95 double filter(double x)
96 {
97         static double l;
98         static bool init = false;
99
100         if (init) {
101                 l = 0.05 * x + 0.95 * l;
102         } else {
103                 init = true;
104                 l = x;
105         }
106         return l;
107 }
108
109 int main(int argc, char **argv)
110 {
111         FILE *in1, *in2, *skew;
112
113         // open input1 (reference)
114         if (strcmp(argv[1], "-") == 0) {
115                 in1 = stdin;
116         } else {
117                 in1 = fopen(argv[1], "rb");
118                 if (in1 == NULL) {
119                         perror(argv[1]);
120                         exit(1);
121                 }
122         }
123
124         // open input2
125         if (strcmp(argv[2], "-") == 0) {
126                 in2 = stdin;
127         } else {
128                 in2 = fopen(argv[2], "rb");
129                 if (in2 == NULL) {
130                         perror(argv[2]);
131                         exit(1);
132                 }
133         }
134
135         // open (estimated) skew
136         if (strcmp(argv[3], "-") == 0) {
137                 skew = stderr;
138         } else {
139                 skew = fopen(argv[3], "wb");
140                 if (skew == NULL) {
141                         perror(argv[3]);
142                         exit(1);
143                 }
144         }
145
146         FlankDetector f1, f2;
147
148         // initial sync, reference
149         do {
150                 short s;
151                 if (fread(&s, sizeof(short), 1, in1) != 1) {
152                         exit(0);
153                 }
154
155                 f1.update(s);
156         } while (!f1.check_flag() || !f1.get_status());
157         
158         // initial sync, input
159         do {
160                 short s;
161                 if (fread(&s, sizeof(short), 1, in2) != 1) {
162                         exit(0);
163                 }
164
165                 f2.update(s);
166         } while (!f2.check_flag() || !f2.get_status());
167
168         InterpolatingReader intp(in2);
169         double speed = 1.000;
170
171         while (!feof(in1) && !feof(in2)) {
172                 short refs;
173
174                 // read reference until the next triggering
175                 unsigned num_ref = 0;
176                 while (!feof(in1) && !f1.check_flag()) {
177                         if (fread(&refs, sizeof(short), 1, in1) != 1) {
178                                 exit(0);
179                         }
180                         f1.update(refs);
181                         ++num_ref;
182                 }
183
184                 // same here
185                 unsigned num_inp = 0;
186                 while (!feof(in2) && !f2.check_flag()) {
187                         double s = intp.read_sample(speed);
188                         f2.update((short)s);
189                         ++num_inp;
190                 }
191
192                 double ns = filter(speed * double(num_inp) / double(num_ref));
193                 printf("%u vs. %u -- ratio %.3f, speed %.3f, filtered speed %.3f\n", num_inp, num_ref,
194                         double(num_inp) / double(num_ref), speed * double(num_inp) / double(num_ref), ns);
195                 speed = ns;
196         }
197 }