/* riftv is the first value into the rift -> or <- */ void i_analyze_rift_f(int16_t *A,int16_t *B, long sizeA, long sizeB, long aoffset, long boffset, long *matchA,long *matchB,long *matchC){ long apast=sizeA-aoffset; long bpast=sizeB-boffset; long i; *matchA=0, *matchB=0, *matchC=0; /* Look for three possible matches... (A) Ariftv->B, (B) Briftv->A and (c) AB->AB. */ for(i=0;;i++){ if(i<bpast) /* A */ if(i_paranoia_overlap_f(A,B,aoffset,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){ *matchA=i; break; } if(i<apast){ /* B */ if(i_paranoia_overlap_f(A,B,aoffset+i,boffset,sizeA,sizeB)>=MIN_WORDS_RIFT){ *matchB=i; break; } if(i<bpast) /* C */ if(i_paranoia_overlap_f(A,B,aoffset+i,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){ *matchC=i; break; } }else if(i>=bpast)break; } if(*matchA==0 && *matchB==0 && *matchC==0)return; if(*matchC)return; if(*matchA){ if(i_stutter_or_gap(A,B,aoffset-*matchA,boffset,*matchA)) return; *matchB=-*matchA; /* signify we need to remove n bytes from B */ *matchA=0; return; }else{ if(i_stutter_or_gap(B,A,boffset-*matchB,aoffset,*matchB)) return; *matchA=-*matchB; *matchB=0; return; } }
/* =========================================================================== * i_analyze_rift_r (internal) * * This function examines a leading rift to see how far back the rift goes * and to determine what kind of rift it is. This function is called by * i_stage2_each() when a leading rift is detected. (aoffset,boffset) are * the offsets into (A,B) of the first mismatching sample. * * This function returns: * matchA > 0 if there are (matchA) samples missing from A * matchA < 0 if there are (-matchA) duplicate samples (stuttering) in A * matchB > 0 if there are (matchB) samples missing from B * matchB < 0 if there are (-matchB) duplicate samples in B * matchC != 0 if there are (matchC) samples of garbage, after which * both A and B are in sync again */ void i_analyze_rift_r(int16_t *A,int16_t *B, long sizeA, long sizeB, long aoffset, long boffset, long *matchA,long *matchB,long *matchC){ long apast=aoffset+1; long bpast=boffset+1; long i; *matchA=0, *matchB=0, *matchC=0; /* Look backward to see where we regain agreement between vectors * A and B (of at least MIN_WORDS_RIFT samples). We look for one of * the following possible matches: * * edge * v * (1) (... aoffset matches)|(A matching run ...) * (... boffset-i matches)| (rift) |(B matching run ...) * * (2) (... aoffset-i matches)| (rift) |(A matching run ...) * (... boffset matches)|(B matching run ...) * * (3) (... aoffset-i matches)| (rift) |(A matching run ...) * (... boffset-i matches)| (rift) |(B matching run ...) * * Anything that doesn't match one of these three is too corrupt to * for us to recover from. E.g.: * * (... eventual match)| (rift) |(A matching run ...) * (... eventual match) | (big rift) |(B matching run ...) * * We won't find the eventual match, since we wouldn't be sure how * to fix the rift. */ for(i=1;;i++){ /* Search for whatever case we hit first, so as to end up with the * smallest rift. */ /* Don't search for (1) past the beginning of B */ if(i<bpast) /* See if we match case (1) above, which either means that A dropped * samples at the rift, or that B stuttered. */ if(i_paranoia_overlap_r(A,B,aoffset,boffset-i)>=MIN_WORDS_RIFT){ *matchA=i; break; } /* Don't search for (2) or (3) past the beginning of A */ if(i<apast){ /* See if we match case (2) above, which either means that B dropped * samples at the rift, or that A stuttered. */ if(i_paranoia_overlap_r(A,B,aoffset-i,boffset)>=MIN_WORDS_RIFT){ *matchB=i; break; } /* Don't search for (3) past the beginning of B */ if(i<bpast) /* See if we match case (3) above, which means that a fixed-length * rift of samples is getting read unreliably. */ if(i_paranoia_overlap_r(A,B,aoffset-i,boffset-i)>=MIN_WORDS_RIFT){ *matchC=i; break; } }else /* Stop searching when we've reached the end of both vectors. * In theory we could stop when there aren't MIN_WORDS_RIFT samples * left in both vectors, but this case should happen fairly rarely. */ if(i>=bpast)break; /* Try the search again with a larger tentative rift. */ } if(*matchA==0 && *matchB==0 && *matchC==0)return; if(*matchC)return; /* For case (1) or (2), we need to determine whether the rift contains * samples dropped by the other vector (that should be inserted), or * whether the rift contains a stutter (that should be dropped). To * distinguish, we check the contents of the rift against the good samples * just after the rift. If the contents match, then the rift contains * a stutter. * * A stutter in the second vector: * (...newly matched run... 234)|(5678 ...good samples...) * (...newly matched run... 234)| (5678) |(5678 ...good samples...) * * Samples missing from the first vector: * (...newly matched run... 890)|(5678 ...good samples...) * (...newly matched run... 890)| (1234) |(5678 ...good samples...) * * Of course, there's no theoretical guarantee that a non-stutter * truly represents missing samples, but given that we're dealing with * verified fragments in stage 2, we can have some confidence that this * is the case. */ if(*matchA){ /* For case (1), we need to determine whether A dropped samples at the * rift or whether B stuttered. * * If the rift doesn't match the good samples in A (and hence in B), * it's not a stutter, and the rift should be inserted into A. * * ???BUG??? It's possible for aoffset+1+*matchA to be > sizeA, in * which case the comparison in i_stutter_or_gap() will extend beyond * the bounds of A. Thankfully, this isn't writing data and thus * trampling memory, but it's still a memory access error that should * be fixed. * * This bug is not fixed yet. */ if(i_stutter_or_gap(A,B,aoffset+1,boffset-*matchA+1,*matchA)) return; /* It is a stutter, so we need to signal that we need to remove * (matchA) bytes from B. */ *matchB=-*matchA; *matchA=0; return; }else{ /* Case (2) is the inverse of case (1) above. */ if(i_stutter_or_gap(B,A,boffset+1,aoffset-*matchB+1,*matchB)) return; *matchA=-*matchB; *matchB=0; return; } }