]> Shamusworld >> Repos - wozmaker/blob - src/dsp.cpp
Flesh out the disk settings dialog.
[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 uint32_t sNum[6];
21 double initSyncTime[6];
22
23 static const double SIGMA_THRESHOLD = 2.5;
24
25
26 double StdDeviation(double * a, uint32_t num, double * pMean/*= NULL*/)
27 {
28         double sigma = 0, mean = 0;
29
30         for(uint32_t i=0; i<num; i++)
31                 mean += a[i];
32
33         mean = mean / (double)num;
34
35         if (pMean)
36                 *pMean = mean;
37
38         for(uint32_t i=0; i<num; i++)
39                 sigma += (a[i] - mean) * (a[i] - mean);
40
41         return sqrt(sigma / (double)num);
42 }
43
44
45 double StdDeviationWave(uint32_t * sync, uint32_t num, double * pMean/*= NULL*/)
46 {
47         double sigma = 0, mean = 0;
48         double a[6];
49
50         for(uint32_t i=0; i<num; i++)
51         {
52                 a[i] = (double)Global::wave[sNum[i]][sync[i]];
53                 mean += a[i];
54         }
55
56         mean = mean / (double)num;
57
58         // Capture the mean, if a pointer was passed in
59         if (pMean)
60                 *pMean = mean;
61
62         for(uint32_t i=0; i<num; i++)
63                 sigma += (a[i] - mean) * (a[i] - mean);
64
65         return sqrt(sigma / (double)num);
66 }
67
68
69 double Largest(double * a, uint32_t num)
70 {
71         double largest = a[0];
72
73         for(uint32_t i=1; i<num; i++)
74         {
75                 if (a[i] > largest)
76                         largest = a[i];
77         }
78
79         return largest;
80 }
81
82
83 uint32_t Largest(uint32_t * a, uint32_t num)
84 {
85         uint32_t largest = a[0];
86
87         for(uint32_t i=1; i<num; i++)
88         {
89                 if (a[i] > largest)
90                         largest = a[i];
91         }
92
93         return largest;
94 }
95
96
97 uint32_t LargestIndex(double * a, uint32_t num)
98 {
99         double largest = a[0];
100         uint32_t index = 0;
101
102         for(uint32_t i=1; i<num; i++)
103         {
104                 if (a[i] > largest)
105                 {
106                         largest = a[i];
107                         index = i;
108                 }
109         }
110
111         return index;
112 }
113
114
115 uint32_t LargestIndex(uint32_t * a, uint32_t num)
116 {
117         uint32_t largest = a[0];
118         uint32_t index = 0;
119
120         for(uint32_t i=1; i<num; i++)
121         {
122                 if (a[i] > largest)
123                 {
124                         largest = a[i];
125                         index = i;
126                 }
127         }
128
129         return index;
130 }
131
132
133 double Smallest(double * a, uint32_t num)
134 {
135         double smallest = a[0];
136
137         for(uint32_t i=1; i<num; i++)
138         {
139                 if (a[i] < smallest)
140                         smallest = a[i];
141         }
142
143         return smallest;
144 }
145
146
147 uint32_t Smallest(uint32_t * a, uint32_t num)
148 {
149         uint32_t smallest = a[0];
150
151         for(uint32_t i=1; i<num; i++)
152         {
153                 if (a[i] < smallest)
154                         smallest = a[i];
155         }
156
157         return smallest;
158 }
159
160
161 uint32_t SmallestIndex(double * a, uint32_t num)
162 {
163         double smallest = a[0];
164         uint32_t index = 0;
165
166         for(uint32_t i=1; i<num; i++)
167         {
168                 if (a[i] < smallest)
169                 {
170                         smallest = a[i];
171                         index = i;
172                 }
173         }
174
175         return index;
176 }
177
178
179 uint32_t SmallestIndex(uint32_t * a, uint32_t num)
180 {
181         uint32_t smallest = a[0];
182         uint32_t index = 0;
183
184         for(uint32_t i=1; i<num; i++)
185         {
186                 if (a[i] < smallest)
187                 {
188                         smallest = a[i];
189                         index = i;
190                 }
191         }
192
193         return index;
194 }
195
196
197 //
198 // Compare two arrays to see if they are equal
199 //
200 bool Equal(uint32_t * a1, uint32_t * a2, uint32_t num)
201 {
202         for(uint32_t i=0; i<num; i++)
203         {
204                 if (a1[i] != a2[i])
205                         return false;
206         }
207
208         return true;
209 }
210
211
212 uint32_t IndexForTime(uint32_t trackNum, uint32_t time)
213 {
214         uint32_t curTime = 0, pos = 0;
215
216         while (curTime < time)
217                 curTime += Global::synWave[trackNum][pos++];
218
219         return pos;
220 }
221
222
223 //
224 // 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.)
225 //
226 // 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
227 //
228 // 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.
229 //
230 // 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.
231 //
232
233 void FindInitialSyncForStreams2(uint32_t * sync, uint32_t num)
234 {
235         bool lookAt[6] = { true, true, false, false, false, false };
236
237 //      while (FindSyncBetweenFirstTwo(sync) == false)
238         while (FindSyncBetweenFirstTwo(sync) < 1000)
239         {
240                 for(uint32_t i=0; i<num; i++)
241                 {
242                         sync[i] += 200;
243
244                         if (sync[i] >= Global::waveLen[sNum[i]])
245                         {
246                                 printf("Could not find initial sync!!\n");
247                                 return;// -1;
248                         }
249                 }
250         }
251
252         uint32_t lookahead = LookaheadWave(sync, 2);
253
254         if (lookAt[0])
255                 printf("Found sync for streams 1 & 2 at %d and %d (la=%d)\n", sync[0], sync[1], lookahead);
256
257         // Add in the others, one at a time and try to synchronize them
258         uint32_t bestSync[6];
259
260         for(uint32_t i=2; i<num; i++)
261         {
262                 lookAt[i] = true;
263                 uint32_t bestLA = 0;
264
265                 for(uint32_t j=0; j<200; j++)
266                 {
267                         uint32_t syncSave = sync[i];
268
269                         // And check again for a match
270                         for(uint32_t k=0; k<200; k++)
271                         {
272                                 uint32_t la = LookaheadWave(sync, i + 1);
273
274                                 if (la > bestLA)
275                                 {
276                                         bestLA = la;
277                                         memcpy(bestSync, sync, sizeof(bestSync));
278                                 }
279
280                                 sync[i]++;
281                         }
282
283                         sync[i] = syncSave;
284
285                         // Kick synchronized streams forward to check the rest...
286                         for(uint32_t k=0; k<i; k++)
287                                 sync[k]++;
288                 }
289
290                 memcpy(sync, bestSync, sizeof(bestSync));
291         }
292
293         for(uint32_t i=0; i<num; i++)
294                 printf("Sync for stream %d: %d (%s)\n", i, sync[i], (lookAt[i] ? "yes" : "no"));
295         printf("Lookahead: %d\n", LookaheadWave(sync, num));
296 }
297
298
299 #if 1
300 uint32_t Synthesize2(uint32_t * sync, uint32_t num, uint32_t * synthWave, float * swAmplitude)
301 {
302         uint32_t swLen = 0;
303         uint32_t syncPt[7], syncSave[7];
304         double a[7], b[7], currentRow[7];
305         Global::bloops = 0;
306
307         memcpy(syncPt, sync, sizeof(syncPt));
308
309         while (true)
310         {
311                 for(uint32_t i=0; i<num; i++)
312                 {
313                         if (syncPt[i] >= Global::streamLen[i])
314                                 return swLen;
315                 }
316
317                 // Save these *before* we step forward
318                 memcpy(syncSave, syncPt, sizeof(syncSave));
319 //              StepForward(syncPt, a, num);
320                 for(uint32_t i=0; i<num; i++)
321                 {
322                         a[i] = (double)Global::wave[sNum[i]][syncPt[i]];
323                         syncPt[i]++;
324                 }
325
326                 double mean;
327                 double sigma = StdDeviation(a, num, &mean);
328
329                 if (sigma <= SIGMA_THRESHOLD)
330                 {
331                         synthWave[swLen] = (uint32_t)(mean + 0.5);
332                         swAmplitude[swLen] = 1.0f;
333                         swLen++;
334                 }
335                 else
336                 {
337                         Global::bloops++;
338                         // 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.
339                         uint32_t syncSteps = 0;
340                         uint32_t lookahead = LookaheadWave(syncPt, num);
341
342                         // 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.
343 /*
344 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.
345 */
346 #ifdef NOISY
347 printf("a: ");
348 for(uint32_t i=0; i<num; i++)
349         printf("[%.2lf]", a[i]);
350 //printf(" => %.2lf {drift=%.2lf, la=%d}\n", sigma, driftSigma, lookahead);
351 printf(" => %.2lf {la=%d}\n", sigma, lookahead);
352
353 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", syncPt[j], (j < num - 1 ? "-" : "")); }
354 printf("\n");//*/
355 #endif
356                         bool keepWorking = true;
357
358                         do
359                         {
360                                 syncSteps++;
361
362                                 // If we've been in this loop too long, something's very wrong
363                                 if (syncSteps > 20)
364                                         return swLen;
365
366                                 // Pull the lesser streams forward to catch up to the largest
367                                 uint32_t largestIdx = LargestIndex(a, num);
368                                 bool pulled = false;
369
370                                 for(uint32_t i=0; i<num; i++)
371                                 {
372                                         if (i == largestIdx)
373 #ifdef NOISY
374                                         {
375                                                 printf("  ~~~~  ");
376 #endif
377                                                 continue;
378 #ifdef NOISY
379                                         }
380 #endif
381 //                                      if ((a[largestIdx] - a[i]) > 7.0)
382                                         if ((a[largestIdx] - a[i]) > 9.0)
383                                         {
384                                                 pulled = true;
385                                                 a[i] += (double)Global::wave[sNum[i]][syncPt[i]];
386 #ifdef NOISY
387                                                 printf(" %6d ", Global::wave[sNum[i]][syncPt[i]]);
388 #endif
389                                                 syncPt[i]++;
390                                         }
391 #ifdef NOISY
392                                         else
393                                                 printf("        ");
394 #endif
395                                         // See if we've run out of stream to synthesize...
396                                         if (syncPt[i] >= Global::waveLen[sNum[i]])
397                                                 return swLen;
398                                 }
399
400 #ifdef NOISY
401                                 printf("\n");
402
403                                 for(uint32_t i=0; i<num; i++)
404                                         printf("<%6.2lf>", a[i]);
405 #endif
406                                 // Calculate the standard deviation at this new point
407                                 sigma = StdDeviation(a, num);//, &mean);
408
409                                 // Calculate the following sigma & lookahead too
410                                 for(uint32_t i=0; i<num; i++)
411                                         b[i] = (double)Global::wave[sNum[i]][syncPt[i]];
412
413                                 double nextSigma = StdDeviation(b, num);
414                                 lookahead = LookaheadWave(syncPt, num);
415 #ifdef NOISY
416                                 printf(" ==> %.2lf%s", sigma, (sigma <= SIGMA_THRESHOLD ? " (OK)" : (!pulled ? "(STEP)" : "")));
417                                 printf(" (lookahead=%.2lf, %d)\n", nextSigma, lookahead);
418
419 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", syncPt[j], (j < num - 1 ? "-" : "")); }
420 printf("\n");//*/
421 #endif
422                                 // A handful of heuristics.  If the sigma is OK, we're done
423                                 if (sigma < 2.5)
424                                         keepWorking = false;
425
426                                 // If we couldn't pull any streams forward for some reason, punt
427                                 if (!pulled)
428                                         keepWorking = false;
429
430                                 // If the average of the current & next sigmas is OK, go ahead
431                                 if (((sigma + nextSigma) / 2.0) < 2.5)
432                                         keepWorking = false;
433
434                                 // If the next sigma is OK and the lookahead too, move on
435                                 if ((nextSigma < 2.5) && (lookahead > 10))
436                                         keepWorking = false;
437                         }
438                         while (keepWorking);
439
440                         // Now, we've re-established sync, now fill the appropriate spots
441
442 /*
443 So the algorithm to do this proppaly is like so:
444
445 Step 1: Find the smallest step forward through the section; set amplitude to 0.2.
446 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.
447 Step 3: Add the mean value of the corresponding values to the synthesized waveform + wave amplitude
448 Step 4: If all of the stream starts are at the end of the section, we are done.
449 [maybe.  how do you handle the case where you have streams that look like so:
450
451 200
452 150 50
453 150 50
454 175 25
455 200
456
457 .......................................|
458 .............................|.........|
459 .............................|.........|
460 ..................................|....|
461 .......................................|
462
463 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:
464
465 synthWave[swLen] = (uint32_t)((mean - baseline) + 0.5)
466 swAmplitude[swLen] = amplitude;
467
468 no need for that.  the times that step directly to the end can safely be ignored.
469 ]
470
471 150 -> 150 (ignores 175)
472 150 goes in, ampl. .4, we now have:
473
474 200
475 50
476 50
477 175 25
478 200
479
480 only one is left that we can grab:
481
482 175
483
484 last pulse was at 150 (40%), so we need to subtract that out
485
486 -> 25
487
488 so maybe we'd do like so:
489 -1) create a list containing the start values for the start of the anomalous section and replace them as the counters advance.
490 0) are streams at the end? if so, stuff in the final value to the synthesized wave & stop, otherwise:
491 1) find the smallest in the current row and use that as a basis.
492 2) find streams that correlate, if any
493 3) advance the streams that correlate & subtract out the minimum from the other rows
494 4) go to 0)
495
496 200
497 150 50
498 150 50
499 175 25
500 200
501
502 smallest is 150: pick 150 -> picks up 150
503 advance the 150 rows & subtract 150 from the rest:
504
505 50
506 50
507 50
508 25 25
509 50
510
511 pick smallest: 25 -> picks up nothing
512 advance the 25 & subtract it from the rest:
513
514 25
515 25
516 25
517 25
518 25
519
520 We've reached the end of the section, add the final amount
521
522 --------------------------------------------------------------------------------
523 syncSave before: [2->4][2->6][2->4][2->6][2->6]
524 syncSave after: [3->4][3->6][3->4][3->6][3->6]
525
526 currentRow: [120.89][49.97][46.98][49.98][48.98] => 28.78
527
528 2: [3->4][3->6][3->4][3->6][3->6]
529
530 a[0]=46.98: [120.89] ==> 36.95
531         [49.97]{17.00} ==> 1.50
532         <106.00>[49.97][49.98]{28.00} ==> 1.41
533         [49.97][49.98][48.98]{26.00} ==> 1.22
534
535 3: [3->4][4->6][4->4][4->6][4->6]
536
537 a[0]=17.00: [73.91] ==> 28.45
538         <56.00>[28.00]{45.00} ==> 5.50
539         [28.00][26.00]{47.00} ==> 4.78
540
541 4: [3->4][5->6][4->4][5->6][5->6]
542
543 a[0]=45.00: [56.91] ==> 5.95
544         [56.00]{32.00} ==> 5.50
545         <32.00>[56.00][47.00]{32.00} ==> 4.78
546
547 5: [3->4][6->6][4->4][6->6][6->6]
548
549 a[0]=11.91: <32.00>
550
551 6: [4->4][6->6][4->4][6->6][6->6]
552
553  2->4    2->6    2->4    2->6    2->6
554 [120.89][ 49.97][ 46.98][ 49.98][ 48.98] => 28.78
555 ( 73.91)  17.00  106.00   28.00   26.00
556 ( 56.91)  56.00           45.00   47.00
557   32.00   32.00           32.00   32.00
558
559 */
560 #ifdef NOISY
561 /*printf("syncSave before: ");
562 for(uint32_t i=0; i<num; i++)
563         printf("[%d->%d]", syncSave[i], syncPt[i]);
564 printf("\n");//*/
565
566 for(uint32_t i=0; i<num; i++)
567 {
568         printf("Sync %d: %d -> %d (", sNum[i], syncSave[i], syncPt[i]);
569         for(uint32_t j=syncSave[i]; j<=syncPt[i]; j++)
570                 printf("%d%s", Global::wave[sNum[i]][j], (j == syncPt[i] ? "" : ", "));
571         printf(")\n");
572 }
573 #endif
574                         // Collect the current row
575                         for(uint32_t i=0; i<num; i++)
576                         {
577                                 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
578                                 syncSave[i]++;
579                         }
580
581 /*printf("syncSave after: ");
582 for(uint32_t i=0; i<num; i++)
583         printf("[%d->%d]", syncSave[i], syncPt[i]);
584 printf("\n");
585 printf("currentRow: ");
586 for(uint32_t i=0; i<num; i++)
587         printf("[%.2lf]", currentRow[i]);
588 printf(" => %.2lf\n", StdDeviation(currentRow, num));//*/
589
590 //printf("%d: ", swLen);
591
592                         float ampStep = 1.0f / (float)num;
593
594                         while (true)
595                         {
596                                 if (Equal(syncSave, syncPt, num))
597                                         break;
598
599                                 float amplitude = ampStep;
600                                 uint32_t smallestIdx = SmallestIndex(currentRow, num);
601                                 uint32_t cnt = 1;
602                                 a[0] = currentRow[smallestIdx];
603 //printf("a[0]=%.2lf: ", a[0]);
604
605                                 for(uint32_t i=0; i<num; i++)
606                                 {
607                                         // Make sure we haven't gone beyond the end of any of the streams we're looking at
608                                         if (syncSave[i] >= Global::streamLen[i])
609                                                 return swLen;
610
611                                         if (i == smallestIdx)
612                                         {
613                                                 // We always pick up the smallest in the current set, since that's our basis
614                                                 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
615                                                 syncSave[i]++;
616 //printf("<%.2lf>", currentRow[i]);
617                                                 continue;
618                                         }
619
620                                         // Save the current row & subtract out the smallest as a basis
621                                         double crSave = currentRow[i];
622                                         currentRow[i] -= a[0];
623
624                                         // Don't bother with stuff that's out of range (@ current sync point!)  :-P
625                                         if (syncSave[i] == syncPt[i])
626                                                 continue;
627
628                                         // Try to find correlates
629                                         a[cnt] = crSave;
630                                         cnt++;
631                                         sigma = StdDeviation(a, cnt);
632 //for(uint32_t j=1; j<cnt; j++)
633 //      printf("[%.2lf]", a[j]);
634
635 //relaxed sigma...
636                                         if (sigma <= 5.5)//SIGMA_THRESHOLD)
637                                         {
638                                                 // If the sigma is in range for this item, pick it up
639                                                 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
640                                                 syncSave[i]++;
641
642 //printf("{%.2lf}", currentRow[i]);
643                                                 amplitude += ampStep;
644                                         }
645                                         else
646                                         {
647                                                 // Otherwise reject the last item; it's too far out
648                                                 cnt--;
649                                         }
650 //printf(" ==> %.2lf\n\t", sigma);
651                                 }
652
653                                 // Get the average of the items picked up and add it to the wave
654                                 sigma = StdDeviation(a, cnt, &mean);
655                                 synthWave[swLen] = (uint32_t)(mean + 0.5);
656                                 swAmplitude[swLen] = amplitude;
657                                 swLen++;
658                         }
659
660                         sigma = StdDeviation(currentRow, num, &mean);
661                         synthWave[swLen] = mean;
662                         swAmplitude[swLen] = 1.0f;
663                         swLen++;
664                 }
665         }
666
667         return swLen;
668 }
669 #endif
670
671
672 bool ResyncWave(uint32_t * sync, uint32_t num, int8_t dir/*= 1*/)
673 {
674         double a[6];
675
676         for(uint32_t i=0; i<num; i++)
677         {
678                 a[i] = (double)Global::wave[sNum[i]][sync[i]];
679                 sync[i] += dir;
680         }
681
682 #ifdef NOISY
683         for(uint32_t i=0; i<num; i++)
684                 printf("<%4d>", (uint32_t)a[i]);
685
686         printf(" {la: %d}\n", LookaheadWave(sync, num, dir));
687 #endif
688
689         uint32_t syncCount = 0;
690         bool keepGoing = true;
691
692         do
693         {
694                 if (syncCount > 42)
695                 {
696                         printf("Could not synchronize streams...\n");
697                         return false;
698                 }
699
700                 for(uint32_t i=0; i<num; i++)
701                 {
702                         if (((dir == 1) && (sync[i] >= Global::waveLen[sNum[i]]))
703                                 || ((dir == -1) && (sync[i] == 0)))
704                         {
705                                 printf("End of stream...\n");
706                                 return true;
707                         }
708                 }
709
710                 // 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.
711                 uint32_t largestIdx = LargestIndex(a, num);
712                 bool stepped = false;
713
714                 for(uint32_t i=0; i<num; i++)
715                 {
716                         if (i == largestIdx)
717 #ifdef NOISY
718                         {
719                                 printf(" ~~~~ ");
720 #endif
721                                 continue;
722 #ifdef NOISY
723                         }
724 #endif
725
726                         // If the difference between the highest and this is over 7, add the next time interval and let the sync counter, uh, slip :-)
727 //                      if ((a[largestIdx] - a[i]) > 7.0)
728                         if ((a[largestIdx] - a[i]) > 9.0)
729                         {
730                                 stepped = true;
731                                 double ttn = (double)Global::wave[sNum[i]][sync[i]];
732                                 a[i] += ttn;
733                                 sync[i] += dir;
734 #ifdef NOISY
735                                 printf(" %4d ", (uint32_t)ttn);
736 #endif
737                         }
738 #ifdef NOISY
739                         else
740                                 printf("      ");
741 #endif
742                 }
743
744                 double sigma = StdDeviation(a, num);
745                 double nextSigma = StdDeviationWave(sync, num);
746                 uint32_t lookahead = LookaheadWave(sync, num, dir);
747 #ifdef NOISY
748                 printf("\n");
749
750                 for(uint32_t i=0; i<num; i++)
751                         printf("<%4d>", (uint32_t)a[i]);
752
753                 printf(" ==> %.2lf ", sigma);
754                 printf("(next: %.2lf, la: %d)\n", nextSigma, lookahead);
755 #endif
756                 syncCount++;
757
758                 // A handful of heuristics...  1st: If sigma is good, we're done
759                 if (sigma < 2.50)
760                         keepGoing = false;
761
762                 // Couldn't pull, so punt for now
763                 if (!stepped)
764                         keepGoing = false;
765
766                 // If the next sigma + current / 2 is OK, move on
767                 if (((sigma + nextSigma) / 2.0) < 2.50)
768                         keepGoing = false;
769
770                 // If the next sigma is good, and the lookahead is good, move on
771                 // [Slight tweak: only do this if the current sigma isn't terrible]
772                 if ((nextSigma < 2.50) && (lookahead > 10) && (sigma < 20.0))
773                         keepGoing = false;
774         }
775         while (keepGoing);
776
777         return true;
778 }
779
780
781 uint32_t LookaheadWave(uint32_t * passedInSync, uint32_t num, int8_t dir/*= 1*/, bool * perfect/*= NULL*/)
782 {
783         uint32_t sync[6];
784         uint32_t count = 0;
785         memcpy(sync, passedInSync, sizeof(sync));
786
787         if (perfect)
788                 *perfect = true;
789
790         while (true)
791         {
792                 if (StdDeviationWave(sync, num) > 2.50)
793                 {
794                         if (perfect)
795                                 *perfect = false;
796
797                         break;
798                 }
799
800                 for(uint32_t i=0; i<num; i++)
801                 {
802                         sync[i] += dir;
803
804                         if (((dir == 1) && (sync[i] >= Global::waveLen[sNum[i]]))
805                                 || ((dir == -1) && (sync[i] == 0)))
806                                 return count;
807                 }
808
809                 count++;
810         }
811
812         return count;
813 }
814
815
816 uint32_t FindSyncBetweenFirstTwo(uint32_t * sync)
817 {
818         uint32_t bestSync[2], bestLA = 0, syncSave = sync[0];
819         bool perfect;
820
821         // Move the first stream first...
822         for(uint32_t i=0; i<200; i++)
823         {
824                 uint32_t la = LookaheadWave(sync, 2, 1, &perfect);
825
826                 // See if the sync we've found is the best so far...
827                 if (la > bestLA)
828                 {
829                         bestLA = la;
830                         memcpy(bestSync, sync, sizeof(bestSync));
831                 }
832
833                 if (perfect)
834                         break;
835
836                 sync[0]++;
837         }
838
839         // Otherwise, reset the first stream and move the 2nd
840         sync[0] = syncSave;
841
842         for(uint32_t i=0; i<200; i++)
843         {
844                 // We can bump this first since we already checked the [0][0] case above
845                 sync[1]++;
846                 uint32_t la = LookaheadWave(sync, 2, 1, &perfect);
847
848                 // See if the sync we've found is the best so far...
849                 if (la > bestLA)
850                 {
851                         bestLA = la;
852                         memcpy(bestSync, sync, sizeof(bestSync));
853                 }
854
855                 if (perfect)
856                         break;
857         }
858
859         // Set sync to the best we found & return the best lookahead count
860         memcpy(sync, bestSync, sizeof(bestSync));
861
862         return bestLA;
863 }
864
865
866 //
867 // Walk backwards through the streams to try to find the starting point
868 //
869 bool AttemptToFindStart(uint32_t * sync, uint32_t num)
870 {
871         // Sanity check...
872         for(uint32_t i=0; i<num; i++)
873         {
874                 if (sync[i] == 0)
875                         return true;
876         }
877
878         bool keepGoing = true;
879
880         do
881         {
882                 double sigma = StdDeviationWave(sync, num);
883
884                 if (sigma > 2.50)
885                 {
886                         bool result = ResyncWave(sync, num, -1);
887
888                         if (result == false)
889                                 return false;
890                 }
891                 else
892                 {
893                         for(uint32_t i=0; i<num; i++)
894                                 sync[i]--;
895                 }
896
897                 for(uint32_t i=0; i<num; i++)
898                 {
899                         if (sync[i] == 0)
900                                 keepGoing = false;
901                 }
902         }
903         while (keepGoing);
904
905 //#ifdef NOISY
906 #if 1
907         for(uint32_t i=0; i<num; i++)
908                 printf("Sync for stream %d: %d\n", i, sync[i]);
909         printf("Lookahead: %d\n", LookaheadWave(sync, num));
910 #endif
911
912         return true;
913 }
914
915
916 bool InitialSync(uint32_t * sync, uint32_t num)
917 {
918         // Let's try a different approach to this...
919         bool lookAt[6] = { true, true, false, false, false, false };
920         uint32_t syncSave[2];
921
922 //      while (FindSyncBetweenFirstTwo(sync) == false)
923 //      while (FindSyncBetweenFirstTwo(sync) < 1000)
924         while (true)
925         {
926                 memcpy(syncSave, sync, sizeof(syncSave));
927                 uint32_t bestSBFT = FindSyncBetweenFirstTwo(sync);
928
929                 if (bestSBFT >= 1000)
930                         break;
931
932                 memcpy(sync, syncSave, sizeof(syncSave));
933
934                 for(uint32_t i=0; i<num; i++)
935                 {
936                         sync[i] += 200;
937
938                         if (sync[i] >= Global::waveLen[sNum[i]])
939                         {
940                                 printf("Could not find initial sync!!\n");
941                                 return false;
942                         }
943                 }
944         }
945
946         uint32_t lookahead = LookaheadWave(sync, 2);
947
948         if (lookAt[0])
949                 printf("Found sync for streams 1 & 2 at %d and %d (la=%d)\n", sync[0], sync[1], lookahead);
950
951         // Add in the others, one at a time and try to synchronize them
952         uint32_t syncBest[6];
953         bool perfect;
954
955         for(uint32_t i=2; i<num; i++)
956         {
957                 lookAt[i] = true;
958                 uint32_t bestLA = 0;
959
960                 for(uint32_t j=0; j<200; j++)
961                 {
962                         uint32_t syncSave = sync[i];
963
964                         for(uint32_t k=0; k<200; k++)
965                         {
966                                 uint32_t la = LookaheadWave(sync, i + 1, 1, &perfect);
967
968                                 if (la > bestLA)
969                                 {
970                                         bestLA = la;
971                                         memcpy(syncBest, sync, sizeof(syncBest));
972                                 }
973
974                                 if (perfect || ((bestLA + j) == lookahead))
975                                 {
976                                         j = 200;
977                                         break;
978                                 }
979
980                                 sync[i]++;
981                         }
982
983                         sync[i] = syncSave;
984
985                         // Kick all the other streams forward to check the rest...
986                         for(uint32_t k=0; k<i; k++)
987                                 sync[k]++;
988                 }
989
990                 memcpy(sync, syncBest, sizeof(syncBest));
991         }
992
993         for(uint32_t i=0; i<num; i++)
994                 printf("Sync for stream %d: %d (%s)\n", i, sync[i], (lookAt[i] ? "yes" : "no"));
995         printf("Lookahead: %d\n", LookaheadWave(sync, num));
996
997         return true;
998 }
999
1000
1001 uint32_t LoopLookahead(uint32_t trackNum, uint32_t start, uint32_t loopPoint, bool * test/*= NULL*/)
1002 {
1003         uint32_t count = 0;
1004         bool equal = true;
1005         double a[2];
1006
1007         for(uint32_t i=loopPoint, pos=start; i<Global::synWaveLen[trackNum]; i++, pos++)
1008         {
1009                 a[0] = Global::synWave[trackNum][pos];
1010                 a[1] = Global::synWave[trackNum][i];
1011                 double sigma = StdDeviation(a, 2);
1012
1013                 if (sigma > 2.50)
1014                 {
1015                         equal = false;
1016                         break;
1017                 }
1018
1019                 count++;
1020         }
1021
1022         if (test)
1023                 *test = equal;
1024
1025         return count;
1026 }
1027
1028
1029 #define NOISYSYNTH
1030 //#define DEBUGSYNTH
1031 void SynthesizeTrack(uint32_t trackNum)
1032 {
1033         uint32_t num = 0;
1034         uint32_t sync[6] = { 0 };
1035
1036         for(uint32_t i=0; i<Global::numStreams; i++)
1037         {
1038                 // Skip streams that aren't on the current track & BITS captures
1039                 if ((Global::stream[i]->location != trackNum)
1040                         || (Global::stream[i]->captureType == 2))
1041                         continue;
1042
1043 #ifdef DEBUGSYNTH
1044 printf("sNum[%d] = %d\n", num, i);
1045 #endif
1046                 // Save the stream # so we can find it later
1047                 sNum[num++] = i;
1048         }
1049
1050         // We should just bypass the synthesis part of this, not the loop point finding...  :-P  !!! FIX !!!
1051         if (num == 1)
1052         {
1053                 printf("%.2f: Single stream, length: %d\n", (float) trackNum / 4.0f, Uint32LE(Global::stream[sNum[0]]->dataLength));
1054
1055                 memcpy(Global::synWave[trackNum], Global::wave[sNum[0]], Global::waveLen[sNum[0]] * 4);
1056                 Global::synWaveLen[trackNum] = Global::waveLen[sNum[0]];
1057         }
1058
1059 /*
1060 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)
1061 */
1062         if (num > 1)
1063         {
1064                 InitialSync(sync, num);
1065                 AttemptToFindStart(sync, num);
1066
1067                 uint32_t count = 0, bloops = 0;
1068                 bool keepGoing = true;
1069                 Global::synWaveLen[trackNum] = 0;
1070                 double mean;
1071
1072                 do
1073                 {
1074                         double sigma = StdDeviationWave(sync, num, &mean);
1075
1076                         if (sigma <= 2.50)
1077                         {
1078                                 count++;
1079                                 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(mean + 0.5);
1080                                 Global::synWaveLen[trackNum]++;
1081
1082                                 for(uint32_t i=0; i<num; i++)
1083                                         sync[i]++;
1084                         }
1085                         else
1086                         {
1087 #ifdef NOISYSYNTH
1088                                 uint32_t startOfSynth = Global::synWaveLen[trackNum];
1089 #endif
1090 #ifdef NOISYSYNTH
1091                                 if (bloops < 2)
1092                                 {
1093                                         printf("Bloop seen at pos ");
1094                                         for(uint32_t k=0; k<num; k++)
1095                                                 printf("%d%s", sync[k], (k == num - 1 ? "" : ", "));
1096                                         printf("...\n");
1097                                 }
1098 #endif
1099                                 bloops++;       // Count the # of times we've had to punt
1100                                 uint32_t syncSave[6] = { 0 };
1101                                 memcpy(syncSave, sync, sizeof(syncSave));
1102                                 /*bool result =*/ ResyncWave(sync, num);
1103
1104                                 // Now go through the catty wampus crap and zero out the parts that aren't all ones across the board
1105                                 double timeToOnes = 0;
1106                                 double a[6], currentRow[6];
1107
1108                                 // Collect the current row
1109                                 for(uint32_t i=0; i<num; i++)
1110                                 {
1111                                         currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
1112                                         syncSave[i]++;
1113                                 }
1114 #ifdef DEBUGSYNTH
1115 for(uint32_t i=0; i<num; i++)
1116         printf("syncSave[%d]=%d (sync: %d)\n", i, syncSave[i], sync[i]);
1117 #endif
1118
1119                                 while (true)
1120                                 {
1121                                         if (Equal(syncSave, sync, num))
1122                                                 break;
1123 #ifdef DEBUGSYNTH
1124 printf("syncSave: ");
1125 for(uint32_t i=0; i<num; i++)
1126         printf("%d%s", syncSave[i], (i == num - 1 ? "" : ", "));
1127 printf("\n    sync: ");
1128 for(uint32_t i=0; i<num; i++)
1129         printf("%d%s", sync[i], (i == num - 1 ? "" : ", "));
1130 printf("\n");
1131 #endif
1132
1133                                         uint32_t amplitude = 1;
1134                                         uint32_t smallestIdx = SmallestIndex(currentRow, num);
1135                                         uint32_t cnt = 1;
1136                                         a[0] = currentRow[smallestIdx];
1137 #ifdef DEBUGSYNTH
1138 printf("a[0]=%.2lf:\n", a[0]);
1139 #endif
1140
1141                                         for(uint32_t i=0; i<num; i++)
1142                                         {
1143                                                 // Make sure we haven't gone beyond the end of any of the streams we're looking at
1144                                                 if (syncSave[i] >= Global::waveLen[sNum[i]])
1145                                                 {
1146                                                         printf("Ran past end of stream %d (stream %d): syncSave=%d, waveLen=%d\n", i, sNum[i], syncSave[i], Global::waveLen[sNum[i]]);
1147                                                         return;
1148                                                 }
1149
1150                                                 if (i == smallestIdx)
1151                                                 {
1152                                                         // Maybe we should chuck this above the if()?
1153 //                                                      if (syncSave[i] == sync[i])
1154 //                                                              continue;
1155
1156                                                         // We always pick up the smallest in the current set, since that's our basis
1157 //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
1158                                                         currentRow[i] = Global::wave[sNum[i]][syncSave[i]];
1159 //                                                      currentRow[i] += Global::wave[sNum[i]][syncSave[i]];
1160                                                         syncSave[i]++;
1161 #ifdef DEBUGSYNTH
1162 printf("\t<%.2lf> (i=%d)\n", currentRow[i], i);
1163 #endif
1164                                                         continue;
1165                                                 }
1166
1167                                                 // Save the current row & subtract out the smallest as a basis
1168                                                 double crSave = currentRow[i];
1169                                                 currentRow[i] -= a[0];
1170
1171                                                 // Don't bother with stuff that's out of range (@ current sync point!)  :-P
1172                                                 if (syncSave[i] == sync[i])
1173                                                         continue;
1174
1175                                                 // Try to find correlates
1176                                                 a[cnt] = crSave;
1177                                                 cnt++;
1178                                                 sigma = StdDeviation(a, cnt);
1179 #ifdef DEBUGSYNTH
1180 printf("\t");
1181 for(uint32_t j=1; j<cnt; j++)
1182         printf("[%.2lf]", a[j]);
1183 #endif
1184
1185 //relaxed sigma...
1186                                                 if (sigma <= 5.5)//SIGMA_THRESHOLD)
1187                                                 {
1188                                                         // If the sigma is in range for this item, pick it up
1189                                                         currentRow[i] += (double)Global::wave[sNum[i]][syncSave[i]];
1190                                                         syncSave[i]++;
1191
1192 #ifdef DEBUGSYNTH
1193 printf("{%.2lf}", currentRow[i]);
1194 #endif
1195                                                         amplitude++;
1196                                                 }
1197                                                 else
1198                                                 {
1199                                                         // Otherwise reject the last item; it's too far out
1200                                                         cnt--;
1201                                                 }
1202 #ifdef DEBUGSYNTH
1203 printf(" ==> %.2lf\n", sigma);
1204 #endif
1205                                         }
1206
1207                                         // Get the average of the items picked up and add it to the wave
1208                                         sigma = StdDeviation(a, cnt, &mean);
1209                                         timeToOnes += mean;
1210
1211                                         // Did we find the line of ones yet?  If so, chuck it in the wave
1212                                         if (amplitude == num)
1213                                         {
1214                                                 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(timeToOnes + 0.5);
1215                                                 Global::synWaveLen[trackNum]++;
1216                                                 timeToOnes = 0;
1217                                         }
1218 #ifdef DEBUGSYNTH
1219 printf("\t");
1220 for(uint32_t j=0; j<num; j++)
1221         printf("_%.2lf_", currentRow[j]);
1222 printf("\n\n");
1223 #endif
1224                                 }
1225
1226                                 // Finally, chuck the final line of ones in
1227                                 sigma = StdDeviation(currentRow, num, &mean);
1228                                 timeToOnes += mean;
1229                                 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(timeToOnes + 0.5);
1230                                 Global::synWaveLen[trackNum]++;
1231 #ifdef NOISYSYNTH
1232 printf("Blip @ %d: ", startOfSynth);
1233 for(uint32_t w=startOfSynth; w<Global::synWaveLen[trackNum]; w++)
1234         printf("%d%s", Global::synWave[trackNum][w], (w == Global::synWaveLen[trackNum] - 1 ? "" : ", "));
1235 printf("\n");
1236 #endif
1237                         }
1238
1239                         for(uint32_t i=0; i<num; i++)
1240                         {
1241                                 if (sync[i] >= Global::waveLen[sNum[i]])
1242                                 {
1243                                         keepGoing = false;
1244                                         break;
1245                                 }
1246                         }
1247                 }
1248                 while (keepGoing);
1249
1250                 printf("\n%.2f: Synthesis done. Bit count: %d, bloop count: %d\n", (float)trackNum / 4.0f, count, bloops);
1251         }
1252
1253         printf("%.2f: Synthesized wave length: %d\n", (float)trackNum / 4.0f    , Global::synWaveLen[trackNum]);
1254
1255         // Now, find the loop point and make BITS from it
1256 /*
1257 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?
1258
1259 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).
1260
1261 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.
1262 */
1263         uint32_t loopStart, loopEnd;
1264         bool perfect = FindLoopPoint(trackNum, loopStart, loopEnd);
1265 #if 0
1266         // We use the loop point from stream #1 because we're lazy
1267         uint32_t estLoopTime = Uint32LE(Global::stream[sNum[0]]->estLoopPoint);
1268         uint32_t curTime = 0;
1269         uint32_t pos = 0, startOfLoop = 0;
1270         double a[2];
1271         uint32_t maxLookahead = 0;
1272         uint32_t maxPos = 0;
1273         bool /*full, full2,*/ full0, full1;
1274         uint32_t blips, worstBlips = 0, longestStretch, stretch, maxLongestStretch = 0, worstBlipsPos = 0, mlsPos = 0;
1275         worstBlips = 1e9;
1276
1277         // Get the index to the correct time in "pos"
1278         while (curTime < estLoopTime)
1279                 curTime += Global::synWave[trackNum][pos++];
1280
1281 printf("%.2f: estLoopTime=%d, curTime=%d, pos=%d\n", (float)trackNum / 4.0f, estLoopTime, curTime, pos);
1282         uint32_t posSave = pos;
1283
1284         // First, see if we have basically a perfect loop out of the box (typically, all $AAs)
1285         bool perfect;
1286         mlsPos = pos;
1287         worstBlipsPos = pos;
1288         maxPos = pos;
1289         maxLongestStretch = LoopLookahead(trackNum, 0, pos, &perfect);
1290
1291         if (!perfect)
1292         {
1293                 worstBlips = 1e9;
1294
1295                 // "pos" now holds the start of the search for our loop point.
1296                 for(uint32_t i=0; i<200; i++)
1297                 {
1298                         uint32_t lookahead = 0;
1299                         uint32_t j, pos0;
1300                         bool first = true;
1301                         blips = 0;
1302                         longestStretch = stretch = 0;
1303                         startOfLoop = 0;//shouldn't be necessary...
1304
1305                         for(j=(pos+i-100), pos0=0; j<Global::synWaveLen[trackNum]; j++, pos0++)
1306                         {
1307                                 uint32_t lla0 = LoopLookahead(trackNum, pos0 + 0, j, &full0);
1308                                 uint32_t lla1 = LoopLookahead(trackNum, pos0 + 1, j, &full1);
1309
1310                                 lookahead += lla0;
1311                                 stretch = lla0;
1312
1313                                 if (stretch > longestStretch)
1314                                         longestStretch = stretch;
1315
1316                                 if (full0)
1317                                 {
1318                                         break;
1319                                 }
1320                                 else if (full1 && first) // only check 1st time (for now)
1321                                 {
1322                                         startOfLoop = 1;
1323                                         lookahead = lla1;
1324                                         stretch = lla1;
1325                                         break;
1326                                 }
1327
1328                                 if (first)
1329                                         first = false;
1330
1331                                 pos0 += lla0;
1332                                 j += lla0;
1333
1334                                 a[0] = Global::synWave[trackNum][pos0++];
1335                                 a[1] = Global::synWave[trackNum][j++];
1336
1337 #if 0
1338                                 double sigma = StdDeviation(a, 2);
1339
1340 if (first)
1341 {
1342         first = false;
1343 //      printf("First blip: %.0lf, %.0lf (sigma=%.2lf) [pos=%d, la=%d]\n", a[0], a[1], sigma, i + pos - 100, pos0);
1344
1345         if (trackNum == 137)
1346         {
1347                 uint32_t lla = LoopLookahead(trackNum, 0, j, &full);
1348                 uint32_t llap1 = LoopLookahead(trackNum, 1, j, &full2);
1349                 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" : ""));
1350         }
1351 }
1352 #endif
1353
1354                                 // Hmm, not in sync.  See if we can re-sync
1355                                 stretch = 0;
1356                                 blips++;
1357
1358                                 do
1359                                 {
1360                                         if (a[0] < a[1])
1361                                                 a[0] += Global::synWave[trackNum][pos0++];
1362                                         else
1363                                                 a[1] += Global::synWave[trackNum][j++];
1364
1365                                         // Maybe put all the other heuristics in too?
1366                                         if (StdDeviation(a, 2) <= 2.50)
1367                                                 break;
1368
1369                                         // Now you've gone *too* far...
1370                                         if (j >= Global::synWaveLen[trackNum])
1371                                                 break;
1372                                 }
1373                                 while (true);
1374                         }
1375
1376 #if 0
1377 if (trackNum == 137)
1378         printf(" blips=%d, la=%d\n", blips, lookahead);
1379 #endif
1380
1381 //maybe we should keep an array of the analyses so we can decide afterward which one is best...
1382                         if (blips < worstBlips)
1383                         {
1384                                 worstBlips = blips;
1385                                 worstBlipsPos = pos + i - 100;
1386                         }
1387
1388                         if (lookahead > maxLookahead)
1389                         {
1390                                 maxLookahead = lookahead;
1391                                 maxPos = pos + i - 100;
1392                         }
1393
1394                         if (longestStretch > maxLongestStretch)
1395                         {
1396                                 maxLongestStretch = longestStretch;
1397                                 mlsPos = pos + i - 100;
1398                         }
1399
1400                         if (blips == 0)
1401                                 break;
1402                 }
1403         }
1404 #endif
1405
1406 #if 0
1407         bitLen[trackNum] = RenderBitstream(bits[trackNum], &byteLen[trackNum], Global::synWave[trackNum], startOfLoop, maxPos);
1408 #endif
1409
1410         if (perfect)
1411         {
1412                 uint32_t estLoopTime = Uint32LE(Global::stream[sNum[0]]->estLoopPoint);
1413                 uint32_t pos = IndexForTime(trackNum, estLoopTime);
1414                 printf("Perfect loop point found at position %d (elp%+d, start=%d, end=%d)\n----------------------------------------------------------------------\n", loopEnd + 1, loopEnd + 1 - pos, loopStart, loopEnd);
1415         }
1416 #if 0
1417         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);
1418 #endif
1419 /*
1420 Track 1.00:
1421 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...]
1422 */
1423
1424 /*      for(uint32_t i=0; i<maxLookahead+5; i++)
1425         {
1426                 a[0] = Global::synWave[trackNum][i];
1427                 a[1] = Global::synWave[trackNum][i + maxPos];
1428                 double sigma = StdDeviation(a, 2);
1429                 printf("[%.2lf]", sigma);
1430         }
1431
1432         printf("\n");//*/
1433 }
1434
1435
1436 //
1437 // Attempt to find where the track loop is.  Passes back what it thinks they
1438 // are in start and end.
1439 //
1440 bool FindLoopPoint(uint32_t trackNum, uint32_t & start, uint32_t & end)
1441 {
1442 /*
1443 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 with the resynchronization code.  So how do we do this?
1444
1445 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).
1446
1447 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.
1448 */
1449         // We use the loop point from stream #1 because we're lazy (better would prolly be to take the average of all of them)
1450         uint32_t estLoopTime = Uint32LE(Global::stream[sNum[0]]->estLoopPoint);
1451         uint32_t pos = IndexForTime(trackNum, estLoopTime);
1452         uint32_t posSave = pos;
1453
1454         bool full0, full1, perfect;
1455
1456 printf("%.2f: estLoopTime=%d, pos=%d\n", (float)trackNum / 4.0f, estLoopTime, pos);
1457
1458         // First, see if we have basically a perfect loop out of the box
1459         // (typically, a track of all $AAs)
1460         LoopLookahead(trackNum, 0, pos, &perfect);
1461
1462         if (perfect)
1463         {
1464                 start = 0;
1465                 end = pos - 1;
1466                 return true;
1467         }
1468
1469         uint32_t bestMatchCount = 0, bestBlips = 1e9, longestStretch = 0;
1470         uint32_t bestMatchCountPos = 0, bestBlipsPos = 0, longestStretchPos = 0;
1471
1472         // "pos" now holds the start of the search for our loop point.
1473         // Step from -99 to +99 around "pos" to find the loop point.  If the input wave is very noisy, this might fail!
1474         for(int32_t i=-99; i<100; i++)
1475         {
1476                 uint32_t matchCount = 0;
1477                 uint32_t j, pos0;
1478                 bool first = true;
1479                 uint32_t blips = 0;
1480                 start = 0;
1481
1482                 for(j=pos+i, pos0=0; j<Global::synWaveLen[trackNum]; j++, pos0++)
1483                 {
1484                         uint32_t lla0 = LoopLookahead(trackNum, pos0 + 0, j, &full0);
1485 /*
1486 We do this because it may be the case that the start of the wave has an extraneous one that doesn't exist near the loop point; this way, we can still get a perfect loop point by skipping that bad one at the start.
1487 */
1488                         uint32_t lla1 = LoopLookahead(trackNum, pos0 + 1, j, &full1);
1489
1490                         // We count the # of successful matches, since there might be spots where it doesn't sync up perfectly--the combination of good matches plus least amount of desyncs ("blips") is what we're looking for
1491                         matchCount += lla0;
1492
1493                         if (lla0 > longestStretch)
1494                         {
1495                                 longestStretch = lla0;
1496                                 longestStretchPos = pos + i;
1497                         }
1498
1499                         if (full0)
1500                         {
1501                                 // If we found perfect sync and it's the first time, return
1502                                 if (blips == 0)
1503                                 {
1504                                         end = pos + i - 1;
1505                                         return true;
1506                                 }
1507
1508                                 // Otherwise, just break out of the loop since it might not be the best
1509                                 break;
1510                         }
1511                         else if (full1 && first) // only check 1st time (for now)
1512                         {
1513                                 // Since we found perfect sync, return
1514                                 start = 1;
1515                                 end = pos + i - 1;
1516                                 return true;
1517                         }
1518
1519                         if (first)
1520                                 first = false;
1521
1522                         pos0 += lla0;
1523                         j += lla0;
1524
1525                         double a[2];
1526                         a[0] = Global::synWave[trackNum][pos0++];
1527                         a[1] = Global::synWave[trackNum][j++];
1528
1529 #if 0
1530                         double sigma = StdDeviation(a, 2);
1531
1532 if (first)
1533 {
1534 first = false;
1535 //      printf("First blip: %.0lf, %.0lf (sigma=%.2lf) [pos=%d, la=%d]\n", a[0], a[1], sigma, i + pos - 100, pos0);
1536
1537 if (trackNum == 137)
1538 {
1539         uint32_t lla = LoopLookahead(trackNum, 0, j, &full);
1540         uint32_t llap1 = LoopLookahead(trackNum, 1, j, &full2);
1541         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" : ""));
1542 }
1543 }
1544 #endif
1545
1546                         // Hmm, not in sync.  See if we can re-sync
1547                         blips++;
1548
1549                         do
1550                         {
1551                                 if (a[0] < a[1])
1552                                         a[0] += Global::synWave[trackNum][pos0++];
1553                                 else
1554                                         a[1] += Global::synWave[trackNum][j++];
1555
1556                                 // Maybe put all the other heuristics in too?  :-/
1557                                 if ((StdDeviation(a, 2) <= 2.50)
1558                                         || (j >= Global::synWaveLen[trackNum]))
1559                                         break;
1560                         }
1561                         while (true);
1562                 }
1563
1564 #if 0
1565 if (trackNum == 137)
1566 printf(" blips=%d, la=%d\n", blips, matchCount);
1567 #endif
1568
1569 //maybe we should keep an array of the analyses so we can decide afterward which one is best... probably not necessary...
1570                 if (blips < bestBlips)
1571                 {
1572                         bestBlips = blips;
1573                         bestBlipsPos = pos + i;
1574                 }
1575
1576                 if (matchCount > bestMatchCount)
1577                 {
1578                         bestMatchCount = matchCount;
1579                         bestMatchCountPos = pos + i;
1580                 }
1581
1582                 // Did we find a perfect lookahead? If so, we're done.
1583 //              if (blips == 0)
1584 //                      break;
1585         }
1586
1587         // Now we're done trying to fit the loop, and we didn't find a perfect one, so set up the best we found:
1588         end = bestMatchCountPos - 1;
1589 #if 1
1590 uint32_t possibleCoverage = Global::synWaveLen[trackNum] - pos;
1591 printf("Possible loop point found at position %d (elp%+d, bestMatchCount=%d (out of %d, %.1f%%), startPos=%d, blips=%d, blipsPos=%d, longest stretch=%d, mlsPos=%d)\n----------------------------------------------------------------------\n", end + 1, end + 1 - posSave, bestMatchCount, possibleCoverage, ((float)bestMatchCount / (float)possibleCoverage) * 100.0f, pos, bestBlips, bestBlipsPos, longestStretch, longestStretchPos);
1592 #endif
1593         return false;
1594 }
1595
1596
1597 /*
1598 Using a histogram, we can get an idea of the drift from the ones:
1599
1600                 @@
1601                 @@
1602                 @@
1603                 @@
1604                 @@
1605                 @@
1606                 @@
1607                 @@        @@
1608                 @@        @@
1609                 @@        @@
1610                 @@        @@
1611                 @@        @@
1612                 @@   @@   @@
1613            @@   @@   @@   @@
1614            @@   @@   @@   @@
1615       @@   @@   @@   @@   @@
1616 -------------------------------------------------
1617 0000|0584|1792|9611|2627|5382|0482|0058|0013|0000
1618  28   29   30   31   32   33   34   35   36   37
1619
1620 Peak of the ones occurs at 31, with a secondary at 33. Twos drift:
1621
1622                 @@
1623                 @@        @@
1624                 @@        @@
1625                 @@        @@
1626                 @@        @@
1627                 @@        @@
1628                 @@        @@
1629                 @@   @@   @@
1630       @@        @@   @@   @@
1631 -------------------------------------------------
1632 0000|0545|0277|5482|1223|5168|0252|0082|0102|0000
1633  57   58   59   60   61   62   63   64   65   66
1634
1635 This looks like stretched out ones (they might all be spurious...):
1636
1637       @@
1638       @@
1639       @@             @@
1640       @@             @@
1641       @@   @@        @@
1642       @@   @@        @@
1643       @@   @@        @@
1644       @@   @@   @@   @@        @@
1645 ---------------------------------------
1646 0000|0015|0007|0002|0011|0001|0002|0000
1647  43   44   45   46   47   48   49   50
1648
1649
1650 */
1651
1652