2 // dsp.cpp: Digital Signal Processing module
4 // Part of the WOZ Maker project
6 // (C) 2018 Underground Software
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];
24 double initSyncTime[9];
26 static const double SIGMA_THRESHOLD = 2.5;
29 double StdDeviation(double * a, uint32_t num, double * pMean/*= NULL*/)
31 double sigma = 0, mean = 0;
33 for(uint32_t i=0; i<num; i++)
36 mean = mean / (double)num;
41 for(uint32_t i=0; i<num; i++)
42 sigma += (a[i] - mean) * (a[i] - mean);
44 sigma *= 1.0 / (double)num;
49 double StdDeviationWave(uint32_t * sync, uint32_t num, double * m = NULL);
50 double StdDeviationWave(uint32_t * sync, uint32_t num, double * m/*= NULL*/)
52 double sigma = 0, mean = 0;
55 for(uint32_t i=0; i<num; i++)
57 a[i] = (double)Global::wave[sNum[i]][sync[i]];
61 mean = mean / (double)num;
63 // Capture the mean, if a pointer was passed in
67 for(uint32_t i=0; i<num; i++)
68 sigma += (a[i] - mean) * (a[i] - mean);
70 return sqrt(sigma / (double)num);
74 double Largest(double * a, uint32_t num)
76 double largest = a[0];
78 for(uint32_t i=1; i<num; i++)
88 uint32_t Largest(uint32_t * a, uint32_t num)
90 uint32_t largest = a[0];
92 for(uint32_t i=1; i<num; i++)
102 uint32_t LargestIndex(double * a, uint32_t num)
104 double largest = a[0];
107 for(uint32_t i=1; i<num; i++)
120 uint32_t LargestIndex(uint32_t * a, uint32_t num)
122 uint32_t largest = a[0];
125 for(uint32_t i=1; i<num; i++)
138 double Smallest(double * a, uint32_t num)
140 double smallest = a[0];
142 for(uint32_t i=1; i<num; i++)
152 uint32_t Smallest(uint32_t * a, uint32_t num)
154 uint32_t smallest = a[0];
156 for(uint32_t i=1; i<num; i++)
166 uint32_t SmallestIndex(double * a, uint32_t num)
168 double smallest = a[0];
171 for(uint32_t i=1; i<num; i++)
184 uint32_t SmallestIndex(uint32_t * a, uint32_t num)
186 uint32_t smallest = a[0];
189 for(uint32_t i=1; i<num; i++)
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.)
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
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.
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.
212 uint32_t Synthesize(uint32_t * sync, uint32_t num, uint32_t * synthWave, float * swAmplitude)
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;
220 memcpy(syncPt, sync, sizeof(syncPt));
224 for(uint32_t i=0; i<num; i++)
226 if (syncPt[i] >= Global::streamLen[i])
230 // Save these *before* we step forward
231 memcpy(syncSave, syncPt, sizeof(syncSave));
232 StepForward(syncPt, a, num);
234 double sigma = StdDeviation(a, num, &mean);
236 if (sigma <= SIGMA_THRESHOLD)
238 for(uint32_t i=0; i<num; i++)
239 time[i][timePtr] = a[i];
241 timePtr = (timePtr + 1) % 32;
243 synthWave[swLen] = (uint32_t)(mean + 0.5);
244 swAmplitude[swLen] = 1.0f;
249 // Calculate drift over the last 32 time steps...
250 for(uint32_t i=0; i<num; i++)
254 for(uint32_t j=0; j<32; j++)
255 drift[i] += time[i][j];
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);
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;
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.
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.
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);
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
281 This works until you hit this:
282 a: [1167.00][1174.00][1169.00] => 2.94
284 <1167.00><1174.00><1169.00> ==> 2.94 {drift=0.82}(!!!) (lookahead=2.94, 630)
285 {12168}-{12166}-{12166}
287 <1198.00><1205.00><1200.00> ==> 2.94 {drift=0.82} (lookahead=0.00, 629)
288 {12169}-{12167}-{12167}
290 <1231.00><1238.00><1233.00> ==> 2.94 {drift=0.82} (lookahead=0.00, 628)
292 <337.00><334.00><335.00> ==> 1.25 (OK) (lookahead=18.40, 1705)
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}
297 < 62.00>< 51.00>< 45.00> ==> 7.04 (lookahead=13.42, 0)
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())
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}
306 <1182.00><1173.00>< 47.00> ==> 532.94 (lookahead=40.94, 0)
307 {27657}-{27641}-{27627}
309 <1182.00><1204.00><1202.00> ==> 9.93 (lookahead=46.20, 6)
310 {27657}-{27642}-{27633}
312 <1213.00><1204.00><1202.00> ==> 4.78 (lookahead=0.00, 149)
313 {27658}-{27642}-{27633}
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...
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.
321 if ((mean > 9.0)//00.0)
322 && ((sigma < StdDeviation(drift, num))
323 || (((sigma + nextSigma) / 2.0) < SIGMA_THRESHOLD)))
334 // If we've been in this loop too long, something's very wrong
338 // Pull the lesser streams forward to catch up to the largest
339 uint32_t largestIdx = LargestIdx(a, num);
342 for(uint32_t i=0; i<num; i++)
355 uint32_t walkahead = syncPt[i];
357 while ((a[largestIdx] - (a[i] + ttn)) > 7.0)
361 if (walkahead >= Global::streamLen[i])
363 // We ran out of road, so we're done for now
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.
373 StepAndAddForward(walkahead, ttn, i);
376 syncPt[i] = walkahead;
380 printf(" %6.2lf ", ttn);
389 for(uint32_t i=0; i<num; i++)
390 printf("<%6.2lf>", a[i]);
392 // Calculate the standard deviation at this new point
393 sigma = StdDeviation(a, num, &mean);
395 printf(" ==> %.2lf%s", sigma, (sigma <= SIGMA_THRESHOLD ? " (OK)" : (!pulled ? "(STEP)" : "")));
398 //printf(" {drift=%.2lf}", driftSigma);
399 uint32_t minSyncIdx = SmallestIdx(syncPt, num);
400 if (syncPt[minSyncIdx] > 0)
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));
409 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", syncPt[j], (j < num - 1 ? "-" : "")); }
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)
416 for(uint32_t i=0; i<num; i++)
417 StepAndAddForward(syncPt[i], a[i], i);
419 sigma = StdDeviation(a, num, &mean);
423 while ((sigma > SIGMA_THRESHOLD) && pulled);
426 // Now, we've re-established sync, now fill the appropriate spots
429 So the algorithm to do this proppaly is like so:
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:
443 .......................................|
444 .............................|.........|
445 .............................|.........|
446 ..................................|....|
447 .......................................|
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:
451 synthWave[swLen] = (uint32_t)((mean - baseline) + 0.5)
452 swAmplitude[swLen] = amplitude;
454 no need for that. the times that step directly to the end can safely be ignored.
457 150 -> 150 (ignores 175)
458 150 goes in, ampl. .4, we now have:
466 only one is left that we can grab:
470 last pulse was at 150 (40%), so we need to subtract that out
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
488 smallest is 150: pick 150 -> picks up 150
489 advance the 150 rows & subtract 150 from the rest:
497 pick smallest: 25 -> picks up nothing
498 advance the 25 & subtract it from the rest:
506 We've reached the end of the section, add the final amount
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]
512 currentRow: [120.89][49.97][46.98][49.98][48.98] => 28.78
514 2: [3->4][3->6][3->4][3->6][3->6]
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
521 3: [3->4][4->6][4->4][4->6][4->6]
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
527 4: [3->4][5->6][4->4][5->6][5->6]
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
533 5: [3->4][6->6][4->4][6->6][6->6]
537 6: [4->4][6->6][4->4][6->6][6->6]
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
546 /*printf("syncSave before: ");
547 for(uint32_t i=0; i<num; i++)
548 printf("[%d->%d]", syncSave[i], syncPt[i]);
551 // Collect the current row
552 StepForward(syncSave, currentRow, num);
554 float ampStep = 1.0f / (float)num;
556 /*printf("syncSave after: ");
557 for(uint32_t i=0; i<num; i++)
558 printf("[%d->%d]", syncSave[i], syncPt[i]);
560 printf("currentRow: ");
561 for(uint32_t i=0; i<num; i++)
562 printf("[%.2lf]", currentRow[i]);
563 printf(" => %.2lf\n", StdDeviation(currentRow, num));//*/
567 //printf("%d: ", swLen);
568 for(uint32_t i=0; i<num; i++)
570 //printf("[%d->%d]", syncSave[i], syncPt[i]);
571 if (syncSave[i] != syncPt[i])
581 float amplitude = ampStep;
582 uint32_t smallestIdx = SmallestIdx(currentRow, num);
584 a[0] = currentRow[smallestIdx];
585 //printf("a[0]=%.2lf: ", a[0]);
587 for(uint32_t i=0; i<num; i++)
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])
593 if (i == smallestIdx)
596 StepAndAddForward(syncSave[i], currentRow[i], i);
597 //printf("<%.2lf>", currentRow[i]);
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);
606 double crSave = currentRow[i];
607 currentRow[i] -= a[0];
609 // Don't bother with stuff that's out of range! :-P
610 if (syncSave[i] == syncPt[i])
613 // Try to find correlates
614 a[cnt] = crSave;//currentRow[i];
616 sigma = StdDeviation(a, cnt, &mean);
617 //for(uint32_t j=1; j<cnt; j++)
618 // printf("[%.2lf]", a[j]);
621 if (sigma <= 5.5)//SIGMA_THRESHOLD)
624 StepAndAddForward(syncSave[i], currentRow[i], i);
625 //printf("{%.2lf}", currentRow[i]);
626 amplitude += ampStep;
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);
636 //printf(" ==> %.2lf\n\t", sigma);
639 sigma = StdDeviation(a, cnt, &mean);
640 synthWave[swLen] = (uint32_t)(mean + 0.5);
641 swAmplitude[swLen] = amplitude;
645 //printf("%d: ", swLen);
646 for(uint32_t i=0; i<num; i++)
648 //printf("[%d->%d]", syncSave[i], syncPt[i]);
649 if (syncSave[i] != syncPt[i])
658 sigma = StdDeviation(currentRow, num, &mean);
659 synthWave[swLen] = mean;
660 swAmplitude[swLen] = 1.0f;
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.
674 bool FindSync(uint32_t stream1, uint32_t stream2, uint32_t & sync1, uint32_t & sync2)
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++)
681 uint32_t strmLen = Uint32LE(Global::stream[stream1]->dataLength);
684 // How many bits should we consider as synchronized? All of them?
685 for(uint32_t i=1, i2=1; i<strmLen; i++, i2++)
687 double time1 = (double)Global::stream[stream1]->data[i];
688 double time2 = (double)Global::stream[stream2]->data[i2 + offset];
690 while (Global::stream[stream1]->data[i] == 0xFF)
693 time1 += (double)Global::stream[stream1]->data[i];
696 while (Global::stream[stream2]->data[i2] == 0xFF)
699 time2 += (double)Global::stream[stream2]->data[i2 + offset];
702 double mean = (time1 + time2) * 0.5;
703 double sigma = sqrt(0.5 * (((time1 - mean) * (time1 - mean))
704 + ((time2 - mean) * (time2 - mean))));
708 // How many bits is enough to say we found it?
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
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++)
729 uint32_t strmLen = Uint32LE(Global::stream[stream2]->dataLength);
732 // How many bits should we consider as synchronized? All of them?
733 for(uint32_t i=1, i2=1; i<strmLen; i++, i2++)
735 double time1 = (double)Global::stream[stream2]->data[i];
736 double time2 = (double)Global::stream[stream1]->data[i2 + offset];
738 while (Global::stream[stream2]->data[i] == 0xFF)
741 time1 += (double)Global::stream[stream2]->data[i];
744 while (Global::stream[stream1]->data[i2] == 0xFF)
747 time2 += (double)Global::stream[stream1]->data[i2 + offset];
750 double mean = (time1 + time2) * 0.5;
751 double sigma = sqrt(0.5 * (((time1 - mean) * (time1 - mean))
752 + ((time2 - mean) * (time2 - mean))));
756 // How many bits is enough to say we found it?
775 void FindSyncForStreams(uint32_t * syncPt, uint32_t num)
777 // uint32_t syncPt[10] = { 0 };
781 for(uint32_t i=1; i<num; i++)
783 if (FindSync(sNum[base], sNum[i], syncPt[base], syncPt[i]) == true)
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)
788 for(uint32_t j=0; j<i; j++)
791 syncPt[j] += syncPt[base];
799 // should we do this? or just set a flag that we couldn't sync this one?
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;
808 for(uint32_t i=1; i<num; i++)
810 if (syncPt[i] == (uint32_t)-1)
814 // Signal that sync failed
815 if (nonSync == (num - 1))
819 0 0 0 0 0 base = 0, i = 1
825 0 10 0 0 0 base = 0, i = 2
832 5 15 0 0 0 base = 2, i = 3
839 5 15 0 7 0 base = 2, i = 4
845 13 23 8 15 0 base = 4
847 if (FindSync(sNum[0], sNum[1], syncPt[0], syncPt[1]) == false)
849 // give up, we couldn't sync stream 0 & 1... :-/
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);
855 if (FindSync(sNum[base], sNum[2], syncPt[base], syncPt[2]) == false)
857 // give up, we couldn't sync stream 0 & 1... :-/
860 // check again, to see which one moved and the other...
861 uint32_t base2 = (syncPt[base] == 0 ? base, 2);
870 void FindInitialSyncForStreams(uint32_t * sync, uint32_t num)
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.
875 // Let's try aligning samples to each other by counting to a short stream
877 uint64_t bitPat0 = 0;
879 for(uint32_t i=0; i<num; i++)
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++)
888 uint32_t timeToNext = Global::streamData[i][j];
890 while (Global::streamData[i][j] == 0xFF)
893 timeToNext += Global::streamData[i][j];
896 initSyncTime[i] += (double)timeToNext;
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;
906 while (timeToNext > 32)
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)
927 if ((i != 0) && (bitPat != bitPat0))
930 sync[i] = j - (j - 25 >= 0 ? 25 : 0);
933 else if ((bitPat & 0xFFFFFFFF0101) == 0x7F9FE7F90101)
935 if ((i != 0) && (bitPat != bitPat0))
938 sync[i] = j - (j - 25 >= 0 ? 25 : 0);
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!).
949 void BacktrackInitialSync(uint32_t * syncPt, uint32_t num)
951 // uint32_t count = 0;
953 // uint32_t syncSave[10];
955 // Save the original sync points (do we need to?)
956 // for(uint32_t i=0; i<num; i++)
957 // syncSave[i] = syncPt[i];
959 uint32_t minSlip = (uint32_t)-1;
961 for(uint32_t i=0; i<num; i++)
963 if (syncPt[i] < minSlip)
969 // Get the time for this step into a[]
970 for(uint32_t i=0; i<num; i++)
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];
975 while ((syncPt[i] > 0)
976 && (Global::stream[sNum[i]]->data[syncPt[i] - 1] == 0xFF))
979 a[i] += (double)Global::stream[sNum[i]]->data[syncPt[i]];// * ratio[i];
983 double sigma = StdDeviation(a, num);
986 if (sigma > SIGMA_THRESHOLD)
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]);
994 printf(" --> %.2lf\n", sigma);
996 uint32_t syncCount = 0;
998 // Save sync origins for later analysis
999 // for(uint32_t j=0; j<num; j++)
1000 // syncSave[j] = syncPt[j];
1002 // It may turn out that this is too large too...
1003 while (sigma > 3.30)//SIGMA_THRESHOLD)
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);
1008 for(uint32_t i=0; i<num; i++)
1010 if (i == largestIdx)
1016 int32_t walkBack = syncPt[i] - 1;
1017 double ttn = (double)Global::stream[sNum[i]]->data[walkBack];
1019 while ((walkBack > 0)
1020 && (Global::stream[sNum[i]]->data[walkBack - 1] == 0xFF))
1023 ttn += (double)Global::stream[sNum[i]]->data[walkBack];// * ratio[i];
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)
1029 syncPt[i] = walkBack;
1031 printf(" %6.2lf ", ttn);
1039 for(uint32_t i=0; i<num; i++)
1040 printf("<%6.2lf>", a[i]);
1042 sigma = StdDeviation(a, num);
1043 printf(" ==> %.2lf\n", sigma);
1049 // Back up the train
1050 for(uint32_t i=0; i<num; i++)
1052 syncPt[i] -= (syncPt[i] >= 40 ? 40 : 0);
1054 if ((int32_t)syncPt[i] < 0)
1059 printf("Could not synchronize streams...\n");
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++)
1070 if (syncPt[i] < minSlip)
1071 minSlip = syncPt[i];
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.]
1080 void BacktrackInitialSync2(uint32_t * syncPt, uint32_t num)
1083 uint32_t syncSave[10];
1084 uint32_t minSlip = Smallest(syncPt, num);
1088 // Get the time for this step into a[]
1089 for(uint32_t i=0; i<num; i++)
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];
1094 while ((syncPt[i] > 0)
1095 && (Global::stream[sNum[i]]->data[syncPt[i] - 1] == 0xFF))
1098 a[i] += (double)Global::stream[sNum[i]]->data[syncPt[i]];// * ratio[i];
1102 double sigma = StdDeviation(a, num);
1104 if (sigma > SIGMA_THRESHOLD)
1106 uint32_t syncCount = 0;
1108 // Save sync origins for later analysis
1109 memcpy(syncSave, syncPt, sizeof(syncSave));
1111 // It may turn out that this is too large too...
1112 while (sigma > SIGMA_THRESHOLD)
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);
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++)
1121 if (i == largestIdx)
1125 int32_t walkback = syncPt[i];
1127 while((a[largestIdx] - (a[i] + ttn)) > 7.0)
1131 memcpy(syncPt, syncSave, sizeof(syncSave));
1132 printf("Synchronized as far back as possible...\n");
1137 ttn += (double)Global::stream[sNum[i]]->data[walkback];// * ratio[i];
1139 while ((walkback > 0)
1140 && (Global::stream[sNum[i]]->data[walkback - 1] == 0xFF))
1143 ttn += (double)Global::stream[sNum[i]]->data[walkback];// * ratio[i];
1147 syncPt[i] = walkback;
1151 sigma = StdDeviation(a, num);
1157 // Back up the train
1158 for(uint32_t i=0; i<num; i++)
1160 syncPt[i] -= (syncPt[i] >= 40 ? 40 : 0);
1162 if ((int32_t)syncPt[i] < 0)
1167 printf("Could not synchronize streams...\n");
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++)
1178 if (syncPt[i] < minSlip)
1179 minSlip = syncPt[i];
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.]
1188 void BacktrackInitialSync3(uint32_t * sync, uint32_t num)
1191 uint32_t syncSave[9];
1195 uint32_t minSlip = Smallest(sync, num);
1200 // Save sync origins for later analysis if necessary
1201 memcpy(syncSave, sync, sizeof(syncSave));
1203 // Get the time for this step into a[]
1204 StepBack(sync, a, num);
1205 double sigma = StdDeviation(a, num);
1207 if (sigma > SIGMA_THRESHOLD)
1209 uint32_t syncCount = 0;
1218 // Back up the train
1219 for(uint32_t i=0; i<num; i++)
1221 sync[i] -= (sync[i] >= 40 ? 40 : 0);
1223 if ((int32_t)sync[i] < 0)
1227 printf("Could not synchronize streams...\n");
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);
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++)
1239 if (i == largestIdx)
1243 uint32_t walkback = sync[i];
1245 while((a[largestIdx] - (a[i] + ttn)) > 7.0)
1249 if ((int32_t)walkback <= 0)
1251 memcpy(sync, syncSave, sizeof(syncSave));
1252 printf("Synchronized as far back as possible...\n");
1256 StepAndAddBack(walkback, ttn, i);
1263 // Calculate the standard deviation at this new point
1264 sigma = StdDeviation(a, num);
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)
1269 for(uint32_t i=0; i<num; i++)
1270 StepAndAddBack(sync[i], a[i], i);
1272 sigma = StdDeviation(a, num);//, &mean);
1276 while ((sigma > SIGMA_THRESHOLD) && pulled);
1282 void BacktrackInitialSync4(uint32_t * sync, uint32_t num)
1285 uint32_t syncSave[9];
1289 uint32_t minSlip = Smallest(sync, num);
1294 // Save sync origins for later analysis if necessary
1295 memcpy(syncSave, sync, sizeof(syncSave));
1297 // Get the time for this step into a[]
1298 StepBack(sync, a, num);
1299 double sigma = StdDeviation(a, num);
1301 if (sigma > SIGMA_THRESHOLD)
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);
1309 // Well, we failed to find synchronization... :-(
1312 memcpy(sync, syncSave, sizeof(syncSave));
1316 // OK, we have a good result, but what kind (1=end, 0=sync OK)?
1318 StepBack(sync, a2, num);
1319 else if (result == 1)
1321 for(uint32_t j=0; j<num; j++) { printf("{%d} ", sync[j]); }
1323 memcpy(sync, syncSave, sizeof(syncSave));
1324 for(uint32_t j=0; j<num; j++) { printf("<%d> ", sync[j]); }
1326 StepBack(sync, a2, num);
1334 void StepBackUntilBad(uint32_t * sync, double * a, uint32_t num)
1338 // See where the minimum sync point is now...
1339 uint32_t minSlip = Smallest(sync, num);
1344 // Get the time for this step into a[]
1345 StepBack(sync, a, num);
1346 double sigma = StdDeviation(a, num);
1348 if (sigma > SIGMA_THRESHOLD)
1352 for(uint32_t i=0; i<num; i++)
1353 printf("<%6.2lf>", a[i]);
1355 printf(" --> %.2lf\n", sigma);
1360 printf("---------------------------------------------------\nAT START\n\n");
1364 bool StepBackThruBad(uint32_t * sync, double * a, uint32_t num)
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);
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.
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).
1374 for(uint32_t i=0; i<num; i++)
1376 if (i == largestIdx)
1385 uint32_t walkback = sync[i];
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)
1391 StepAndAddBack(walkback, ttn, i);
1398 printf(" %6.2lf ", ttn);
1405 for(uint32_t i=0; i<num; i++)
1406 printf("<%6.2lf>", a[i]);
1408 double sigma = StdDeviation(a, num);
1409 printf(" ==> %.2lf%s", sigma, (sigma <= SIGMA_THRESHOLD ? " (OK)" : ""));
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 ? "-" : "")); }
1418 if (sigma < SIGMA_THRESHOLD)
1420 // If we're out of the woods, make sure to step to the next step...
1422 StepBack(sync, b, num);
1430 void StepBack(uint32_t * sync, double * a, uint32_t num)
1432 for(uint32_t i=0; i<num; i++)
1434 int32_t walkback = sync[i] - 1;
1435 a[i] = (double)Global::streamData[i][walkback] * ratio[i];
1437 while ((walkback > 0)
1438 && (Global::streamData[i][walkback - 1] == 0xFF))
1441 a[i] += (double)Global::streamData[i][walkback] * ratio[i];
1449 void StepAndAddBack(uint32_t * sync, double * a, uint32_t num)
1451 for(uint32_t i=0; i<num; i++)
1453 int32_t walkback = sync[i] - 1;
1454 a[i] += (double)Global::streamData[i][walkback] * ratio[i];
1456 while ((walkback > 0)
1457 && (Global::streamData[i][walkback - 1] == 0xFF))
1460 a[i] += (double)Global::streamData[i][walkback] * ratio[i];
1468 void StepAndAddBack(uint32_t & loc, double & a, uint32_t i)
1470 int32_t walkback = loc - 1;
1471 a += (double)Global::streamData[i][walkback] * ratio[i];
1473 while ((walkback > 0)
1474 && (Global::streamData[i][walkback - 1] == 0xFF))
1477 a += (double)Global::streamData[i][walkback] * ratio[i];
1480 loc = (uint32_t)walkback;
1485 // Move every stream forward by one step
1487 void StepForward(uint32_t * sync, double * a, uint32_t num)
1489 for(uint32_t i=0; i<num; i++)
1491 uint32_t walkahead = sync[i] + 1;
1492 a[i] = (double)Global::streamData[i][walkahead] * ratio[i];
1494 while ((walkahead < Global::streamLen[i])
1495 && (Global::streamData[i][walkahead] == 0xFF))
1498 a[i] += (double)Global::streamData[i][walkahead] * ratio[i];
1501 sync[i] = walkahead;
1507 // Move every stream forward by one step
1509 void StepAndAddForward(uint32_t * sync, double * a, uint32_t num)
1511 for(uint32_t i=0; i<num; i++)
1513 uint32_t walkahead = sync[i] + 1;
1514 a[i] += (double)Global::streamData[i][walkahead] * ratio[i];
1516 while ((walkahead < Global::streamLen[i])
1517 && (Global::streamData[i][walkahead] == 0xFF))
1520 a[i] += (double)Global::streamData[i][walkahead] * ratio[i];
1523 sync[i] = walkahead;
1529 // Move just *this* stream forward by one step
1531 void StepAndAddForward(uint32_t & loc, double & a, uint32_t i)
1534 a += (double)Global::streamData[i][loc] * ratio[i];
1536 while ((loc < Global::streamLen[i])
1537 && (Global::streamData[i][loc] == 0xFF))
1540 a += (double)Global::streamData[i][loc] * ratio[i];
1546 // Return the number of times with good correlation in the specified direction
1547 // (1 for forward, -1 for backwards)
1549 uint32_t Lookahead(uint32_t * syncPt, uint32_t num, int32_t dir /*= 1*/)
1555 // Use temporary sync array instead of the one passed in
1556 memcpy(tSync, syncPt, sizeof(tSync));
1560 uint32_t smallestIdx = SmallestIdx(tSync, num);
1562 while (tSync[smallestIdx] > 0)
1564 StepBack(tSync, a, num);
1565 double sigma = StdDeviation(a, num);
1567 if (sigma > SIGMA_THRESHOLD)
1571 smallestIdx = SmallestIdx(tSync, num);
1576 uint32_t largestIdx = LargestIdx(tSync, num);
1578 while (tSync[largestIdx] < Global::streamLen[largestIdx])
1580 StepForward(tSync, a, num);
1581 double sigma = StdDeviation(a, num);
1583 if (sigma > SIGMA_THRESHOLD)
1587 largestIdx = LargestIdx(tSync, num);
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")
1600 // Returns -1 on failure, 0 is sync was successful, or 1 if reached end of
1601 // stream before finding sync
1603 int Resync(uint32_t * sync, double * a, uint32_t num, int32_t dir/*= 1*/)
1605 uint32_t syncCount = 0;
1609 for(uint32_t j=0; j<num; j++) { printf("{%d} ", sync[j]); }
1617 // Back up the train
1618 printf("Could not synchronize streams...\n");
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);
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++)
1630 if (i == largestIdx)
1637 uint32_t walkback = sync[i];
1639 while ((a[largestIdx] - (a[i] + ttn)) > 7.0)
1643 if (((dir == 1) && (walkback >= Global::streamLen[i]))
1644 || ((dir == -1) && ((int32_t)walkback <= 0)))
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]); }
1654 StepAndAddForward(walkback, ttn, i);
1656 StepAndAddBack(walkback, ttn, i);
1663 printf(" %6.2lf ", ttn);
1670 for(uint32_t i=0; i<num; i++)
1671 printf("<%6.2lf>", a[i]);
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)" : "")));
1677 double lookahead[9];
1678 uint32_t minSyncIdx = SmallestIdx(sync, num);
1679 if (sync[minSyncIdx] > 0 && dir == -1)
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));
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)
1689 StepAndAddForward(sync, a, num);
1691 StepAndAddBack(sync, a, num);
1693 sigma = StdDeviation(a, num);//, &mean);
1697 while ((sigma > SIGMA_THRESHOLD) && pulled);
1700 // StepBack(sync, a2, num);
1709 // Compare two arrays to see if they are equal
1711 bool Equal(uint32_t * a1, uint32_t * a2, uint32_t num)
1713 for(uint32_t i=0; i<num; i++)
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*/)
1728 memcpy(sync, passedInSync, sizeof(sync));
1732 if (StdDeviationWave(sync, num) > 2.50)
1735 for(uint32_t i=0; i<num; i++)
1737 if (((dir == 1) && (sync[i] >= Global::waveLen[sNum[i]]))
1738 || ((dir == -1) && (sync[i] == 0)))
1751 uint32_t FindSyncBetweenFirstTwo(uint32_t * sync)
1753 uint32_t bestSync[2], bestLA = 0, syncSave = sync[0];
1755 // Move the first stream first...
1756 for(uint32_t i=0; i<200; i++)
1758 uint32_t la = LookaheadWave(sync, 2);
1760 // See if the sync we've found is the best so far...
1764 memcpy(bestSync, sync, sizeof(bestSync));
1770 // Otherwise, reset the first stream and move the 2nd
1773 for(uint32_t i=0; i<200; i++)
1775 // We can bump this first since we already checked the [0][0] case above
1777 uint32_t la = LookaheadWave(sync, 2);
1779 // See if the sync we've found is the best so far...
1783 memcpy(bestSync, sync, sizeof(bestSync));
1787 // Set sync to the best we found & return the best lookahead count
1788 memcpy(sync, bestSync, sizeof(bestSync));
1794 void FindInitialSyncForStreams2(uint32_t * sync, uint32_t num)
1796 bool lookAt[6] = { true, true, false, false, false, false };
1798 // while (FindSyncBetweenFirstTwo(sync) == false)
1799 while (FindSyncBetweenFirstTwo(sync) < 1000)
1801 for(uint32_t i=0; i<num; i++)
1805 if (sync[i] >= Global::waveLen[sNum[i]])
1807 printf("Could not find initial sync!!\n");
1813 uint32_t lookahead = LookaheadWave(sync, 2);
1816 printf("Found sync for streams 1 & 2 at %d and %d (la=%d)\n", sync[0], sync[1], lookahead);
1818 // Add in the others, one at a time and try to synchronize them
1819 uint32_t bestSync[6];
1821 for(uint32_t i=2; i<num; i++)
1824 uint32_t bestLA = 0;
1826 for(uint32_t j=0; j<200; j++)
1828 uint32_t syncSave = sync[i];
1830 // And check again for a match
1831 for(uint32_t k=0; k<200; k++)
1833 uint32_t la = LookaheadWave(sync, i + 1);
1838 memcpy(bestSync, sync, sizeof(bestSync));
1846 // Kick synchronized streams forward to check the rest...
1847 for(uint32_t k=0; k<i; k++)
1851 memcpy(sync, bestSync, sizeof(bestSync));
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));
1861 uint32_t Synthesize2(uint32_t * sync, uint32_t num, uint32_t * synthWave, float * swAmplitude)
1864 uint32_t syncPt[7], syncSave[7];
1865 double a[7], b[7], currentRow[7];
1868 memcpy(syncPt, sync, sizeof(syncPt));
1872 for(uint32_t i=0; i<num; i++)
1874 if (syncPt[i] >= Global::streamLen[i])
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++)
1883 a[i] = (double)Global::wave[sNum[i]][syncPt[i]];
1888 double sigma = StdDeviation(a, num, &mean);
1890 if (sigma <= SIGMA_THRESHOLD)
1892 synthWave[swLen] = (uint32_t)(mean + 0.5);
1893 swAmplitude[swLen] = 1.0f;
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);
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.
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.
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);
1914 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", syncPt[j], (j < num - 1 ? "-" : "")); }
1917 bool keepWorking = true;
1923 // If we've been in this loop too long, something's very wrong
1927 // Pull the lesser streams forward to catch up to the largest
1928 uint32_t largestIdx = LargestIndex(a, num);
1929 bool pulled = false;
1931 for(uint32_t i=0; i<num; i++)
1933 if (i == largestIdx)
1942 // if ((a[largestIdx] - a[i]) > 7.0)
1943 if ((a[largestIdx] - a[i]) > 9.0)
1946 a[i] += (double)Global::wave[sNum[i]][syncPt[i]];
1948 printf(" %6d ", Global::wave[sNum[i]][syncPt[i]]);
1956 // See if we've run out of stream to synthesize...
1957 if (syncPt[i] >= Global::waveLen[sNum[i]])
1964 for(uint32_t i=0; i<num; i++)
1965 printf("<%6.2lf>", a[i]);
1967 // Calculate the standard deviation at this new point
1968 sigma = StdDeviation(a, num);//, &mean);
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]];
1974 double nextSigma = StdDeviation(b, num);
1975 lookahead = LookaheadWave(syncPt, num);
1977 printf(" ==> %.2lf%s", sigma, (sigma <= SIGMA_THRESHOLD ? " (OK)" : (!pulled ? "(STEP)" : "")));
1978 printf(" (lookahead=%.2lf, %d)\n", nextSigma, lookahead);
1980 for(uint32_t j=0; j<num; j++) { printf("{%d}%s", syncPt[j], (j < num - 1 ? "-" : "")); }
1983 // A handful of heuristics. If the sigma is OK, we're done
1985 keepWorking = false;
1987 // If we couldn't pull any streams forward for some reason, punt
1989 keepWorking = false;
1991 // If the average of the current & next sigmas is OK, go ahead
1992 if (((sigma + nextSigma) / 2.0) < 2.5)
1993 keepWorking = false;
1995 // If the next sigma is OK and the lookahead too, move on
1996 if ((nextSigma < 2.5) && (lookahead > 10))
1997 keepWorking = false;
1999 while (keepWorking);
2001 // Now, we've re-established sync, now fill the appropriate spots
2004 So the algorithm to do this proppaly is like so:
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:
2018 .......................................|
2019 .............................|.........|
2020 .............................|.........|
2021 ..................................|....|
2022 .......................................|
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:
2026 synthWave[swLen] = (uint32_t)((mean - baseline) + 0.5)
2027 swAmplitude[swLen] = amplitude;
2029 no need for that. the times that step directly to the end can safely be ignored.
2032 150 -> 150 (ignores 175)
2033 150 goes in, ampl. .4, we now have:
2041 only one is left that we can grab:
2045 last pulse was at 150 (40%), so we need to subtract that out
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
2063 smallest is 150: pick 150 -> picks up 150
2064 advance the 150 rows & subtract 150 from the rest:
2072 pick smallest: 25 -> picks up nothing
2073 advance the 25 & subtract it from the rest:
2081 We've reached the end of the section, add the final amount
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]
2087 currentRow: [120.89][49.97][46.98][49.98][48.98] => 28.78
2089 2: [3->4][3->6][3->4][3->6][3->6]
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
2096 3: [3->4][4->6][4->4][4->6][4->6]
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
2102 4: [3->4][5->6][4->4][5->6][5->6]
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
2108 5: [3->4][6->6][4->4][6->6][6->6]
2112 6: [4->4][6->6][4->4][6->6][6->6]
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
2122 /*printf("syncSave before: ");
2123 for(uint32_t i=0; i<num; i++)
2124 printf("[%d->%d]", syncSave[i], syncPt[i]);
2127 for(uint32_t i=0; i<num; i++)
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] ? "" : ", "));
2135 // Collect the current row
2136 for(uint32_t i=0; i<num; i++)
2138 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
2142 /*printf("syncSave after: ");
2143 for(uint32_t i=0; i<num; i++)
2144 printf("[%d->%d]", syncSave[i], syncPt[i]);
2146 printf("currentRow: ");
2147 for(uint32_t i=0; i<num; i++)
2148 printf("[%.2lf]", currentRow[i]);
2149 printf(" => %.2lf\n", StdDeviation(currentRow, num));//*/
2151 //printf("%d: ", swLen);
2153 float ampStep = 1.0f / (float)num;
2157 if (Equal(syncSave, syncPt, num))
2160 float amplitude = ampStep;
2161 uint32_t smallestIdx = SmallestIndex(currentRow, num);
2163 a[0] = currentRow[smallestIdx];
2164 //printf("a[0]=%.2lf: ", a[0]);
2166 for(uint32_t i=0; i<num; i++)
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])
2172 if (i == smallestIdx)
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]];
2177 //printf("<%.2lf>", currentRow[i]);
2181 // Save the current row & subtract out the smallest as a basis
2182 double crSave = currentRow[i];
2183 currentRow[i] -= a[0];
2185 // Don't bother with stuff that's out of range (@ current sync point!) :-P
2186 if (syncSave[i] == syncPt[i])
2189 // Try to find correlates
2192 sigma = StdDeviation(a, cnt);
2193 //for(uint32_t j=1; j<cnt; j++)
2194 // printf("[%.2lf]", a[j]);
2197 if (sigma <= 5.5)//SIGMA_THRESHOLD)
2199 // If the sigma is in range for this item, pick it up
2200 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
2203 //printf("{%.2lf}", currentRow[i]);
2204 amplitude += ampStep;
2208 // Otherwise reject the last item; it's too far out
2211 //printf(" ==> %.2lf\n\t", sigma);
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;
2221 sigma = StdDeviation(currentRow, num, &mean);
2222 synthWave[swLen] = mean;
2223 swAmplitude[swLen] = 1.0f;
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*/)
2238 for(uint32_t i=0; i<num; i++)
2240 a[i] = (double)Global::wave[sNum[i]][sync[i]];
2245 for(uint32_t i=0; i<num; i++)
2246 printf("<%4d>", (uint32_t)a[i]);
2248 printf(" {la: %d}\n", LookaheadWave(sync, num, dir));
2251 uint32_t syncCount = 0;
2252 bool keepGoing = true;
2258 printf("Could not synchronize streams...\n");
2262 for(uint32_t i=0; i<num; i++)
2264 if (((dir == 1) && (sync[i] >= Global::waveLen[sNum[i]]))
2265 || ((dir == -1) && (sync[i] == 0)))
2267 printf("End of stream...\n");
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;
2276 for(uint32_t i=0; i<num; i++)
2278 if (i == largestIdx)
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)
2293 double ttn = (double)Global::wave[sNum[i]][sync[i]];
2297 printf(" %4d ", (uint32_t)ttn);
2306 double sigma = StdDeviation(a, num);
2307 double nextSigma = StdDeviationWave(sync, num);
2308 uint32_t lookahead = LookaheadWave(sync, num, dir);
2312 for(uint32_t i=0; i<num; i++)
2313 printf("<%4d>", (uint32_t)a[i]);
2315 printf(" ==> %.2lf ", sigma);
2316 printf("(next: %.2lf, la: %d)\n", nextSigma, lookahead);
2320 // A handful of heuristics... 1st: If sigma is good, we're done
2324 // Couldn't pull, so punt for now
2328 // If the next sigma + current / 2 is OK, move on
2329 if (((sigma + nextSigma) / 2.0) < 2.50)
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))
2343 bool AttemptToFindStart(uint32_t * sync, uint32_t num)
2346 for(uint32_t i=0; i<num; i++)
2352 bool keepGoing = true;
2356 double sigma = StdDeviationWave(sync, num);
2360 bool result = ResyncWave(sync, num, -1);
2362 if (result == false)
2367 for(uint32_t i=0; i<num; i++)
2371 for(uint32_t i=0; i<num; i++)
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));
2390 bool InitialSync(uint32_t * sync, uint32_t num)
2392 // Let's try a different approach to this...
2393 bool lookAt[6] = { true, true, false, false, false, false };
2395 // while (FindSyncBetweenFirstTwo(sync) == false)
2396 while (FindSyncBetweenFirstTwo(sync) < 1000)
2398 for(uint32_t i=0; i<num; i++)
2402 if (sync[i] >= Global::waveLen[sNum[i]])
2404 printf("Could not find initial sync!!\n");
2410 uint32_t lookahead = LookaheadWave(sync, 2);
2413 printf("Found sync for streams 1 & 2 at %d and %d (la=%d)\n", sync[0], sync[1], lookahead);
2415 // Add in the others, one at a time and try to synchronize them
2416 uint32_t syncBest[6];
2418 for(uint32_t i=2; i<num; i++)
2421 uint32_t bestLA = 0;
2423 for(uint32_t j=0; j<200; j++)
2425 uint32_t syncSave = sync[i];
2427 for(uint32_t k=0; k<200; k++)
2429 uint32_t la = LookaheadWave(sync, i + 1);
2434 memcpy(syncBest, sync, sizeof(syncBest));
2442 // Kick all the other streams forward to check the rest...
2443 for(uint32_t k=0; k<i; k++)
2447 memcpy(sync, syncBest, sizeof(syncBest));
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));
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*/)
2465 for(uint32_t i=loopPoint, pos=start; i<Global::synWaveLen[trackNum]; i++, pos++)
2467 a[0] = Global::synWave[trackNum][pos];
2468 a[1] = Global::synWave[trackNum][i];
2469 double sigma = StdDeviation(a, 2);
2488 //#define DEBUGSYNTH
2489 void SynthesizeTrack(uint32_t trackNum)
2492 uint32_t sync[6] = { 0 };
2494 for(uint32_t i=0; i<Global::numStreams; i++)
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))
2502 printf("sNum[%d] = %d\n", num, i);
2504 // Save the stream # so we can find it later
2508 // We should just bypass the synthesis part of this, not the loop point finding... :-P !!! FIX !!!
2511 printf("%.2f: Single stream, length: %d\n", (float) trackNum / 4.0f, Uint32LE(Global::stream[sNum[0]]->dataLength));
2513 memcpy(Global::synWave[trackNum], Global::wave[sNum[0]], Global::waveLen[sNum[0]] * 4);
2514 Global::synWaveLen[trackNum] = Global::waveLen[sNum[0]];
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)
2522 InitialSync(sync, num);
2523 AttemptToFindStart(sync, num);
2525 uint32_t count = 0, bloops = 0;
2526 bool keepGoing = true;
2527 Global::synWaveLen[trackNum] = 0;
2532 double sigma = StdDeviationWave(sync, num, &mean);
2537 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(mean + 0.5);
2538 Global::synWaveLen[trackNum]++;
2540 for(uint32_t i=0; i<num; i++)
2546 uint32_t startOfSynth = Global::synWaveLen[trackNum];
2551 printf("Bloop seen at pos ");
2552 for(uint32_t k=0; k<num; k++)
2553 printf("%d%s", sync[k], (k == num - 1 ? "" : ", "));
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);
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];
2566 // Collect the current row
2567 for(uint32_t i=0; i<num; i++)
2569 currentRow[i] = (double)Global::wave[sNum[i]][syncSave[i]];
2573 for(uint32_t i=0; i<num; i++)
2574 printf("syncSave[%d]=%d (sync: %d)\n", i, syncSave[i], sync[i]);
2579 if (Equal(syncSave, sync, num))
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 ? "" : ", "));
2591 uint32_t amplitude = 1;
2592 uint32_t smallestIdx = SmallestIndex(currentRow, num);
2594 a[0] = currentRow[smallestIdx];
2596 printf("a[0]=%.2lf:\n", a[0]);
2599 for(uint32_t i=0; i<num; i++)
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]])
2604 printf("Ran past end of stream %d (stream %d): syncSave=%d, waveLen=%d\n", i, sNum[i], syncSave[i], Global::waveLen[sNum[i]]);
2608 if (i == smallestIdx)
2610 // Maybe we should chuck this above the if()?
2611 // if (syncSave[i] == sync[i])
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]];
2620 printf("\t<%.2lf> (i=%d)\n", currentRow[i], i);
2625 // Save the current row & subtract out the smallest as a basis
2626 double crSave = currentRow[i];
2627 currentRow[i] -= a[0];
2629 // Don't bother with stuff that's out of range (@ current sync point!) :-P
2630 if (syncSave[i] == sync[i])
2633 // Try to find correlates
2636 sigma = StdDeviation(a, cnt);
2639 for(uint32_t j=1; j<cnt; j++)
2640 printf("[%.2lf]", a[j]);
2644 if (sigma <= 5.5)//SIGMA_THRESHOLD)
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]];
2652 printf("{%.2lf}", currentRow[i]);
2658 // Otherwise reject the last item; it's too far out
2662 printf(" ==> %.2lf\n", sigma);
2666 // Get the average of the items picked up and add it to the wave
2667 sigma = StdDeviation(a, cnt, &mean);
2670 // Did we find the line of ones yet? If so, chuck it in the wave
2671 if (amplitude == num)
2673 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(timeToOnes + 0.5);
2674 Global::synWaveLen[trackNum]++;
2679 for(uint32_t j=0; j<num; j++)
2680 printf("_%.2lf_", currentRow[j]);
2685 // Finally, chuck the final line of ones in
2686 sigma = StdDeviation(currentRow, num, &mean);
2688 Global::synWave[trackNum][Global::synWaveLen[trackNum]] = (uint32_t)(timeToOnes + 0.5);
2689 Global::synWaveLen[trackNum]++;
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 ? "" : ", "));
2698 for(uint32_t i=0; i<num; i++)
2700 if (sync[i] >= Global::waveLen[sNum[i]])
2709 printf("\n%.2f: Synthesis done. Bit count: %d, bloop count: %d\n", (float)trackNum / 4.0f, count, bloops);
2712 // Now, find the loop point and make BITS from it
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?
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).
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.
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;
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;
2731 // Get the index to the correct time in "pos"
2732 while (curTime < estLoopTime)
2733 curTime += Global::synWave[trackNum][pos++];
2735 printf("%.2f: estLoopTime=%d, curTime=%d, pos=%d\n", (float)trackNum / 4.0f, estLoopTime, curTime, pos);
2736 uint32_t posSave = pos;
2738 // "pos" now holds the start of the search for our loop point.
2739 for(uint32_t i=0; i<200; i++)
2741 uint32_t lookahead = 0;
2745 longestStretch = stretch = 0;
2746 startOfLoop = 0;//shouldn't be necessary...
2748 for(j=(pos+i-100), pos0=0; j<Global::synWaveLen[trackNum]; j++, pos0++)
2750 uint32_t lla0 = LoopLookahead(trackNum, pos0 + 0, j, &full0);
2751 uint32_t lla1 = LoopLookahead(trackNum, pos0 + 1, j, &full1);
2756 if (stretch > longestStretch)
2757 longestStretch = stretch;
2763 else if (full1 && first) // only check 1st time (for now)
2777 a[0] = Global::synWave[trackNum][pos0++];
2778 a[1] = Global::synWave[trackNum][j++];
2779 double sigma = StdDeviation(a, 2);
2785 // printf("First blip: %.0lf, %.0lf (sigma=%.2lf) [pos=%d, la=%d]\n", a[0], a[1], sigma, i + pos - 100, pos0);
2787 if (trackNum == 137)
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" : ""));
2796 /* if (sigma <= 2.50)
2801 if (stretch > longestStretch)
2802 longestStretch = stretch;
2806 // Hmm, not in sync. See if we can re-sync
2813 a[0] += Global::synWave[trackNum][pos0++];
2815 a[1] += Global::synWave[trackNum][j++];
2817 // Maybe put all the other heuristics in too?
2818 if (StdDeviation(a, 2) <= 2.50)
2821 // Now you've gone *too* far...
2822 if (j >= Global::synWaveLen[trackNum])
2830 if (trackNum == 137)
2831 printf(" blips=%d, la=%d\n", blips, lookahead);
2834 //maybe we should keep an array of the analyses so we can decide afterward which one is best...
2835 if (blips < worstBlips)
2838 worstBlipsPos = pos + i - 100;
2841 if (lookahead > maxLookahead)
2843 maxLookahead = lookahead;
2844 maxPos = pos + i - 100;
2847 if (longestStretch > maxLongestStretch)
2849 maxLongestStretch = longestStretch;
2850 mlsPos = pos + i - 100;
2858 bitLen[trackNum] = RenderBitstream(bits[trackNum], &byteLen[trackNum], Global::synWave[trackNum], startOfLoop, maxPos);
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);
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...]
2868 /* for(uint32_t i=0; i<maxLookahead+5; i++)
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);
2881 Using a histogram, we can get an idea of the drift from the ones:
2899 -------------------------------------------------
2900 0000|0584|1792|9611|2627|5382|0482|0058|0013|0000
2901 28 29 30 31 32 33 34 35 36 37
2903 Peak of the ones occurs at 31, with a secondary at 33. Twos drift:
2914 -------------------------------------------------
2915 0000|0545|0277|5482|1223|5168|0252|0082|0102|0000
2916 57 58 59 60 61 62 63 64 65 66
2918 This looks like stretched out ones (they might all be spurious...):
2928 ---------------------------------------
2929 0000|0015|0007|0002|0011|0001|0002|0000
2930 43 44 45 46 47 48 49 50