Beispiel #1
0
Datei: gap.c Projekt: IMSoP/CDex
/* 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;
  }
}
Beispiel #2
0
/* ===========================================================================
 * 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;
  }
}