/* 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_f (internal) * * This function examines a trailing rift to see how far forward the rift goes * and to determine what kind of rift it is. This function is called by * i_stage2_each() when a trailing 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_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 forward 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) (... A matching run)|(aoffset matches ...) * (... B matching run)| (rift) |(boffset+i matches ...) * * (2) (... A matching run)| (rift) |(aoffset+i matches ...) * (... B matching run)|(boffset matches ...) * * (3) (... A matching run)| (rift) |(aoffset+i matches ...) * (... B matching run)| (rift) |(boffset+i matches ...) * * Anything that doesn't match one of these three is too corrupt to * for us to recover from. E.g.: * * (... A matching run)| (rift) |(eventual match ...) * (... B matching run)| (big rift) |(eventual match ...) * * 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 end 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_f(A,B,aoffset,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){ *matchA=i; break; } /* Don't search for (2) or (3) past the end 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_f(A,B,aoffset+i,boffset,sizeA,sizeB)>=MIN_WORDS_RIFT){ *matchB=i; break; } /* Don't search for (3) past the end 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_f(A,B,aoffset+i,boffset+i,sizeA,sizeB)>=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 before the rift. If the contents match, then the rift contains * a stutter. * * A stutter in the second vector: * (...good samples... 1234)|(567 ...newly matched run...) * (...good samples... 1234)| (1234) | (567 ...newly matched run) * * Samples missing from the first vector: * (...good samples... 1234)|(901 ...newly matched run...) * (...good samples... 1234)| (5678) |(901 ...newly matched run...) * * 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. */ if(i_stutter_or_gap(A,B,aoffset-*matchA,boffset,*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-*matchB,aoffset,*matchB)) return; *matchA=-*matchB; *matchB=0; return; } }