]> Shamusworld >> Repos - wozmaker/blob - src/dsp.cpp
98800a26bb6aceaf3eef6b26dc69b4c664cecc78
[wozmaker] / src / dsp.cpp
1 //
2 // dsp.cpp: Digital Signal Processing module
3 //
4 // Part of the WOZ Maker project
5 // by James Hammons
6 // (C) 2018 Underground Software
7 //
8
9 #include "dsp.h"
10 #include <math.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include "fileio.h"
14 #include "global.h"
15
16
17 //#define NOISY
18
19 // Really, there shouldn't be more than 5 waveforms per track
20 //static uint32_t total = 0;//trkStrms
21 //static uint32_t slip[9];
22 //double ratio[9];
23 uint32_t sNum[9];
24 double initSyncTime[9];
25
26 static const double SIGMA_THRESHOLD = 2.5;
27
28
29 double StdDeviation(double * a, uint32_t num, double * pMean/*= NULL*/)
30 {
31         double sigma = 0, mean = 0;
32
33         for(uint32_t i=0; i<num; i++)
34                 mean += a[i];
35
36         mean = mean / (double)num;
37
38         if (pMean)
39                 *pMean = mean;
40
41         for(uint32_t i=0; i<num; i++)
42                 sigma += (a[i] - mean) * (a[i] - mean);
43
44         sigma *= 1.0 / (double)num;
45         return sqrt(sigma);
46 }
47
48
49 double StdDeviationWave(uint32_t * sync, uint32_t num, double * m = NULL);
50 double StdDeviationWave(uint32_t * sync, uint32_t num, double * m/*= NULL*/)
51 {
52         double sigma = 0, mean = 0;
53         double a[7];
54
55         for(uint32_t i=0; i<num; i++)
56         {
57                 a[i] = (double)Global::wave[sNum[i]][sync[i]];
58                 mean += a[i];
59         }
60
61         mean = mean / (double)num;
62
63         // Capture the mean, if a pointer was passed in
64         if (m)
65                 *m = mean;
66
67         for(uint32_t i=0; i<num; i++)
68                 sigma += (a[i] - mean) * (a[i] - mean);
69
70         return sqrt(sigma / (double)num);
71 }
72
73
74 double Largest(double * a, uint32_t num)
75 {
76         double largest = a[0];
77
78         for(uint32_t i=1; i<num; i++)
79         {
80                 if (a[i] > largest)
81                         largest = a[i];
82         }
83
84         return largest;
85 }
86
87
88 uint32_t Largest(uint32_t * a, uint32_t num)
89 {
90         uint32_t largest = a[0];
91
92         for(uint32_t i=1; i<num; i++)
93         {
94                 if (a[i] > largest)
95                         largest = a[i];
96         }
97
98         return largest;
99 }
100
101
102 uint32_t LargestIndex(double * a, uint32_t num)
103 {
104         double largest = a[0];
105         uint32_t index = 0;
106
107         for(uint32_t i=1; i<num; i++)
108         {
109                 if (a[i] > largest)
110                 {
111                         largest = a[i];
112                         index = i;
113                 }
114         }
115
116         return index;
117 }
118
119
120 uint32_t LargestIndex(uint32_t * a, uint32_t num)
121 {
122         uint32_t largest = a[0];
123         uint32_t index = 0;
124
125         for(uint32_t i=1; i<num; i++)
126         {
127                 if (a[i] > largest)
128                 {
129                         largest = a[i];
130                         index = i;
131                 }
132         }
133
134         return index;
135 }
136
137
138 double Smallest(double * a, uint32_t num)
139 {
140         double smallest = a[0];
141
142         for(uint32_t i=1; i<num; i++)
143         {
144                 if (a[i] < smallest)
145                         smallest = a[i];
146         }
147
148         return smallest;
149 }
150
151
152 uint32_t Smallest(uint32_t * a, uint32_t num)
153 {
154         uint32_t smallest = a[0];
155
156         for(uint32_t i=1; i<num; i++)
157         {
158                 if (a[i] < smallest)
159                         smallest = a[i];
160         }
161
162         return smallest;
163 }
164
165
166 uint32_t SmallestIndex(double * a, uint32_t num)
167 {
168         double smallest = a[0];
169         uint32_t index = 0;
170
171         for(uint32_t i=1; i<num; i++)
172         {
173                 if (a[i] < smallest)
174                 {
175                         smallest = a[i];
176                         index = i;
177                 }
178         }
179
180         return index;
181 }
182
183
184 uint32_t SmallestIndex(uint32_t * a, uint32_t num)
185 {
186         uint32_t smallest = a[0];
187         uint32_t index = 0;
188
189         for(uint32_t i=1; i<num; i++)
190         {
191                 if (a[i] < smallest)
192                 {
193                         smallest = a[i];
194                         index = i;
195                 }
196         }
197
198         return index;
199 }
200
201
202 //
203 // This is where we attempt to use the stream data to collapse them down to a single track.  Taken as wholes, each individual track will drift out of sync with respect to the others, and fairly quickly as the drive mechanism does not read consistently at a set RPM as you might expect, but instead it fluctuates all over the place--which throws a big ol' monkey wrench into the works.  (Yes, the overall *average* stays around a set RPM, but locally--nope.)
204 //
205 // The big problem is that the disk spins via a motor which isn't perfect in its rotation that is connected to the hub that spins the disk via a belt, which further adds more uncertainty to the speed of the disk as it rotates.  The end result is that there is no consistency vis-a-vis the speed of the disk, and so the results of one read to the next can and will vary wildly.  It's a miracle that these things are readable at all.  O_o
206 //
207 // So how do we cope with it?  I'm sure there's a well known paper or set of papers which addresses noise rejection from multiple signals read from a single source, but I have yet to find them.  So what we have below is a set of ad-hoc assumptions and heuristics that attempt to deal with this problem.
208 //
209 // The basic assumption is that from any given pulse to the next one, the drift will tend to be small and thus as we move from pulse to pulse, we can stay more or less in sync by resetting the base from which we calculate the next time interval to the previous step.  This works remarkably well until we run into a long period of zeroes, which seems to throw off the Applesauce hardware which read these streams in the first place; or when some spurious one pulses pop up in one stream that doesn't in one or more of the others.
210 //
211 #if 0
212 uint32_t Synthesize(uint32_t * sync, uint32_t num, uint32_t * synthWave, float * swAmplitude)
213 {
214         uint32_t swLen = 0;
215         uint32_t syncPt[9], syncSave[9], nrSync[9];
216         double a[9], currentRow[9], nextRow[9];
217         double time[9][32], drift[9];
218         uint32_t timePtr = 0;
219
220         memcpy(syncPt, sync, sizeof(syncPt));
221
222         while (true)
223         {
224                 for(uint32_t i=0; i<num; i++)
225                 {
226                         if (syncPt[i] >= Global::streamLen[i])
227                                 return swLen;
228                 }
229
230                 // Save these *before* we step forward
231                 memcpy(syncSave, syncPt, sizeof(syncSave));
232                 StepForward(syncPt, a, num);
233                 double mean;
234                 double sigma = StdDeviation(a, num, &mean);
235
236                 if (sigma <= SIGMA_THRESHOLD)
237                 {
238                         for(uint32_t i=0; i<num; i++)
239                                 time[i][timePtr] = a[i];
240
241                         timePtr = (timePtr + 1) % 32;
242
243                         synthWave[swLen] = (uint32_t)(mean + 0.5);
244                         swAmplitude[swLen] = 1.0f;
245                         swLen++;
246                 }
247                 else
248                 {
249                         // Calculate drift over the last 32 time steps...
250                         for(uint32_t i=0; i<num; i++)
251                         {
252                                 drift[i] = 0;
253
254                                 for(uint32_t j=0; j<32; j++)
255                                         drift[i] += time[i][j];
256                         }
257
258                         double driftSigma = StdDeviation(drift, num);
259                         memcpy(nrSync, syncPt, sizeof(nrSync));
260                         StepForward(nrSync, nextRow, num);
261                         double nextSigma = StdDeviation(nextRow, num);
262                         uint32_t lookahead = Lookahead(nrSync, num, +1);
263
264                         // The basic idea is to find the extent of this anomalous region and then use what's there as an amplitude by summing the signals where they correspond.
265 //                      memcpy(syncSave, syncPt, sizeof(syncSave));
266                         bool pulled, doSync = true;
267                         uint32_t syncSteps = 0;
268
269                         // Basically we move forward thru the area until either 1) the sigma is OK, or 2) we've pulled everything as far as it can go and thus this becomes our new local start. 3) will go in at some point which is, do a lookahead and see what the sigma looks like; if it's good and the current one is stinko, (not *too* stinko) then we've found a new local start point, otherwise keep going.
270 /*
271 Note that 3) works OK to get out of sticky situations, but sometimes the signals are fairly noisy and you will end up in situations where the lookahead is zero and the next sigma isn't great (& the current isn't any good either), but using that as the new local start is OK and will permit walking forward/backward through the stream.  Some of the time you will find the average of the current sigma and the following will be below the threshold with a good lookahead value (10, 100, 1000), this is also a good time to set the new local start.
272 */
273 #ifdef NOISY
274 printf("a: ");
275 for(uint32_t i=0; i<num; i++)
276         printf("[%.2lf]", a[i]);
277 printf(" => %.2lf {drift=%.2lf, la=%d}\n", sigma, driftSigma, lookahead);
278 #endif
279                         // New heuristic: if the sigma of the current row is less than the sigma of the drift over the last 32 steps, we consider that to be "in sync"; otherwise, do the usual stuff
280 /*
281 This works until you hit this:
282 a: [1167.00][1174.00][1169.00] => 2.94
283           ~~~~
284 <1167.00><1174.00><1169.00> ==> 2.94 {drift=0.82}(!!!) (lookahead=2.94, 630)
285 {12168}-{12166}-{12166}
286           ~~~~
287 <1198.00><1205.00><1200.00> ==> 2.94 {drift=0.82} (lookahead=0.00, 629)
288 {12169}-{12167}-{12167}
289           ~~~~
290 <1231.00><1238.00><1233.00> ==> 2.94 {drift=0.82} (lookahead=0.00, 628)
291 ----------------
292 <337.00><334.00><335.00> ==> 1.25 (OK) (lookahead=18.40, 1705)
293 {1260}-{1259}-{1258}
294 a: [1111.00][1100.00][1097.00] => 6.02 {drift=7.72, la=0}
295 a: [42.00][51.00][45.00] => 3.74 {drift=7.72, la=150}
296   20.00   ~~~~     0.00
297 < 62.00>< 51.00>< 45.00> ==> 7.04 (lookahead=13.42, 0)
298 {2972}-{2970}-{2969}
299   ~~~~    20.00   13.00 <-- the more I look at it, the more I think we need to coalesce these into their next steps... (can be done in StepForward/Back())
300 -------------------
301 it does OK but fails because we don't check *inside* the loop
302 <363.00><364.00><364.00> ==> 0.47 (OK) (lookahead=52.33, 1704)
303 {25947}-{25931}-{25922}
304 a: [33.00][15.00][47.00] => 13.10 {drift=3.86, la=150}
305  1149.00  1158.00   ~~~~
306 <1182.00><1173.00>< 47.00> ==> 532.94 (lookahead=40.94, 0)
307 {27657}-{27641}-{27627}
308   ~~~~    31.00  1155.00
309 <1182.00><1204.00><1202.00> ==> 9.93 (lookahead=46.20, 6)
310 {27657}-{27642}-{27633}
311   31.00   ~~~~     0.00
312 <1213.00><1204.00><1202.00> ==> 4.78 (lookahead=0.00, 149)
313 {27658}-{27642}-{27633}
314
315 */
316                         // We check for large zero areas for the new heuristic
317 //buuuuuuuut... it fails for the stuff that tags along at the end, so...
318 /*
319 After looking at this long and hard, and thinking about the fairly random nature of the disk speed as it turns, I've come to the conclusion that trying to use the local speed drift (whatever that means) is futile.  It's random; it just doesn't correlate, period.  So stuff like the following is pretty much crap.
320 */
321                         if ((mean > 9.0)//00.0)
322                                 && ((sigma < StdDeviation(drift, num))
323                                         || (((sigma + nextSigma) / 2.0) < SIGMA_THRESHOLD)))
324                         {
325                                 doSync = false;
326                         }
327
328                         if (doSync)
329                         {
330                                 do
331                                 {
332                                         syncSteps++;
333
334                                         // If we've been in this loop too long, something's very wrong
335                                         if (syncSteps > 20)
336                                                 return swLen;
337
338                                         // Pull the lesser streams forward to catch up to the largest
339                                         uint32_t largestIdx = LargestIdx(a, num);
340                                         pulled = false;
341
342                                         for(uint32_t i=0; i<num; i++)
343                                         {
344                                                 if (i == largestIdx)
345 #ifdef NOISY
346                                                 {
347                                                         printf("  ~~~~  ");
348 #endif
349                                                         continue;
350 #ifdef NOISY
351                                                 }
352 #endif
353
354                                                 double ttn = 0;
355                                                 uint32_t walkahead = syncPt[i];
356
357                                                 while ((a[largestIdx] - (a[i] + ttn)) > 7.0)
358                                                 {
359                                                         pulled = true;
360
361                                                         if (walkahead >= Global::streamLen[i])
362                                                         {
363                                                                 // We ran out of road, so we're done for now
364                                                                 return swLen;
365                                                         }
366 /*
367 Maybe rename this to StepForwardSngl and the other to StepForwardAll?
368 because otherwise, this can become murky
369 [well, should be able to tell from the context.
370 well, the thing that's murky is the all clears the array while the single adds to the existing.  now *that's* confusing...  :-P]
371 we can call it StepAndAddForward/Back; that would clear it up.
372 */
373                                                         StepAndAddForward(walkahead, ttn, i);
374                                                 }
375
376                                                 syncPt[i] = walkahead;
377                                                 a[i] += ttn;
378 #ifdef NOISY
379                                                 if (pulled)
380                                                         printf(" %6.2lf ", ttn);
381                                                 else
382                                                         printf("        ");
383 #endif
384                                         }
385
386 #ifdef NOISY
387                                         printf("\n");
388
389                                         for(uint32_t i=0; i<num; i++)
390                                                 printf("<%6.2lf>", a[i]);
391 #endif
392                                         // Calculate the standard deviation at this new point
393                                         sigma = StdDeviation(a, num, &mean);
394 #ifdef NOISY
395                                         printf(" ==> %.2lf%s", sigma, (sigma <= SIGMA_THRESHOLD ? " (OK)" : (!pulled ? "(STEP)" : "")));
396
397 double lookahead[9];
398 //printf(" {drift=%.2lf}", driftSigma);
399 uint32_t minSyncIdx = SmallestIdx(syncPt, num);
400 if (syncPt[minSyncIdx] > 0)
401 {
402         for(uint32_t i=0; i<num; i++)
403                 lookahead[i] = (double)Global::streamData[i][syncPt[i] + 0] * ratio[i];
404         printf(" (lookahead=%.2lf, %d)\n", StdDeviation(lookahead, num), Lookahead(syncPt, num, +1));
405 }
406 else
407         printf("\n");
408
409 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", syncPt[j], (j < num - 1 ? "-" : "")); }
410 printf("\n");
411 #endif
412
413                                         // Heuristic: see if we're stuck with a bad sigma and can't pull any more forward; if so, pull forward one step and see if that gets us any traction...
414                                         if ((sigma > SIGMA_THRESHOLD) && !pulled)
415                                         {
416                                                 for(uint32_t i=0; i<num; i++)
417                                                         StepAndAddForward(syncPt[i], a[i], i);
418
419                                                 sigma = StdDeviation(a, num, &mean);
420                                                 pulled = true;
421                                         }
422                                 }
423                                 while ((sigma > SIGMA_THRESHOLD) && pulled);
424                         }
425
426                         // Now, we've re-established sync, now fill the appropriate spots
427
428 /*
429 So the algorithm to do this proppaly is like so:
430
431 Step 1: Find the smallest step forward through the section; set amplitude to 0.2.
432 Step 2: Loop thru the other streams and see if they correspond.  If so, advance their stream start & add 0.2 to the amplitude for each one seen.
433 Step 3: Add the mean value of the corresponding values to the synthesized waveform + wave amplitude
434 Step 4: If all of the stream starts are at the end of the section, we are done.
435 [maybe.  how do you handle the case where you have streams that look like so:
436
437 200
438 150 50
439 150 50
440 175 25
441 200
442
443 .......................................|
444 .............................|.........|
445 .............................|.........|
446 ..................................|....|
447 .......................................|
448
449 this will fail to add in the correct amount for the times that had no part in the anomaly.  so to fix this, maybe have a baseline value that bumps upward to show where the "cursor" (so to speak) is, so at the end we can subtract the mean that we got above from this baseline to get the remaining time to synthesize, like so:
450
451 synthWave[swLen] = (uint32_t)((mean - baseline) + 0.5)
452 swAmplitude[swLen] = amplitude;
453
454 no need for that.  the times that step directly to the end can safely be ignored.
455 ]
456
457 150 -> 150 (ignores 175)
458 150 goes in, ampl. .4, we now have:
459
460 200
461 50
462 50
463 175 25
464 200
465
466 only one is left that we can grab:
467
468 175
469
470 last pulse was at 150 (40%), so we need to subtract that out
471
472 -> 25
473
474 so maybe we'd do like so:
475 -1) create a list containing the start values for the start of the anomalous section and replace them as the counters advance.
476 0) are streams at the end? if so, stuff in the final value to the synthesized wave & stop, otherwise:
477 1) find the smallest in the current row and use that as a basis.
478 2) find streams that correlate, if any
479 3) advance the streams that correlate & subtract out the minimum from the other rows
480 4) go to 0)
481
482 200
483 150 50
484 150 50
485 175 25
486 200
487
488 smallest is 150: pick 150 -> picks up 150
489 advance the 150 rows & subtract 150 from the rest:
490
491 50
492 50
493 50
494 25 25
495 50
496
497 pick smallest: 25 -> picks up nothing
498 advance the 25 & subtract it from the rest:
499
500 25
501 25
502 25
503 25
504 25
505
506 We've reached the end of the section, add the final amount
507
508 --------------------------------------------------------------------------------
509 syncSave before: [2->4][2->6][2->4][2->6][2->6]
510 syncSave after: [3->4][3->6][3->4][3->6][3->6]
511
512 currentRow: [120.89][49.97][46.98][49.98][48.98] => 28.78
513
514 2: [3->4][3->6][3->4][3->6][3->6]
515
516 a[0]=46.98: [120.89] ==> 36.95
517         [49.97]{17.00} ==> 1.50
518         <106.00>[49.97][49.98]{28.00} ==> 1.41
519         [49.97][49.98][48.98]{26.00} ==> 1.22
520
521 3: [3->4][4->6][4->4][4->6][4->6]
522
523 a[0]=17.00: [73.91] ==> 28.45
524         <56.00>[28.00]{45.00} ==> 5.50
525         [28.00][26.00]{47.00} ==> 4.78
526
527 4: [3->4][5->6][4->4][5->6][5->6]
528
529 a[0]=45.00: [56.91] ==> 5.95
530         [56.00]{32.00} ==> 5.50
531         <32.00>[56.00][47.00]{32.00} ==> 4.78
532
533 5: [3->4][6->6][4->4][6->6][6->6]
534
535 a[0]=11.91: <32.00>
536
537 6: [4->4][6->6][4->4][6->6][6->6]
538
539  2->4    2->6    2->4    2->6    2->6
540 [120.89][ 49.97][ 46.98][ 49.98][ 48.98] => 28.78
541 ( 73.91)  17.00  106.00   28.00   26.00
542 ( 56.91)  56.00           45.00   47.00
543   32.00   32.00           32.00   32.00
544
545 */
546 /*printf("syncSave before: ");
547 for(uint32_t i=0; i<num; i++)
548         printf("[%d->%d]", syncSave[i], syncPt[i]);
549 printf("\n");//*/
550
551                         // Collect the current row
552                         StepForward(syncSave, currentRow, num);
553                         bool done2;
554                         float ampStep = 1.0f / (float)num;
555
556 /*printf("syncSave after: ");
557 for(uint32_t i=0; i<num; i++)
558         printf("[%d->%d]", syncSave[i], syncPt[i]);
559 printf("\n");
560 printf("currentRow: ");
561 for(uint32_t i=0; i<num; i++)
562         printf("[%.2lf]", currentRow[i]);
563 printf(" => %.2lf\n", StdDeviation(currentRow, num));//*/
564
565                         done2 = true;
566
567 //printf("%d: ", swLen);
568                         for(uint32_t i=0; i<num; i++)
569                         {
570 //printf("[%d->%d]", syncSave[i], syncPt[i]);
571                                 if (syncSave[i] != syncPt[i])
572                                 {
573                                         done2 = false;
574 //                                      break;
575                                 }
576                         }
577 //printf("\n");
578
579                         while (!done2)
580                         {
581                                 float amplitude = ampStep;
582                                 uint32_t smallestIdx = SmallestIdx(currentRow, num);
583                                 uint32_t cnt = 1;
584                                 a[0] = currentRow[smallestIdx];
585 //printf("a[0]=%.2lf: ", a[0]);
586
587                                 for(uint32_t i=0; i<num; i++)
588                                 {
589                                         // Make sure we haven't gone beyond the end of any of the streams we're looking at
590                                         if (syncSave[i] >= Global::streamLen[i])
591                                                 return swLen;
592
593                                         if (i == smallestIdx)
594                                         {
595                                                 currentRow[i] = 0;
596                                                 StepAndAddForward(syncSave[i], currentRow[i], i);
597 //printf("<%.2lf>", currentRow[i]);
598
599                                                 // Make sure no spurious signals are looked at
600                                                 if ((syncSave[i] < syncPt[i]) && (currentRow[i] < 24.0))
601                                                         StepAndAddForward(syncSave[i], currentRow[i], i);
602
603                                                 continue;
604                                         }
605
606                                         double crSave = currentRow[i];
607                                         currentRow[i] -= a[0];
608
609                                         // Don't bother with stuff that's out of range!  :-P
610                                         if (syncSave[i] == syncPt[i])
611                                                 continue;
612
613                                         // Try to find correlates
614                                         a[cnt] = crSave;//currentRow[i];
615                                         cnt++;
616                                         sigma = StdDeviation(a, cnt, &mean);
617 //for(uint32_t j=1; j<cnt; j++)
618 //      printf("[%.2lf]", a[j]);
619
620 //relaxed sigma...
621                                         if (sigma <= 5.5)//SIGMA_THRESHOLD)
622                                         {
623                                                 currentRow[i] = 0;
624                                                 StepAndAddForward(syncSave[i], currentRow[i], i);
625 //printf("{%.2lf}", currentRow[i]);
626                                                 amplitude += ampStep;
627
628                                                 // Make sure no spurious signals are looked at
629                                                 if ((syncSave[i] < syncPt[i]) && (currentRow[i] < 24.0))
630                                                         StepAndAddForward(syncSave[i], currentRow[i], i);
631                                         }
632                                         else
633                                         {
634                                                 cnt--;
635                                         }
636 //printf(" ==> %.2lf\n\t", sigma);
637                                 }
638
639                                 sigma = StdDeviation(a, cnt, &mean);
640                                 synthWave[swLen] = (uint32_t)(mean + 0.5);
641                                 swAmplitude[swLen] = amplitude;
642                                 swLen++;
643                                 done2 = true;
644
645 //printf("%d: ", swLen);
646                                 for(uint32_t i=0; i<num; i++)
647                                 {
648 //printf("[%d->%d]", syncSave[i], syncPt[i]);
649                                         if (syncSave[i] != syncPt[i])
650                                         {
651                                                 done2 = false;
652 //                                              break;
653                                         }
654                                 }
655 //printf("\n");
656                         }
657
658                         sigma = StdDeviation(currentRow, num, &mean);
659                         synthWave[swLen] = mean;
660                         swAmplitude[swLen] = 1.0f;
661                         swLen++;
662                 }
663         }
664
665         return swLen;
666 }
667
668
669 //
670 // Attempt to find the sync point for the passed in stream #s.  If found, set
671 // sync1 & sync2 to the spots where sync was found (typically, one or the other
672 // will be zero) and return true, otherwise return false.
673 //
674 bool FindSync(uint32_t stream1, uint32_t stream2, uint32_t & sync1, uint32_t & sync2)
675 {
676         sync1 = sync2 = 0;
677
678         // We *should* be able to synchronize within around 80 fluxes or so.  If not, then there's bigger problems.
679         for(uint32_t offset=0; offset<80; offset++)
680         {
681                 uint32_t strmLen = Uint32LE(Global::stream[stream1]->dataLength);
682                 bool found = true;
683
684                 // How many bits should we consider as synchronized? All of them?
685                 for(uint32_t i=1, i2=1; i<strmLen; i++, i2++)
686                 {
687                         double time1 = (double)Global::stream[stream1]->data[i];
688                         double time2 = (double)Global::stream[stream2]->data[i2 + offset];
689
690                         while (Global::stream[stream1]->data[i] == 0xFF)
691                         {
692                                 i++;
693                                 time1 += (double)Global::stream[stream1]->data[i];
694                         }
695
696                         while (Global::stream[stream2]->data[i2] == 0xFF)
697                         {
698                                 i2++;
699                                 time2 += (double)Global::stream[stream2]->data[i2 + offset];
700                         }
701
702                         double mean = (time1 + time2) * 0.5;
703                         double sigma = sqrt(0.5 * (((time1 - mean) * (time1 - mean))
704                                 + ((time2 - mean) * (time2 - mean))));
705
706                         if (sigma > 2.50)
707                         {
708                                 // How many bits is enough to say we found it?
709 /*
710 N.B.: This (1,000) is fine for Apple Panic (which has shitty captures with junk in between sectors), but not for Championship Lode Runner which doesn't have any sync bytes for a loooooooooooong time
711 */
712                                 if (i < 10000)
713                                         found = false;
714
715                                 break;
716                         }
717                 }
718
719                 if (found)
720                 {
721                         sync2 = offset;
722                         return true;
723                 }
724         }
725
726         // Since we didn't find sync moving stream 2 forward, let's try stream 1
727         for(uint32_t offset=0; offset<80; offset++)
728         {
729                 uint32_t strmLen = Uint32LE(Global::stream[stream2]->dataLength);
730                 bool found = true;
731
732                 // How many bits should we consider as synchronized? All of them?
733                 for(uint32_t i=1, i2=1; i<strmLen; i++, i2++)
734                 {
735                         double time1 = (double)Global::stream[stream2]->data[i];
736                         double time2 = (double)Global::stream[stream1]->data[i2 + offset];
737
738                         while (Global::stream[stream2]->data[i] == 0xFF)
739                         {
740                                 i++;
741                                 time1 += (double)Global::stream[stream2]->data[i];
742                         }
743
744                         while (Global::stream[stream1]->data[i2] == 0xFF)
745                         {
746                                 i2++;
747                                 time2 += (double)Global::stream[stream1]->data[i2 + offset];
748                         }
749
750                         double mean = (time1 + time2) * 0.5;
751                         double sigma = sqrt(0.5 * (((time1 - mean) * (time1 - mean))
752                                 + ((time2 - mean) * (time2 - mean))));
753
754                         if (sigma > 2.50)
755                         {
756                                 // How many bits is enough to say we found it?
757                                 if (i < 10000)
758                                         found = false;
759
760                                 break;
761                         }
762                 }
763
764                 if (found)
765                 {
766                         sync1 = offset;
767                         return true;
768                 }
769         }
770
771         return false;
772 }
773
774
775 void FindSyncForStreams(uint32_t * syncPt, uint32_t num)
776 {
777 //      uint32_t syncPt[10] = { 0 };
778         uint32_t base = 0;
779         syncPt[0] = 0;
780
781         for(uint32_t i=1; i<num; i++)
782         {
783                 if (FindSync(sNum[base], sNum[i], syncPt[base], syncPt[i]) == true)
784                 {
785                         // Check to see which stream has to move.  If it's not the current base, then we don't have to do anything but check the next one; otherwise, we have to shift everything done prior by the amount of the shift and set the new base to be the one that didn't move.
786                         if (syncPt[base] != 0)
787                         {
788                                 for(uint32_t j=0; j<i; j++)
789                                 {
790                                         if (j != base)
791                                                 syncPt[j] += syncPt[base];
792                                 }
793
794                                 base = i;
795                         }
796                 }
797                 else
798                 {
799                         // should we do this? or just set a flag that we couldn't sync this one?
800                         syncPt[i] = -1;
801 //                      return;
802                 }
803         }
804
805         // If there was no sync for any of the other tracks, signal this by counting the number of non-sync tracks and checking against the total # of tracks - 1.
806         uint32_t nonSync = 0;
807
808         for(uint32_t i=1; i<num; i++)
809         {
810                 if (syncPt[i] == (uint32_t)-1)
811                         nonSync++;
812         }
813
814         // Signal that sync failed
815         if (nonSync == (num - 1))
816                 syncPt[0] = -1;
817 /*
818 v v
819 0 0 0 0 0  base = 0, i = 1
820
821 0  1
822 0, 10
823
824 v    v
825 0 10 0 0 0  base = 0, i = 2
826 5 10 0 0 0
827
828 0  2
829 5, 0
830
831      v v
832 5 15 0 0 0  base = 2, i = 3
833 5 15 0 7 0
834
835 2  3
836 0, 7
837
838      v   v
839 5 15 0 7 0  base = 2, i = 4
840 5 15 8 7 0
841
842 2  4
843 8, 0
844
845 13 23 8 15 0  base = 4
846
847         if (FindSync(sNum[0], sNum[1], syncPt[0], syncPt[1]) == false)
848         {
849                 // give up, we couldn't sync stream 0 & 1...  :-/
850         }
851
852         // check to see which one had to move, and use the other to check against the rest...
853         uint32_t base = (syncPt[0] == 0 ? 0 : 1);
854
855         if (FindSync(sNum[base], sNum[2], syncPt[base], syncPt[2]) == false)
856         {
857                 // give up, we couldn't sync stream 0 & 1...  :-/
858         }
859
860         // check again, to see which one moved and the other...
861         uint32_t base2 = (syncPt[base] == 0 ? base, 2);
862
863         // & so on...
864
865
866 */
867 }
868
869
870 void FindInitialSyncForStreams(uint32_t * sync, uint32_t num)
871 {
872 /*
873 What we need to do is find the FF. or FF.. or FE..s, then find the first non-zero trailing byte after that to be our sync point.  If we don't, we run the risk of getting bad starts because some bitstreams might have some sync starts that start with the wrong number of 1 bits, and thus walking back will fail.
874 */
875         // Let's try aligning samples to each other by counting to a short stream
876         // of FF.(.)s...
877         uint64_t bitPat0 = 0;
878
879         for(uint32_t i=0; i<num; i++)
880         {
881                 sync[i] = 0;
882                 uint64_t bitPat = 0;
883                 initSyncTime[i] = 0;
884
885                 // We'll use a naïve window to scan for the bit patterns
886                 for(int32_t j=0; j<Uint32LE(Global::stream[sNum[i]]->dataLength); j++)
887                 {
888                         uint32_t timeToNext = Global::streamData[i][j];
889
890                         while (Global::streamData[i][j] == 0xFF)
891                         {
892                                 j++;
893                                 timeToNext += Global::streamData[i][j];
894                         }
895
896                         initSyncTime[i] += (double)timeToNext;
897
898                         if ((timeToNext >= 24) && (timeToNext <= 49))
899                                 bitPat = (bitPat << 1) | 1;
900                         else if ((timeToNext >= 50) && (timeToNext <= 80))
901                                 bitPat = (bitPat << 2) | 1;
902                         else if ((timeToNext >= 81) && (timeToNext <= 112))
903                                 bitPat = (bitPat << 3) | 1;
904                         else
905                         {
906                                 while (timeToNext > 32)
907                                 {
908                                         bitPat <<= 1;
909                                         timeToNext -= 32;
910                                 }
911                         }
912
913                         if (i == 0)
914                                 bitPat0 = bitPat;
915
916                         // Search for first instance of 3 FF. or 3 FF.. in bitstream
917                         // Might need to look for FE.. as well
918                         //    0 1111 1111 0111 1111 1011 1111 1101
919                         // 0111 1111 1001 1111 1110 0111 1111 1001
920 //                      if (((bitPat & 0x1FFFFFFF) == 0x0FF7FBFD)
921 //                              || (bitPat & 0xFFFFFFFF) == 0x7F9FE7F9)
922                         // Need to see at least two regular bytes after as well:
923                         //    0 1111 1111 0111 1111 1011 1111 1101 xxxx xxx1 xxxx xxx1
924                         // 0111 1111 1001 1111 1110 0111 1111 1001 xxxx xxx1 xxxx xxx1
925                         if ((bitPat & 0x1FFFFFFF0101) == 0x0FF7FBFD0101)
926                         {
927                                 if ((i != 0) && (bitPat != bitPat0))
928                                         continue;
929
930                                 sync[i] = j - (j - 25 >= 0 ? 25 : 0);
931                                 break;
932                         }
933                         else if ((bitPat & 0xFFFFFFFF0101) == 0x7F9FE7F90101)
934                         {
935                                 if ((i != 0) && (bitPat != bitPat0))
936                                         continue;
937
938                                 sync[i] = j - (j - 25 >= 0 ? 25 : 0);
939                                 break;
940                         }
941                 }
942         }
943 }
944
945
946 //
947 // Walk through the streams backwards until we hit the zero point on one of them.  This assumes the sync point we found initially is a good one (it might not be!).
948 //
949 void BacktrackInitialSync(uint32_t * syncPt, uint32_t num)
950 {
951 //      uint32_t count = 0;
952         double a[10];
953 //      uint32_t syncSave[10];
954
955         // Save the original sync points (do we need to?)
956 //      for(uint32_t i=0; i<num; i++)
957 //              syncSave[i] = syncPt[i];
958
959         uint32_t minSlip = (uint32_t)-1;
960
961         for(uint32_t i=0; i<num; i++)
962         {
963                 if (syncPt[i] < minSlip)
964                         minSlip = syncPt[i];
965         }
966
967         while (minSlip > 0)
968         {
969                 // Get the time for this step into a[]
970                 for(uint32_t i=0; i<num; i++)
971                 {
972                         // We scale the time by a factor of the measured RPM to 300 RPM, which should get us closer to a "normal" time for all streams
973                         a[i] = (double)Global::stream[sNum[i]]->data[syncPt[i]];// * ratio[i];
974
975                         while ((syncPt[i] > 0)
976                                 && (Global::stream[sNum[i]]->data[syncPt[i] - 1] == 0xFF))
977                         {
978                                 syncPt[i]--;
979                                 a[i] += (double)Global::stream[sNum[i]]->data[syncPt[i]];// * ratio[i];
980                         }
981                 }
982
983                 double sigma = StdDeviation(a, num);
984 //              count++;
985
986                 if (sigma > SIGMA_THRESHOLD)
987                 {
988                         printf("\n");
989
990                         for(uint32_t i=0; i<num; i++)
991 //                              printf("<%6.2lf>", (double)Global::stream[sNum[i]]->data[syncPt[i]]);// * ratio[j]);
992                                 printf("<%6.2lf>", a[i]);// * ratio[j]);
993
994                         printf(" --> %.2lf\n", sigma);
995
996                         uint32_t syncCount = 0;
997
998                         // Save sync origins for later analysis
999 //                      for(uint32_t j=0; j<num; j++)
1000 //                              syncSave[j] = syncPt[j];
1001
1002                         // It may turn out that this is too large too...
1003                         while (sigma > 3.30)//SIGMA_THRESHOLD)
1004                         {
1005                                 // Deal with the problem.  The heuristic is find the largest value in the set, then advance the other streams by one step until they are "close" to the largest.  If the std. deviation is too large, try again; eventually it should be within good limits.
1006                                 uint32_t largestIdx = LargestIdx(a, num);
1007
1008                                 for(uint32_t i=0; i<num; i++)
1009                                 {
1010                                         if (i == largestIdx)
1011                                         {
1012                                                 printf("  ~~~~  ");
1013                                                 continue;
1014                                         }
1015
1016                                         int32_t walkBack = syncPt[i] - 1;
1017                                         double ttn = (double)Global::stream[sNum[i]]->data[walkBack];
1018
1019                                         while ((walkBack > 0)
1020                                                 && (Global::stream[sNum[i]]->data[walkBack - 1] == 0xFF))
1021                                         {
1022                                                 walkBack--;
1023                                                 ttn += (double)Global::stream[sNum[i]]->data[walkBack];// * ratio[i];
1024                                         }
1025
1026                                         // If the difference between the highest and this is over 5, add the next time interval and let the sync counter, uh, slip (backwards!) :-)
1027                                         if ((a[largestIdx] - a[i]) > 5.0)
1028                                         {
1029                                                 syncPt[i] = walkBack;
1030                                                 a[i] += ttn;
1031                                                 printf(" %6.2lf ", ttn);
1032                                         }
1033                                         else
1034                                                 printf("        ");
1035                                 }
1036
1037                                 printf("\n");
1038
1039                                 for(uint32_t i=0; i<num; i++)
1040                                         printf("<%6.2lf>", a[i]);
1041
1042                                 sigma = StdDeviation(a, num);
1043                                 printf(" ==> %.2lf\n", sigma);
1044
1045                                 syncCount++;
1046
1047                                 if (syncCount > 20)
1048                                 {
1049                                         // Back up the train
1050                                         for(uint32_t i=0; i<num; i++)
1051                                         {
1052                                                 syncPt[i] -= (syncPt[i] >= 40 ? 40 : 0);
1053
1054                                                 if ((int32_t)syncPt[i] < 0)
1055                                                         syncPt[i] = 0;
1056                                         }
1057
1058                                         minSlip = 0;
1059                                         printf("Could not synchronize streams...\n");
1060                                         break;
1061                                 }
1062                         }
1063                 }
1064
1065                 // Point as the next time step and see where the minimum sync point is now...
1066                 for(uint32_t i=0; i<num; i++)
1067                 {
1068                         syncPt[i]--;
1069
1070                         if (syncPt[i] < minSlip)
1071                                 minSlip = syncPt[i];
1072                 }
1073         }
1074 }
1075
1076
1077 //
1078 // Walk through the streams backwards until we hit the zero point on one of them.  This assumes the sync point we found initially is a good one (it might not be!). [We've found that sometimes, the initial sync point is *really* bad.]
1079 //
1080 void BacktrackInitialSync2(uint32_t * syncPt, uint32_t num)
1081 {
1082         double a[10];
1083         uint32_t syncSave[10];
1084         uint32_t minSlip = Smallest(syncPt, num);
1085
1086         while (minSlip > 0)
1087         {
1088                 // Get the time for this step into a[]
1089                 for(uint32_t i=0; i<num; i++)
1090                 {
1091                         // We scale the time by a factor of the measured RPM to 300 RPM, which should get us closer to a "normal" time for all streams
1092                         a[i] = (double)Global::stream[sNum[i]]->data[syncPt[i]];// * ratio[i];
1093
1094                         while ((syncPt[i] > 0)
1095                                 && (Global::stream[sNum[i]]->data[syncPt[i] - 1] == 0xFF))
1096                         {
1097                                 syncPt[i]--;
1098                                 a[i] += (double)Global::stream[sNum[i]]->data[syncPt[i]];// * ratio[i];
1099                         }
1100                 }
1101
1102                 double sigma = StdDeviation(a, num);
1103
1104                 if (sigma > SIGMA_THRESHOLD)
1105                 {
1106                         uint32_t syncCount = 0;
1107
1108                         // Save sync origins for later analysis
1109                         memcpy(syncSave, syncPt, sizeof(syncSave));
1110
1111                         // It may turn out that this is too large too...
1112                         while (sigma > SIGMA_THRESHOLD)
1113                         {
1114                                 // Deal with the problem.  The heuristic is find the largest value in the set, then advance the other streams by one step until they are "close" to the largest.  If the std. deviation is too large, try again; eventually it should be within good limits.
1115                                 uint32_t largestIdx = LargestIdx(a, num);
1116
1117                                 // We now pull all streams "forward" until they are within 7
1118                                 // underneath the largest or past it.
1119                                 for(uint32_t i=0; i<num; i++)
1120                                 {
1121                                         if (i == largestIdx)
1122                                                 continue;
1123
1124                                         double ttn = 0;
1125                                         int32_t walkback = syncPt[i];
1126
1127                                         while((a[largestIdx] - (a[i] + ttn)) > 7.0)
1128                                         {
1129                                                 if (walkback <= 0)
1130                                                 {
1131                                                         memcpy(syncPt, syncSave, sizeof(syncSave));
1132                                                         printf("Synchronized as far back as possible...\n");
1133                                                         return;
1134                                                 }
1135
1136                                                 walkback--;
1137                                                 ttn += (double)Global::stream[sNum[i]]->data[walkback];// * ratio[i];
1138
1139                                                 while ((walkback > 0)
1140                                                         && (Global::stream[sNum[i]]->data[walkback - 1] == 0xFF))
1141                                                 {
1142                                                         walkback--;
1143                                                         ttn += (double)Global::stream[sNum[i]]->data[walkback];// * ratio[i];
1144                                                 }
1145                                         }
1146
1147                                         syncPt[i] = walkback;
1148                                         a[i] += ttn;
1149                                 }
1150
1151                                 sigma = StdDeviation(a, num);
1152
1153                                 syncCount++;
1154
1155                                 if (syncCount > 20)
1156                                 {
1157                                         // Back up the train
1158                                         for(uint32_t i=0; i<num; i++)
1159                                         {
1160                                                 syncPt[i] -= (syncPt[i] >= 40 ? 40 : 0);
1161
1162                                                 if ((int32_t)syncPt[i] < 0)
1163                                                         syncPt[i] = 0;
1164                                         }
1165
1166                                         minSlip = 0;
1167                                         printf("Could not synchronize streams...\n");
1168                                         break;
1169                                 }
1170                         }
1171                 }
1172
1173                 // Point as the next time step and see where the minimum sync point is now...
1174                 for(uint32_t i=0; i<num; i++)
1175                 {
1176                         syncPt[i]--;
1177
1178                         if (syncPt[i] < minSlip)
1179                                 minSlip = syncPt[i];
1180                 }
1181         }
1182 }
1183
1184
1185 //
1186 // Walk through the streams backwards until we hit the zero point on one of them.  This assumes the sync point we found initially is a good one (it might not be!). [We've found that sometimes, the initial sync point is *really* bad.]
1187 //
1188 void BacktrackInitialSync3(uint32_t * sync, uint32_t num)
1189 {
1190         double a[9];
1191         uint32_t syncSave[9];
1192
1193         while (true)
1194         {
1195                 uint32_t minSlip = Smallest(sync, num);
1196
1197                 if (minSlip == 0)
1198                         break;
1199
1200                 // Save sync origins for later analysis if necessary
1201                 memcpy(syncSave, sync, sizeof(syncSave));
1202
1203                 // Get the time for this step into a[]
1204                 StepBack(sync, a, num);
1205                 double sigma = StdDeviation(a, num);
1206
1207                 if (sigma > SIGMA_THRESHOLD)
1208                 {
1209                         uint32_t syncCount = 0;
1210                         bool pulled;
1211
1212                         do
1213                         {
1214                                 syncCount++;
1215
1216                                 if (syncCount > 20)
1217                                 {
1218                                         // Back up the train
1219                                         for(uint32_t i=0; i<num; i++)
1220                                         {
1221                                                 sync[i] -= (sync[i] >= 40 ? 40 : 0);
1222
1223                                                 if ((int32_t)sync[i] < 0)
1224                                                         sync[i] = 0;
1225                                         }
1226
1227                                         printf("Could not synchronize streams...\n");
1228                                         return;
1229                                 }
1230
1231                                 // Deal with the problem.  The heuristic is find the largest value in the set, then advance the other streams by one step until they are "close" to the largest.  If the std. deviation is too large, try again; eventually it should be within good limits.
1232                                 uint32_t largestIdx = LargestIdx(a, num);
1233                                 pulled = false;
1234
1235                                 // We now pull all streams "forward" until they are within 7
1236                                 // underneath the largest or past it.
1237                                 for(uint32_t i=0; i<num; i++)
1238                                 {
1239                                         if (i == largestIdx)
1240                                                 continue;
1241
1242                                         double ttn = 0;
1243                                         uint32_t walkback = sync[i];
1244
1245                                         while((a[largestIdx] - (a[i] + ttn)) > 7.0)
1246                                         {
1247                                                 pulled = true;
1248
1249                                                 if ((int32_t)walkback <= 0)
1250                                                 {
1251                                                         memcpy(sync, syncSave, sizeof(syncSave));
1252                                                         printf("Synchronized as far back as possible...\n");
1253                                                         return;
1254                                                 }
1255
1256                                                 StepAndAddBack(walkback, ttn, i);
1257                                         }
1258
1259                                         sync[i] = walkback;
1260                                         a[i] += ttn;
1261                                 }
1262
1263                                 // Calculate the standard deviation at this new point
1264                                 sigma = StdDeviation(a, num);
1265
1266                                 // Heuristic: see if we're stuck with a bad sigma and can't pull any more forward; if so, pull forward one step and see if that gets us any traction...
1267                                 if ((sigma > SIGMA_THRESHOLD) && !pulled)
1268                                 {
1269                                         for(uint32_t i=0; i<num; i++)
1270                                                 StepAndAddBack(sync[i], a[i], i);
1271
1272                                         sigma = StdDeviation(a, num);//, &mean);
1273                                         pulled = true;
1274                                 }
1275                         }
1276                         while ((sigma > SIGMA_THRESHOLD) && pulled);
1277                 }
1278         }
1279 }
1280
1281
1282 void BacktrackInitialSync4(uint32_t * sync, uint32_t num)
1283 {
1284         double a[9], a2[9];
1285         uint32_t syncSave[9];
1286
1287         while (true)
1288         {
1289                 uint32_t minSlip = Smallest(sync, num);
1290
1291                 if (minSlip == 0)
1292                         break;
1293
1294                 // Save sync origins for later analysis if necessary
1295                 memcpy(syncSave, sync, sizeof(syncSave));
1296
1297                 // Get the time for this step into a[]
1298                 StepBack(sync, a, num);
1299                 double sigma = StdDeviation(a, num);
1300
1301                 if (sigma > SIGMA_THRESHOLD)
1302                 {
1303 printf("\n");
1304 for(uint32_t i=0; i<num; i++) { printf("<%6.2lf>", a[i]); }
1305 printf(" --> %.2lf\n", sigma);
1306                         // Let's see if we can re-sync through this rough patch
1307                         int result = Resync(sync, a, num, -1);
1308
1309                         // Well, we failed to find synchronization...  :-(
1310                         if (result == -1)
1311                         {
1312                                 memcpy(sync, syncSave, sizeof(syncSave));
1313                                 return;
1314                         }
1315
1316                         // OK, we have a good result, but what kind (1=end, 0=sync OK)?
1317                         if (result == 0)
1318                                 StepBack(sync, a2, num);
1319                         else if (result == 1)
1320                         {
1321 for(uint32_t j=0; j<num; j++) { printf("{%d} ", sync[j]); }
1322 printf("\n");
1323                                 memcpy(sync, syncSave, sizeof(syncSave));
1324 for(uint32_t j=0; j<num; j++) { printf("<%d> ", sync[j]); }
1325 printf("\n");
1326                                 StepBack(sync, a2, num);
1327                                 return;
1328                         }
1329                 }
1330         }
1331 }
1332
1333
1334 void StepBackUntilBad(uint32_t * sync, double * a, uint32_t num)
1335 {
1336         while (true)
1337         {
1338                 // See where the minimum sync point is now...
1339                 uint32_t minSlip = Smallest(sync, num);
1340
1341                 if (minSlip == 0)
1342                         break;
1343
1344                 // Get the time for this step into a[]
1345                 StepBack(sync, a, num);
1346                 double sigma = StdDeviation(a, num);
1347
1348                 if (sigma > SIGMA_THRESHOLD)
1349                 {
1350                         printf("\n");
1351
1352                         for(uint32_t i=0; i<num; i++)
1353                                 printf("<%6.2lf>", a[i]);
1354
1355                         printf(" --> %.2lf\n", sigma);
1356                         return;
1357                 }
1358         }
1359
1360         printf("---------------------------------------------------\nAT START\n\n");
1361 }
1362
1363
1364 bool StepBackThruBad(uint32_t * sync, double * a, uint32_t num)
1365 {
1366         // Deal with the problem.  The heuristic is find the largest value in the set, then advance the other streams by one step until they are "close" to the largest.  If the std. deviation is too large, try again; eventually it should be within good limits.
1367         uint32_t largestIdx = LargestIdx(a, num);
1368
1369 /*
1370 New heuristic to try here: advance each stream until it comes within 7 on the bottom end or passes it altogether; check the sigma then.
1371
1372 2nd heuristic: attempt to pull the next 'num' time all at once and *add* it to the current step, check the sigma to see if it's in tolerance (*and* check the lookahead).
1373 */
1374         for(uint32_t i=0; i<num; i++)
1375         {
1376                 if (i == largestIdx)
1377                 {
1378                         printf("  ~~~~  ");
1379                         continue;
1380                 }
1381
1382                 // heuristic 1
1383                 bool seen = false;
1384                 double ttn = 0;
1385                 uint32_t walkback = sync[i];
1386
1387                 // If the difference between the highest and this is over 7, add the next time interval and let the sync counter, uh, slip (backwards!) :-)
1388                 while ((a[largestIdx] - (a[i] + ttn)) > 7.0)
1389                 {
1390                         seen = true;
1391                         StepAndAddBack(walkback, ttn, i);
1392                 }
1393
1394                 sync[i] = walkback;
1395                 a[i] += ttn;
1396
1397                 if (seen)
1398                         printf(" %6.2lf ", ttn);
1399                 else
1400                         printf("        ");
1401         }
1402
1403         printf("\n");
1404
1405         for(uint32_t i=0; i<num; i++)
1406                 printf("<%6.2lf>", a[i]);
1407
1408         double sigma = StdDeviation(a, num);
1409         printf(" ==> %.2lf%s", sigma, (sigma <= SIGMA_THRESHOLD ? " (OK)" : ""));
1410
1411 double lookahead[9];
1412 for(uint32_t i=0; i<num; i++)
1413         lookahead[i] = (double)Global::streamData[i][sync[i] - 1] * ratio[i];
1414 printf(" (lookahead=%.2lf, %d)\n", StdDeviation(lookahead, num), Lookahead(sync, num, -1));
1415 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", sync[j], (j < num - 1 ? "-" : "")); }
1416 printf("\n");
1417
1418         if (sigma < SIGMA_THRESHOLD)
1419         {
1420                 // If we're out of the woods, make sure to step to the next step...
1421                 double b[9];
1422                 StepBack(sync, b, num);
1423                 return false;
1424         }
1425
1426         return true;
1427 }
1428
1429
1430 void StepBack(uint32_t * sync, double * a, uint32_t num)
1431 {
1432         for(uint32_t i=0; i<num; i++)
1433         {
1434                 int32_t walkback = sync[i] - 1;
1435                 a[i] = (double)Global::streamData[i][walkback] * ratio[i];
1436
1437                 while ((walkback > 0)
1438                         && (Global::streamData[i][walkback - 1] == 0xFF))
1439                 {
1440                         walkback--;
1441                         a[i] += (double)Global::streamData[i][walkback] * ratio[i];
1442                 }
1443
1444                 sync[i] = walkback;
1445         }
1446 }
1447
1448
1449 void StepAndAddBack(uint32_t * sync, double * a, uint32_t num)
1450 {
1451         for(uint32_t i=0; i<num; i++)
1452         {
1453                 int32_t walkback = sync[i] - 1;
1454                 a[i] += (double)Global::streamData[i][walkback] * ratio[i];
1455
1456                 while ((walkback > 0)
1457                         && (Global::streamData[i][walkback - 1] == 0xFF))
1458                 {
1459                         walkback--;
1460                         a[i] += (double)Global::streamData[i][walkback] * ratio[i];
1461                 }
1462
1463                 sync[i] = walkback;
1464         }
1465 }
1466
1467
1468 void StepAndAddBack(uint32_t & loc, double & a, uint32_t i)
1469 {
1470         int32_t walkback = loc - 1;
1471         a += (double)Global::streamData[i][walkback] * ratio[i];
1472
1473         while ((walkback > 0)
1474                 && (Global::streamData[i][walkback - 1] == 0xFF))
1475         {
1476                 walkback--;
1477                 a += (double)Global::streamData[i][walkback] * ratio[i];
1478         }
1479
1480         loc = (uint32_t)walkback;
1481 }
1482
1483
1484 //
1485 // Move every stream forward by one step
1486 //
1487 void StepForward(uint32_t * sync, double * a, uint32_t num)
1488 {
1489         for(uint32_t i=0; i<num; i++)
1490         {
1491                 uint32_t walkahead = sync[i] + 1;
1492                 a[i] = (double)Global::streamData[i][walkahead] * ratio[i];
1493
1494                 while ((walkahead < Global::streamLen[i])
1495                         && (Global::streamData[i][walkahead] == 0xFF))
1496                 {
1497                         walkahead++;
1498                         a[i] += (double)Global::streamData[i][walkahead] * ratio[i];
1499                 }
1500
1501                 sync[i] = walkahead;
1502         }
1503 }
1504
1505
1506 //
1507 // Move every stream forward by one step
1508 //
1509 void StepAndAddForward(uint32_t * sync, double * a, uint32_t num)
1510 {
1511         for(uint32_t i=0; i<num; i++)
1512         {
1513                 uint32_t walkahead = sync[i] + 1;
1514                 a[i] += (double)Global::streamData[i][walkahead] * ratio[i];
1515
1516                 while ((walkahead < Global::streamLen[i])
1517                         && (Global::streamData[i][walkahead] == 0xFF))
1518                 {
1519                         walkahead++;
1520                         a[i] += (double)Global::streamData[i][walkahead] * ratio[i];
1521                 }
1522
1523                 sync[i] = walkahead;
1524         }
1525 }
1526
1527
1528 //
1529 // Move just *this* stream forward by one step
1530 //
1531 void StepAndAddForward(uint32_t & loc, double & a, uint32_t i)
1532 {
1533         loc++;
1534         a += (double)Global::streamData[i][loc] * ratio[i];
1535
1536         while ((loc < Global::streamLen[i])
1537                 && (Global::streamData[i][loc] == 0xFF))
1538         {
1539                 loc++;
1540                 a += (double)Global::streamData[i][loc] * ratio[i];
1541         }
1542 }
1543
1544
1545 //
1546 // Return the number of times with good correlation in the specified direction
1547 // (1 for forward, -1 for backwards)
1548 //
1549 uint32_t Lookahead(uint32_t * syncPt, uint32_t num, int32_t dir /*= 1*/)
1550 {
1551         uint32_t tSync[10];
1552         double a[10];
1553         uint32_t count = 0;
1554
1555         // Use temporary sync array instead of the one passed in
1556         memcpy(tSync, syncPt, sizeof(tSync));
1557
1558         if (dir == -1)
1559         {
1560                 uint32_t smallestIdx = SmallestIdx(tSync, num);
1561
1562                 while (tSync[smallestIdx] > 0)
1563                 {
1564                         StepBack(tSync, a, num);
1565                         double sigma = StdDeviation(a, num);
1566
1567                         if (sigma > SIGMA_THRESHOLD)
1568                                 break;
1569
1570                         count++;
1571                         smallestIdx = SmallestIdx(tSync, num);
1572                 }
1573         }
1574         else
1575         {
1576                 uint32_t largestIdx = LargestIdx(tSync, num);
1577
1578                 while (tSync[largestIdx] < Global::streamLen[largestIdx])
1579                 {
1580                         StepForward(tSync, a, num);
1581                         double sigma = StdDeviation(a, num);
1582
1583                         if (sigma > SIGMA_THRESHOLD)
1584                                 break;
1585
1586                         count++;
1587                         largestIdx = LargestIdx(tSync, num);
1588                 }
1589         }
1590
1591         return count;
1592 }
1593
1594
1595 //
1596 // Attempt to resynchronize the current streams
1597 // N.B.: When we get here, we're already at the point *after* where it blew up
1598 //       the sigma (the times for that step are passed-in in "a")
1599 //
1600 // Returns -1 on failure, 0 is sync was successful, or 1 if reached end of
1601 // stream before finding sync
1602 //
1603 int Resync(uint32_t * sync, double * a, uint32_t num, int32_t dir/*= 1*/)
1604 {
1605         uint32_t syncCount = 0;
1606         bool pulled;
1607         double sigma = 0;
1608
1609 for(uint32_t j=0; j<num; j++) { printf("{%d} ", sync[j]); }
1610 printf("\n");
1611         do
1612         {
1613                 syncCount++;
1614
1615                 if (syncCount > 20)
1616                 {
1617                         // Back up the train
1618                         printf("Could not synchronize streams...\n");
1619                         return -1;
1620                 }
1621
1622                 // Deal with the problem.  The heuristic is find the largest value in the set, then advance the other streams by one step until they are "close" to the largest.  If the std. deviation is too large, try again; eventually it should be within good limits.
1623                 uint32_t largestIdx = LargestIdx(a, num);
1624                 pulled = false;
1625
1626                 // We now pull all streams "forward" until they are within 7
1627                 // underneath the largest or past it.
1628                 for(uint32_t i=0; i<num; i++)
1629                 {
1630                         if (i == largestIdx)
1631                         {
1632                                 printf("  ~~~~  ");
1633                                 continue;
1634                         }
1635
1636                         double ttn = 0;
1637                         uint32_t walkback = sync[i];
1638
1639                         while ((a[largestIdx] - (a[i] + ttn)) > 7.0)
1640                         {
1641                                 pulled = true;
1642
1643                                 if (((dir == 1) && (walkback >= Global::streamLen[i]))
1644                                         || ((dir == -1) && ((int32_t)walkback <= 0)))
1645                                 {
1646 //                                      memcpy(sync, syncSave, sizeof(syncSave));
1647                                         printf("\nSynchronized as far back as possible...\n");
1648 for(uint32_t j=0; j<num; j++) { printf("{%d} ", sync[j]); }
1649 printf("\n");
1650                                         return 1;
1651                                 }
1652
1653                                 if (dir == 1)
1654                                         StepAndAddForward(walkback, ttn, i);
1655                                 else
1656                                         StepAndAddBack(walkback, ttn, i);
1657                         }
1658
1659                         sync[i] = walkback;
1660                         a[i] += ttn;
1661
1662                         if (pulled)
1663                                 printf(" %6.2lf ", ttn);
1664                         else
1665                                 printf("        ");
1666                 }
1667
1668                 printf("\n");
1669
1670                 for(uint32_t i=0; i<num; i++)
1671                         printf("<%6.2lf>", a[i]);
1672
1673                 // Calculate the standard deviation at this new point
1674                 sigma = StdDeviation(a, num);
1675 printf(" ==> %.2lf%s", sigma, (sigma <= SIGMA_THRESHOLD ? " (OK)" : (!pulled ? "(STEP)" : "")));
1676
1677 double lookahead[9];
1678 uint32_t minSyncIdx = SmallestIdx(sync, num);
1679 if (sync[minSyncIdx] > 0 && dir == -1)
1680 {
1681 for(uint32_t i=0; i<num; i++)
1682 {       lookahead[i] = (double)Global::streamData[i][sync[i] + dir] * ratio[i]; }
1683 printf(" (lookahead=%.2lf, %d)\n", StdDeviation(lookahead, num), Lookahead(sync, num, dir));
1684 }
1685                 // Heuristic: see if we're stuck with a bad sigma and can't pull any more forward; if so, pull forward one step and see if that gets us any traction...
1686                 if ((sigma > SIGMA_THRESHOLD) && !pulled)
1687                 {
1688                         if (dir == 1)
1689                                 StepAndAddForward(sync, a, num);
1690                         else
1691                                 StepAndAddBack(sync, a, num);
1692
1693                         sigma = StdDeviation(a, num);//, &mean);
1694                         pulled = true;
1695                 }
1696         }
1697         while ((sigma > SIGMA_THRESHOLD) && pulled);
1698
1699 //      double a2[9];
1700 //      StepBack(sync, a2, num);
1701
1702         return 0;
1703 }
1704
1705 #endif
1706
1707
1708 //
1709 // Compare two arrays to see if they are equal
1710 //
1711 bool Equal(uint32_t * a1, uint32_t * a2, uint32_t num)
1712 {
1713         for(uint32_t i=0; i<num; i++)
1714         {
1715                 if (a1[i] != a2[i])
1716                         return false;
1717         }
1718
1719         return true;
1720 }
1721
1722
1723 uint32_t LookaheadWave(uint32_t * passedInSync, uint32_t num, int8_t dir = 1);
1724 uint32_t LookaheadWave(uint32_t * passedInSync, uint32_t num, int8_t dir/*= 1*/)
1725 {
1726         uint32_t sync[6];
1727         uint32_t count = 0;
1728         memcpy(sync, passedInSync, sizeof(sync));
1729
1730         while (true)
1731         {
1732                 if (StdDeviationWave(sync, num) > 2.50)
1733                         break;
1734
1735                 for(uint32_t i=0; i<num; i++)
1736                 {
1737                         if (((dir == 1) && (sync[i] >= Global::waveLen[sNum[i]]))
1738                                 || ((dir == -1) && (sync[i] == 0)))
1739                                 return count;
1740
1741                         sync[i] += dir;
1742                 }
1743
1744                 count++;
1745         }
1746
1747         return count;
1748 }
1749
1750
1751 uint32_t FindSyncBetweenFirstTwo(uint32_t * sync)
1752 {
1753         uint32_t bestSync[2], bestLA = 0, syncSave = sync[0];
1754
1755         // Move the first stream first...
1756         for(uint32_t i=0; i<200; i++)
1757         {
1758                 uint32_t la = LookaheadWave(sync, 2);
1759
1760                 // See if the sync we've found is the best so far...
1761                 if (la > bestLA)
1762                 {
1763                         bestLA = la;
1764                         memcpy(bestSync, sync, sizeof(bestSync));
1765                 }
1766
1767                 sync[0]++;
1768         }
1769
1770         // Otherwise, reset the first stream and move the 2nd
1771         sync[0] = syncSave;
1772
1773         for(uint32_t i=0; i<200; i++)
1774         {
1775                 // We can bump this first since we already checked the [0][0] case above
1776                 sync[1]++;
1777                 uint32_t la = LookaheadWave(sync, 2);
1778
1779                 // See if the sync we've found is the best so far...
1780                 if (la > bestLA)
1781                 {
1782                         bestLA = la;
1783                         memcpy(bestSync, sync, sizeof(bestSync));
1784                 }
1785         }
1786
1787         // Set sync to the best we found & return the best lookahead count
1788         memcpy(sync, bestSync, sizeof(bestSync));
1789
1790         return bestLA;
1791 }
1792
1793
1794 void FindInitialSyncForStreams2(uint32_t * sync, uint32_t num)
1795 {
1796         bool lookAt[6] = { true, true, false, false, false, false };
1797
1798 //      while (FindSyncBetweenFirstTwo(sync) == false)
1799         while (FindSyncBetweenFirstTwo(sync) < 1000)
1800         {
1801                 for(uint32_t i=0; i<num; i++)
1802                 {
1803                         sync[i] += 200;
1804
1805                         if (sync[i] >= Global::waveLen[sNum[i]])
1806                         {
1807                                 printf("Could not find initial sync!!\n");
1808                                 return;// -1;
1809                         }
1810                 }
1811         }
1812
1813         uint32_t lookahead = LookaheadWave(sync, 2);
1814
1815         if (lookAt[0])
1816                 printf("Found sync for streams 1 & 2 at %d and %d (la=%d)\n", sync[0], sync[1], lookahead);
1817
1818         // Add in the others, one at a time and try to synchronize them
1819         uint32_t bestSync[6];
1820
1821         for(uint32_t i=2; i<num; i++)
1822         {
1823                 lookAt[i] = true;
1824                 uint32_t bestLA = 0;
1825
1826                 for(uint32_t j=0; j<200; j++)
1827                 {
1828                         uint32_t syncSave = sync[i];
1829
1830                         // And check again for a match
1831                         for(uint32_t k=0; k<200; k++)
1832                         {
1833                                 uint32_t la = LookaheadWave(sync, i + 1);
1834
1835                                 if (la > bestLA)
1836                                 {
1837                                         bestLA = la;
1838                                         memcpy(bestSync, sync, sizeof(bestSync));
1839                                 }
1840
1841                                 sync[i]++;
1842                         }
1843
1844                         sync[i] = syncSave;
1845
1846                         // Kick synchronized streams forward to check the rest...
1847                         for(uint32_t k=0; k<i; k++)
1848                                 sync[k]++;
1849                 }
1850
1851                 memcpy(sync, bestSync, sizeof(bestSync));
1852         }
1853
1854         for(uint32_t i=0; i<num; i++)
1855                 printf("Sync for stream %d: %d (%s)\n", i, sync[i], (lookAt[i] ? "yes" : "no"));
1856         printf("Lookahead: %d\n", LookaheadWave(sync, num));
1857 }
1858
1859
1860 #if 1
1861 uint32_t Synthesize2(uint32_t * sync, uint32_t num, uint32_t * synthWave, float * swAmplitude)
1862 {
1863         uint32_t swLen = 0;
1864         uint32_t syncPt[7], syncSave[7];
1865         double a[7], b[7], currentRow[7];
1866         Global::bloops = 0;
1867
1868         memcpy(syncPt, sync, sizeof(syncPt));
1869
1870         while (true)
1871         {
1872                 for(uint32_t i=0; i<num; i++)
1873                 {
1874                         if (syncPt[i] >= Global::streamLen[i])
1875                                 return swLen;
1876                 }
1877
1878                 // Save these *before* we step forward
1879                 memcpy(syncSave, syncPt, sizeof(syncSave));
1880 //              StepForward(syncPt, a, num);
1881                 for(uint32_t i=0; i<num; i++)
1882                 {
1883                         a[i] = (double)Global::wave[sNum[i]][syncPt[i]];
1884                         syncPt[i]++;
1885                 }
1886
1887                 double mean;
1888                 double sigma = StdDeviation(a, num, &mean);
1889
1890                 if (sigma <= SIGMA_THRESHOLD)
1891                 {
1892                         synthWave[swLen] = (uint32_t)(mean + 0.5);
1893                         swAmplitude[swLen] = 1.0f;
1894                         swLen++;
1895                 }
1896                 else
1897                 {
1898                         Global::bloops++;
1899                         // The basic idea is to find the extent of this anomalous region and then use what's there as an amplitude by summing the signals where they correspond.
1900                         uint32_t syncSteps = 0;
1901                         uint32_t lookahead = LookaheadWave(syncPt, num);
1902
1903                         // Basically we move forward thru the area until either 1) the sigma is OK, or 2) we've pulled everything as far as it can go and thus this becomes our new local start. 3) will go in at some point which is, do a lookahead and see what the sigma looks like; if it's good and the current one is stinko, (not *too* stinko) then we've found a new local start point, otherwise keep going.
1904 /*
1905 Note that 3) works OK to get out of sticky situations, but sometimes the signals are fairly noisy and you will end up in situations where the lookahead is zero and the next sigma isn't great (& the current isn't any good either), but using that as the new local start is OK and will permit walking forward/backward through the stream.  Some of the time you will find the average of the current sigma and the following will be below the threshold with a good lookahead value (10, 100, 1000), this is also a good time to set the new local start.
1906 */
1907 #ifdef NOISY
1908 printf("a: ");
1909 for(uint32_t i=0; i<num; i++)
1910         printf("[%.2lf]", a[i]);
1911 //printf(" => %.2lf {drift=%.2lf, la=%d}\n", sigma, driftSigma, lookahead);
1912 printf(" => %.2lf {la=%d}\n", sigma, lookahead);
1913
1914 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", syncPt[j], (j < num - 1 ? "-" : "")); }
1915 printf("\n");//*/
1916 #endif
1917                         bool keepWorking = true;
1918
1919                         do
1920                         {
1921                                 syncSteps++;
1922
1923                                 // If we've been in this loop too long, something's very wrong
1924                                 if (syncSteps > 20)
1925                                         return swLen;
1926
1927                                 // Pull the lesser streams forward to catch up to the largest
1928                                 uint32_t largestIdx = LargestIndex(a, num);
1929                                 bool pulled = false;
1930
1931                                 for(uint32_t i=0; i<num; i++)
1932                                 {
1933                                         if (i == largestIdx)
1934 #ifdef NOISY
1935                                         {
1936                                                 printf("  ~~~~  ");
1937 #endif
1938                                                 continue;
1939 #ifdef NOISY
1940                                         }
1941 #endif
1942 //                                      if ((a[largestIdx] - a[i]) > 7.0)
1943                                         if ((a[largestIdx] - a[i]) > 9.0)
1944                                         {
1945                                                 pulled = true;
1946                                                 a[i] += (double)Global::wave[sNum[i]][syncPt[i]];
1947 #ifdef NOISY
1948                                                 printf(" %6d ", Global::wave[sNum[i]][syncPt[i]]);
1949 #endif
1950                                                 syncPt[i]++;
1951                                         }
1952 #ifdef NOISY
1953                                         else
1954                                                 printf("        ");
1955 #endif
1956                                         // See if we've run out of stream to synthesize...
1957                                         if (syncPt[i] >= Global::waveLen[sNum[i]])
1958                                                 return swLen;
1959                                 }
1960
1961 #ifdef NOISY
1962                                 printf("\n");
1963
1964                                 for(uint32_t i=0; i<num; i++)
1965                                         printf("<%6.2lf>", a[i]);
1966 #endif
1967                                 // Calculate the standard deviation at this new point
1968                                 sigma = StdDeviation(a, num);//, &mean);
1969
1970                                 // Calculate the following sigma & lookahead too
1971                                 for(uint32_t i=0; i<num; i++)
1972                                         b[i] = (double)Global::wave[sNum[i]][syncPt[i]];
1973
1974                                 double nextSigma = StdDeviation(b, num);
1975                                 lookahead = LookaheadWave(syncPt, num);
1976 #ifdef NOISY
1977                                 printf(" ==> %.2lf%s", sigma, (sigma <= SIGMA_THRESHOLD ? " (OK)" : (!pulled ? "(STEP)" : "")));
1978                                 printf(" (lookahead=%.2lf, %d)\n", nextSigma, lookahead);
1979
1980 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", syncPt[j], (j < num - 1 ? "-" : "")); }
1981 printf("\n");//*/
1982 #endif
1983                                 // A handful of heuristics.  If the sigma is OK, we're done
1984                                 if (sigma < 2.5)
1985                                         keepWorking = false;
1986
1987                                 // If we couldn't pull any streams forward for some reason, punt
1988                                 if (!pulled)
1989                                         keepWorking = false;
1990
1991                                 // If the average of the current & next sigmas is OK, go ahead
1992                                 if (((sigma + nextSigma) / 2.0) < 2.5)
1993                                         keepWorking = false;
1994
1995                                 // If the next sigma is OK and the lookahead too, move on
1996                                 if ((nextSigma < 2.5) && (lookahead > 10))
1997                                         keepWorking = false;
1998                         }
1999                         while (keepWorking);
2000
2001                         // Now, we've re-established sync, now fill the appropriate spots
2002
2003 /*
2004 So the algorithm to do this proppaly is like so:
2005
2006 Step 1: Find the smallest step forward through the section; set amplitude to 0.2.
2007 Step 2: Loop thru the other streams and see if they correspond.  If so, advance their stream start & add 0.2 to the amplitude for each one seen.
2008 Step 3: Add the mean value of the corresponding values to the synthesized waveform + wave amplitude
2009 Step 4: If all of the stream starts are at the end of the section, we are done.
2010 [maybe.  how do you handle the case where you have streams that look like so:
2011
2012 200
2013 150 50
2014 150 50
2015 175 25
2016 200
2017
2018 .......................................|
2019 .............................|.........|
2020 .............................|.........|
2021 ..................................|....|
2022 .......................................|
2023
2024 this will fail to add in the correct amount for the times that had no part in the anomaly.  so to fix this, maybe have a baseline value that bumps upward to show where the "cursor" (so to speak) is, so at the end we can subtract the mean that we got above from this baseline to get the remaining time to synthesize, like so:
2025
2026 synthWave[swLen] = (uint32_t)((mean - baseline) + 0.5)
2027 swAmplitude[swLen] = amplitude;
2028
2029 no need for that.  the times that step directly to the end can safely be ignored.
2030 ]
2031
2032 150 -> 150 (ignores 175)
2033 150 goes in, ampl. .4, we now have:
2034
2035 200
2036 50
2037 50
2038 175 25
2039 200
2040
2041 only one is left that we can grab:
2042
2043 175
2044
2045 last pulse was at 150 (40%), so we need to subtract that out
2046
2047 -> 25
2048
2049 so maybe we'd do like so:
2050 -1) create a list containing the start values for the start of the anomalous section and replace them as the counters advance.
2051 0) are streams at the end? if so, stuff in the final value to the synthesized wave & stop, otherwise:
2052 1) find the smallest in the current row and use that as a basis.
2053 2) find streams that correlate, if any
2054 3) advance the streams that correlate & subtract out the minimum from the other rows
2055 4) go to 0)
2056
2057 200
2058 150 50
2059 150 50
2060 175 25
2061 200
2062
2063 smallest is 150: pick 150 -> picks up 150
2064 advance the 150 rows & subtract 150 from the rest:
2065
2066 50
2067 50
2068 50
2069 25 25
2070 50
2071
2072 pick smallest: 25 -> picks up nothing
2073 advance the 25 & subtract it from the rest:
2074
2075 25
2076 25
2077 25
2078 25
2079 25
2080
2081 We've reached the end of the section, add the final amount
2082
2083 --------------------------------------------------------------------------------
2084 syncSave before: [2->4][2->6][2->4][2->6][2->6]
2085 syncSave after: [3->4][3->6][3->4][3->6][3->6]
2086
2087 currentRow: [120.89][49.97][46.98][49.98][48.98] => 28.78
2088
2089 2: [3->4][3->6][3->4][3->6][3->6]
2090
2091 a[0]=46.98: [120.89] ==> 36.95
2092         [49.97]{17.00} ==> 1.50
2093         <106.00>[49.97][49.98]{28.00} ==> 1.41
2094         [49.97][49.98][48.98]{26.00} ==> 1.22
2095
2096 3: [3->4][4->6][4->4][4->6][4->6]
2097
2098 a[0]=17.00: [73.91] ==> 28.45
2099         <56.00>[28.00]{45.00} ==> 5.50
2100         [28.00][26.00]{47.00} ==> 4.78
2101
2102 4: [3->4][5->6][4->4][5->6][5->6]
2103
2104 a[0]=45.00: [56.91] ==> 5.95
2105         [56.00]{32.00} ==> 5.50
2106         <32.00>[56.00][47.00]{32.00} ==> 4.78
2107
2108 5: [3->4][6->6][4->4][6->6][6->6]
2109
2110 a[0]=11.91: <32.00>
2111
2112 6: [4->4][6->6][4->4][6->6][6->6]
2113
2114  2->4    2->6    2->4    2->6    2->6
2115 [120.89][ 49.97][ 46.98][ 49.98][ 48.98] => 28.78
2116 ( 73.91)  17.00  106.00   28.00   26.00
2117 ( 56.91)  56.00           45.00   47.00
2118   32.00   32.00           32.00   32.00
2119
2120 */
2121 #ifdef NOISY
2122 /*printf("syncSave before: ");
2123 for(uint32_t i=0; i<num; i++)
2124         printf("[%d->%d]", syncSave[i], syncPt[i]);
2125 printf("\n");//*/
2126
2127 for(uint32_t i=0; i<num; i++)
2128 {
2129         printf("Sync %d: %d -> %d (", sNum[i], syncSave[i], syncPt[i]);
2130         for(uint32_t j=syncSave[i]; j<=syncPt[i]; j++)
2131                 printf("%d%s", Global::wave[sNum[i]][j], (j == syncPt[i] ? "" : ", "));
2132         printf(")\n");
2133 }
2134 #endif
2135                         // Collect the current row
2136                         for(uint32_t i=0; i<num; i++)
2137                         {
2138                                 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
2139                                 syncSave[i]++;
2140                         }
2141
2142 /*printf("syncSave after: ");
2143 for(uint32_t i=0; i<num; i++)
2144         printf("[%d->%d]", syncSave[i], syncPt[i]);
2145 printf("\n");
2146 printf("currentRow: ");
2147 for(uint32_t i=0; i<num; i++)
2148         printf("[%.2lf]", currentRow[i]);
2149 printf(" => %.2lf\n", StdDeviation(currentRow, num));//*/
2150
2151 //printf("%d: ", swLen);
2152
2153                         float ampStep = 1.0f / (float)num;
2154
2155                         while (true)
2156                         {
2157                                 if (Equal(syncSave, syncPt, num))
2158                                         break;
2159
2160                                 float amplitude = ampStep;
2161                                 uint32_t smallestIdx = SmallestIndex(currentRow, num);
2162                                 uint32_t cnt = 1;
2163                                 a[0] = currentRow[smallestIdx];
2164 //printf("a[0]=%.2lf: ", a[0]);
2165
2166                                 for(uint32_t i=0; i<num; i++)
2167                                 {
2168                                         // Make sure we haven't gone beyond the end of any of the streams we're looking at
2169                                         if (syncSave[i] >= Global::streamLen[i])
2170                                                 return swLen;
2171
2172                                         if (i == smallestIdx)
2173                                         {
2174                                                 // We always pick up the smallest in the current set, since that's our basis
2175                                                 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
2176                                                 syncSave[i]++;
2177 //printf("<%.2lf>", currentRow[i]);
2178                                                 continue;
2179                                         }
2180
2181                                         // Save the current row & subtract out the smallest as a basis
2182                                         double crSave = currentRow[i];
2183                                         currentRow[i] -= a[0];
2184
2185                                         // Don't bother with stuff that's out of range (@ current sync point!)  :-P
2186                                         if (syncSave[i] == syncPt[i])
2187                                                 continue;
2188
2189                                         // Try to find correlates
2190                                         a[cnt] = crSave;
2191                                         cnt++;
2192                                         sigma = StdDeviation(a, cnt);
2193 //for(uint32_t j=1; j<cnt; j++)
2194 //      printf("[%.2lf]", a[j]);
2195
2196 //relaxed sigma...
2197                                         if (sigma <= 5.5)//SIGMA_THRESHOLD)
2198                                         {
2199                                                 // If the sigma is in range for this item, pick it up
2200                                                 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
2201                                                 syncSave[i]++;
2202
2203 //printf("{%.2lf}", currentRow[i]);
2204                                                 amplitude += ampStep;
2205                                         }
2206                                         else
2207                                         {
2208                                                 // Otherwise reject the last item; it's too far out
2209                                                 cnt--;
2210                                         }
2211 //printf(" ==> %.2lf\n\t", sigma);
2212                                 }
2213
2214                                 // Get the average of the items picked up and add it to the wave
2215                                 sigma = StdDeviation(a, cnt, &mean);
2216                                 synthWave[swLen] = (uint32_t)(mean + 0.5);
2217                                 swAmplitude[swLen] = amplitude;
2218                                 swLen++;
2219                         }
2220
2221                         sigma = StdDeviation(currentRow, num, &mean);
2222                         synthWave[swLen] = mean;
2223                         swAmplitude[swLen] = 1.0f;
2224                         swLen++;
2225                 }
2226         }
2227
2228         return swLen;
2229 }
2230 #endif
2231
2232
2233 bool ResyncWave(uint32_t * sync, uint32_t num, int8_t dir = 1);
2234 bool ResyncWave(uint32_t * sync, uint32_t num, int8_t dir/*= 1*/)
2235 {
2236         double a[6];
2237
2238         for(uint32_t i=0; i<num; i++)
2239         {
2240                 a[i] = (double)Global::wave[sNum[i]][sync[i]];
2241                 sync[i] += dir;
2242         }
2243
2244 #ifdef NOISY
2245         for(uint32_t i=0; i<num; i++)
2246                 printf("<%4d>", (uint32_t)a[i]);
2247
2248         printf(" {la: %d}\n", LookaheadWave(sync, num, dir));
2249 #endif
2250
2251         uint32_t syncCount = 0;
2252         bool keepGoing = true;
2253
2254         do
2255         {
2256                 if (syncCount > 42)
2257                 {
2258                         printf("Could not synchronize streams...\n");
2259                         return false;
2260                 }
2261
2262                 for(uint32_t i=0; i<num; i++)
2263                 {
2264                         if (((dir == 1) && (sync[i] >= Global::waveLen[sNum[i]]))
2265                                 || ((dir == -1) && (sync[i] == 0)))
2266                         {
2267                                 printf("End of stream...\n");
2268                                 return true;
2269                         }
2270                 }
2271
2272                 // Deal with the problem.  The heuristic is find the largest value in the set, then advance the other streams by one step until they are "close" to the largest.  If the std. deviation is too large, try again; eventually it should be within good limits.
2273                 uint32_t largestIdx = LargestIndex(a, num);
2274                 bool stepped = false;
2275
2276                 for(uint32_t i=0; i<num; i++)
2277                 {
2278                         if (i == largestIdx)
2279 #ifdef NOISY
2280                         {
2281                                 printf(" ~~~~ ");
2282 #endif
2283                                 continue;
2284 #ifdef NOISY
2285                         }
2286 #endif
2287
2288                         // If the difference between the highest and this is over 7, add the next time interval and let the sync counter, uh, slip :-)
2289 //                      if ((a[largestIdx] - a[i]) > 7.0)
2290                         if ((a[largestIdx] - a[i]) > 9.0)
2291                         {
2292                                 stepped = true;
2293                                 double ttn = (double)Global::wave[sNum[i]][sync[i]];
2294                                 a[i] += ttn;
2295                                 sync[i] += dir;
2296 #ifdef NOISY
2297                                 printf(" %4d ", (uint32_t)ttn);
2298 #endif
2299                         }
2300 #ifdef NOISY
2301                         else
2302                                 printf("      ");
2303 #endif
2304                 }
2305
2306                 double sigma = StdDeviation(a, num);
2307                 double nextSigma = StdDeviationWave(sync, num);
2308                 uint32_t lookahead = LookaheadWave(sync, num, dir);
2309 #ifdef NOISY
2310                 printf("\n");
2311
2312                 for(uint32_t i=0; i<num; i++)
2313                         printf("<%4d>", (uint32_t)a[i]);
2314
2315                 printf(" ==> %.2lf ", sigma);
2316                 printf("(next: %.2lf, la: %d)\n", nextSigma, lookahead);
2317 #endif
2318                 syncCount++;
2319
2320                 // A handful of heuristics...  1st: If sigma is good, we're done
2321                 if (sigma < 2.50)
2322                         keepGoing = false;
2323
2324                 // Couldn't pull, so punt for now
2325                 if (!stepped)
2326                         keepGoing = false;
2327
2328                 // If the next sigma + current / 2 is OK, move on
2329                 if (((sigma + nextSigma) / 2.0) < 2.50)
2330                         keepGoing = false;
2331
2332                 // If the next sigma is good, and the lookahead is good, move on
2333                 // [Slight tweak: only do this if the current sigma isn't terrible]
2334                 if ((nextSigma < 2.50) && (lookahead > 10) && (sigma < 20.0))
2335                         keepGoing = false;
2336         }
2337         while (keepGoing);
2338
2339         return true;
2340 }
2341
2342
2343 bool AttemptToFindStart(uint32_t * sync, uint32_t num)
2344 {
2345         // Sanity check...
2346         for(uint32_t i=0; i<num; i++)
2347         {
2348                 if (sync[i] == 0)
2349                         return true;
2350         }
2351
2352         bool keepGoing = true;
2353
2354         do
2355         {
2356                 double sigma = StdDeviationWave(sync, num);
2357
2358                 if (sigma > 2.50)
2359                 {
2360                         bool result = ResyncWave(sync, num, -1);
2361
2362                         if (result == false)
2363                                 return false;
2364                 }
2365                 else
2366                 {
2367                         for(uint32_t i=0; i<num; i++)
2368                                 sync[i]--;
2369                 }
2370
2371                 for(uint32_t i=0; i<num; i++)
2372                 {
2373                         if (sync[i] == 0)
2374                                 keepGoing = false;
2375                 }
2376         }
2377         while (keepGoing);
2378
2379 //#ifdef NOISY
2380 #if 1
2381         for(uint32_t i=0; i<num; i++)
2382                 printf("Sync for stream %d: %d\n", i, sync[i]);
2383         printf("Lookahead: %d\n", LookaheadWave(sync, num));
2384 #endif
2385
2386         return true;
2387 }
2388
2389
2390 bool InitialSync(uint32_t * sync, uint32_t num)
2391 {
2392         // Let's try a different approach to this...
2393         bool lookAt[6] = { true, true, false, false, false, false };
2394
2395 //      while (FindSyncBetweenFirstTwo(sync) == false)
2396         while (FindSyncBetweenFirstTwo(sync) < 1000)
2397         {
2398                 for(uint32_t i=0; i<num; i++)
2399                 {
2400                         sync[i] += 200;
2401
2402                         if (sync[i] >= Global::waveLen[sNum[i]])
2403                         {
2404                                 printf("Could not find initial sync!!\n");
2405                                 return false;
2406                         }
2407                 }
2408         }
2409
2410         uint32_t lookahead = LookaheadWave(sync, 2);
2411
2412         if (lookAt[0])
2413                 printf("Found sync for streams 1 & 2 at %d and %d (la=%d)\n", sync[0], sync[1], lookahead);
2414
2415         // Add in the others, one at a time and try to synchronize them
2416         uint32_t syncBest[6];
2417
2418         for(uint32_t i=2; i<num; i++)
2419         {
2420                 lookAt[i] = true;
2421                 uint32_t bestLA = 0;
2422
2423                 for(uint32_t j=0; j<200; j++)
2424                 {
2425                         uint32_t syncSave = sync[i];
2426
2427                         for(uint32_t k=0; k<200; k++)
2428                         {
2429                                 uint32_t la = LookaheadWave(sync, i + 1);
2430
2431                                 if (la > bestLA)
2432                                 {
2433                                         bestLA = la;
2434                                         memcpy(syncBest, sync, sizeof(syncBest));
2435                                 }
2436
2437                                 sync[i]++;
2438                         }
2439
2440                         sync[i] = syncSave;
2441
2442                         // Kick all the other streams forward to check the rest...
2443                         for(uint32_t k=0; k<i; k++)
2444                                 sync[k]++;
2445                 }
2446
2447                 memcpy(sync, syncBest, sizeof(syncBest));
2448         }
2449
2450         for(uint32_t i=0; i<num; i++)
2451                 printf("Sync for stream %d: %d (%s)\n", i, sync[i], (lookAt[i] ? "yes" : "no"));
2452         printf("Lookahead: %d\n", LookaheadWave(sync, num));
2453
2454         return true;
2455 }
2456
2457
2458 uint32_t LoopLookahead(uint32_t trackNum, uint32_t start, uint32_t loopPoint, bool * test = NULL);
2459 uint32_t LoopLookahead(uint32_t trackNum, uint32_t start, uint32_t loopPoint, bool * test/*= NULL*/)
2460 {
2461         uint32_t count = 0;
2462         bool equal = true;
2463         double a[2];
2464
2465         for(uint32_t i=loopPoint, pos=start; i<Global::synWaveLen[trackNum]; i++, pos++)
2466         {
2467                 a[0] = Global::synWave[trackNum][pos];
2468                 a[1] = Global::synWave[trackNum][i];
2469                 double sigma = StdDeviation(a, 2);
2470
2471                 if (sigma > 2.50)
2472                 {
2473                         equal = false;
2474                         break;
2475                 }
2476
2477                 count++;
2478         }
2479
2480         if (test)
2481                 *test = equal;
2482
2483         return count;
2484 }
2485
2486
2487 #define NOISYSYNTH
2488 //#define DEBUGSYNTH
2489 void SynthesizeTrack(uint32_t trackNum)
2490 {
2491         uint32_t num = 0;
2492         uint32_t sync[6] = { 0 };
2493
2494         for(uint32_t i=0; i<Global::numStreams; i++)
2495         {
2496                 // Skip streams that aren't on the current track & BITS captures
2497                 if ((Global::stream[i]->location != trackNum)
2498                         || (Global::stream[i]->captureType == 2))
2499                         continue;
2500
2501 #ifdef DEBUGSYNTH
2502 printf("sNum[%d] = %d\n", num, i);
2503 #endif
2504                 // Save the stream # so we can find it later
2505                 sNum[num++] = i;
2506         }
2507
2508         // We should just bypass the synthesis part of this, not the loop point finding...  :-P  !!! FIX !!!
2509         if (num == 1)
2510         {
2511                 printf("%.2f: Single stream, length: %d\n", (float) trackNum / 4.0f, Uint32LE(Global::stream[sNum[0]]->dataLength));
2512
2513                 memcpy(Global::synWave[trackNum], Global::wave[sNum[0]], Global::waveLen[sNum[0]] * 4);
2514                 Global::synWaveLen[trackNum] = Global::waveLen[sNum[0]];
2515         }
2516
2517 /*
2518 This is failing for track 9.00: it finds an initial sync @ 202, 200, la=1257 but real sync point is 0,2,2 (it says 5,0,0, which is wrong)
2519 */
2520         if (num > 1)
2521         {
2522                 InitialSync(sync, num);
2523                 AttemptToFindStart(sync, num);
2524
2525                 uint32_t count = 0, bloops = 0;
2526                 bool keepGoing = true;
2527                 Global::synWaveLen[trackNum] = 0;
2528                 double mean;
2529
2530                 do
2531                 {
2532                         double sigma = StdDeviationWave(sync, num, &mean);
2533
2534                         if (sigma <= 2.50)
2535                         {
2536                                 count++;
2537                                 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(mean + 0.5);
2538                                 Global::synWaveLen[trackNum]++;
2539
2540                                 for(uint32_t i=0; i<num; i++)
2541                                         sync[i]++;
2542                         }
2543                         else
2544                         {
2545 #ifdef NOISYSYNTH
2546                         uint32_t startOfSynth = Global::synWaveLen[trackNum];
2547 #endif
2548 #ifdef NOISYSYNTH
2549                                 if (bloops < 2)
2550                                 {
2551                                         printf("Bloop seen at pos ");
2552                                         for(uint32_t k=0; k<num; k++)
2553                                                 printf("%d%s", sync[k], (k == num - 1 ? "" : ", "));
2554                                         printf("...\n");
2555                                 }
2556 #endif
2557                                 bloops++;       // Count the # of times we've had to punt
2558                                 uint32_t syncSave[6] = { 0 };
2559                                 memcpy(syncSave, sync, sizeof(syncSave));
2560                                 bool result = ResyncWave(sync, num);
2561
2562                                 // Now go through the catty wampus crap and zero out the parts that aren't all ones across the board
2563                                 double timeToOnes = 0;
2564                                 double a[6], currentRow[6];
2565
2566                                 // Collect the current row
2567                                 for(uint32_t i=0; i<num; i++)
2568                                 {
2569                                         currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
2570                                         syncSave[i]++;
2571                                 }
2572 #ifdef DEBUGSYNTH
2573 for(uint32_t i=0; i<num; i++)
2574         printf("syncSave[%d]=%d (sync: %d)\n", i, syncSave[i], sync[i]);
2575 #endif
2576
2577                                 while (true)
2578                                 {
2579                                         if (Equal(syncSave, sync, num))
2580                                                 break;
2581 #ifdef DEBUGSYNTH
2582 printf("syncSave: ");
2583 for(uint32_t i=0; i<num; i++)
2584         printf("%d%s", syncSave[i], (i == num - 1 ? "" : ", "));
2585 printf("\n    sync: ");
2586 for(uint32_t i=0; i<num; i++)
2587         printf("%d%s", sync[i], (i == num - 1 ? "" : ", "));
2588 printf("\n");
2589 #endif
2590
2591                                         uint32_t amplitude = 1;
2592                                         uint32_t smallestIdx = SmallestIndex(currentRow, num);
2593                                         uint32_t cnt = 1;
2594                                         a[0] = currentRow[smallestIdx];
2595 #ifdef DEBUGSYNTH
2596 printf("a[0]=%.2lf:\n", a[0]);
2597 #endif
2598
2599                                         for(uint32_t i=0; i<num; i++)
2600                                         {
2601                                                 // Make sure we haven't gone beyond the end of any of the streams we're looking at
2602                                                 if (syncSave[i] >= Global::waveLen[sNum[i]])
2603                                                 {
2604                                                         printf("Ran past end of stream %d (stream %d): syncSave=%d, waveLen=%d\n", i, sNum[i], syncSave[i], Global::waveLen[sNum[i]]);
2605                                                         return;
2606                                                 }
2607
2608                                                 if (i == smallestIdx)
2609                                                 {
2610                                                         // Maybe we should chuck this above the if()?
2611 //                                                      if (syncSave[i] == sync[i])
2612 //                                                              continue;
2613
2614                                                         // We always pick up the smallest in the current set, since that's our basis
2615 //the reason this works is because this simulates the "add next and subtract smallest", since the subtraction of the smallest would always be zero.  :-P
2616                                                         currentRow[i] = Global::wave[sNum[i]][syncSave[i]];
2617 //                                                      currentRow[i] += Global::wave[sNum[i]][syncSave[i]];
2618                                                         syncSave[i]++;
2619 #ifdef DEBUGSYNTH
2620 printf("\t<%.2lf> (i=%d)\n", currentRow[i], i);
2621 #endif
2622                                                         continue;
2623                                                 }
2624
2625                                                 // Save the current row & subtract out the smallest as a basis
2626                                                 double crSave = currentRow[i];
2627                                                 currentRow[i] -= a[0];
2628
2629                                                 // Don't bother with stuff that's out of range (@ current sync point!)  :-P
2630                                                 if (syncSave[i] == sync[i])
2631                                                         continue;
2632
2633                                                 // Try to find correlates
2634                                                 a[cnt] = crSave;
2635                                                 cnt++;
2636                                                 sigma = StdDeviation(a, cnt);
2637 #ifdef DEBUGSYNTH
2638 printf("\t");
2639 for(uint32_t j=1; j<cnt; j++)
2640         printf("[%.2lf]", a[j]);
2641 #endif
2642
2643 //relaxed sigma...
2644                                                 if (sigma <= 5.5)//SIGMA_THRESHOLD)
2645                                                 {
2646                                                         // If the sigma is in range for this item, pick it up
2647 //                                                      currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
2648                                                         currentRow[i] += (double)Global::wave[sNum[i]][syncSave[i]];
2649                                                         syncSave[i]++;
2650
2651 #ifdef DEBUGSYNTH
2652 printf("{%.2lf}", currentRow[i]);
2653 #endif
2654                                                         amplitude++;
2655                                                 }
2656                                                 else
2657                                                 {
2658                                                         // Otherwise reject the last item; it's too far out
2659                                                         cnt--;
2660                                                 }
2661 #ifdef DEBUGSYNTH
2662 printf(" ==> %.2lf\n", sigma);
2663 #endif
2664                                         }
2665
2666                                         // Get the average of the items picked up and add it to the wave
2667                                         sigma = StdDeviation(a, cnt, &mean);
2668                                         timeToOnes += mean;
2669
2670                                         // Did we find the line of ones yet?  If so, chuck it in the wave
2671                                         if (amplitude == num)
2672                                         {
2673                                                 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(timeToOnes + 0.5);
2674                                                 Global::synWaveLen[trackNum]++;
2675                                                 timeToOnes = 0;
2676                                         }
2677 #ifdef DEBUGSYNTH
2678 printf("\t");
2679 for(uint32_t j=0; j<num; j++)
2680         printf("_%.2lf_", currentRow[j]);
2681 printf("\n\n");
2682 #endif
2683                                 }
2684
2685                                 // Finally, chuck the final line of ones in
2686                                 sigma = StdDeviation(currentRow, num, &mean);
2687                                 timeToOnes += mean;
2688                                 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(timeToOnes + 0.5);
2689                                 Global::synWaveLen[trackNum]++;
2690 #ifdef NOISYSYNTH
2691 printf("Blip @ %d: ", startOfSynth);
2692 for(uint32_t w=startOfSynth; w<Global::synWaveLen[trackNum]; w++)
2693         printf("%d%s", Global::synWave[trackNum][w], (w == Global::synWaveLen[trackNum] - 1 ? "" : ", "));
2694 printf("\n");
2695 #endif
2696                         }
2697
2698                         for(uint32_t i=0; i<num; i++)
2699                         {
2700                                 if (sync[i] >= Global::waveLen[sNum[i]])
2701                                 {
2702                                         keepGoing = false;
2703                                         break;
2704                                 }
2705                         }
2706                 }
2707                 while (keepGoing);
2708
2709                 printf("\n%.2f: Synthesis done. Bit count: %d, bloop count: %d\n", (float)trackNum / 4.0f, count, bloops);
2710         }
2711
2712         // Now, find the loop point and make BITS from it
2713 /*
2714 Now, we take the track and make an ouroborus out of it by finding the sync point.  We can also possibly use it to get rid of more false ones like we did above with the resynchronization code.  So how do we do this?
2715
2716 We could use an approach similar to the original sync between 1 & 2, but there's no guarantee that the lookahead will be good right away.  So we need to do a combination where we count the places where it coincides well and plow through spots where it doesn't (and possibly mask any ones in those areas if it's a good match).
2717
2718 We can start with the estimated loop point that the Applesauce hardware found, by walking it a bit before that point we can make sure we don't miss it.
2719 */
2720         // We use the loop point from stream #1 because we're lazy
2721         uint32_t estLoopTime = Uint32LE(Global::stream[sNum[0]]->estLoopPoint);
2722         uint32_t curTime = 0;
2723         uint32_t pos = 0, startOfLoop = 0;
2724         double a[2];
2725         uint32_t maxLookahead = 0;
2726         uint32_t maxPos = 0;
2727         bool full, full2, full0, full1;
2728         uint32_t blips, worstBlips, longestStretch, stretch, maxLongestStretch = 0, worstBlipsPos = 0, mlsPos = 0;
2729         worstBlips = 1e9;
2730
2731         // Get the index to the correct time in "pos"
2732         while (curTime < estLoopTime)
2733                 curTime += Global::synWave[trackNum][pos++];
2734
2735 printf("%.2f: estLoopTime=%d, curTime=%d, pos=%d\n", (float)trackNum / 4.0f, estLoopTime, curTime, pos);
2736         uint32_t posSave = pos;
2737
2738         // "pos" now holds the start of the search for our loop point.
2739         for(uint32_t i=0; i<200; i++)
2740         {
2741                 uint32_t lookahead = 0;
2742                 uint32_t j, pos0;
2743                 bool first = true;
2744                 blips = 0;
2745                 longestStretch = stretch = 0;
2746                 startOfLoop = 0;//shouldn't be necessary...
2747
2748                 for(j=(pos+i-100), pos0=0; j<Global::synWaveLen[trackNum]; j++, pos0++)
2749                 {
2750                         uint32_t lla0 = LoopLookahead(trackNum, pos0 + 0, j, &full0);
2751                         uint32_t lla1 = LoopLookahead(trackNum, pos0 + 1, j, &full1);
2752
2753                         lookahead += lla0;
2754                         stretch = lla0;
2755
2756                         if (stretch > longestStretch)
2757                                 longestStretch = stretch;
2758
2759                         if (full0)
2760                         {
2761                                 break;
2762                         }
2763                         else if (full1 && first) // only check 1st time (for now)
2764                         {
2765                                 startOfLoop = 1;
2766                                 lookahead = lla1;
2767                                 stretch = lla1;
2768                                 break;
2769                         }
2770
2771                         if (first)
2772                                 first = false;
2773
2774                         pos0 += lla0;
2775                         j += lla0;
2776
2777                         a[0] = Global::synWave[trackNum][pos0++];
2778                         a[1] = Global::synWave[trackNum][j++];
2779                         double sigma = StdDeviation(a, 2);
2780
2781 #if 0
2782 if (first)
2783 {
2784         first = false;
2785 //      printf("First blip: %.0lf, %.0lf (sigma=%.2lf) [pos=%d, la=%d]\n", a[0], a[1], sigma, i + pos - 100, pos0);
2786
2787         if (trackNum == 137)
2788         {
2789                 uint32_t lla = LoopLookahead(trackNum, 0, j, &full);
2790                 uint32_t llap1 = LoopLookahead(trackNum, 1, j, &full2);
2791                 printf("%.2f: pos0=%d, j=%d, sigma=%lf, la=%d%s, la+1=%d%s", (float)trackNum / 4.0f, pos0, j, sigma, lla, (full ? " *equal" : ""), llap1, (full2 ? " *equal" : ""));
2792         }
2793 }
2794 #endif
2795
2796 /*                      if (sigma <= 2.50)
2797                         {
2798                                 lookahead++;
2799                                 stretch++;
2800
2801                                 if (stretch > longestStretch)
2802                                         longestStretch = stretch;
2803                         }
2804                         else//*/
2805 //                      {
2806                                 // Hmm, not in sync.  See if we can re-sync
2807                                 stretch = 0;
2808                                 blips++;
2809
2810                                 do
2811                                 {
2812                                         if (a[0] < a[1])
2813                                                 a[0] += Global::synWave[trackNum][pos0++];
2814                                         else
2815                                                 a[1] += Global::synWave[trackNum][j++];
2816
2817                                         // Maybe put all the other heuristics in too?
2818                                         if (StdDeviation(a, 2) <= 2.50)
2819                                                 break;
2820
2821                                         // Now you've gone *too* far...
2822                                         if (j >= Global::synWaveLen[trackNum])
2823                                                 break;
2824                                 }
2825                                 while (true);
2826 //                      }
2827                 }
2828
2829 #if 0
2830 if (trackNum == 137)
2831         printf(" blips=%d, la=%d\n", blips, lookahead);
2832 #endif
2833
2834 //maybe we should keep an array of the analyses so we can decide afterward which one is best...
2835                 if (blips < worstBlips)
2836                 {
2837                         worstBlips = blips;
2838                         worstBlipsPos = pos + i - 100;
2839                 }
2840
2841                 if (lookahead > maxLookahead)
2842                 {
2843                         maxLookahead = lookahead;
2844                         maxPos = pos + i - 100;
2845                 }
2846
2847                 if (longestStretch > maxLongestStretch)
2848                 {
2849                         maxLongestStretch = longestStretch;
2850                         mlsPos = pos + i - 100;
2851                 }
2852
2853                 if (blips == 0)
2854                         break;
2855         }
2856
2857 #if 0
2858         bitLen[trackNum] = RenderBitstream(bits[trackNum], &byteLen[trackNum], Global::synWave[trackNum], startOfLoop, maxPos);
2859 #endif
2860
2861         printf("%.2f: Synthesized wave length: %d\n", (float)trackNum / 4.0f    , Global::synWaveLen[trackNum]);
2862         printf("%s loop point found at position %d (elp%+d, la=%d, startPos=%d, blips=%d, blipsPos=%d, longest stretch=%d, mlsPos=%d, sol=%d)\n----------------------------------------------------------------------\n", (blips == 0 ? "Perfect" : "Possible"), maxPos, maxPos - posSave, maxLookahead, pos, worstBlips, worstBlipsPos, maxLongestStretch, mlsPos, startOfLoop);
2863 /*
2864 Track 1.00:
2865 36110 is the loop point.  But it fails to find it for some reason. [Because it jumped on the first one it found instead of the longest...]
2866 */
2867
2868 /*      for(uint32_t i=0; i<maxLookahead+5; i++)
2869         {
2870                 a[0] = Global::synWave[trackNum][i];
2871                 a[1] = Global::synWave[trackNum][i + maxPos];
2872                 double sigma = StdDeviation(a, 2);
2873                 printf("[%.2lf]", sigma);
2874         }
2875
2876         printf("\n");//*/
2877 }
2878
2879
2880 /*
2881 Using a histogram, we can get an idea of the drift from the ones:
2882
2883                 @@
2884                 @@
2885                 @@
2886                 @@
2887                 @@
2888                 @@
2889                 @@
2890                 @@        @@
2891                 @@        @@
2892                 @@        @@
2893                 @@        @@
2894                 @@        @@
2895                 @@   @@   @@
2896            @@   @@   @@   @@
2897            @@   @@   @@   @@
2898       @@   @@   @@   @@   @@
2899 -------------------------------------------------
2900 0000|0584|1792|9611|2627|5382|0482|0058|0013|0000
2901  28   29   30   31   32   33   34   35   36   37
2902
2903 Peak of the ones occurs at 31, with a secondary at 33. Twos drift:
2904
2905                 @@
2906                 @@        @@
2907                 @@        @@
2908                 @@        @@
2909                 @@        @@
2910                 @@        @@
2911                 @@        @@
2912                 @@   @@   @@
2913       @@        @@   @@   @@
2914 -------------------------------------------------
2915 0000|0545|0277|5482|1223|5168|0252|0082|0102|0000
2916  57   58   59   60   61   62   63   64   65   66
2917
2918 This looks like stretched out ones (they might all be spurious...):
2919
2920       @@
2921       @@
2922       @@             @@
2923       @@             @@
2924       @@   @@        @@
2925       @@   @@        @@
2926       @@   @@        @@
2927       @@   @@   @@   @@        @@
2928 ---------------------------------------
2929 0000|0015|0007|0002|0011|0001|0002|0000
2930  43   44   45   46   47   48   49   50
2931
2932
2933 */
2934
2935