Blame lib/paranoia/paranoia.c

Packit cb6d3d
/*
Packit cb6d3d
  Copyright (C) 2004, 2005, 2006, 2008, 2011, 2017
Packit cb6d3d
  Rocky Bernstein <rocky@gnu.org>
Packit cb6d3d
  Copyright (C) 2014 Robert Kausch <robert.kausch@freac.org>
Packit cb6d3d
  Copyright (C) 1998 Monty xiphmont@mit.edu
Packit cb6d3d
Packit cb6d3d
  This program is free software: you can redistribute it and/or modify
Packit cb6d3d
  it under the terms of the GNU General Public License as published by
Packit cb6d3d
  the Free Software Foundation, either version 3 of the License, or
Packit cb6d3d
  (at your option) any later version.
Packit cb6d3d
Packit cb6d3d
  This program is distributed in the hope that it will be useful,
Packit cb6d3d
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit cb6d3d
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit cb6d3d
  GNU General Public License for more details.
Packit cb6d3d
Packit cb6d3d
  You should have received a copy of the GNU General Public License
Packit cb6d3d
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit cb6d3d
*/
Packit cb6d3d
/***
Packit cb6d3d
 * Toplevel file for the paranoia abstraction over the cdda lib
Packit cb6d3d
 *
Packit cb6d3d
 ***/
Packit cb6d3d
Packit cb6d3d
/* immediate todo:: */
Packit cb6d3d
/* Allow disabling of root fixups? */
Packit cb6d3d
/* Dupe bytes are creeping into cases that require greater overlap
Packit cb6d3d
   than a single fragment can provide.  We need to check against a
Packit cb6d3d
   larger area* (+/-32 sectors of root?) to better eliminate
Packit cb6d3d
   dupes. Of course this leads to other problems... Is it actually a
Packit cb6d3d
   practically solvable problem? */
Packit cb6d3d
/* Bimodal overlap distributions break us. */
Packit cb6d3d
/* scratch detection/tolerance not implemented yet */
Packit cb6d3d
Packit cb6d3d
/***************************************************************
Packit cb6d3d
Packit cb6d3d
  Da new shtick: verification now a two-step assymetric process.
Packit cb6d3d
Packit cb6d3d
  A single 'verified/reconstructed' data segment cache, and then the
Packit cb6d3d
  multiple fragment cache
Packit cb6d3d
Packit cb6d3d
  verify a newly read block against previous blocks; do it only this
Packit cb6d3d
  once. We maintain a list of 'verified sections' from these matches.
Packit cb6d3d
Packit cb6d3d
  We then glom these verified areas into a new data buffer.
Packit cb6d3d
  Defragmentation fixups are allowed here alone.
Packit cb6d3d
Packit cb6d3d
  We also now track where read boundaries actually happened; do not
Packit cb6d3d
  verify across matching boundaries.
Packit cb6d3d
Packit cb6d3d
  **************************************************************/
Packit cb6d3d
Packit cb6d3d
/***************************************************************
Packit cb6d3d
Packit cb6d3d
  Silence.  "It's BAAAAAAaaack."
Packit cb6d3d
Packit cb6d3d
  audio is now treated as great continents of values floating on a
Packit cb6d3d
  mantle of molten silence.  Silence is not handled by basic
Packit cb6d3d
  verification at all; we simply anchor sections of nonzero audio to a
Packit cb6d3d
  position and fill in everything else as silence.  We also note the
Packit cb6d3d
  audio that interfaces with silence; an edge must be 'wet'.
Packit cb6d3d
Packit cb6d3d
  **************************************************************/
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * Let's translate the above vivid metaphor into something a mere mortal
Packit cb6d3d
 * can understand:
Packit cb6d3d
 *
Packit cb6d3d
 * Non-silent audio is "solid."  Silent audio is "wet" and fluid.  The reason
Packit cb6d3d
 * to treat silence as fluid is that if there's a long enough span of
Packit cb6d3d
 * silence, we can't reliably detect jitter or dropped samples within that
Packit cb6d3d
 * span (since all silence looks alike).  Non-silent audio, on the other
Packit cb6d3d
 * hand, is distinctive and can be reliably reassembled.
Packit cb6d3d
 *
Packit cb6d3d
 * So we treat long spans of silence specially.  We only consider an edge
Packit cb6d3d
 * of a non-silent region ("continent" or "island") to be "wet" if it borders
Packit cb6d3d
 * a long span of silence.  Short spans of silence are merely damp and can
Packit cb6d3d
 * be reliably placed within a continent.
Packit cb6d3d
 *
Packit cb6d3d
 * We position ("anchor") the non-silent regions somewhat arbitrarily (since
Packit cb6d3d
 * they may be jittered and we have no way to verify their exact position),
Packit cb6d3d
 * and fill the intervening space with silence.
Packit cb6d3d
 *
Packit cb6d3d
 * See i_silence_match() for the gory details.
Packit cb6d3d
 * ===========================================================================
Packit cb6d3d
 */
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
#ifdef HAVE_CONFIG_H
Packit cb6d3d
# include "config.h"
Packit cb6d3d
# define __CDIO_CONFIG_H__ 1
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
#ifdef HAVE_STDLIB_H
Packit cb6d3d
#include <stdlib.h>
Packit cb6d3d
#endif
Packit cb6d3d
#include <unistd.h>
Packit cb6d3d
#include <stdio.h>
Packit cb6d3d
#include <limits.h>
Packit cb6d3d
#ifdef HAVE_STRING_H
Packit cb6d3d
#include <string.h>
Packit cb6d3d
#endif
Packit cb6d3d
#include <math.h>
Packit cb6d3d
#include <cdio/paranoia/cdda.h>
Packit cb6d3d
#include "../cdda_interface/smallft.h"
Packit cb6d3d
#include <cdio/paranoia/version.h>
Packit cb6d3d
#include "p_block.h"
Packit cb6d3d
#include <cdio/paranoia/paranoia.h>
Packit cb6d3d
#include "overlap.h"
Packit cb6d3d
#include "gap.h"
Packit cb6d3d
#include "isort.h"
Packit cb6d3d
#include <errno.h>
Packit cb6d3d
Packit cb6d3d
#define MIN_SEEK_MS 6
Packit cb6d3d
Packit cb6d3d
const char *paranoia_cb_mode2str[] = {
Packit cb6d3d
  "read",
Packit cb6d3d
  "verify",
Packit cb6d3d
  "fixup edge",
Packit cb6d3d
  "fixup atom",
Packit cb6d3d
  "scratch",
Packit cb6d3d
  "repair",
Packit cb6d3d
  "skip",
Packit cb6d3d
  "drift",
Packit cb6d3d
  "backoff",
Packit cb6d3d
  "overlap",
Packit cb6d3d
  "fixup dropped",
Packit cb6d3d
  "fixup duplicated",
Packit cb6d3d
  "read error"
Packit cb6d3d
};
Packit cb6d3d
Packit cb6d3d
/** The below variables are trickery to force the above enum symbol
Packit cb6d3d
    values to be recorded in debug symbol tables. They are used to
Packit cb6d3d
    allow one to refer to the enumeration value names in the typedefs
Packit cb6d3d
    above in a debugger and debugger expressions
Packit cb6d3d
*/
Packit cb6d3d
Packit cb6d3d
paranoia_mode_t    debug_paranoia_mode;
Packit cb6d3d
paranoia_cb_mode_t debug_paranoia_cb_mode;
Packit cb6d3d
Packit cb6d3d
static inline long
Packit cb6d3d
re(root_block *root)
Packit cb6d3d
{
Packit cb6d3d
  if (!root)return(-1);
Packit cb6d3d
  if (!root->vector)return(-1);
Packit cb6d3d
  return(ce(root->vector));
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
static inline long
Packit cb6d3d
rb(root_block *root)
Packit cb6d3d
{
Packit cb6d3d
  if (!root)return(-1);
Packit cb6d3d
  if (!root->vector)return(-1);
Packit cb6d3d
  return(cb(root->vector));
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
static inline
Packit cb6d3d
long rs(root_block *root)
Packit cb6d3d
{
Packit cb6d3d
  if (!root)return(-1);
Packit cb6d3d
  if (!root->vector)return(-1);
Packit cb6d3d
  return(cs(root->vector));
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
static inline int16_t *
Packit cb6d3d
rv(root_block *root){
Packit cb6d3d
  if (!root)return(NULL);
Packit cb6d3d
  if (!root->vector)return(NULL);
Packit cb6d3d
  return(cv(root->vector));
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
#define rc(r) (r->vector)
Packit cb6d3d
Packit cb6d3d
/**
Packit cb6d3d
    Flags indicating the status of a read samples.
Packit cb6d3d
Packit cb6d3d
    Imagine the below enumeration values are \#defines to be used in a
Packit cb6d3d
    bitmask rather than distinct values of an enum.
Packit cb6d3d
Packit cb6d3d
    The variable part of the declaration is trickery to force the enum
Packit cb6d3d
    symbol values to be recorded in debug symbol tables. They are used
Packit cb6d3d
    to allow one refer to the enumeration value names in a debugger
Packit cb6d3d
    and in debugger expressions.
Packit cb6d3d
*/
Packit cb6d3d
enum  {
Packit cb6d3d
  FLAGS_EDGE    =0x1, /**< first/last N words of frame */
Packit cb6d3d
  FLAGS_UNREAD  =0x2, /**< unread, hence missing and unmatchable */
Packit cb6d3d
  FLAGS_VERIFIED=0x4  /**< block read and verified */
Packit cb6d3d
} paranoia_read_flags;
Packit cb6d3d
Packit cb6d3d
/**** matching and analysis code *****************************************/
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_paranoia_overlap() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called when buffA[offsetA] == buffB[offsetB].  This
Packit cb6d3d
 * function searches backward and forward to see how many consecutive
Packit cb6d3d
 * samples also match.
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called by do_const_sync() when we're not doing any
Packit cb6d3d
 * verification.  Its more complicated sibling is i_paranoia_overlap2.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns the number of consecutive matching samples.
Packit cb6d3d
 * If (ret_begin) or (ret_end) are not NULL, it fills them with the
Packit cb6d3d
 * offsets of the first and last matching samples in A.
Packit cb6d3d
 */
Packit cb6d3d
static inline long
Packit cb6d3d
i_paranoia_overlap(int16_t *buffA,int16_t *buffB,
Packit cb6d3d
		   long offsetA, long offsetB,
Packit cb6d3d
		   long sizeA,long sizeB,
Packit cb6d3d
		   long *ret_begin, long *ret_end)
Packit cb6d3d
{
Packit cb6d3d
  long beginA=offsetA,endA=offsetA;
Packit cb6d3d
  long beginB=offsetB,endB=offsetB;
Packit cb6d3d
Packit cb6d3d
  /* Scan backward to extend the matching run in that direction. */
Packit cb6d3d
  for(; beginA>=0 && beginB>=0; beginA--,beginB--)
Packit cb6d3d
    if (buffA[beginA] != buffB[beginB]) break;
Packit cb6d3d
  beginA++;
Packit cb6d3d
  beginB++;
Packit cb6d3d
Packit cb6d3d
  /* Scan forward to extend the matching run in that direction. */
Packit cb6d3d
  for(; endA
Packit cb6d3d
    if (buffA[endA] != buffB[endB]) break;
Packit cb6d3d
Packit cb6d3d
  /* Return the result of our search. */
Packit cb6d3d
  if (ret_begin) *ret_begin = beginA;
Packit cb6d3d
  if (ret_end) *ret_end = endA;
Packit cb6d3d
  return (endA-beginA);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_paranoia_overlap2() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called when buffA[offsetA] == buffB[offsetB].  This
Packit cb6d3d
 * function searches backward and forward to see how many consecutive
Packit cb6d3d
 * samples also match.
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called by do_const_sync() when we're verifying the
Packit cb6d3d
 * data coming off the CD.  Its less complicated sibling is
Packit cb6d3d
 * i_paranoia_overlap, which is a good place to look to see the simplest
Packit cb6d3d
 * outline of how this function works.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns the number of consecutive matching samples.
Packit cb6d3d
 * If (ret_begin) or (ret_end) are not NULL, it fills them with the
Packit cb6d3d
 * offsets of the first and last matching samples in A.
Packit cb6d3d
 */
Packit cb6d3d
static inline long
Packit cb6d3d
i_paranoia_overlap2(int16_t *buffA,int16_t *buffB,
Packit cb6d3d
		    unsigned char *flagsA,
Packit cb6d3d
		    unsigned char *flagsB,
Packit cb6d3d
		    long offsetA, long offsetB,
Packit cb6d3d
		    long sizeA,long sizeB,
Packit cb6d3d
		    long *ret_begin, long *ret_end)
Packit cb6d3d
{
Packit cb6d3d
  long beginA=offsetA, endA=offsetA;
Packit cb6d3d
  long beginB=offsetB, endB=offsetB;
Packit cb6d3d
Packit cb6d3d
  /* Scan backward to extend the matching run in that direction. */
Packit cb6d3d
  for (; beginA>=0 && beginB>=0; beginA--,beginB--) {
Packit cb6d3d
    if (buffA[beginA] != buffB[beginB]) break;
Packit cb6d3d
Packit cb6d3d
    /* don't allow matching across matching sector boundaries. The
Packit cb6d3d
       liklihood of the drive skipping identically in two
Packit cb6d3d
       different reads with the same sector read boundary is actually
Packit cb6d3d
       relatively very high compared to the liklihood of it skipping
Packit cb6d3d
       when one read is continuous across the boundary and other was
Packit cb6d3d
       discontinuous */
Packit cb6d3d
    /* Stop if both samples were at the edges of a low-level read.
Packit cb6d3d
     * ???: What implications does this have?
Packit cb6d3d
     * ???: Why do we include the first sample for which this is true?
Packit cb6d3d
     */
Packit cb6d3d
    if ((flagsA[beginA]&flagsB[beginB]&FLAGS_EDGE)) {
Packit cb6d3d
      beginA--;
Packit cb6d3d
      beginB--;
Packit cb6d3d
      break;
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* don't allow matching through known missing data */
Packit cb6d3d
    if ((flagsA[beginA]&FLAGS_UNREAD) || (flagsB[beginB]&FLAGS_UNREAD))
Packit cb6d3d
      break;
Packit cb6d3d
  }
Packit cb6d3d
  beginA++;
Packit cb6d3d
  beginB++;
Packit cb6d3d
Packit cb6d3d
  /* Scan forward to extend the matching run in that direction. */
Packit cb6d3d
  for (; endA
Packit cb6d3d
    if (buffA[endA] != buffB[endB]) break;
Packit cb6d3d
Packit cb6d3d
    /* don't allow matching across matching sector boundaries */
Packit cb6d3d
    /* Stop if both samples were at the edges of a low-level read.
Packit cb6d3d
     * ???: What implications does this have?
Packit cb6d3d
     * ???: Why do we not stop if endA == beginA?
Packit cb6d3d
     */
Packit cb6d3d
    if ((flagsA[endA]&flagsB[endB]&FLAGS_EDGE) && endA!=beginA){
Packit cb6d3d
      break;
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* don't allow matching through known missing data */
Packit cb6d3d
    if ((flagsA[endA]&FLAGS_UNREAD) || (flagsB[endB]&FLAGS_UNREAD))
Packit cb6d3d
      break;
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  /* Return the result of our search. */
Packit cb6d3d
  if (ret_begin) *ret_begin = beginA;
Packit cb6d3d
  if (ret_end) *ret_end = endA;
Packit cb6d3d
  return (endA-beginA);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * do_const_sync() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called when samples A[posA] == B[posB].  It tries to
Packit cb6d3d
 * build a matching run from that point, looking forward and backward to
Packit cb6d3d
 * see how many consecutive samples match.  Since the starting samples
Packit cb6d3d
 * might only be coincidentally identical, we only consider the run to
Packit cb6d3d
 * be a true match if it's longer than MIN_WORDS_SEARCH.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns the length of the run if a matching run was found,
Packit cb6d3d
 * or 0 otherwise.  If a matching run was found, (begin) and (end) are set
Packit cb6d3d
 * to the absolute positions of the beginning and ending samples of the
Packit cb6d3d
 * run in A, and (offset) is set to the jitter between the c_blocks.
Packit cb6d3d
 * (I.e., offset indicates the distance between what A considers sample N
Packit cb6d3d
 * on the CD and what B considers sample N.)
Packit cb6d3d
 */
Packit cb6d3d
static inline long int
Packit cb6d3d
do_const_sync(c_block_t *A,
Packit cb6d3d
	      sort_info_t *B,
Packit cb6d3d
	      unsigned char *flagB,
Packit cb6d3d
	      long posA, long posB,
Packit cb6d3d
	      long *begin, long *end, long *offset)
Packit cb6d3d
{
Packit cb6d3d
  unsigned char *flagA=A->flags;
Packit cb6d3d
  long ret=0;
Packit cb6d3d
Packit cb6d3d
  /* If we're doing any verification whatsoever, we have flags in stage
Packit cb6d3d
   * 1, and will take them into account.  Otherwise (e.g. in stage 2),
Packit cb6d3d
   * we just do the simple equality test for samples on both sides of
Packit cb6d3d
   * the initial match.
Packit cb6d3d
   */
Packit cb6d3d
  if (flagB==NULL)
Packit cb6d3d
    ret=i_paranoia_overlap(cv(A), iv(B), posA, posB,
Packit cb6d3d
			   cs(A), is(B), begin, end);
Packit cb6d3d
  else
Packit cb6d3d
    if ((flagB[posB]&FLAGS_UNREAD)==0)
Packit cb6d3d
      ret=i_paranoia_overlap2(cv(A), iv(B), flagA, flagB,
Packit cb6d3d
			      posA, posB, cs(A), is(B),
Packit cb6d3d
			      begin, end);
Packit cb6d3d
Packit cb6d3d
  /* Small matching runs could just be coincidental.  We only consider this
Packit cb6d3d
   * a real match if it's long enough.
Packit cb6d3d
   */
Packit cb6d3d
  if (ret > MIN_WORDS_SEARCH) {
Packit cb6d3d
    *offset=+(posA+cb(A))-(posB+ib(B));
Packit cb6d3d
Packit cb6d3d
    /* Note that try_sort_sync()'s swaps A & B when it calls this function,
Packit cb6d3d
     * so while we adjust begin & end to be relative to A here, that means
Packit cb6d3d
     * it's relative to B in try_sort_sync().
Packit cb6d3d
     */
Packit cb6d3d
    *begin+=cb(A);
Packit cb6d3d
    *end+=cb(A);
Packit cb6d3d
    return(ret);
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  return(0);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * try_sort_sync() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * Starting from the sample in B with the absolute position (post), look
Packit cb6d3d
 * for a matching run in A.  This search will look in A for a first
Packit cb6d3d
 * matching sample within (p->dynoverlap) samples around (post).  If it
Packit cb6d3d
 * finds one, it will then determine how many consecutive samples match
Packit cb6d3d
 * both A and B from that point, looking backwards and forwards.  If
Packit cb6d3d
 * this search produces a matching run longer than MIN_WORDS_SEARCH, we
Packit cb6d3d
 * consider it a match.
Packit cb6d3d
 *
Packit cb6d3d
 * When used by stage 1, the "post" is planted with respect to the old
Packit cb6d3d
 * c_block being compare to the new c_block.  In stage 2, the "post" is
Packit cb6d3d
 * planted with respect to the verified root.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns 1 if a match is found and 0 if not.  When a match
Packit cb6d3d
 * is found, (begin) and (end) are set to the boundaries of the run, and
Packit cb6d3d
 * (offset) is set to the difference in position of the run in A and B.
Packit cb6d3d
 * (begin) and (end) are the absolute positions of the samples in
Packit cb6d3d
 * B.  (offset) transforms A to B's frame of reference.  I.e., an offset of
Packit cb6d3d
 * 2 would mean that A's absolute 3 is equivalent to B's 5.
Packit cb6d3d
 */
Packit cb6d3d
Packit cb6d3d
/* post is w.r.t. B.  in stage one, we post from old.  In stage 2 we
Packit cb6d3d
   post from root. Begin, end, offset count from B's frame of
Packit cb6d3d
   reference */
Packit cb6d3d
Packit cb6d3d
static inline long int
Packit cb6d3d
try_sort_sync(cdrom_paranoia_t *p,
Packit cb6d3d
	      sort_info_t *A, unsigned char *Aflags,
Packit cb6d3d
	      c_block_t *B,
Packit cb6d3d
	      long int post,
Packit cb6d3d
	      long int *begin,
Packit cb6d3d
	      long int *end,
Packit cb6d3d
	      long *offset,
Packit cb6d3d
	      void (*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
Packit cb6d3d
  long int dynoverlap=p->dynoverlap;
Packit cb6d3d
  sort_link_t *ptr=NULL;
Packit cb6d3d
  unsigned char *Bflags=B->flags;
Packit cb6d3d
Packit cb6d3d
  /* block flag matches FLAGS_UNREAD (and hence unmatchable) */
Packit cb6d3d
  if (Bflags==NULL || (Bflags[post-cb(B)]&FLAGS_UNREAD)==0){
Packit cb6d3d
    /* always try absolute offset zero first! */
Packit cb6d3d
    {
Packit cb6d3d
      long zeropos=post-ib(A);
Packit cb6d3d
      if (zeropos>=0 && zeropos
Packit cb6d3d
Packit cb6d3d
	/* Before we bother with the search for a matching samples,
Packit cb6d3d
	 * we check the simple case.  If there's no jitter at all
Packit cb6d3d
	 * (i.e. the absolute positions of A's and B's samples are
Packit cb6d3d
	 * consistent), A's sample at (post) should be identical
Packit cb6d3d
	 * to B's sample at the same position.
Packit cb6d3d
	 */
Packit cb6d3d
	if ( cv(B)[post-cb(B)] == iv(A)[zeropos] ) {
Packit cb6d3d
Packit cb6d3d
	  /* The first sample matched, now try to grow the matching run
Packit cb6d3d
	   * in both directions.  We only consider it a match if more
Packit cb6d3d
	   * than MIN_WORDS_SEARCH consecutive samples match.
Packit cb6d3d
	   */
Packit cb6d3d
	  if (do_const_sync(B, A, Aflags,
Packit cb6d3d
			    post-cb(B), zeropos,
Packit cb6d3d
			    begin, end, offset) ) {
Packit cb6d3d
Packit cb6d3d
	    /* ???BUG??? Jitter cannot be accurately detected when there are
Packit cb6d3d
	     * large regions of silence.  Silence all looks alike, so if
Packit cb6d3d
	     * there is actually jitter but lots of silence, jitter (offset)
Packit cb6d3d
	     * will be incorrectly identified as 0.  When the incorrect zero
Packit cb6d3d
	     * jitter is passed to offset_add_value, it eventually reduces
Packit cb6d3d
	     * dynoverlap so much that it's impossible for stage 2 to merge
Packit cb6d3d
	     * jittered fragments into the root (it doesn't search far enough).
Packit cb6d3d
	     *
Packit cb6d3d
	     * A potential solution (tested, but not committed) is to check
Packit cb6d3d
	     * for silence in do_const_sync and simply not call
Packit cb6d3d
	     * offset_add_value if the match is all silence.
Packit cb6d3d
	     *
Packit cb6d3d
	     * This bug is not fixed yet.
Packit cb6d3d
	     */
Packit cb6d3d
	    /* ???: To be studied. */
Packit cb6d3d
	    offset_add_value(p,&(p->stage1),*offset,callback);
Packit cb6d3d
Packit cb6d3d
	    return(1);
Packit cb6d3d
	  }
Packit cb6d3d
	}
Packit cb6d3d
      }
Packit cb6d3d
    }
Packit cb6d3d
  } else
Packit cb6d3d
    return(0);
Packit cb6d3d
Packit cb6d3d
  /* If the samples with the same absolute position didn't match, it's
Packit cb6d3d
   * either a bad sample, or the two c_blocks are jittered with respect
Packit cb6d3d
   * to each other.  Now we search through A for samples that do have
Packit cb6d3d
   * the same value as B's post.  The search looks from first to last
Packit cb6d3d
   * occurrence witin (dynoverlap) samples of (post).
Packit cb6d3d
   */
Packit cb6d3d
  ptr=sort_getmatch(A,post-ib(A),dynoverlap,cv(B)[post-cb(B)]);
Packit cb6d3d
Packit cb6d3d
  while (ptr){
Packit cb6d3d
Packit cb6d3d
    /* We've found a matching sample, so try to grow the matching run in
Packit cb6d3d
     * both directions.  If we find a long enough run (longer than
Packit cb6d3d
     * MIN_WORDS_SEARCH), we've found a match.
Packit cb6d3d
     */
Packit cb6d3d
    if (do_const_sync(B,A,Aflags,
Packit cb6d3d
		     post-cb(B),ipos(A,ptr),
Packit cb6d3d
		     begin,end,offset)){
Packit cb6d3d
Packit cb6d3d
      /* ???BUG??? Jitter cannot be accurately detected when there are
Packit cb6d3d
       * large regions of silence.  Silence all looks alike, so if
Packit cb6d3d
       * there is actually jitter but lots of silence, jitter (offset)
Packit cb6d3d
       * will be incorrectly identified as 0.  When the incorrect zero
Packit cb6d3d
       * jitter is passed to offset_add_value, it eventually reduces
Packit cb6d3d
       * dynoverlap so much that it's impossible for stage 2 to merge
Packit cb6d3d
       * jittered fragments into the root (it doesn't search far enough).
Packit cb6d3d
       *
Packit cb6d3d
       * A potential solution (tested, but not committed) is to check
Packit cb6d3d
       * for silence in do_const_sync and simply not call
Packit cb6d3d
       * offset_add_value if the match is all silence.
Packit cb6d3d
       *
Packit cb6d3d
       * This bug is not fixed yet.
Packit cb6d3d
       */
Packit cb6d3d
      /* ???: To be studied. */
Packit cb6d3d
      offset_add_value(p,&(p->stage1),*offset,callback);
Packit cb6d3d
      return(1);
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* The matching sample was just a fluke -- there weren't enough adjacent
Packit cb6d3d
     * samples that matched to consider a matching run.  So now we check
Packit cb6d3d
     * for the next occurrence of that value in A.
Packit cb6d3d
     */
Packit cb6d3d
    ptr=sort_nextmatch(A,ptr);
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  /* We didn't find any matches. */
Packit cb6d3d
  *begin=-1;
Packit cb6d3d
  *end=-1;
Packit cb6d3d
  *offset=-1;
Packit cb6d3d
  return(0);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * STAGE 1 MATCHING
Packit cb6d3d
 *
Packit cb6d3d
 * ???: Insert high-level explanation here.
Packit cb6d3d
 * ===========================================================================
Packit cb6d3d
 */
Packit cb6d3d
Packit cb6d3d
/* Top level of the first stage matcher */
Packit cb6d3d
Packit cb6d3d
/* We match each analysis point of new to the preexisting blocks
Packit cb6d3d
recursively.  We can also optionally maintain a list of fragments of
Packit cb6d3d
the preexisting block that didn't match anything, and match them back
Packit cb6d3d
afterward. */
Packit cb6d3d
Packit cb6d3d
#define OVERLAP_ADJ (MIN_WORDS_OVERLAP/2-1)
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * stage1_matched() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called whenever stage 1 verification finds two identical
Packit cb6d3d
 * runs of samples from different reads.  The runs must be more than
Packit cb6d3d
 * MIN_WORDS_SEARCH samples long.  They may be jittered (i.e. their absolute
Packit cb6d3d
 * positions on the CD may not match due to inaccurate seeking) with respect
Packit cb6d3d
 * to each other, but they have been verified to have no dropped samples
Packit cb6d3d
 * within them.
Packit cb6d3d
 *
Packit cb6d3d
 * This function provides feedback via the callback mechanism and marks the
Packit cb6d3d
 * runs as verified.  The details of the marking are somehwat subtle and
Packit cb6d3d
 * are described near the relevant code.
Packit cb6d3d
 *
Packit cb6d3d
 * Subsequent portions of the stage 1 code will build a verified fragment
Packit cb6d3d
 * from this run.  The verified fragment will eventually be merged
Packit cb6d3d
 * into the verified root (and its absolute position determined) in
Packit cb6d3d
 * stage 2.
Packit cb6d3d
 */
Packit cb6d3d
static inline void
Packit cb6d3d
stage1_matched(c_block_t *old, c_block_t *new,
Packit cb6d3d
	       long matchbegin,long matchend,
Packit cb6d3d
	       long matchoffset,
Packit cb6d3d
	       void (*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
  long i;
Packit cb6d3d
  long oldadjbegin=matchbegin-cb(old);
Packit cb6d3d
  long oldadjend=matchend-cb(old);
Packit cb6d3d
  long newadjbegin=matchbegin-matchoffset-cb(new);
Packit cb6d3d
  long newadjend=matchend-matchoffset-cb(new);
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
  /* Provide feedback via the callback about the samples we've just
Packit cb6d3d
   * verified.
Packit cb6d3d
   *
Packit cb6d3d
   * "???: How can matchbegin ever be < cb(old)?"
Packit cb6d3d
   *      Sorry, old bulletproofing habit.  I often use <= to mean "not >"
Packit cb6d3d
   *      --Monty
Packit cb6d3d
   *
Packit cb6d3d
   * "???: Why do edge samples get logged only when there's jitter
Packit cb6d3d
   * between the matched runs (matchoffset != 0)?"
Packit cb6d3d
   *      FIXUP_EDGE is actually logging a jitter event, not a rift--
Packit cb6d3d
   *      a rift is FIXUP_ATOM --Monty
Packit cb6d3d
   */
Packit cb6d3d
  if ( matchbegin-matchoffset<=cb(new)
Packit cb6d3d
       || matchbegin<=cb(old)
Packit cb6d3d
       || (new->flags[newadjbegin]&FLAGS_EDGE)
Packit cb6d3d
       || (old->flags[oldadjbegin]&FLAGS_EDGE) ) {
Packit cb6d3d
    if ( matchoffset && callback )
Packit cb6d3d
	(*callback)(matchbegin,PARANOIA_CB_FIXUP_EDGE);
Packit cb6d3d
  } else
Packit cb6d3d
    if (callback)
Packit cb6d3d
      (*callback)(matchbegin,PARANOIA_CB_FIXUP_ATOM);
Packit cb6d3d
Packit cb6d3d
  if ( matchend-matchoffset>=ce(new) ||
Packit cb6d3d
       (new->flags[newadjend]&FLAGS_EDGE) ||
Packit cb6d3d
       matchend>=ce(old) ||
Packit cb6d3d
       (old->flags[oldadjend]&FLAGS_EDGE) ) {
Packit cb6d3d
    if ( matchoffset && callback )
Packit cb6d3d
      (*callback)(matchend,PARANOIA_CB_FIXUP_EDGE);
Packit cb6d3d
  } else
Packit cb6d3d
    if (callback)
Packit cb6d3d
      (*callback)(matchend, PARANOIA_CB_FIXUP_ATOM);
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 1
Packit cb6d3d
  fprintf(stderr, "-   Matched [%ld-%ld] against [%ld-%ld]\n",
Packit cb6d3d
	  newadjbegin+cb(new), newadjend+cb(new),
Packit cb6d3d
	  oldadjbegin+cb(old), oldadjend+cb(old));
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  /* Mark verified samples as "verified," but trim the verified region
Packit cb6d3d
   * by OVERLAP_ADJ samples on each side.  There are several significant
Packit cb6d3d
   * implications of this trimming:
Packit cb6d3d
   *
Packit cb6d3d
   * 1) Why we trim at all:  We have to trim to distinguish between two
Packit cb6d3d
   * adjacent verified runs and one long verified run.  We encounter this
Packit cb6d3d
   * situation when samples have been dropped:
Packit cb6d3d
   *
Packit cb6d3d
   *   matched portion of read 1 ....)(.... matched portion of read 1
Packit cb6d3d
   *       read 2 adjacent run  .....)(..... read 2 adjacent run
Packit cb6d3d
   *                                 ||
Packit cb6d3d
   *                      dropped samples in read 2
Packit cb6d3d
   *
Packit cb6d3d
   * So at this point, the fact that we have two adjacent runs means
Packit cb6d3d
   * that we have not yet verified that the two runs really are adjacent.
Packit cb6d3d
   * (In fact, just the opposite:  there are two runs because they were
Packit cb6d3d
   * matched by separate runs, indicating that some samples didn't match
Packit cb6d3d
   * across the length of read 2.)
Packit cb6d3d
   *
Packit cb6d3d
   * If we verify that they are actually adjacent (e.g. if the two runs
Packit cb6d3d
   * are simply a result of matching runs from different reads, not from
Packit cb6d3d
   * dropped samples), we will indeed mark them as one long merged run.
Packit cb6d3d
   *
Packit cb6d3d
   * 2) Why we trim by this amount: We want to ensure that when we
Packit cb6d3d
   * verify the relationship between these two runs, we do so with
Packit cb6d3d
   * an overlapping fragment at least OVERLAP samples long.  Following
Packit cb6d3d
   * from the above example:
Packit cb6d3d
   *
Packit cb6d3d
   *                (..... matched portion of read 3 .....)
Packit cb6d3d
   *       read 2 adjacent run  .....)(..... read 2 adjacent run
Packit cb6d3d
   *
Packit cb6d3d
   * Assuming there were no dropped samples between the adjacent runs,
Packit cb6d3d
   * the matching portion of read 3 will need to be at least OVERLAP
Packit cb6d3d
   * samples long to mark the two runs as one long verified run.
Packit cb6d3d
   * If there were dropped samples, read 3 wouldn't match across the
Packit cb6d3d
   * two runs, proving our caution worthwhile.
Packit cb6d3d
   *
Packit cb6d3d
   * 3) Why we partially discard the work we've done:  We don't.
Packit cb6d3d
   * When subsequently creating verified fragments from this run,
Packit cb6d3d
   * we compensate for this trimming.  Thus the verified fragment will
Packit cb6d3d
   * contain the full length of verified samples.  Only the c_blocks
Packit cb6d3d
   * will reflect this trimming.
Packit cb6d3d
   *
Packit cb6d3d
   * ???: The comment below indicates that the sort cache is updated in
Packit cb6d3d
   * some way, but this does not appear to be the case.
Packit cb6d3d
   */
Packit cb6d3d
Packit cb6d3d
  /* Mark the verification flags.  Don't mark the first or
Packit cb6d3d
     last OVERLAP/2 elements so that overlapping fragments
Packit cb6d3d
     have to overlap by OVERLAP to actually merge. We also
Packit cb6d3d
     remove elements from the sort such that later sorts do
Packit cb6d3d
     not have to sift through already matched data */
Packit cb6d3d
Packit cb6d3d
  newadjbegin+=OVERLAP_ADJ;
Packit cb6d3d
  newadjend-=OVERLAP_ADJ;
Packit cb6d3d
  for(i=newadjbegin;i
Packit cb6d3d
    new->flags[i]|=FLAGS_VERIFIED; /* mark verified */
Packit cb6d3d
Packit cb6d3d
  oldadjbegin+=OVERLAP_ADJ;
Packit cb6d3d
  oldadjend-=OVERLAP_ADJ;
Packit cb6d3d
  for(i=oldadjbegin;i
Packit cb6d3d
    old->flags[i]|=FLAGS_VERIFIED; /* mark verified */
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_iterate_stage1 (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called by i_stage1() to compare newly read samples with
Packit cb6d3d
 * previously read samples, searching for contiguous runs of identical
Packit cb6d3d
 * samples.  Matching runs indicate that at least two reads of the CD
Packit cb6d3d
 * returned identical data, with no dropped samples in that run.
Packit cb6d3d
 * The runs may be jittered (i.e. their absolute positions on the CD may
Packit cb6d3d
 * not be accurate due to inaccurate seeking) at this point.  Their
Packit cb6d3d
 * positions will be determined in stage 2.
Packit cb6d3d
 *
Packit cb6d3d
 * This function compares the new c_block (which has been indexed in
Packit cb6d3d
 * p->sortcache) to a previous c_block.  It is called for each previous
Packit cb6d3d
 * c_block.  It searches for runs of identical samples longer than
Packit cb6d3d
 * MIN_WORDS_SEARCH.  Samples in matched runs are marked as verified.
Packit cb6d3d
 *
Packit cb6d3d
 * Subsequent stage 1 code builds verified fragments from the runs of
Packit cb6d3d
 * verified samples.  These fragments are merged into the verified root
Packit cb6d3d
 * in stage 2.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns the number of distinct runs verified in the new
Packit cb6d3d
 * c_block when compared against this old c_block.
Packit cb6d3d
 */
Packit cb6d3d
static long int
Packit cb6d3d
i_iterate_stage1(cdrom_paranoia_t *p, c_block_t *old, c_block_t *new,
Packit cb6d3d
		 void(*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
  long matchbegin = -1;
Packit cb6d3d
  long matchend   = -1;
Packit cb6d3d
  long matchoffset;
Packit cb6d3d
Packit cb6d3d
  /* "???: Why do we limit our search only to the samples with overlapping
Packit cb6d3d
   * absolute positions?  It could be because it eliminates some further
Packit cb6d3d
   * bounds checking."
Packit cb6d3d
   *  Short answer is yes --Monty
Packit cb6d3d
   *
Packit cb6d3d
   * "Why do we "no longer try to spread the ... search" as mentioned
Packit cb6d3d
   * below?"
Packit cb6d3d
   * The search is normally much faster without the spread,
Packit cb6d3d
   * even in heavy jitter.  Dynoverlap tends to be a bigger deal in
Packit cb6d3d
   * stage 2. --Monty
Packit cb6d3d
   */
Packit cb6d3d
Packit cb6d3d
  /* we no longer try to spread the stage one search area by dynoverlap */
Packit cb6d3d
  long searchend   = min(ce(old), ce(new));
Packit cb6d3d
  long searchbegin = max(cb(old), cb(new));
Packit cb6d3d
  long searchsize  = searchend-searchbegin;
Packit cb6d3d
  sort_info_t *i = p->sortcache;
Packit cb6d3d
  long ret = 0;
Packit cb6d3d
  long int j;
Packit cb6d3d
Packit cb6d3d
  long tried = 0;
Packit cb6d3d
  long matched = 0;
Packit cb6d3d
Packit cb6d3d
  if (searchsize<=0)
Packit cb6d3d
    return(0);
Packit cb6d3d
Packit cb6d3d
  /* match return values are in terms of the new vector, not old */
Packit cb6d3d
  /* "???: Why 23?" Odd, prime number --Monty  */
Packit cb6d3d
Packit cb6d3d
  for (j=searchbegin; j
Packit cb6d3d
Packit cb6d3d
    /* Skip past any samples verified in previous comparisons to
Packit cb6d3d
     * other old c_blocks.  Also, obviously, don't bother verifying
Packit cb6d3d
     * unread/unmatchable samples.
Packit cb6d3d
     */
Packit cb6d3d
    if ((new->flags[j-cb(new)] & (FLAGS_VERIFIED|FLAGS_UNREAD)) == 0) {
Packit cb6d3d
      tried++;
Packit cb6d3d
Packit cb6d3d
      /* Starting from the sample in the old c_block with the absolute
Packit cb6d3d
       * position j, look for a matching run in the new c_block.  This
Packit cb6d3d
       * search will look a certain distance around j, and if successful
Packit cb6d3d
       * will extend the matching run as far backward and forward as
Packit cb6d3d
       * it can.
Packit cb6d3d
       *
Packit cb6d3d
       * The search will only return 1 if it finds a matching run long
Packit cb6d3d
       * enough to be deemed significant.
Packit cb6d3d
       */
Packit cb6d3d
      if (try_sort_sync(p, i, new->flags, old, j,
Packit cb6d3d
			&matchbegin, &matchend, &matchoffset,
Packit cb6d3d
			callback) == 1) {
Packit cb6d3d
Packit cb6d3d
	matched+=matchend-matchbegin;
Packit cb6d3d
Packit cb6d3d
	/* purely cosmetic: if we're matching zeros, don't use the
Packit cb6d3d
           callback because they will appear to be all skewed */
Packit cb6d3d
	{
Packit cb6d3d
	  long j = matchbegin-cb(old);
Packit cb6d3d
	  long end = matchend-cb(old);
Packit cb6d3d
	  for (; j
Packit cb6d3d
Packit cb6d3d
	  /* Mark the matched samples in both c_blocks as verified.
Packit cb6d3d
	   * In reality, not all the samples are marked.  See
Packit cb6d3d
	   * stage1_matched() for details.
Packit cb6d3d
	   */
Packit cb6d3d
	  if (j
Packit cb6d3d
	    stage1_matched(old,new,matchbegin,matchend,matchoffset,callback);
Packit cb6d3d
	  } else {
Packit cb6d3d
	    stage1_matched(old,new,matchbegin,matchend,matchoffset,NULL);
Packit cb6d3d
	  }
Packit cb6d3d
	}
Packit cb6d3d
	ret++;
Packit cb6d3d
Packit cb6d3d
	/* Skip past this verified run to look for more matches. */
Packit cb6d3d
	if (matchend-1 > j)
Packit cb6d3d
	  j = matchend-1;
Packit cb6d3d
      }
Packit cb6d3d
    }
Packit cb6d3d
  } /* end for */
Packit cb6d3d
Packit cb6d3d
#ifdef NOISY
Packit cb6d3d
  fprintf(stderr,"iterate_stage1: search area=%ld[%ld-%ld] tried=%ld matched=%ld spans=%ld\n",
Packit cb6d3d
	  searchsize,searchbegin,searchend,tried,matched,ret);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  return(ret);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_stage1() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * Compare newly read samples against previously read samples, searching
Packit cb6d3d
 * for contiguous runs of identical samples.  Matching runs indicate that
Packit cb6d3d
 * at least two reads of the CD returned identical data, with no dropped
Packit cb6d3d
 * samples in that run.  The runs may be jittered (i.e. their absolute
Packit cb6d3d
 * positions on the CD may not be accurate due to inaccurate seeking) at
Packit cb6d3d
 * this point.  Their positions will be determined in stage 2.
Packit cb6d3d
 *
Packit cb6d3d
 * This function compares a new c_block against all other c_blocks in memory,
Packit cb6d3d
 * searching for sufficiently long runs of identical samples.  Since each
Packit cb6d3d
 * c_block represents a separate call to read_c_block, this ensures that
Packit cb6d3d
 * multiple reads have returned identical data.  (Additionally, read_c_block
Packit cb6d3d
 * varies the reads so that multiple reads are unlikely to produce identical
Packit cb6d3d
 * errors, so any matches between reads are considered verified.  See
Packit cb6d3d
 * i_read_c_block for more details.)
Packit cb6d3d
 *
Packit cb6d3d
 * Each time we find such a  run (longer than MIN_WORDS_SEARCH), we mark
Packit cb6d3d
 * the samples as "verified" in both c_blocks.  Runs of verified samples in
Packit cb6d3d
 * the new c_block are promoted into verified fragments, which will later
Packit cb6d3d
 * be merged into the verified root in stage 2.
Packit cb6d3d
 *
Packit cb6d3d
 * In reality, not all the verified samples are marked as "verified."
Packit cb6d3d
 * See stage1_matched() for an explanation.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns the number of verified fragments created by the
Packit cb6d3d
 * stage 1 matching.
Packit cb6d3d
 */
Packit cb6d3d
static long int
Packit cb6d3d
i_stage1(cdrom_paranoia_t *p, c_block_t *p_new,
Packit cb6d3d
	 void (*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
  long size=cs(p_new);
Packit cb6d3d
  c_block_t *ptr=c_last(p);
Packit cb6d3d
  int ret=0;
Packit cb6d3d
  long int begin=0;
Packit cb6d3d
  long int end;
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 1
Packit cb6d3d
  long int block_count = 0;
Packit cb6d3d
  fprintf(stderr,
Packit cb6d3d
	  "Verifying block %ld:[%ld-%ld] against previously read blocks...\n",
Packit cb6d3d
	  p->cache->active,
Packit cb6d3d
	  cb(p_new), ce(p_new));
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  /* We're going to be comparing the new c_block against the other
Packit cb6d3d
   * c_blocks in memory.  Initialize the "sort cache" index to allow
Packit cb6d3d
   * for fast searching through the new c_block.  (The index will
Packit cb6d3d
   * actually be built the first time we search.)
Packit cb6d3d
   */
Packit cb6d3d
  if (ptr)
Packit cb6d3d
    sort_setup( p->sortcache, cv(p_new), &cb(p_new), cs(p_new), cb(p_new),
Packit cb6d3d
		ce(p_new) );
Packit cb6d3d
Packit cb6d3d
  /* Iterate from oldest to newest c_block, comparing the new c_block
Packit cb6d3d
   * to each, looking for a sufficiently long run of identical samples
Packit cb6d3d
   * (longer than MIN_WORDS_SEARCH), which will be marked as "verified"
Packit cb6d3d
   * in both c_blocks.
Packit cb6d3d
   *
Packit cb6d3d
   * Since the new c_block is already in the list (at the head), don't
Packit cb6d3d
   * compare it against itself.
Packit cb6d3d
   */
Packit cb6d3d
  while ( ptr && ptr != p_new ) {
Packit cb6d3d
#if TRACE_PARANOIA & 1
Packit cb6d3d
    block_count++;
Packit cb6d3d
    fprintf(stderr,
Packit cb6d3d
	    "- Verifying against block %ld:[%ld-%ld] dynoverlap=%ld\n",
Packit cb6d3d
	    block_count, cb(ptr), ce(ptr), p->dynoverlap);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
    if (callback)
Packit cb6d3d
      (*callback)(cb(p_new), PARANOIA_CB_VERIFY);
Packit cb6d3d
    i_iterate_stage1(p,ptr,p_new,callback);
Packit cb6d3d
Packit cb6d3d
    ptr=c_prev(ptr);
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  /* parse the verified areas of p_new into v_fragments */
Packit cb6d3d
Packit cb6d3d
  /* Find each run of contiguous verified samples in the new c_block
Packit cb6d3d
   * and create a verified fragment from each run.
Packit cb6d3d
   */
Packit cb6d3d
  begin=0;
Packit cb6d3d
  while (begin
Packit cb6d3d
    for ( ; begin < size; begin++)
Packit cb6d3d
      if (p_new->flags[begin]&FLAGS_VERIFIED) break;
Packit cb6d3d
    for (end=begin; end < size; end++)
Packit cb6d3d
      if ((p_new->flags[end]&FLAGS_VERIFIED)==0) break;
Packit cb6d3d
    if (begin>=size) break;
Packit cb6d3d
Packit cb6d3d
    ret++;
Packit cb6d3d
Packit cb6d3d
    /* We create a new verified fragment from the contiguous run
Packit cb6d3d
     * of verified samples.
Packit cb6d3d
     *
Packit cb6d3d
     * We expand the "verified" range by OVERLAP_ADJ on each side
Packit cb6d3d
     * to compensate for trimming done to the verified range by
Packit cb6d3d
     * stage1_matched().  The samples were actually verified, and
Packit cb6d3d
     * hence belong in the verified fragment.  See stage1_matched()
Packit cb6d3d
     * for an explanation of the trimming.
Packit cb6d3d
     */
Packit cb6d3d
    new_v_fragment(p,p_new,cb(p_new)+max(0,begin-OVERLAP_ADJ),
Packit cb6d3d
		   cb(p_new)+min(size,end+OVERLAP_ADJ),
Packit cb6d3d
		   (end+OVERLAP_ADJ>=size && p_new->lastsector));
Packit cb6d3d
Packit cb6d3d
    begin=end;
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  /* Return the number of distinct verified fragments we found with
Packit cb6d3d
   * stage 1 matching.
Packit cb6d3d
   */
Packit cb6d3d
  return(ret);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * STAGE 2 MATCHING
Packit cb6d3d
 *
Packit cb6d3d
 * ???: Insert high-level explanation here.
Packit cb6d3d
 * ===========================================================================
Packit cb6d3d
 */
Packit cb6d3d
Packit cb6d3d
typedef struct sync_result {
Packit cb6d3d
  long offset;
Packit cb6d3d
  long begin;
Packit cb6d3d
  long end;
Packit cb6d3d
} sync_result_t;
Packit cb6d3d
Packit cb6d3d
/* Reconcile v_fragments to root buffer.  Free if matched, fragment/fixup root
Packit cb6d3d
   if necessary.
Packit cb6d3d
Packit cb6d3d
   Do *not* match using zero posts
Packit cb6d3d
*/
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_iterate_stage2 (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function searches for a sufficiently long run of identical samples
Packit cb6d3d
 * between the passed verified fragment and the verified root.  The search
Packit cb6d3d
 * is similar to that performed by i_iterate_stage1.  Of course, what we do
Packit cb6d3d
 * as a result of a match is different.
Packit cb6d3d
 *
Packit cb6d3d
 * Our search is slightly different in that we refuse to match silence to
Packit cb6d3d
 * silence.  All silence looks alike, and it would result in too many false
Packit cb6d3d
 * positives here, so we handle silence separately.
Packit cb6d3d
 *
Packit cb6d3d
 * Also, because we're trying to determine whether this fragment as a whole
Packit cb6d3d
 * overlaps with the root at all, we narrow our search (since it should match
Packit cb6d3d
 * immediately or not at all).  This is in contrast to stage 1, where we
Packit cb6d3d
 * search the entire vector looking for all possible matches.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns 0 if no match was found (including failure to find
Packit cb6d3d
 * one due to silence), or 1 if we found a match.
Packit cb6d3d
 *
Packit cb6d3d
 * When a match is found, the sync_result_t is set to the boundaries of
Packit cb6d3d
 * matching run (begin/end, in terms of the root) and how far out of sync
Packit cb6d3d
 * the fragment is from the canonical root (offset).  Note that this offset
Packit cb6d3d
 * is opposite in sign from the notion of offset used by try_sort_sync()
Packit cb6d3d
 * and stage 1 generally.
Packit cb6d3d
 */
Packit cb6d3d
static long int
Packit cb6d3d
i_iterate_stage2(cdrom_paranoia_t *p,
Packit cb6d3d
		 v_fragment_t *v,
Packit cb6d3d
		 sync_result_t *r,
Packit cb6d3d
		 void(*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
  root_block *root=&(p->root);
Packit cb6d3d
  long matchbegin=-1,matchend=-1,offset;
Packit cb6d3d
  long fbv,fev;
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
  fprintf(stderr, "- Comparing fragment [%ld-%ld] to root [%ld-%ld]...",
Packit cb6d3d
	  fb(v), fe(v), rb(root), re(root));
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
#ifdef NOISY
Packit cb6d3d
      fprintf(stderr,"Stage 2 search: fbv=%ld fev=%ld\n",fb(v),fe(v));
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  /* Quickly check whether there could possibly be any overlap between
Packit cb6d3d
   * the verified fragment and the root.  Our search will allow up to
Packit cb6d3d
   * (p->dynoverlap) jitter between the two, so we expand the fragment
Packit cb6d3d
   * search area by p->dynoverlap on both sides and see if that expanded
Packit cb6d3d
   * area overlaps with the root.
Packit cb6d3d
   *
Packit cb6d3d
   * We could just as easily expand root's boundaries by p->dynoverlap
Packit cb6d3d
   * instead and achieve the same result.
Packit cb6d3d
   */
Packit cb6d3d
  if (min(fe(v) + p->dynoverlap,re(root)) -
Packit cb6d3d
    max(fb(v) - p->dynoverlap,rb(root)) <= 0)
Packit cb6d3d
    return(0);
Packit cb6d3d
Packit cb6d3d
  if (callback)
Packit cb6d3d
    (*callback)(fb(v), PARANOIA_CB_VERIFY);
Packit cb6d3d
Packit cb6d3d
  /* We're going to try to match the fragment to the root while allowing
Packit cb6d3d
   * for p->dynoverlap jitter, so we'll actually be looking at samples
Packit cb6d3d
   * in the fragment whose position claims to be up to p->dynoverlap
Packit cb6d3d
   * outside the boundaries of the root.  But, of course, don't extend
Packit cb6d3d
   * past the edges of the fragment.
Packit cb6d3d
   */
Packit cb6d3d
  fbv = max(fb(v), rb(root)-p->dynoverlap);
Packit cb6d3d
Packit cb6d3d
  /* Skip past leading zeroes in the fragment, and bail if there's nothing
Packit cb6d3d
   * but silence.  We handle silence later separately.
Packit cb6d3d
   */
Packit cb6d3d
  while (fbv
Packit cb6d3d
    fbv++;
Packit cb6d3d
  if (fbv == fe(v))
Packit cb6d3d
    return(0);
Packit cb6d3d
Packit cb6d3d
  /* This is basically the same idea as the initial calculation for fbv
Packit cb6d3d
   * above.  Look at samples up to p->dynoverlap outside the boundaries
Packit cb6d3d
   * of the root, but don't extend past the edges of the fragment.
Packit cb6d3d
   *
Packit cb6d3d
   * However, we also limit the search to no more than 256 samples.
Packit cb6d3d
   * Unlike stage 1, we're not trying to find all possible matches within
Packit cb6d3d
   * two runs -- rather, we're trying to see if the fragment as a whole
Packit cb6d3d
   * overlaps with the root.  If we can't find a match within 256 samples,
Packit cb6d3d
   * there's probably no match to be found (because this fragment doesn't
Packit cb6d3d
   * overlap with the root).
Packit cb6d3d
   *
Packit cb6d3d
   * "??? Is this why?  Why 256?" 256 is simply a 'large enough number'. --Monty
Packit cb6d3d
   */
Packit cb6d3d
  fev = min(min(fbv+256, re(root)+p->dynoverlap), fe(v));
Packit cb6d3d
Packit cb6d3d
  {
Packit cb6d3d
    /* Because we'll allow for up to (p->dynoverlap) jitter between the
Packit cb6d3d
     * fragment and the root, we expand the search area (fbv to fev) by
Packit cb6d3d
     * p->dynoverlap on both sides.  But, because we're iterating through
Packit cb6d3d
     * root, we need to constrain the search area not to extend beyond
Packit cb6d3d
     * the root's boundaries.
Packit cb6d3d
     */
Packit cb6d3d
    long searchend=min(fev+p->dynoverlap,re(root));
Packit cb6d3d
    long searchbegin=max(fbv-p->dynoverlap,rb(root));
Packit cb6d3d
    sort_info_t *i=p->sortcache;
Packit cb6d3d
    long j;
Packit cb6d3d
    long min_matchbegin = -1;
Packit cb6d3d
    long min_matchend = -1;
Packit cb6d3d
    long min_offset = LONG_MAX;
Packit cb6d3d
Packit cb6d3d
    /* Initialize the "sort cache" index to allow for fast searching
Packit cb6d3d
     * through the verified fragment between (fbv,fev).  (The index will
Packit cb6d3d
     * actually be built the first time we search.)
Packit cb6d3d
     */
Packit cb6d3d
    sort_setup(i, fv(v), &fb(v), fs(v), fbv, fev);
Packit cb6d3d
Packit cb6d3d
    /* ??? Why 23? */
Packit cb6d3d
    for(j=searchbegin; j
Packit cb6d3d
Packit cb6d3d
      /* Skip past silence in the root.  If there are just a few silent
Packit cb6d3d
       * samples, the effect is minimal.  The real reason we need this is
Packit cb6d3d
       * for large regions of silence.  All silence looks alike, so you
Packit cb6d3d
       * could false-positive "match" two runs of silence that are either
Packit cb6d3d
       * unrelated or ought to be jittered, and try_sort_sync can't
Packit cb6d3d
       * accurately determine jitter (offset) from silence.
Packit cb6d3d
       *
Packit cb6d3d
       * Therefore, we want to post on a non-zero sample.  If there's
Packit cb6d3d
       * nothing but silence left in the root, bail.  We don't want
Packit cb6d3d
       * to match it here.
Packit cb6d3d
       */
Packit cb6d3d
      while (j
Packit cb6d3d
      if (j==searchend) break;
Packit cb6d3d
Packit cb6d3d
      /* Starting from the (non-zero) sample in the root with the absolute
Packit cb6d3d
       * position j, look for a matching run in the verified fragment.  This
Packit cb6d3d
       * search will look a certain distance around j, and if successful
Packit cb6d3d
       * will extend the matching run as far backward and forward as
Packit cb6d3d
       * it can.
Packit cb6d3d
       *
Packit cb6d3d
       * The search will only return 1 if it finds a matching run long
Packit cb6d3d
       * enough to be deemed significant.  Note that the search is limited
Packit cb6d3d
       * by the boundaries given to sort_setup() above.
Packit cb6d3d
       *
Packit cb6d3d
       * Note also that flags aren't used in stage 2 (since neither verified
Packit cb6d3d
       * fragments nor the root have them).
Packit cb6d3d
       */
Packit cb6d3d
      if (try_sort_sync(p, i, NULL, rc(root), j, &matchbegin,&matchend,&offset,callback)){
Packit cb6d3d
        if(labs(offset) < labs(min_offset)) {
Packit cb6d3d
          min_matchbegin = matchbegin;
Packit cb6d3d
          min_matchend = matchend;
Packit cb6d3d
          min_offset = offset;
Packit cb6d3d
          if(min_offset >= 0) {
Packit cb6d3d
            /* We will never find a smaller offset by continuing */
Packit cb6d3d
            break;
Packit cb6d3d
          }
Packit cb6d3d
        }
Packit cb6d3d
      }
Packit cb6d3d
    }
Packit cb6d3d
    /* If we found a matching run, we return the results of our match.
Packit cb6d3d
     *
Packit cb6d3d
     * Note that we flip the sign of (offset) because try_sort_sync()
Packit cb6d3d
     * returns it in terms of the fragment (i.e. what we add
Packit cb6d3d
     * to the fragment's position to yield the corresponding position
Packit cb6d3d
     * in the root), but here we consider the root to be canonical,
Packit cb6d3d
     * and so our returned "offset" reflects how the fragment is offset
Packit cb6d3d
     * from the root.
Packit cb6d3d
     *
Packit cb6d3d
     * E.g.: If the fragment's sample 10 corresponds to root's 12,
Packit cb6d3d
     * try_sort_sync() would return 2.  But since root is canonical,
Packit cb6d3d
     * we say that the fragment is off by -2.
Packit cb6d3d
     */
Packit cb6d3d
   if(min_offset != LONG_MAX) {
Packit cb6d3d
      r->begin=min_matchbegin;
Packit cb6d3d
      r->end=min_matchend;
Packit cb6d3d
      r->offset=-min_offset;
Packit cb6d3d
      if(min_offset)if(callback)(*callback)(r->begin,PARANOIA_CB_FIXUP_EDGE);
Packit cb6d3d
      return(1);
Packit cb6d3d
    }
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  return(0);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_silence_test() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * If the entire root is silent, or there's enough trailing silence
Packit cb6d3d
 * to be significant (MIN_SILENCE_BOUNDARY samples), mark the beginning
Packit cb6d3d
 * of the silence and "light" the silence flag.  This flag will remain lit
Packit cb6d3d
 * until i_silence_match() appends some non-silent samples to the root.
Packit cb6d3d
 *
Packit cb6d3d
 * We do this because if there's a long enough span of silence, we can't
Packit cb6d3d
 * reliably detect jitter or dropped samples within that span.  See
Packit cb6d3d
 * i_silence_match() for details on how we recover from this situation.
Packit cb6d3d
 */
Packit cb6d3d
static void
Packit cb6d3d
i_silence_test(root_block *root)
Packit cb6d3d
{
Packit cb6d3d
  int16_t *vec=rv(root);
Packit cb6d3d
  long end=re(root)-rb(root)-1;
Packit cb6d3d
  long j;
Packit cb6d3d
Packit cb6d3d
  /* Look backward from the end of the root to find the first non-silent
Packit cb6d3d
   * sample.
Packit cb6d3d
   */
Packit cb6d3d
  for(j=end-1;j>=0;j--)
Packit cb6d3d
    if (vec[j]!=0) break;
Packit cb6d3d
Packit cb6d3d
  /* If the entire root is silent, or there's enough trailing silence
Packit cb6d3d
   * to be significant, mark the beginning of the silence and "light"
Packit cb6d3d
   * the silence flag.
Packit cb6d3d
   */
Packit cb6d3d
  if (j<0 || end-j>MIN_SILENCE_BOUNDARY) {
Packit cb6d3d
    /* ???BUG???:
Packit cb6d3d
     *
Packit cb6d3d
     * The original code appears to have a bug, as it points to the
Packit cb6d3d
     * last non-zero sample, and silence matching appears to treat
Packit cb6d3d
     * silencebegin as the first silent sample.  As a result, in certain
Packit cb6d3d
     * situations, the last non-zero sample can get clobbered.
Packit cb6d3d
     *
Packit cb6d3d
     * This bug has been tentatively fixed, since it allows more regression
Packit cb6d3d
     * tests to pass.  The original code was:
Packit cb6d3d
     *   if (j<0)j=0;
Packit cb6d3d
     */
Packit cb6d3d
    j++;
Packit cb6d3d
Packit cb6d3d
    root->silenceflag=1;
Packit cb6d3d
    root->silencebegin=rb(root)+j;
Packit cb6d3d
Packit cb6d3d
    /* ???: To be studied. */
Packit cb6d3d
    if (root->silencebegin<root->returnedlimit)
Packit cb6d3d
      root->silencebegin=root->returnedlimit;
Packit cb6d3d
  }
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_silence_match() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function is merges verified fragments into the verified root in cases
Packit cb6d3d
 * where there is a problematic amount of silence (MIN_SILENCE_BOUNDARY
Packit cb6d3d
 * samples) at the end of the root.
Packit cb6d3d
 *
Packit cb6d3d
 * We need a special approach because if there's a long enough span of
Packit cb6d3d
 * silence, we can't reliably detect jitter or dropped samples within that
Packit cb6d3d
 * span (since all silence looks alike).
Packit cb6d3d
 *
Packit cb6d3d
 * Only fragments that begin with MIN_SILENCE_BOUNDARY samples are eligible
Packit cb6d3d
 * to be merged in this case.  Fragments that are too far beyond the edge
Packit cb6d3d
 * of the root to possibly overlap are also disregarded.
Packit cb6d3d
 *
Packit cb6d3d
 * Our first approach is to assume that such fragments have no jitter (since
Packit cb6d3d
 * we can't establish otherwise) and merge them.  However, if it's clear
Packit cb6d3d
 * that there must be jitter (i.e. because non-silent samples overlap when
Packit cb6d3d
 * we assume no jitter), we assume the fragment has the minimum possible
Packit cb6d3d
 * jitter and then merge it.
Packit cb6d3d
 *
Packit cb6d3d
 * This function extends silence fairly aggressively, so it must be called
Packit cb6d3d
 * with fragments in ascending order (beginning position) in case there are
Packit cb6d3d
 * small non-silent regions within the silence.
Packit cb6d3d
 */
Packit cb6d3d
static long int
Packit cb6d3d
i_silence_match(root_block *root, v_fragment_t *v,
Packit cb6d3d
		void(*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
Packit cb6d3d
  cdrom_paranoia_t *p=v->p;
Packit cb6d3d
  int16_t *vec=fv(v);
Packit cb6d3d
  long end=fs(v),begin;
Packit cb6d3d
  long j;
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
  fprintf(stderr, "- Silence matching fragment [%ld-%ld] to root [%ld-%ld]"
Packit cb6d3d
	  " silencebegin=%ld\n",
Packit cb6d3d
	  fb(v), fe(v), rb(root), re(root), root->silencebegin);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  /* See how much leading silence this fragment has.  If there are fewer than
Packit cb6d3d
   * MIN_SILENCE_BOUNDARY leading silent samples, we don't do this special
Packit cb6d3d
   * silence matching.
Packit cb6d3d
   *
Packit cb6d3d
   * This fragment could actually belong here, but we can't be sure unless
Packit cb6d3d
   * it has enough silence on its leading edge.  This fragment will likely
Packit cb6d3d
   * stick around until we do successfully extend the root, at which point
Packit cb6d3d
   * it will be merged using the usual method.
Packit cb6d3d
   */
Packit cb6d3d
  if (end
Packit cb6d3d
  for(j=0;j
Packit cb6d3d
    if (vec[j]!=0) break;
Packit cb6d3d
  if (j
Packit cb6d3d
Packit cb6d3d
  /* Convert the offset of the first non-silent sample to an absolute
Packit cb6d3d
   * position.  For the time being, we will assume that this position
Packit cb6d3d
   * is accurate, with no jitter.
Packit cb6d3d
   */
Packit cb6d3d
  j+=fb(v);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
  fprintf(stderr, "- Fragment begins with silence [%ld-%ld]\n", fb(v), j);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  /* If this fragment is ahead of the root, see if that could just be due
Packit cb6d3d
   * to jitter (if it's within p->dynoverlap samples of the end of root).
Packit cb6d3d
   */
Packit cb6d3d
  if (fb(v)>=re(root) && fb(v)-p->dynoverlap
Packit cb6d3d
Packit cb6d3d
    /* This fragment is within jitter range of the root, so we extend the
Packit cb6d3d
     * root's silence so that it overlaps with this fragment.  At this point
Packit cb6d3d
     * we know that the fragment has at least MIN_SILENCE_BOUNDARY silent
Packit cb6d3d
     * samples at the beginning, so we overlap by that amount.
Packit cb6d3d
     */
Packit cb6d3d
    long addto   = fb(v) + MIN_SILENCE_BOUNDARY - re(root);
Packit cb6d3d
    int16_t *vec = calloc(addto, sizeof(int16_t));
Packit cb6d3d
    c_append(rc(root), vec, addto);
Packit cb6d3d
    free(vec);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
    fprintf(stderr, "* Adding silence [%ld-%ld] to root\n",
Packit cb6d3d
	    re(root)-addto, re(root));
Packit cb6d3d
#endif
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  /* Calculate the overlap of the root's trailing silence and the fragment's
Packit cb6d3d
   * leading silence.  (begin,end) are the boundaries of that overlap.
Packit cb6d3d
   */
Packit cb6d3d
  begin = max(fb(v),root->silencebegin);
Packit cb6d3d
  end = min(j,re(root));
Packit cb6d3d
Packit cb6d3d
  /* If there is an overlap, we assume that both the root and the fragment
Packit cb6d3d
   * are jitter-free (since there's no way for us to tell otherwise).
Packit cb6d3d
   */
Packit cb6d3d
  if (begin
Packit cb6d3d
Packit cb6d3d
    /* If the fragment will extend the root, then we append it to the root.
Packit cb6d3d
     * Otherwise, no merging is necessary, as the fragment should already
Packit cb6d3d
     * be contained within the root.
Packit cb6d3d
     */
Packit cb6d3d
    if (fe(v)>re(root)){
Packit cb6d3d
      long int voff = begin-fb(v);
Packit cb6d3d
Packit cb6d3d
      /* Truncate the overlapping silence from the end of the root.
Packit cb6d3d
       */
Packit cb6d3d
      c_remove(rc(root),begin-rb(root),-1);
Packit cb6d3d
Packit cb6d3d
      /* Append the fragment to the root, starting from the point of overlap.
Packit cb6d3d
       */
Packit cb6d3d
      c_append(rc(root),vec+voff,fs(v)-voff);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
      fprintf(stderr, "* Adding [%ld-%ld] to root (no jitter)\n",
Packit cb6d3d
	      begin, re(root));
Packit cb6d3d
#endif
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* Record the fact that we merged this fragment assuming zero jitter.
Packit cb6d3d
     */
Packit cb6d3d
    offset_add_value(p,&p->stage2,0,callback);
Packit cb6d3d
Packit cb6d3d
  } else {
Packit cb6d3d
Packit cb6d3d
    /* We weren't able to merge the fragment assuming zero jitter.
Packit cb6d3d
     *
Packit cb6d3d
     * Check whether the fragment's leading silence ends before the root's
Packit cb6d3d
     * trailing silence begins.  If it does, we assume that the root is
Packit cb6d3d
     * jittered forward.
Packit cb6d3d
     */
Packit cb6d3d
    if (j
Packit cb6d3d
Packit cb6d3d
      /* We're going to append the non-silent samples of the fragment
Packit cb6d3d
       * to the root where its silence begins.
Packit cb6d3d
       *
Packit cb6d3d
       * "??? This seems to be a very strange approach.  At this point
Packit cb6d3d
       *  the root has a lot of trailing silence, and the fragment has
Packit cb6d3d
       *  the lot of leading silence.  This merge will drop the silence
Packit cb6d3d
       *  and just splice the non-silence together.
Packit cb6d3d
       *
Packit cb6d3d
       *  In theory, rift analysis will either confirm or fix this result.
Packit cb6d3d
       *  What circumstances motivated this approach?"
Packit cb6d3d
       *
Packit cb6d3d
       * This is an 'all bets are off' situation and we choose to make
Packit cb6d3d
       * the best guess we can, based on absolute position being
Packit cb6d3d
       * returned by the most recent reads.  There are drives that
Packit cb6d3d
       * will randomly lose what they're doing during a read and just
Packit cb6d3d
       * pad out the results with zeros and return no error.  This at
Packit cb6d3d
       * least has a shot of addressing that situation. --Monty
Packit cb6d3d
       */
Packit cb6d3d
Packit cb6d3d
      /* Compute the amount of silence at the beginning of the fragment.
Packit cb6d3d
       */
Packit cb6d3d
      long voff = j - fb(v);
Packit cb6d3d
Packit cb6d3d
      /* If attaching the non-silent tail of the fragment to the end
Packit cb6d3d
       * of the non-silent portion of the root will extend the root,
Packit cb6d3d
       * then we'll append the samples to the root.  Otherwise, no
Packit cb6d3d
       * merging is necessary, as the fragment should already be contained
Packit cb6d3d
       * within the root.
Packit cb6d3d
       */
Packit cb6d3d
      if (begin+fs(v)-voff>re(root)) {
Packit cb6d3d
Packit cb6d3d
	/* Truncate the trailing silence from the root.
Packit cb6d3d
	 */
Packit cb6d3d
	c_remove(rc(root),root->silencebegin-rb(root),-1);
Packit cb6d3d
Packit cb6d3d
	/* Append the non-silent tail of the fragment to the root.
Packit cb6d3d
	 */
Packit cb6d3d
	c_append(rc(root),vec+voff,fs(v)-voff);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
	fprintf(stderr, "* Adding [%ld-%ld] to root (jitter=%ld)\n",
Packit cb6d3d
		root->silencebegin, re(root), end-begin);
Packit cb6d3d
#endif
Packit cb6d3d
      }
Packit cb6d3d
Packit cb6d3d
      /* Record the fact that we merged this fragment assuming (end-begin)
Packit cb6d3d
       * jitter.
Packit cb6d3d
       */
Packit cb6d3d
      offset_add_value(p,&p->stage2,end-begin,callback);
Packit cb6d3d
Packit cb6d3d
    } else
Packit cb6d3d
Packit cb6d3d
      /* We only get here if the fragment is past the end of the root,
Packit cb6d3d
       * which means it must be farther than (dynoverlap) away, due to our
Packit cb6d3d
       * root extension above.
Packit cb6d3d
       */
Packit cb6d3d
Packit cb6d3d
      /* We weren't able to merge this fragment into the root after all.
Packit cb6d3d
       */
Packit cb6d3d
      return(0);
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
  /* We only get here if we merged the fragment into the root.  Update
Packit cb6d3d
   * the root's silence flag.
Packit cb6d3d
   *
Packit cb6d3d
   * Note that this is the only place silenceflag is reset.  In other words,
Packit cb6d3d
   * once i_silence_test() lights the silence flag, it can only be reset
Packit cb6d3d
   * by i_silence_match().
Packit cb6d3d
   */
Packit cb6d3d
  root->silenceflag = 0;
Packit cb6d3d
Packit cb6d3d
  /* Now see if the new, extended root ends in silence.
Packit cb6d3d
   */
Packit cb6d3d
  i_silence_test(root);
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
  /* Since we merged the fragment, we can free it now.  But first we propagate
Packit cb6d3d
   * its lastsector flag.
Packit cb6d3d
   */
Packit cb6d3d
  if (v->lastsector) root->lastsector=1;
Packit cb6d3d
  free_v_fragment(v);
Packit cb6d3d
  return(1);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_stage2_each (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function (which is entirely too long) attempts to merge the passed
Packit cb6d3d
 * verified fragment into the verified root.
Packit cb6d3d
 *
Packit cb6d3d
 * First this function looks for a run of identical samples between
Packit cb6d3d
 * the root and the fragment.  If it finds a long enough run, it then
Packit cb6d3d
 * checks for "rifts" (see below) and fixes the root and/or fragment as
Packit cb6d3d
 * necessary.  Finally, if the fragment will extend the tail of the root,
Packit cb6d3d
 * we merge the fragment and extend the root.
Packit cb6d3d
 *
Packit cb6d3d
 * Most of the ugliness in this function has to do with handling "rifts",
Packit cb6d3d
 * which are points of disagreement between the root and the verified
Packit cb6d3d
 * fragment.  This can happen when a drive consistently drops a few samples
Packit cb6d3d
 * or stutters and repeats a few samples.  It has to be consistent enough
Packit cb6d3d
 * to result in a verified fragment (i.e. it happens twice), but inconsistent
Packit cb6d3d
 * enough (e.g. due to the jiggled reads) not to happen every time.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns 1 if the fragment was successfully merged into the
Packit cb6d3d
 * root, and 0 if not.
Packit cb6d3d
 */
Packit cb6d3d
static long int
Packit cb6d3d
i_stage2_each(root_block *root, v_fragment_t *v,
Packit cb6d3d
	      void(*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
Packit cb6d3d
  /* If this fragment has already been merged & freed, abort. */
Packit cb6d3d
  if (!v || !v->one) return(0);
Packit cb6d3d
Packit cb6d3d
  cdrom_paranoia_t *p=v->p;
Packit cb6d3d
Packit cb6d3d
  /* "??? Why do we round down to an even dynoverlap?" Dynoverlap is
Packit cb6d3d
     in samples, not stereo frames --Monty */
Packit cb6d3d
  long dynoverlap=p->dynoverlap/2*2;
Packit cb6d3d
Packit cb6d3d
  /* If there's no verified root yet, abort. */
Packit cb6d3d
  if (!rv(root)){
Packit cb6d3d
    return(0);
Packit cb6d3d
  } else {
Packit cb6d3d
    sync_result_t r;
Packit cb6d3d
Packit cb6d3d
    /* Search for a sufficiently long run of identical samples between
Packit cb6d3d
     * the verified fragment and the verified root.  There's a little
Packit cb6d3d
     * bit of subtlety in the search when silence is involved.
Packit cb6d3d
     */
Packit cb6d3d
    if (i_iterate_stage2(p,v,&r,callback)){
Packit cb6d3d
Packit cb6d3d
      /* Convert the results of the search to be relative to the root. */
Packit cb6d3d
      long int begin=r.begin-rb(root);
Packit cb6d3d
      long int end=r.end-rb(root);
Packit cb6d3d
Packit cb6d3d
      /* Convert offset into a value that will transform a relative
Packit cb6d3d
       * position in the root to the corresponding relative position in
Packit cb6d3d
       * the fragment.  I.e., if offset = -2, then the sample at relative
Packit cb6d3d
       * position 2 in the root is at relative position 0 in the fragment.
Packit cb6d3d
       *
Packit cb6d3d
       * While a bit opaque, this does reduce the number of calculations
Packit cb6d3d
       * below.
Packit cb6d3d
       */
Packit cb6d3d
      long int offset=r.begin+r.offset-fb(v)-begin;
Packit cb6d3d
      long int temp;
Packit cb6d3d
      c_block_t *l=NULL;
Packit cb6d3d
Packit cb6d3d
      /* we have a match! We don't rematch off rift, we chase the
Packit cb6d3d
	 match all the way to both extremes doing rift analysis. */
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
      fprintf(stderr, "matched [%ld-%ld], offset=%ld\n",
Packit cb6d3d
	      r.begin, r.end, r.offset);
Packit cb6d3d
      int traced = 0;
Packit cb6d3d
#endif
Packit cb6d3d
#ifdef NOISY
Packit cb6d3d
      fprintf(stderr,"Stage 2 match\n");
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
      /* Now that we've found a sufficiently long run of identical samples
Packit cb6d3d
       * between the fragment and the root, we need to check for rifts.
Packit cb6d3d
       *
Packit cb6d3d
       * A "rift", as mentioned above, is a disagreement between the
Packit cb6d3d
       * fragment and the root.  When there's a rift, the matching run
Packit cb6d3d
       * found by i_iterate_stage2() will obviously stop where the root
Packit cb6d3d
       * and the fragment disagree.
Packit cb6d3d
       *
Packit cb6d3d
       * So we detect rifts by checking whether the matching run extends
Packit cb6d3d
       * to the ends of the fragment and root.  If the run does extend to
Packit cb6d3d
       * the ends of the fragment and root, then all overlapping samples
Packit cb6d3d
       * agreed, and there's no rift.  If, however, the matching run
Packit cb6d3d
       * stops with samples left over in both the root and the fragment,
Packit cb6d3d
       * that means the root and fragment disagreed at that point.
Packit cb6d3d
       * Leftover samples at the beginning of the match indicate a
Packit cb6d3d
       * leading rift, and leftover samples at the end of the match indicate
Packit cb6d3d
       * a trailing rift.
Packit cb6d3d
       *
Packit cb6d3d
       * Once we detect a rift, we attempt to fix it, depending on the
Packit cb6d3d
       * nature of the disagreement.  See i_analyze_rift_[rf] for details
Packit cb6d3d
       * on how we determine what kind of rift it is.  See below for
Packit cb6d3d
       * how we attempt to fix the rifts.
Packit cb6d3d
       */
Packit cb6d3d
Packit cb6d3d
      /* First, check for a leading rift, fix it if possible, and then
Packit cb6d3d
       * extend the match forward until either we hit the limit of the
Packit cb6d3d
       * overlapping samples, or until we encounter another leading rift.
Packit cb6d3d
       * Keep doing this until we hit the beginning of the overlap.
Packit cb6d3d
       *
Packit cb6d3d
       * Note that while we do fix up leading rifts, we don't extend
Packit cb6d3d
       * the root backward (earlier samples) -- only forward (later
Packit cb6d3d
       * samples).
Packit cb6d3d
       */
Packit cb6d3d
Packit cb6d3d
      /* If the beginning of the match didn't reach the beginning of
Packit cb6d3d
       * either the fragment or the root, we have a leading rift to be
Packit cb6d3d
       * examined.
Packit cb6d3d
       *
Packit cb6d3d
       * Remember that (begin) is the offset into the root, and (begin+offset)
Packit cb6d3d
       * is the equivalent offset into the fragment.  If neither one is at
Packit cb6d3d
       * zero, then they both have samples before the match, and hence a
Packit cb6d3d
       * rift.
Packit cb6d3d
       */
Packit cb6d3d
      while ((begin+offset>0 && begin>0)){
Packit cb6d3d
	long matchA=0,matchB=0,matchC=0;
Packit cb6d3d
Packit cb6d3d
	/* (begin) is the offset into the root of the first matching sample,
Packit cb6d3d
	 * (beginL) is the offset into the fragment of the first matching
Packit cb6d3d
	 * sample.  These samples are at the edge of the rift.
Packit cb6d3d
	 */
Packit cb6d3d
	long beginL=begin+offset;
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
	if ((traced & 1) == 0) {
Packit cb6d3d
	  fprintf(stderr, "- Analyzing leading rift...\n");
Packit cb6d3d
	  traced |= 1;
Packit cb6d3d
	}
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
	/* The first time we encounter a leading rift, allocate a
Packit cb6d3d
	 * scratch copy of the verified fragment which we'll use if
Packit cb6d3d
	 * we need to fix up the fragment before merging it into
Packit cb6d3d
	 * the root.
Packit cb6d3d
	 */
Packit cb6d3d
	if (l==NULL){
Packit cb6d3d
	  int16_t *buff=malloc(fs(v)*sizeof(int16_t));
Packit cb6d3d
	  l=c_alloc(buff,fb(v),fs(v));
Packit cb6d3d
	  memcpy(buff,fv(v),fs(v)*sizeof(int16_t));
Packit cb6d3d
	}
Packit cb6d3d
Packit cb6d3d
	/* Starting at the first mismatching sample, see how far back the
Packit cb6d3d
	 * rift goes, and determine what kind of rift it is.  Note that
Packit cb6d3d
	 * we're searching through the fixed up copy of the fragment.
Packit cb6d3d
	 *
Packit cb6d3d
	 * matchA  > 0 if there are samples missing from the root
Packit cb6d3d
	 * matchA  < 0 if there are duplicate samples (stuttering) in the root
Packit cb6d3d
	 * matchB  > 0 if there are samples missing from the fragment
Packit cb6d3d
	 * matchB  < 0 if there are duplicate samples in the fragment
Packit cb6d3d
	 * matchC != 0 if there's a section of garbage, after which
Packit cb6d3d
	 *             the fragment and root agree and are in sync
Packit cb6d3d
	 */
Packit cb6d3d
	i_analyze_rift_r(rv(root),cv(l),
Packit cb6d3d
			 rs(root),cs(l),
Packit cb6d3d
			 begin-1,beginL-1,
Packit cb6d3d
			 &matchA,&matchB,&matchC);
Packit cb6d3d
Packit cb6d3d
#ifdef NOISY
Packit cb6d3d
	fprintf(stderr,"matching rootR: matchA:%ld matchB:%ld matchC:%ld\n",
Packit cb6d3d
		matchA,matchB,matchC);
Packit cb6d3d
#endif
Packit cb6d3d
	/* "??? The root.returnedlimit checks below are presently a mystery." */
Packit cb6d3d
	/* Those are for the case where our backtracking wants to take
Packit cb6d3d
	   us to back before bytes we've already returned to the
Packit cb6d3d
	   application.  In short, it's a "we're screwed"
Packit cb6d3d
	   check. --Monty */
Packit cb6d3d
	if (matchA){
Packit cb6d3d
	  /* There's a problem with the root */
Packit cb6d3d
Packit cb6d3d
	  if (matchA>0){
Packit cb6d3d
	    /* There were (matchA) samples dropped from the root.  We'll add
Packit cb6d3d
	     * them back from the fixed up fragment.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (callback)
Packit cb6d3d
	      (*callback)(begin+rb(root)-1,PARANOIA_CB_FIXUP_DROPPED);
Packit cb6d3d
	    if (rb(root)+begin<p->root.returnedlimit)
Packit cb6d3d
	      break;
Packit cb6d3d
	    else{
Packit cb6d3d
Packit cb6d3d
	      /* At the edge of the rift in the root, insert the missing
Packit cb6d3d
	       * samples from the fixed up fragment.  They're the (matchA)
Packit cb6d3d
	       * samples immediately preceding the edge of the rift in the
Packit cb6d3d
	       * fragment.
Packit cb6d3d
	       */
Packit cb6d3d
	      c_insert(rc(root),begin,cv(l)+beginL-matchA,
Packit cb6d3d
		       matchA);
Packit cb6d3d
Packit cb6d3d
	      /* We just inserted (matchA) samples into the root, so update
Packit cb6d3d
	       * our begin/end offsets accordingly.  Also adjust the
Packit cb6d3d
	       * (offset) to compensate (since we use it to find samples in
Packit cb6d3d
	       * the fragment, and the fragment hasn't changed).
Packit cb6d3d
	       */
Packit cb6d3d
	      offset-=matchA;
Packit cb6d3d
	      begin+=matchA;
Packit cb6d3d
	      end+=matchA;
Packit cb6d3d
	    }
Packit cb6d3d
Packit cb6d3d
	  } else {
Packit cb6d3d
	    /* There were (-matchA) duplicate samples (stuttering) in the
Packit cb6d3d
	     * root.  We'll drop them.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (callback)
Packit cb6d3d
	      (*callback)(begin+rb(root)-1,PARANOIA_CB_FIXUP_DUPED);
Packit cb6d3d
	    if (rb(root)+begin+matchA<p->root.returnedlimit)
Packit cb6d3d
	      break;
Packit cb6d3d
	    else{
Packit cb6d3d
Packit cb6d3d
	      /* Remove the (-matchA) samples immediately preceding the
Packit cb6d3d
	       * edge of the rift in the root.
Packit cb6d3d
	       */
Packit cb6d3d
	      c_remove(rc(root),begin+matchA,-matchA);
Packit cb6d3d
Packit cb6d3d
	      /* We just removed (-matchA) samples from the root, so update
Packit cb6d3d
	       * our begin/end offsets accordingly.  Also adjust the offset
Packit cb6d3d
	       * to compensate.  Remember that matchA < 0, so we're actually
Packit cb6d3d
	       * subtracting from begin/end.
Packit cb6d3d
	       */
Packit cb6d3d
	      offset-=matchA;
Packit cb6d3d
	      begin+=matchA;
Packit cb6d3d
	      end+=matchA;
Packit cb6d3d
	    }
Packit cb6d3d
	  }
Packit cb6d3d
	} else if (matchB){
Packit cb6d3d
	  /* There's a problem with the fragment */
Packit cb6d3d
Packit cb6d3d
	  if (matchB>0){
Packit cb6d3d
	    /* There were (matchB) samples dropped from the fragment.  We'll
Packit cb6d3d
	     * add them back from the root.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (callback)
Packit cb6d3d
	      (*callback)(begin+rb(root)-1,PARANOIA_CB_FIXUP_DROPPED);
Packit cb6d3d
Packit cb6d3d
	    /* At the edge of the rift in the fragment, insert the missing
Packit cb6d3d
	     * samples from the root.  They're the (matchB) samples
Packit cb6d3d
	     * immediately preceding the edge of the rift in the root.
Packit cb6d3d
	     * Note that we're fixing up the scratch copy of the fragment.
Packit cb6d3d
	     */
Packit cb6d3d
	    c_insert(l,beginL,rv(root)+begin-matchB,
Packit cb6d3d
			 matchB);
Packit cb6d3d
Packit cb6d3d
	    /* We just inserted (matchB) samples into the fixed up fragment,
Packit cb6d3d
	     * so update (offset), since we use it to find samples in the
Packit cb6d3d
	     * fragment based on the root's unchanged offsets.
Packit cb6d3d
	     */
Packit cb6d3d
	    offset+=matchB;
Packit cb6d3d
Packit cb6d3d
	  } else {
Packit cb6d3d
	    /* There were (-matchB) duplicate samples (stuttering) in the
Packit cb6d3d
	     * fixed up fragment.  We'll drop them.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (callback)
Packit cb6d3d
	      (*callback)(begin+rb(root)-1,PARANOIA_CB_FIXUP_DUPED);
Packit cb6d3d
Packit cb6d3d
	    /* Remove the (-matchB) samples immediately preceding the edge
Packit cb6d3d
	     * of the rift in the fixed up fragment.
Packit cb6d3d
	     */
Packit cb6d3d
	    c_remove(l,beginL+matchB,-matchB);
Packit cb6d3d
Packit cb6d3d
	    /* We just removed (-matchB) samples from the fixed up fragment,
Packit cb6d3d
	     * so update (offset), since we use it to find samples in the
Packit cb6d3d
	     * fragment based on the root's unchanged offsets.
Packit cb6d3d
	     */
Packit cb6d3d
	    offset+=matchB;
Packit cb6d3d
	  }
Packit cb6d3d
Packit cb6d3d
	} else if (matchC){
Packit cb6d3d
Packit cb6d3d
	  /* There are (matchC) samples that simply disagree between the
Packit cb6d3d
	   * fragment and the root.  On the other side of the mismatch, the
Packit cb6d3d
	   * fragment and root agree again.  We can't classify the mismatch
Packit cb6d3d
	   * as either a stutter or dropped samples, and we have no way of
Packit cb6d3d
	   * telling whether the fragment or the root is right.
Packit cb6d3d
	   *
Packit cb6d3d
	   * "The original comment indicated that we set "disagree"
Packit cb6d3d
	   * flags in the root, but it seems to be historical."  The
Packit cb6d3d
	   * disagree flags were from a time when we did interpolation
Packit cb6d3d
	   * over samples we simply couldn't get to agree.  Yes,
Packit cb6d3d
	   * historical functionality that didn;t work well. --Monty
Packit cb6d3d
	   */
Packit cb6d3d
Packit cb6d3d
	  if (rb(root)+begin-matchC<p->root.returnedlimit)
Packit cb6d3d
	    break;
Packit cb6d3d
Packit cb6d3d
	  /* Overwrite the mismatching (matchC) samples in root with the
Packit cb6d3d
	   * samples from the fixed up fragment.
Packit cb6d3d
	   *
Packit cb6d3d
	   * "??? Do we think the fragment is more likely correct, is this
Packit cb6d3d
	   * just arbitrary, or is there some other reason for overwriting
Packit cb6d3d
	   * the root?"
Packit cb6d3d
	   *   We think these samples are more likely to be correct --Monty
Packit cb6d3d
	   */
Packit cb6d3d
	  c_overwrite(rc(root),begin-matchC,
Packit cb6d3d
			cv(l)+beginL-matchC,matchC);
Packit cb6d3d
Packit cb6d3d
	} else {
Packit cb6d3d
Packit cb6d3d
	  /* We may have had a mismatch because we ran into leading silence.
Packit cb6d3d
	   *
Packit cb6d3d
	   * "??? To be studied: why would this cause a mismatch?
Packit cb6d3d
	   * Neither i_analyze_rift_r nor i_iterate_stage2() nor
Packit cb6d3d
	   * i_paranoia_overlap() appear to take silence into
Packit cb6d3d
	   * consideration in this regard.  It could be due to our
Packit cb6d3d
	   * skipping of silence when searching for a match."  Jitter
Packit cb6d3d
	   * and or skipping in sections of silence could end up with
Packit cb6d3d
	   * two sets of verified vectors that agree completely except
Packit cb6d3d
	   * for the length of the silence.  Silence is a huge bugaboo
Packit cb6d3d
	   * in general because there's no entropy within it to base
Packit cb6d3d
	   * verification on. --Monty
Packit cb6d3d
	   *
Packit cb6d3d
	   * Since we don't extend the root in that direction, we don't
Packit cb6d3d
	   * do anything, just move on to trailing rifts.
Packit cb6d3d
	   */
Packit cb6d3d
Packit cb6d3d
	  /* If the rift was too complex to fix (see i_analyze_rift_r),
Packit cb6d3d
	   * we just stop and leave the leading edge where it is.
Packit cb6d3d
	   */
Packit cb6d3d
Packit cb6d3d
	  /*RRR(*callback)(post,PARANOIA_CB_XXX);*/
Packit cb6d3d
	  break;
Packit cb6d3d
	}
Packit cb6d3d
Packit cb6d3d
	/* Recalculate the offset of the edge of the rift in the fixed
Packit cb6d3d
	 * up fragment, in case it changed.
Packit cb6d3d
	 *
Packit cb6d3d
	 * "??? Why is this done here rather than in the (matchB) case above,
Packit cb6d3d
	 * which should be the only time beginL will change."
Packit cb6d3d
	 * Because there's no reason not to? --Monty
Packit cb6d3d
	 */
Packit cb6d3d
	beginL=begin+offset;
Packit cb6d3d
Packit cb6d3d
	/* Now that we've fixed up the root or fragment as necessary, see
Packit cb6d3d
	 * how far we can extend the matching run.  This function is
Packit cb6d3d
	 * overkill, as it tries to extend the matching run in both
Packit cb6d3d
	 * directions (and rematches what we already matched), but it works.
Packit cb6d3d
	 */
Packit cb6d3d
	i_paranoia_overlap(rv(root),cv(l),
Packit cb6d3d
			   begin,beginL,
Packit cb6d3d
			   rs(root),cs(l),
Packit cb6d3d
			   &begin,&end;;
Packit cb6d3d
Packit cb6d3d
      } /* end while (leading rift) */
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
      /* Second, check for a trailing rift, fix it if possible, and then
Packit cb6d3d
       * extend the match forward until either we hit the limit of the
Packit cb6d3d
       * overlapping samples, or until we encounter another trailing rift.
Packit cb6d3d
       * Keep doing this until we hit the end of the overlap.
Packit cb6d3d
       */
Packit cb6d3d
Packit cb6d3d
      /* If the end of the match didn't reach the end of either the fragment
Packit cb6d3d
       * or the root, we have a trailing rift to be examined.
Packit cb6d3d
       *
Packit cb6d3d
       * Remember that (end) is the offset into the root, and (end+offset)
Packit cb6d3d
       * is the equivalent offset into the fragment.  If neither one is
Packit cb6d3d
       * at the end of the vector, then they both have samples after the
Packit cb6d3d
       * match, and hence a rift.
Packit cb6d3d
       *
Packit cb6d3d
       * (temp) is the size of the (potentially fixed-up) fragment.  If
Packit cb6d3d
       * there was a leading rift, (l) is the fixed up fragment, and
Packit cb6d3d
       * (offset) is now relative to it.
Packit cb6d3d
       */
Packit cb6d3d
      temp=l ? cs(l) : fs(v);
Packit cb6d3d
      while (end+offset
Packit cb6d3d
	long matchA=0,matchB=0,matchC=0;
Packit cb6d3d
Packit cb6d3d
	/* (begin) is the offset into the root of the first matching sample,
Packit cb6d3d
	 * (beginL) is the offset into the fragment of the first matching
Packit cb6d3d
	 * sample.  We know these samples match and will use these offsets
Packit cb6d3d
	 * later when we try to extend the matching run.
Packit cb6d3d
	 */
Packit cb6d3d
	long beginL=begin+offset;
Packit cb6d3d
Packit cb6d3d
	/* (end) is the offset into the root of the first mismatching sample
Packit cb6d3d
	 * after the matching run, (endL) is the offset into the fragment of
Packit cb6d3d
	 * the equivalent sample.  These samples are at the edge of the rift.
Packit cb6d3d
	 */
Packit cb6d3d
	long endL=end+offset;
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
	if ((traced & 2) == 0) {
Packit cb6d3d
	  fprintf(stderr, "- Analyzing trailing rift...\n");
Packit cb6d3d
	  traced |= 2;
Packit cb6d3d
	}
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
	/* The first time we encounter a rift, allocate a scratch copy of
Packit cb6d3d
	 * the verified fragment which we'll use if we need to fix up the
Packit cb6d3d
	 * fragment before merging it into the root.
Packit cb6d3d
	 *
Packit cb6d3d
	 * Note that if there was a leading rift, we'll already have
Packit cb6d3d
	 * this (potentially fixed-up) scratch copy allocated.
Packit cb6d3d
	 */
Packit cb6d3d
	if (l==NULL){
Packit cb6d3d
	  int16_t *buff=malloc(fs(v)*sizeof(int16_t));
Packit cb6d3d
	  l=c_alloc(buff,fb(v),fs(v));
Packit cb6d3d
	  memcpy(buff,fv(v),fs(v)*sizeof(int16_t));
Packit cb6d3d
	}
Packit cb6d3d
Packit cb6d3d
	/* Starting at the first mismatching sample, see how far forward the
Packit cb6d3d
	 * rift goes, and determine what kind of rift it is.  Note that we're
Packit cb6d3d
	 * searching through the fixed up copy of the fragment.
Packit cb6d3d
	 *
Packit cb6d3d
	 * matchA  > 0 if there are samples missing from the root
Packit cb6d3d
	 * matchA  < 0 if there are duplicate samples (stuttering) in the root
Packit cb6d3d
	 * matchB  > 0 if there are samples missing from the fragment
Packit cb6d3d
	 * matchB  < 0 if there are duplicate samples in the fragment
Packit cb6d3d
	 * matchC != 0 if there's a section of garbage, after which
Packit cb6d3d
	 *             the fragment and root agree and are in sync
Packit cb6d3d
	 */
Packit cb6d3d
	i_analyze_rift_f(rv(root),cv(l),
Packit cb6d3d
			 rs(root),cs(l),
Packit cb6d3d
			 end,endL,
Packit cb6d3d
			 &matchA,&matchB,&matchC);
Packit cb6d3d
Packit cb6d3d
#ifdef NOISY
Packit cb6d3d
	fprintf(stderr,"matching rootF: matchA:%ld matchB:%ld matchC:%ld\n",
Packit cb6d3d
		matchA,matchB,matchC);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
	/* ??? The root.returnedlimit checks below are presently a mystery. */
Packit cb6d3d
Packit cb6d3d
	if (matchA){
Packit cb6d3d
	  /* There's a problem with the root */
Packit cb6d3d
Packit cb6d3d
	  if (matchA>0){
Packit cb6d3d
	    /* There were (matchA) samples dropped from the root.  We'll add
Packit cb6d3d
	     * them back from the fixed up fragment.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (callback)(*callback)(end+rb(root),PARANOIA_CB_FIXUP_DROPPED);
Packit cb6d3d
	    if (end+rb(root)<p->root.returnedlimit)
Packit cb6d3d
	      break;
Packit cb6d3d
Packit cb6d3d
	    /* At the edge of the rift in the root, insert the missing
Packit cb6d3d
	     * samples from the fixed up fragment.  They're the (matchA)
Packit cb6d3d
	     * samples immediately preceding the edge of the rift in the
Packit cb6d3d
	     * fragment.
Packit cb6d3d
	     */
Packit cb6d3d
	    c_insert(rc(root),end,cv(l)+endL,matchA);
Packit cb6d3d
Packit cb6d3d
	    /* Although we just inserted samples into the root, we did so
Packit cb6d3d
	     * after (begin) and (end), so we needn't update those offsets.
Packit cb6d3d
	     */
Packit cb6d3d
Packit cb6d3d
	  } else {
Packit cb6d3d
	    /* There were (-matchA) duplicate samples (stuttering) in the
Packit cb6d3d
	     * root.  We'll drop them.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (callback)(*callback)(end+rb(root),PARANOIA_CB_FIXUP_DUPED);
Packit cb6d3d
	    if (end+rb(root)<p->root.returnedlimit)
Packit cb6d3d
	      break;
Packit cb6d3d
Packit cb6d3d
	    /* Remove the (-matchA) samples immediately following the edge
Packit cb6d3d
	     * of the rift in the root.
Packit cb6d3d
	     */
Packit cb6d3d
	    c_remove(rc(root),end,-matchA);
Packit cb6d3d
Packit cb6d3d
	    /* Although we just removed samples from the root, we did so
Packit cb6d3d
	     * after (begin) and (end), so we needn't update those offsets.
Packit cb6d3d
	     */
Packit cb6d3d
Packit cb6d3d
	  }
Packit cb6d3d
	} else if (matchB){
Packit cb6d3d
	  /* There's a problem with the fragment */
Packit cb6d3d
Packit cb6d3d
	  if (matchB>0){
Packit cb6d3d
	    /* There were (matchB) samples dropped from the fragment.  We'll
Packit cb6d3d
	     * add them back from the root.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (callback)(*callback)(end+rb(root),PARANOIA_CB_FIXUP_DROPPED);
Packit cb6d3d
Packit cb6d3d
	    /* At the edge of the rift in the fragment, insert the missing
Packit cb6d3d
	     * samples from the root.  They're the (matchB) samples
Packit cb6d3d
	     * immediately following the dge of the rift in the root.
Packit cb6d3d
	     * Note that we're fixing up the scratch copy of the fragment.
Packit cb6d3d
	     */
Packit cb6d3d
	    c_insert(l,endL,rv(root)+end,matchB);
Packit cb6d3d
Packit cb6d3d
	    /* Although we just inserted samples into the fragment, we did so
Packit cb6d3d
	     * after (begin) and (end), so (offset) hasn't changed either.
Packit cb6d3d
	     */
Packit cb6d3d
Packit cb6d3d
	  } else {
Packit cb6d3d
	    /* There were (-matchB) duplicate samples (stuttering) in the
Packit cb6d3d
	     * fixed up fragment.  We'll drop them.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (callback)(*callback)(end+rb(root),PARANOIA_CB_FIXUP_DUPED);
Packit cb6d3d
Packit cb6d3d
	    /* Remove the (-matchB) samples immediately following the edge
Packit cb6d3d
	     * of the rift in the fixed up fragment.
Packit cb6d3d
	     */
Packit cb6d3d
	    c_remove(l,endL,-matchB);
Packit cb6d3d
Packit cb6d3d
	    /* Although we just removed samples from the fragment, we did so
Packit cb6d3d
	     * after (begin) and (end), so (offset) hasn't changed either.
Packit cb6d3d
	     */
Packit cb6d3d
	  }
Packit cb6d3d
	} else if (matchC){
Packit cb6d3d
Packit cb6d3d
          /* There are (matchC) samples that simply disagree between the
Packit cb6d3d
           * fragment and the root.  On the other side of the mismatch, the
Packit cb6d3d
           * fragment and root agree again.  We can't classify the mismatch
Packit cb6d3d
           * as either a stutter or dropped samples, and we have no way of
Packit cb6d3d
           * telling whether the fragment or the root is right.
Packit cb6d3d
           *
Packit cb6d3d
           * The original comment indicated that we set "disagree" flags
Packit cb6d3d
           * in the root, but it seems to be historical.
Packit cb6d3d
           */
Packit cb6d3d
Packit cb6d3d
	  if (end+rb(root)<p->root.returnedlimit)
Packit cb6d3d
	    break;
Packit cb6d3d
Packit cb6d3d
          /* Overwrite the mismatching (matchC) samples in root with the
Packit cb6d3d
           * samples from the fixed up fragment.
Packit cb6d3d
           *
Packit cb6d3d
           * ??? Do we think the fragment is more likely correct, is this
Packit cb6d3d
           * just arbitrary, or is there some other reason for overwriting
Packit cb6d3d
           * the root?
Packit cb6d3d
           */
Packit cb6d3d
	  c_overwrite(rc(root),end,cv(l)+endL,matchC);
Packit cb6d3d
Packit cb6d3d
	} else {
Packit cb6d3d
Packit cb6d3d
	  /* We may have had a mismatch because we ran into trailing silence.
Packit cb6d3d
	   *
Packit cb6d3d
	   * ??? To be studied: why would this cause a mismatch?  Neither
Packit cb6d3d
	   * i_analyze_rift_f nor i_iterate_stage2() nor i_paranoia_overlap()
Packit cb6d3d
	   * appear to take silence into consideration in this regard.
Packit cb6d3d
           * It could be due to our skipping of silence when searching for
Packit cb6d3d
           * a match.
Packit cb6d3d
	   */
Packit cb6d3d
Packit cb6d3d
	  /* At this point we have a trailing rift.  We check whether
Packit cb6d3d
	   * one of the vectors (fragment or root) has trailing silence.
Packit cb6d3d
	   */
Packit cb6d3d
	  analyze_rift_silence_f(rv(root),cv(l),
Packit cb6d3d
				 rs(root),cs(l),
Packit cb6d3d
				 end,endL,
Packit cb6d3d
				 &matchA,&matchB);
Packit cb6d3d
	  if (matchA){
Packit cb6d3d
Packit cb6d3d
	    /* The contents of the root's trailing rift are silence.  The
Packit cb6d3d
	     * fragment's are not (otherwise there wouldn't be a rift).
Packit cb6d3d
	     * We therefore assume that the root has garbage from this
Packit cb6d3d
	     * point forward and truncate it.
Packit cb6d3d
	     *
Packit cb6d3d
	     * This will have the effect of eliminating the trailing
Packit cb6d3d
	     * rift, causing the fragment's samples to be appended to
Packit cb6d3d
	     * the root.
Packit cb6d3d
	     *
Packit cb6d3d
	     * ??? Does this have any negative side effects?  Why is this
Packit cb6d3d
	     * a good idea?
Packit cb6d3d
	     */
Packit cb6d3d
	    /* ??? TODO: returnedlimit */
Packit cb6d3d
	    /* Can only do this if we haven't already returned data */
Packit cb6d3d
	    if (end+rb(root)>=p->root.returnedlimit){
Packit cb6d3d
	      c_remove(rc(root),end,-1);
Packit cb6d3d
	    }
Packit cb6d3d
Packit cb6d3d
	  } else if (matchB){
Packit cb6d3d
Packit cb6d3d
	    /* The contents of the fragment's trailing rift are silence.
Packit cb6d3d
	     * The root's are not (otherwise there wouldn't be a rift).
Packit cb6d3d
	     * We therefore assume that the fragment has garbage from this
Packit cb6d3d
	     * point forward.
Packit cb6d3d
	     *
Packit cb6d3d
	     * We needn't actually truncate the fragment, because the root
Packit cb6d3d
	     * has already been fixed up from this fragment as much as
Packit cb6d3d
	     * possible, and the truncated fragment wouldn't extend the
Packit cb6d3d
	     * root.  Therefore, we can consider this (truncated) fragment
Packit cb6d3d
	     * to be already merged into the root.  So we dispose of it and
Packit cb6d3d
	     * return a success.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (l)i_cblock_destructor(l);
Packit cb6d3d
	    free_v_fragment(v);
Packit cb6d3d
	    return(1);
Packit cb6d3d
Packit cb6d3d
	  } else {
Packit cb6d3d
Packit cb6d3d
	    /* If the rift was too complex to fix (see i_analyze_rift_f),
Packit cb6d3d
	     * we just stop and leave the trailing edge where it is.
Packit cb6d3d
	     */
Packit cb6d3d
Packit cb6d3d
	    /*RRR(*callback)(post,PARANOIA_CB_XXX);*/
Packit cb6d3d
	  }
Packit cb6d3d
	  break;
Packit cb6d3d
	}
Packit cb6d3d
Packit cb6d3d
        /* Now that we've fixed up the root or fragment as necessary, see
Packit cb6d3d
         * how far we can extend the matching run.  This function is
Packit cb6d3d
         * overkill, as it tries to extend the matching run in both
Packit cb6d3d
         * directions (and rematches what we already matched), but it works.
Packit cb6d3d
         */
Packit cb6d3d
	i_paranoia_overlap(rv(root),cv(l),
Packit cb6d3d
			   begin,beginL,
Packit cb6d3d
			   rs(root),cs(l),
Packit cb6d3d
			   NULL,&end;;
Packit cb6d3d
Packit cb6d3d
	temp=cs(l);
Packit cb6d3d
      } /* end while (trailing rift) */
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
      /* Third and finally, if the overlapping verified fragment extends
Packit cb6d3d
       * our range forward (later samples), we append ("glom") the new
Packit cb6d3d
       * samples to the end of the root.
Packit cb6d3d
       *
Packit cb6d3d
       * Note that while we did fix up leading rifts, we don't extend
Packit cb6d3d
       * the root backward (earlier samples) -- only forward (later
Packit cb6d3d
       * samples).
Packit cb6d3d
       *
Packit cb6d3d
       * This is generally fine, since the verified root is supposed to
Packit cb6d3d
       * slide from earlier samples to later samples across multiple calls
Packit cb6d3d
       * to paranoia_read().
Packit cb6d3d
       *
Packit cb6d3d
       * "??? But, is this actually right?  Because of this, we don't
Packit cb6d3d
       * extend the root to hold the earliest read sample, if we
Packit cb6d3d
       * happened to initialize the root with a later sample due to
Packit cb6d3d
       * jitter.  There are probably some ugly side effects from
Packit cb6d3d
       * extending the root backward, in the general case, but it may
Packit cb6d3d
       * not be so dire if we're near sample 0.  To be investigated."
Packit cb6d3d
       * In the begin case, any start position is arbitrary due to
Packit cb6d3d
       * inexact seeking.  Later, we can't back-extend the root as the
Packit cb6d3d
       * samples preceeding the beginning have already been returned
Packit cb6d3d
       * to the application! --Monty
Packit cb6d3d
       */
Packit cb6d3d
      {
Packit cb6d3d
	long sizeA=rs(root);
Packit cb6d3d
	long sizeB;
Packit cb6d3d
	long vecbegin;
Packit cb6d3d
	int16_t *vector;
Packit cb6d3d
Packit cb6d3d
	/* If there were any rifts, we'll use the fixed up fragment (l),
Packit cb6d3d
	 * otherwise, we use the original fragment (v).
Packit cb6d3d
	 */
Packit cb6d3d
	if (l){
Packit cb6d3d
	  sizeB=cs(l);
Packit cb6d3d
	  vector=cv(l);
Packit cb6d3d
	  vecbegin=cb(l);
Packit cb6d3d
	} else {
Packit cb6d3d
	  sizeB=fs(v);
Packit cb6d3d
	  vector=fv(v);
Packit cb6d3d
	  vecbegin=fb(v);
Packit cb6d3d
	}
Packit cb6d3d
Packit cb6d3d
	/* Convert the fragment-relative offset (sizeB) into an offset
Packit cb6d3d
	 * relative to the root (A), and see if the offset is past the
Packit cb6d3d
	 * end of the root (> sizeA).  If it is, this fragment will extend
Packit cb6d3d
	 * our root.
Packit cb6d3d
	 *
Packit cb6d3d
	 * "??? Why do we check for v->lastsector separately?" Because
Packit cb6d3d
	 * of the case where root extends *too* far; if we never get a
Packit cb6d3d
	 * read that accidentally extends that far again, we could
Packit cb6d3d
	 * hang and loop forever. --Monty
Packit cb6d3d
	 */
Packit cb6d3d
	if (sizeB-offset>sizeA || v->lastsector){
Packit cb6d3d
	  if (v->lastsector){
Packit cb6d3d
	    root->lastsector=1;
Packit cb6d3d
	  }
Packit cb6d3d
Packit cb6d3d
	  /* "??? Why would end be < sizeA? Why do we truncate root?"
Packit cb6d3d
	     Because it can happen (seeking is very very inexact) and
Packit cb6d3d
	     end of disk tends to be very problematic in terms of
Packit cb6d3d
	     stopping point.  We also generally believe more recent
Packit cb6d3d
	     information over previous information when they disagree
Packit cb6d3d
	     and both are 'verified'. --Monty */
Packit cb6d3d
	  if (end
Packit cb6d3d
Packit cb6d3d
	  /* Extend the root with the samples from the end of the
Packit cb6d3d
	   * (potentially fixed up) fragment.
Packit cb6d3d
	   *
Packit cb6d3d
	   * ??? When would this condition not be true?
Packit cb6d3d
	   */
Packit cb6d3d
	  if (sizeB-offset-end)c_append(rc(root),vector+end+offset,
Packit cb6d3d
					 sizeB-offset-end);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
	  fprintf(stderr, "* Adding [%ld-%ld] to root\n",
Packit cb6d3d
		  rb(root)+end, re(root));
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
	  /* Any time we update the root we need to check whether it ends
Packit cb6d3d
	   * with a large span of silence.
Packit cb6d3d
	   */
Packit cb6d3d
	  i_silence_test(root);
Packit cb6d3d
Packit cb6d3d
	  /* Add the offset into our stage 2 statistics.
Packit cb6d3d
	   *
Packit cb6d3d
	   * Note that we convert our peculiar offset (which is in terms of
Packit cb6d3d
	   * the relative positions of samples within each vector) back into
Packit cb6d3d
	   * the actual offset between what A considers sample N and what B
Packit cb6d3d
	   * considers sample N.
Packit cb6d3d
	   *
Packit cb6d3d
	   * We do this at the end of rift handling because any original
Packit cb6d3d
	   * offset returned by i_iterate_stage2() might have been due to
Packit cb6d3d
	   * dropped or duplicated samples.  Once we've fixed up the root
Packit cb6d3d
	   * and the fragment, we have an offset which more reliably
Packit cb6d3d
	   * indicates jitter.
Packit cb6d3d
	   */
Packit cb6d3d
	  offset_add_value(p,&p->stage2,offset+vecbegin-rb(root),callback);
Packit cb6d3d
	}
Packit cb6d3d
      }
Packit cb6d3d
      if (l)i_cblock_destructor(l);
Packit cb6d3d
      free_v_fragment(v);
Packit cb6d3d
      return(1);
Packit cb6d3d
Packit cb6d3d
    } else { /* !i_iterate_stage2(...) */
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
      fprintf(stderr, "no match");
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
      /* We were unable to merge this fragment into the root.
Packit cb6d3d
       *
Packit cb6d3d
       * Check whether the fragment should have overlapped with the root,
Packit cb6d3d
       * even taking possible jitter into account.  (I.e., If the fragment
Packit cb6d3d
       * ends so far before the end of the root that even (dynoverlap)
Packit cb6d3d
       * samples of jitter couldn't push it beyond the end of the root,
Packit cb6d3d
       * it should have overlapped.)
Packit cb6d3d
       *
Packit cb6d3d
       * It is, however, possible that we failed to match using the normal
Packit cb6d3d
       * tests because we're dealing with silence, which we handle
Packit cb6d3d
       * separately.
Packit cb6d3d
       *
Packit cb6d3d
       * If the fragment should have overlapped, and we're not dealing
Packit cb6d3d
       * with the special silence case, we don't know what to make of
Packit cb6d3d
       * this fragment, and we just discard it.
Packit cb6d3d
       */
Packit cb6d3d
      if (fe(v)+dynoverlap<re(root) && !root->silenceflag){
Packit cb6d3d
	/* It *should* have matched.  No good; free it. */
Packit cb6d3d
	free_v_fragment(v);
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
	fprintf(stderr, ", discarding fragment.");
Packit cb6d3d
#endif
Packit cb6d3d
      }
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
      fprintf(stderr, "\n");
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
      /* otherwise, we likely want this for an upcoming match */
Packit cb6d3d
      /* we don't free the sort info (if it was collected) */
Packit cb6d3d
      return(0);
Packit cb6d3d
Packit cb6d3d
    }
Packit cb6d3d
  } /* endif rv(root) */
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
static int
Packit cb6d3d
i_init_root(root_block *root, v_fragment_t *v,long int begin,
Packit cb6d3d
		       void(*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
  if (fb(v)<=begin && fe(v)>begin){
Packit cb6d3d
Packit cb6d3d
    root->lastsector=v->lastsector;
Packit cb6d3d
    root->returnedlimit=begin;
Packit cb6d3d
Packit cb6d3d
    if (rv(root)){
Packit cb6d3d
      i_cblock_destructor(rc(root));
Packit cb6d3d
      rc(root)=NULL;
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    {
Packit cb6d3d
      int16_t *buff=malloc(fs(v)*sizeof(int16_t));
Packit cb6d3d
      memcpy(buff,fv(v),fs(v)*sizeof(int16_t));
Packit cb6d3d
      root->vector=c_alloc(buff,fb(v),fs(v));
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* Check whether the new root has a long span of trailing silence.
Packit cb6d3d
     */
Packit cb6d3d
    i_silence_test(root);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
    fprintf(stderr,
Packit cb6d3d
	    "* Assigning fragment [%ld-%ld] to root, silencebegin=%ld\n",
Packit cb6d3d
	    rb(root), re(root), root->silencebegin);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
    return(1);
Packit cb6d3d
  } else
Packit cb6d3d
    return(0);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
static int
Packit cb6d3d
vsort(const void *a,const void *b)
Packit cb6d3d
{
Packit cb6d3d
  return((*(v_fragment_t **)a)->begin-(*(v_fragment_t **)b)->begin);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * i_stage2 (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This function attempts to extend the verified root by merging verified
Packit cb6d3d
 * fragments into it.  It keeps extending the tail end of the root until
Packit cb6d3d
 * it runs out of matching fragments.  See i_stage2_each (and
Packit cb6d3d
 * i_iterate_stage2) for details of fragment matching and merging.
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called by paranoia_read_limited when the verified root
Packit cb6d3d
 * doesn't contain sufficient data to satisfy the request for samples.
Packit cb6d3d
 * If this function fails to extend the verified root far enough (having
Packit cb6d3d
 * exhausted the currently available verified fragments), the caller
Packit cb6d3d
 * will then read the device again to try and establish more verified
Packit cb6d3d
 * fragments.
Packit cb6d3d
 *
Packit cb6d3d
 * We first try to merge all the fragments in ascending order using the
Packit cb6d3d
 * standard method (i_stage2_each()), and then we try to merge the
Packit cb6d3d
 * remaining fragments using silence matching (i_silence_match())
Packit cb6d3d
 * if the root has a long span of trailing silence.  See the initial
Packit cb6d3d
 * comments on silence and  i_silence_match() for an explanation of this
Packit cb6d3d
 * distinction.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns the number of verified fragments successfully
Packit cb6d3d
 * merged into the verified root.
Packit cb6d3d
 */
Packit cb6d3d
static int
Packit cb6d3d
i_stage2(cdrom_paranoia_t *p, long int beginword, long int endword,
Packit cb6d3d
	 void (*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
Packit cb6d3d
  int flag=1,ret=0;
Packit cb6d3d
  root_block *root=&(p->root);
Packit cb6d3d
Packit cb6d3d
#ifdef NOISY
Packit cb6d3d
  fprintf(stderr,"Fragments:%ld\n",p->fragments->active);
Packit cb6d3d
  fflush(stderr);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  /* even when the 'silence flag' is lit, we try to do non-silence
Packit cb6d3d
     matching in the event that there are still audio vectors with
Packit cb6d3d
     content to be sunk before the silence */
Packit cb6d3d
Packit cb6d3d
  /* This flag is not the silence flag.  Rather, it indicates whether
Packit cb6d3d
   * we succeeded in adding a verified fragment to the verified root.
Packit cb6d3d
   * In short, we keep adding fragments until we no longer find a
Packit cb6d3d
   * match.
Packit cb6d3d
   */
Packit cb6d3d
  while (flag) {
Packit cb6d3d
Packit cb6d3d
    /* Convert the linked list of verified fragments into an array,
Packit cb6d3d
     * to be sorted in order of beginning sample position
Packit cb6d3d
     */
Packit cb6d3d
    v_fragment_t *first=v_first(p);
Packit cb6d3d
    long active=p->fragments->active,count=0;
Packit cb6d3d
    v_fragment_t **list = calloc(active, sizeof(v_fragment_t *));
Packit cb6d3d
Packit cb6d3d
    while (first){
Packit cb6d3d
      v_fragment_t *next=v_next(first);
Packit cb6d3d
      list[count++]=first;
Packit cb6d3d
      first=next;
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* Reset the flag so that if we don't match any fragments, we
Packit cb6d3d
     * stop looping.  Then, proceed only if there are any fragments
Packit cb6d3d
     * to match.
Packit cb6d3d
     */
Packit cb6d3d
    flag=0;
Packit cb6d3d
    if (count){
Packit cb6d3d
Packit cb6d3d
      /* Sort the array of verified fragments in order of beginning
Packit cb6d3d
       * sample position.
Packit cb6d3d
       */
Packit cb6d3d
      qsort(list,active,sizeof(v_fragment_t *),&vsort);
Packit cb6d3d
Packit cb6d3d
      /* We don't check for the silence flag yet, because even if the
Packit cb6d3d
       * verified root ends in silence (and thus the silence flag is set),
Packit cb6d3d
       * there may be a non-silent region at the beginning of the verified
Packit cb6d3d
       * root, into which we can merge the verified fragments.
Packit cb6d3d
       */
Packit cb6d3d
Packit cb6d3d
      /* Iterate through the verified fragments, starting at the fragment
Packit cb6d3d
       * with the lowest beginning sample position.
Packit cb6d3d
       */
Packit cb6d3d
      for(count=0;count
Packit cb6d3d
	first=list[count];
Packit cb6d3d
Packit cb6d3d
	/* Make sure this fragment hasn't already been merged (and
Packit cb6d3d
	 * thus freed). */
Packit cb6d3d
	if (first->one){
Packit cb6d3d
Packit cb6d3d
	  /* If we don't have a verified root yet, just promote the first
Packit cb6d3d
	   * fragment (with lowest beginning sample) to be the verified
Packit cb6d3d
	   * root.
Packit cb6d3d
	   *
Packit cb6d3d
	   * "??? It seems that this could be fairly arbitrary if jitter
Packit cb6d3d
	   * is an issue.  If we've verified two fragments allegedly
Packit cb6d3d
	   * beginning at "0" (which are actually slightly offset due to
Packit cb6d3d
	   * jitter), the root might not begin at the earliest read
Packit cb6d3d
	   * sample.  Additionally, because subsequent fragments are
Packit cb6d3d
	   * only merged at the tail end of the root, this situation
Packit cb6d3d
	   * won't be fixed by merging the earlier samples.
Packit cb6d3d
	   *
Packit cb6d3d
	   * Practically, this ends up not being critical since most
Packit cb6d3d
	   * drives insert some extra silent samples at the beginning
Packit cb6d3d
	   * of the stream.  Missing a few of them doesn't cause any
Packit cb6d3d
	   * real lost data.  But it is non-deterministic."
Packit cb6d3d
	   *
Packit cb6d3d
	   * On such a drive, the entire act of CDDA read is highly
Packit cb6d3d
	   * nondeterministic.  All redbook says is +/- 75 sectors.
Packit cb6d3d
	   * If you insist on the earliest possible sample, you can
Packit cb6d3d
	   * get into a situation where the first read was far earlier
Packit cb6d3d
	   * than all the others and no other read ever repeats the
Packit cb6d3d
	   * early positioning. --Monty */
Packit cb6d3d
	  if (rv(root)==NULL){
Packit cb6d3d
	    if (i_init_root(&(p->root),first,beginword,callback)){
Packit cb6d3d
	      free_v_fragment(first);
Packit cb6d3d
Packit cb6d3d
	      /* Consider this a merged fragment, so set the flag
Packit cb6d3d
	       * to keep looping.
Packit cb6d3d
	       */
Packit cb6d3d
	      flag=1;
Packit cb6d3d
	      ret++;
Packit cb6d3d
	    }
Packit cb6d3d
	  } else {
Packit cb6d3d
Packit cb6d3d
	    /* Try to merge this fragment with the verified root,
Packit cb6d3d
	     * extending the tail of the root.
Packit cb6d3d
	     */
Packit cb6d3d
	    if (i_stage2_each(root,first,callback)){
Packit cb6d3d
Packit cb6d3d
	      /* If we successfully merged the fragment, set the flag
Packit cb6d3d
	       * to keep looping.
Packit cb6d3d
	       */
Packit cb6d3d
	      ret++;
Packit cb6d3d
	      flag=1;
Packit cb6d3d
	    }
Packit cb6d3d
	  }
Packit cb6d3d
	}
Packit cb6d3d
      }
Packit cb6d3d
Packit cb6d3d
      /* If the verified root ends in a long span of silence, iterate
Packit cb6d3d
       * through the remaining unmerged fragments to see if they can be
Packit cb6d3d
       * merged using our special silence matching.
Packit cb6d3d
       */
Packit cb6d3d
      if (!flag && p->root.silenceflag){
Packit cb6d3d
	for(count=0;count
Packit cb6d3d
	  first=list[count];
Packit cb6d3d
Packit cb6d3d
	  /* Make sure this fragment hasn't already been merged (and
Packit cb6d3d
	   * thus freed). */
Packit cb6d3d
	  if (first->one){
Packit cb6d3d
	    if (rv(root)!=NULL){
Packit cb6d3d
Packit cb6d3d
	      /* Try to merge the fragment into the root.  This will only
Packit cb6d3d
	       * succeed if the fragment overlaps and begins with sufficient
Packit cb6d3d
	       * silence to be a presumed match.
Packit cb6d3d
	       *
Packit cb6d3d
	       * Note that the fragments must be passed to i_silence_match()
Packit cb6d3d
	       * in ascending order, as they are here.
Packit cb6d3d
	       */
Packit cb6d3d
	      if (i_silence_match(root,first,callback)){
Packit cb6d3d
Packit cb6d3d
		/* If we successfully merged the fragment, set the flag
Packit cb6d3d
		 * to keep looping.
Packit cb6d3d
		 */
Packit cb6d3d
		ret++;
Packit cb6d3d
		flag=1;
Packit cb6d3d
	      }
Packit cb6d3d
	    }
Packit cb6d3d
	  }
Packit cb6d3d
	} /* end for */
Packit cb6d3d
      }
Packit cb6d3d
    } /* end if(count) */
Packit cb6d3d
    free(list);
Packit cb6d3d
Packit cb6d3d
    /* If we were able to extend the verified root at all during this pass
Packit cb6d3d
     * through the loop, loop again to see if we can merge any remaining
Packit cb6d3d
     * fragments with the extended root.
Packit cb6d3d
     */
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 2
Packit cb6d3d
    if (flag)
Packit cb6d3d
      fprintf(stderr,
Packit cb6d3d
	      "- Root updated, comparing remaining fragments again.\n");
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  } /* end while */
Packit cb6d3d
Packit cb6d3d
  /* Return the number of fragments we successfully merged into the
Packit cb6d3d
   * verified root.
Packit cb6d3d
   */
Packit cb6d3d
  return(ret);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
static void
Packit cb6d3d
i_end_case(cdrom_paranoia_t *p,long endword,
Packit cb6d3d
	   void(*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
Packit cb6d3d
  root_block *root=&p->root;
Packit cb6d3d
Packit cb6d3d
  /* have an 'end' flag; if we've just read in the last sector in a
Packit cb6d3d
     session, set the flag.  If we verify to the end of a fragment
Packit cb6d3d
     which has the end flag set, we're done (set a done flag).  Pad
Packit cb6d3d
     zeroes to the end of the read */
Packit cb6d3d
Packit cb6d3d
  if (root->lastsector==0)return;
Packit cb6d3d
  if (endword
Packit cb6d3d
Packit cb6d3d
  {
Packit cb6d3d
    long addto=endword-re(root);
Packit cb6d3d
    char *temp=calloc(addto,sizeof(char)*2);
Packit cb6d3d
Packit cb6d3d
    c_append(rc(root),(void *)temp,addto);
Packit cb6d3d
    free(temp);
Packit cb6d3d
Packit cb6d3d
    /* trash da cache */
Packit cb6d3d
    paranoia_resetcache(p);
Packit cb6d3d
Packit cb6d3d
  }
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/* We want to add a sector. Look through the caches for something that
Packit cb6d3d
   spans.  Also look at the flags on the c_block... if this is an
Packit cb6d3d
   obliterated sector, get a bit of a chunk past the obliteration. */
Packit cb6d3d
Packit cb6d3d
/* Not terribly smart right now, actually.  We can probably find
Packit cb6d3d
   *some* match with a cache block somewhere.  Take it and continue it
Packit cb6d3d
   through the skip */
Packit cb6d3d
Packit cb6d3d
static void
Packit cb6d3d
verify_skip_case(cdrom_paranoia_t *p,
Packit cb6d3d
		 void(*callback)(long int, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
Packit cb6d3d
  root_block *root=&(p->root);
Packit cb6d3d
  c_block_t *graft=NULL;
Packit cb6d3d
  int vflag=0;
Packit cb6d3d
  int gend=0;
Packit cb6d3d
  long post;
Packit cb6d3d
Packit cb6d3d
#ifdef NOISY
Packit cb6d3d
	fprintf(stderr,"\nskipping\n");
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  if (rv(root)==NULL){
Packit cb6d3d
    post=0;
Packit cb6d3d
  } else {
Packit cb6d3d
    post=re(root);
Packit cb6d3d
  }
Packit cb6d3d
  if (post==-1)post=0;
Packit cb6d3d
Packit cb6d3d
  if (callback)(*callback)(post,PARANOIA_CB_SKIP);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA
Packit cb6d3d
  fprintf(stderr, "Skipping [%ld-", post);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  /* We want to add a sector.  Look for a c_block that spans,
Packit cb6d3d
     preferrably a verified area */
Packit cb6d3d
Packit cb6d3d
  {
Packit cb6d3d
    c_block_t *c=c_first(p);
Packit cb6d3d
    while (c){
Packit cb6d3d
      long cbegin=cb(c);
Packit cb6d3d
      long cend=ce(c);
Packit cb6d3d
      if (cbegin<=post && cend>post){
Packit cb6d3d
	long vend=post;
Packit cb6d3d
Packit cb6d3d
	if (c->flags[post-cbegin]&FLAGS_VERIFIED){
Packit cb6d3d
	  /* verified area! */
Packit cb6d3d
	  while (vend<cend && (c->flags[vend-cbegin]&FLAGS_VERIFIED))vend++;
Packit cb6d3d
	  if (!vflag || vend>vflag){
Packit cb6d3d
	    graft=c;
Packit cb6d3d
	    gend=vend;
Packit cb6d3d
	  }
Packit cb6d3d
	  vflag=1;
Packit cb6d3d
	} else {
Packit cb6d3d
	  /* not a verified area */
Packit cb6d3d
	  if (!vflag){
Packit cb6d3d
	    while (vend<cend && (c->flags[vend-cbegin]&FLAGS_VERIFIED)==0)vend++;
Packit cb6d3d
	    if (graft==NULL || gend>vend){
Packit cb6d3d
	      /* smallest unverified area */
Packit cb6d3d
	      graft=c;
Packit cb6d3d
	      gend=vend;
Packit cb6d3d
	    }
Packit cb6d3d
	  }
Packit cb6d3d
	}
Packit cb6d3d
      }
Packit cb6d3d
      c=c_next(c);
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    if (graft){
Packit cb6d3d
      long cbegin=cb(graft);
Packit cb6d3d
      long cend=ce(graft);
Packit cb6d3d
Packit cb6d3d
      while (gend<cend && (graft->flags[gend-cbegin]&FLAGS_VERIFIED))gend++;
Packit cb6d3d
      gend=min(gend+OVERLAP_ADJ,cend);
Packit cb6d3d
Packit cb6d3d
      if (rv(root)==NULL){
Packit cb6d3d
	int16_t *buff=malloc(cs(graft));
Packit cb6d3d
	memcpy(buff,cv(graft),cs(graft));
Packit cb6d3d
	rc(root)=c_alloc(buff,cb(graft),cs(graft));
Packit cb6d3d
      } else {
Packit cb6d3d
	c_append(rc(root),cv(graft)+post-cbegin,
Packit cb6d3d
		 gend-post);
Packit cb6d3d
      }
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA
Packit cb6d3d
      fprintf(stderr, "%d], filled with %s data from block [%ld-%ld]\n",
Packit cb6d3d
	      gend, (graft->flags[post-cbegin]&FLAGS_VERIFIED)
Packit cb6d3d
	      ? "verified" : "unverified", cbegin, cend);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
      root->returnedlimit=re(root);
Packit cb6d3d
      return;
Packit cb6d3d
    }
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  /* No?  Fine.  Great.  Write in some zeroes :-P */
Packit cb6d3d
  {
Packit cb6d3d
    void *temp=calloc(CDIO_CD_FRAMESIZE_RAW,sizeof(int16_t));
Packit cb6d3d
Packit cb6d3d
    if (rv(root)==NULL){
Packit cb6d3d
      rc(root)=c_alloc(temp,post,CDIO_CD_FRAMESIZE_RAW);
Packit cb6d3d
    } else {
Packit cb6d3d
      c_append(rc(root),temp,CDIO_CD_FRAMESIZE_RAW);
Packit cb6d3d
      free(temp);
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA
Packit cb6d3d
    fprintf(stderr, "%ld], filled with zero\n", re(root));
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
    root->returnedlimit=re(root);
Packit cb6d3d
  }
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/**** toplevel ****************************************/
Packit cb6d3d
Packit cb6d3d
void
Packit cb6d3d
paranoia_free(cdrom_paranoia_t *p)
Packit cb6d3d
{
Packit cb6d3d
  paranoia_resetall(p);
Packit cb6d3d
  sort_free(p->sortcache);
Packit cb6d3d
  free_list(p->cache, 1);
Packit cb6d3d
  free_list(p->fragments, 1);
Packit cb6d3d
  free(p);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*!
Packit cb6d3d
  Set the kind of repair you want to on for reading.
Packit cb6d3d
  The modes are listed above
Packit cb6d3d
Packit cb6d3d
  @param p           paranoia type
Packit cb6d3d
  @param  mode_flags paranoia mode flags built from values in  paranoia_mode_t,
Packit cb6d3d
  e.g. PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP
Packit cb6d3d
*/
Packit cb6d3d
void
Packit cb6d3d
paranoia_modeset(cdrom_paranoia_t *p, int mode_flags)
Packit cb6d3d
{
Packit cb6d3d
  p->enable=mode_flags;
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/*!
Packit cb6d3d
  reposition reading offset.
Packit cb6d3d
Packit cb6d3d
  @param p       paranoia type
Packit cb6d3d
  @param seek    byte offset to seek to
Packit cb6d3d
  @param whence  like corresponding parameter in libc's lseek, e.g.
Packit cb6d3d
  SEEK_SET or SEEK_END.
Packit cb6d3d
*/
Packit cb6d3d
lsn_t
Packit cb6d3d
paranoia_seek(cdrom_paranoia_t *p, int32_t seek, int whence)
Packit cb6d3d
{
Packit cb6d3d
  long sector;
Packit cb6d3d
  long ret;
Packit cb6d3d
  switch(whence){
Packit cb6d3d
  case SEEK_SET:
Packit cb6d3d
    sector=seek;
Packit cb6d3d
    break;
Packit cb6d3d
  case SEEK_END:
Packit cb6d3d
    sector=cdda_disc_lastsector(p->d)+seek;
Packit cb6d3d
    break;
Packit cb6d3d
  default:
Packit cb6d3d
    sector=p->cursor+seek;
Packit cb6d3d
    break;
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  if (cdda_sector_gettrack(p->d,sector)==-1)return(-1);
Packit cb6d3d
Packit cb6d3d
  i_cblock_destructor(p->root.vector);
Packit cb6d3d
  p->root.vector=NULL;
Packit cb6d3d
  p->root.lastsector=0;
Packit cb6d3d
  p->root.returnedlimit=0;
Packit cb6d3d
Packit cb6d3d
  ret=p->cursor;
Packit cb6d3d
  p->cursor=sector;
Packit cb6d3d
Packit cb6d3d
  i_paranoia_firstlast(p);
Packit cb6d3d
Packit cb6d3d
  /* Evil hack to fix pregap patch for NEC drives! To be rooted out in a10 */
Packit cb6d3d
  p->current_firstsector=sector;
Packit cb6d3d
Packit cb6d3d
  return(ret);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
static void cdrom_cache_update(cdrom_paranoia_t *p, int lba, int sectors){
Packit cb6d3d
Packit cb6d3d
  if(lba+sectors > p->cdcache_size){
Packit cb6d3d
    int end = lba+sectors;
Packit cb6d3d
    lba=end-p->cdcache_size;
Packit cb6d3d
    sectors = end-lba;
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  if(lba < p->cdcache_begin){
Packit cb6d3d
    /* a backseek flushes the cache */
Packit cb6d3d
    p->cdcache_begin=lba;
Packit cb6d3d
    p->cdcache_end=lba+sectors;
Packit cb6d3d
  }else{
Packit cb6d3d
    if(lba+sectors>p->cdcache_end)
Packit cb6d3d
      p->cdcache_end = lba+sectors;
Packit cb6d3d
    if(lba+sectors-p->cdcache_size > p->cdcache_begin){
Packit cb6d3d
      if(lba+sectors-p->cdcache_size < p->cdcache_end){
Packit cb6d3d
	p->cdcache_begin = lba+sectors-p->cdcache_size;
Packit cb6d3d
      }else{
Packit cb6d3d
	p->cdcache_begin = lba;
Packit cb6d3d
      }
Packit cb6d3d
    }
Packit cb6d3d
  }
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
static void cdrom_cache_handler(cdrom_paranoia_t *p, int lba, void(*callback)(long, paranoia_cb_mode_t)){
Packit cb6d3d
  int seekpos;
Packit cb6d3d
  int ms;
Packit cb6d3d
  if(lba>=p->cdcache_end)return; /* nothing to do */
Packit cb6d3d
Packit cb6d3d
  if(lba<0)lba=0;
Packit cb6d3d
Packit cb6d3d
  if(lba<p->cdcache_begin){
Packit cb6d3d
    /* should always trigger a backseek so let's do that here and look for the timing */
Packit cb6d3d
    seekpos=(lba==0 || lba-1<cdda_disc_firstsector(p->d) ? lba : lba-1); /* keep reads linear when possible */
Packit cb6d3d
  }else{
Packit cb6d3d
    int pre = p->cdcache_begin-1;
Packit cb6d3d
    int post = lba+p->cdcache_size;
Packit cb6d3d
Packit cb6d3d
    seekpos = (pre<cdda_disc_firstsector(p->d) ? post : pre);
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  if(cdda_read_timed(p->d,NULL,seekpos,1,&ms)==1)
Packit cb6d3d
    if(seekpos<p->cdcache_begin && ms
Packit cb6d3d
      if(cdio_get_driver_id(p->d->p_cdio)==cdio_os_driver)
Packit cb6d3d
        callback(seekpos*CD_FRAMEWORDS,PARANOIA_CB_CACHEERR);
Packit cb6d3d
  cdrom_cache_update(p,seekpos,1);
Packit cb6d3d
  return;
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/* ===========================================================================
Packit cb6d3d
 * read_c_block() (internal)
Packit cb6d3d
 *
Packit cb6d3d
 * This funtion reads many (p->readahead) sectors, encompassing at least
Packit cb6d3d
 * the requested words.
Packit cb6d3d
 *
Packit cb6d3d
 * It returns a c_block which encapsulates these sectors' data and sector
Packit cb6d3d
 * number.  The sectors come come from multiple low-level read requests.
Packit cb6d3d
 *
Packit cb6d3d
 * This function reads many sectors in order to exhaust any caching on the
Packit cb6d3d
 * drive itself, as caching would simply return the same incorrect data
Packit cb6d3d
 * over and over.  Paranoia depends on truly re-reading portions of the
Packit cb6d3d
 * disc to make sure the reads are accurate and correct any inaccuracies.
Packit cb6d3d
 *
Packit cb6d3d
 * Which precise sectors are read varies ("jiggles") between calls to
Packit cb6d3d
 * read_c_block, to prevent consistent errors across multiple reads
Packit cb6d3d
 * from being misinterpreted as correct data.
Packit cb6d3d
 *
Packit cb6d3d
 * The size of each low-level read is determined by the underlying driver
Packit cb6d3d
 * (p->d->nsectors), which allows the driver to specify how many sectors
Packit cb6d3d
 * can be read in a single request.  Historically, the Linux kernel could
Packit cb6d3d
 * only read 8 sectors at a time, with likely dropped samples between each
Packit cb6d3d
 * read request.  Other operating systems may have different limitations.
Packit cb6d3d
 *
Packit cb6d3d
 * This function is called by paranoia_read_limited(), which breaks the
Packit cb6d3d
 * c_block of read data into runs of samples that are likely to be
Packit cb6d3d
 * contiguous, verifies them and stores them in verified fragments, and
Packit cb6d3d
 * eventually merges the fragments into the verified root.
Packit cb6d3d
 *
Packit cb6d3d
 * This function returns the last c_block read or NULL on error.
Packit cb6d3d
 */
Packit cb6d3d
Packit cb6d3d
static c_block_t *
Packit cb6d3d
i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
Packit cb6d3d
	       void(*callback)(long, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
Packit cb6d3d
/* why do it this way?  We need to read lots of sectors to kludge
Packit cb6d3d
   around stupid read ahead buffers on cheap drives, as well as avoid
Packit cb6d3d
   expensive back-seeking. We also want to 'jiggle' the start address
Packit cb6d3d
   to try to break borderline drives more noticeably (and make broken
Packit cb6d3d
   drives with unaddressable sectors behave more often). */
Packit cb6d3d
Packit cb6d3d
  long readat,firstread;
Packit cb6d3d
  long totaltoread=p->cdcache_size;
Packit cb6d3d
  long sectatonce=p->d->nsectors;
Packit cb6d3d
  long driftcomp=(float)p->dyndrift/CD_FRAMEWORDS+.5;
Packit cb6d3d
  c_block_t *new=NULL;
Packit cb6d3d
  root_block *root=&p->root;
Packit cb6d3d
  int16_t *buffer=NULL;
Packit cb6d3d
  unsigned char *flags=NULL;
Packit cb6d3d
  long sofar;
Packit cb6d3d
  long dynoverlap=(p->dynoverlap+CD_FRAMEWORDS-1)/CD_FRAMEWORDS;
Packit cb6d3d
  long anyflag=0;
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
  /* Calculate the first sector to read.  This calculation takes
Packit cb6d3d
   * into account the need to jitter the starting point of the read
Packit cb6d3d
   * to reveal consistent errors as well as the low reliability of
Packit cb6d3d
   * the edge words of a read.
Packit cb6d3d
   *
Packit cb6d3d
   * ???: Document more clearly how dynoverlap and MIN_SECTOR_BACKUP
Packit cb6d3d
   * are calculated and used.
Packit cb6d3d
   */
Packit cb6d3d
Packit cb6d3d
  /* What is the first sector to read?  want some pre-buffer if
Packit cb6d3d
     we're not at the extreme beginning of the disc */
Packit cb6d3d
Packit cb6d3d
  if (p->enable&(PARANOIA_MODE_VERIFY|PARANOIA_MODE_OVERLAP)){
Packit cb6d3d
Packit cb6d3d
    long target;
Packit cb6d3d
    if (rv(root)==NULL || rb(root)>beginword)
Packit cb6d3d
      target=p->cursor-dynoverlap;
Packit cb6d3d
    else
Packit cb6d3d
      target=re(root)/(CD_FRAMEWORDS)-dynoverlap;
Packit cb6d3d
Packit cb6d3d
    /* we want to jitter the read alignment boundary, as some
Packit cb6d3d
       drives, beginning from a specific point, will tend to
Packit cb6d3d
       lose bytes between sectors in the same place.  Also, as
Packit cb6d3d
       our vectors are being made up of multiple reads, we want
Packit cb6d3d
       the overlap boundaries to move.... */
Packit cb6d3d
Packit cb6d3d
    readat=(target&(~((long)JIGGLE_MODULO-1)))+p->jitter;
Packit cb6d3d
    if (readat>target)readat-=JIGGLE_MODULO;
Packit cb6d3d
    p->jitter--;
Packit cb6d3d
    if (p->jitter<0)
Packit cb6d3d
      p->jitter+=JIGGLE_MODULO;
Packit cb6d3d
Packit cb6d3d
  } else {
Packit cb6d3d
    readat=p->cursor;
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  readat+=driftcomp;
Packit cb6d3d
Packit cb6d3d
  /* Create a new, empty c_block and add it to the head of the
Packit cb6d3d
   * list of c_blocks in memory.  It will be empty until the end of
Packit cb6d3d
   * this subroutine.
Packit cb6d3d
   */
Packit cb6d3d
  if (p->enable&(PARANOIA_MODE_OVERLAP|PARANOIA_MODE_VERIFY)) {
Packit cb6d3d
    flags=calloc(totaltoread*CD_FRAMEWORDS, 1);
Packit cb6d3d
    new=new_c_block(p);
Packit cb6d3d
    recover_cache(p);
Packit cb6d3d
  } else {
Packit cb6d3d
    /* in the case of root it's just the buffer */
Packit cb6d3d
    paranoia_resetall(p);
Packit cb6d3d
    new=new_c_block(p);
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  buffer=calloc(totaltoread*CDIO_CD_FRAMESIZE_RAW, 1);
Packit cb6d3d
  sofar=0;
Packit cb6d3d
  firstread=-1;
Packit cb6d3d
Packit cb6d3d
  /* we have a read span; flush the drive cache if needed */
Packit cb6d3d
  cdrom_cache_handler(p, readat, callback);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA
Packit cb6d3d
  fprintf(stderr, "Reading [%ld-%ld] from media\n",
Packit cb6d3d
	  readat*CD_FRAMEWORDS, (readat+totaltoread)*CD_FRAMEWORDS);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
  /* Issue each of the low-level reads; the optimal read size is
Packit cb6d3d
   * approximately the cachemodel's cdrom cache size.  The only reason
Packit cb6d3d
   * to read less would be memory considerations.
Packit cb6d3d
   *
Packit cb6d3d
   * p->readahead   = total number of sectors to read
Packit cb6d3d
   * p->d->nsectors = number of sectors to read per request
Packit cb6d3d
   */
Packit cb6d3d
Packit cb6d3d
  /* actual read loop */
Packit cb6d3d
Packit cb6d3d
  while (sofar
Packit cb6d3d
    long secread=sectatonce;  /* number of sectors to read this request */
Packit cb6d3d
    long adjread=readat;      /* first sector to read for this request */
Packit cb6d3d
    long thisread;            /* how many sectors were read this request */
Packit cb6d3d
Packit cb6d3d
    /* don't under/overflow the audio session */
Packit cb6d3d
    if (adjread<p->current_firstsector){
Packit cb6d3d
      secread-=p->current_firstsector-adjread;
Packit cb6d3d
      adjread=p->current_firstsector;
Packit cb6d3d
    }
Packit cb6d3d
    if (adjread+secread-1>p->current_lastsector)
Packit cb6d3d
      secread=p->current_lastsector-adjread+1;
Packit cb6d3d
Packit cb6d3d
    if (sofar+secread>totaltoread)secread=totaltoread-sofar;
Packit cb6d3d
Packit cb6d3d
    if (secread>0){
Packit cb6d3d
Packit cb6d3d
      if (firstread<0) firstread = adjread;
Packit cb6d3d
Packit cb6d3d
      /* Issue the low-level read to the driver.
Packit cb6d3d
       */
Packit cb6d3d
Packit cb6d3d
      thisread = cdda_read(p->d, buffer+sofar*CD_FRAMEWORDS, adjread, secread);
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 1
Packit cb6d3d
      fprintf(stderr, "- Read [%ld-%ld] (0x%04X...0x%04X)%s",
Packit cb6d3d
	      adjread*CD_FRAMEWORDS, (adjread+thisread)*CD_FRAMEWORDS,
Packit cb6d3d
	      buffer[sofar*CD_FRAMEWORDS] & 0xFFFF,
Packit cb6d3d
	      buffer[(sofar+thisread)*CD_FRAMEWORDS - 1] & 0xFFFF,
Packit cb6d3d
	      thisread < secread ? "" : "\n");
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
      /* If the low-level read returned too few sectors, pad the result
Packit cb6d3d
       * with null data and mark it as invalid (FLAGS_UNREAD).  We pad
Packit cb6d3d
       * because we're going to be appending further reads to the current
Packit cb6d3d
       * c_block.
Packit cb6d3d
       *
Packit cb6d3d
       * "???: Why not re-read?  It might be to keep you from getting
Packit cb6d3d
       * hung up on a bad sector.  Or it might be to avoid
Packit cb6d3d
       * interrupting the streaming as much as possible."
Packit cb6d3d
       *
Packit cb6d3d
       * There are drives on which you will never get a full read in
Packit cb6d3d
       * some positions.  They always abort out early due to firmware
Packit cb6d3d
       * boundary cases.  Reread will cause exactly the same thing to
Packit cb6d3d
       * happen again.  NEC MultiSpeed 4x is one such drive. In these
Packit cb6d3d
       * cases, you take what part of the read you know is good, and
Packit cb6d3d
       * you get substantially better performance. --Monty
Packit cb6d3d
       */
Packit cb6d3d
      if ( thisread < secread) {
Packit cb6d3d
Packit cb6d3d
	if(thisread<0){
Packit cb6d3d
#ifdef ENOMEDIUM
Packit cb6d3d
	  if(errno==ENOMEDIUM){
Packit cb6d3d
	    /* the one error we bail on immediately */
Packit cb6d3d
	    if(new)free_c_block(new);
Packit cb6d3d
	    if(buffer)free(buffer);
Packit cb6d3d
	    if(flags)free(flags);
Packit cb6d3d
	    return NULL;
Packit cb6d3d
	  }
Packit cb6d3d
#endif
Packit cb6d3d
	  thisread=0;
Packit cb6d3d
	}
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA & 1
Packit cb6d3d
	fprintf(stderr, " -- couldn't read [%ld-%ld]\n",
Packit cb6d3d
		(adjread+thisread)*CD_FRAMEWORDS,
Packit cb6d3d
		(adjread+secread)*CD_FRAMEWORDS);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
	/* Uhhh... right.  Make something up. But don't make us seek
Packit cb6d3d
           backward! */
Packit cb6d3d
Packit cb6d3d
	if (callback)
Packit cb6d3d
	  (*callback)((adjread+thisread)*CD_FRAMEWORDS, PARANOIA_CB_READERR);
Packit cb6d3d
	memset(buffer+(sofar+thisread)*CD_FRAMEWORDS,0,
Packit cb6d3d
	       CDIO_CD_FRAMESIZE_RAW*(secread-thisread));
Packit cb6d3d
	if (flags)
Packit cb6d3d
          memset(flags+(sofar+thisread)*CD_FRAMEWORDS, FLAGS_UNREAD,
Packit cb6d3d
	         CD_FRAMEWORDS*(secread-thisread));
Packit cb6d3d
      }
Packit cb6d3d
      if (thisread!=0)anyflag=1;
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
      /* Because samples are likely to be dropped between read requests,
Packit cb6d3d
       * mark the samples near the the boundaries of the read requests
Packit cb6d3d
       * as suspicious (FLAGS_EDGE).  This means that any span of samples
Packit cb6d3d
       * against which these adjacent read requests are compared must
Packit cb6d3d
       * overlap beyond the edges and into the more trustworthy data.
Packit cb6d3d
       * Such overlapping spans are accordingly at least MIN_WORDS_OVERLAP
Packit cb6d3d
       * words long (and naturally longer if any samples were dropped
Packit cb6d3d
       * between the read requests).
Packit cb6d3d
       *
Packit cb6d3d
       *          (EEEEE...overlapping span...EEEEE)
Packit cb6d3d
       * (read 1 ...........EEEEE)   (EEEEE...... read 2 ......EEEEE) ...
Packit cb6d3d
       *         dropped samples --^
Packit cb6d3d
       */
Packit cb6d3d
      if (flags && sofar!=0){
Packit cb6d3d
	/* Don't verify across overlaps that are too close to one
Packit cb6d3d
           another */
Packit cb6d3d
	int i=0;
Packit cb6d3d
	for(i=-MIN_WORDS_OVERLAP/2;i
Packit cb6d3d
	  flags[sofar*CD_FRAMEWORDS+i]|=FLAGS_EDGE;
Packit cb6d3d
      }
Packit cb6d3d
Packit cb6d3d
      if (adjread+secread-1==p->current_lastsector)
Packit cb6d3d
	new->lastsector=-1;
Packit cb6d3d
Packit cb6d3d
      if (callback)(*callback)((adjread+secread-1)*CD_FRAMEWORDS,PARANOIA_CB_READ);
Packit cb6d3d
Packit cb6d3d
      cdrom_cache_update(p,adjread,secread);
Packit cb6d3d
      sofar+=secread;
Packit cb6d3d
      readat=adjread+secread;
Packit cb6d3d
    } else /* secread <= 0 */
Packit cb6d3d
      if (readat<p->current_firstsector)
Packit cb6d3d
	readat+=sectatonce; /* due to being before the readable area */
Packit cb6d3d
      else
Packit cb6d3d
	break; /* due to being past the readable area */
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
    /* Keep issuing read requests until we've read enough sectors to
Packit cb6d3d
     * exhaust the drive's cache.
Packit cb6d3d
     */
Packit cb6d3d
Packit cb6d3d
  } /* end while */
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
  /* If we managed to read any sectors at all (anyflag), fill in the
Packit cb6d3d
   * previously allocated c_block with the read data.  Otherwise, free
Packit cb6d3d
   * our buffers, dispose of the c_block, and return NULL.
Packit cb6d3d
   */
Packit cb6d3d
  if (anyflag) {
Packit cb6d3d
    new->vector=buffer;
Packit cb6d3d
    new->begin=firstread*CD_FRAMEWORDS-p->dyndrift;
Packit cb6d3d
    new->size=sofar*CD_FRAMEWORDS;
Packit cb6d3d
    new->flags=flags;
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA
Packit cb6d3d
    fprintf(stderr, "- Read block %ld:[%ld-%ld] from media\n",
Packit cb6d3d
	    p->cache->active, cb(new), ce(new));
Packit cb6d3d
#endif
Packit cb6d3d
  } else {
Packit cb6d3d
    if (new)free_c_block(new);
Packit cb6d3d
    free(buffer);
Packit cb6d3d
    free(flags);
Packit cb6d3d
    new=NULL;
Packit cb6d3d
  }
Packit cb6d3d
  return(new);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
/** ==========================================================================
Packit cb6d3d
 * cdio_paranoia_read(), cdio_paranoia_read_limited()
Packit cb6d3d
 *
Packit cb6d3d
 * These functions "read" the next sector of audio data and returns
Packit cb6d3d
 * a pointer to a full sector of verified samples (2352 bytes).
Packit cb6d3d
 *
Packit cb6d3d
 * The returned buffer is *not* to be freed by the caller.  It will
Packit cb6d3d
 *   persist only until the next call to paranoia_read() for this p
Packit cb6d3d
*/
Packit cb6d3d
Packit cb6d3d
int16_t *
Packit cb6d3d
cdio_paranoia_read(cdrom_paranoia_t *p,
Packit cb6d3d
		   void(*callback)(long, paranoia_cb_mode_t))
Packit cb6d3d
{
Packit cb6d3d
  return paranoia_read_limited(p, callback, 20);
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/* I added max_retry functionality this way in order to avoid
Packit cb6d3d
   breaking any old apps using the new libs.  cdparanoia 9.8 will
Packit cb6d3d
   need the updated libs, but nothing else will require it. */
Packit cb6d3d
int16_t *
Packit cb6d3d
cdio_paranoia_read_limited(cdrom_paranoia_t *p,
Packit cb6d3d
			   void(*callback)(long int, paranoia_cb_mode_t),
Packit cb6d3d
			   int max_retries)
Packit cb6d3d
{
Packit cb6d3d
  long int beginword  =  p->cursor*(CD_FRAMEWORDS);
Packit cb6d3d
  long int endword    =  beginword+CD_FRAMEWORDS;
Packit cb6d3d
  long int retry_count=  0;
Packit cb6d3d
  long int lastend    = -2;
Packit cb6d3d
  root_block *root    = &p->root;
Packit cb6d3d
Packit cb6d3d
  if(p->d->opened==0){
Packit cb6d3d
    errno=EBADF;
Packit cb6d3d
    return NULL;
Packit cb6d3d
  }
Packit cb6d3d
Packit cb6d3d
  if (beginword > p->root.returnedlimit)
Packit cb6d3d
    p->root.returnedlimit=beginword;
Packit cb6d3d
  lastend=re(root);
Packit cb6d3d
Packit cb6d3d
Packit cb6d3d
  /* Since paranoia reads and verifies chunks of data at a time
Packit cb6d3d
   * (which it needs to counteract dropped samples and inaccurate
Packit cb6d3d
   * seeking), the requested samples may already be in memory,
Packit cb6d3d
   * in the verified "root".
Packit cb6d3d
   *
Packit cb6d3d
   * The root is where paranoia stores samples that have been
Packit cb6d3d
   * verified and whose position has been accurately determined.
Packit cb6d3d
   */
Packit cb6d3d
Packit cb6d3d
  /* First, is the sector we want already in the root? */
Packit cb6d3d
  while (rv(root)==NULL ||
Packit cb6d3d
	rb(root)>beginword ||
Packit cb6d3d
	(re(root)
Packit cb6d3d
	 p->enable&(PARANOIA_MODE_VERIFY|PARANOIA_MODE_OVERLAP)) ||
Packit cb6d3d
	re(root)
Packit cb6d3d
Packit cb6d3d
    /* Nope; we need to build or extend the root verified range */
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA
Packit cb6d3d
    fprintf(stderr, "Trying to expand root [%ld-%ld]...\n",
Packit cb6d3d
	    rb(root), re(root));
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
    /* We may have already read the necessary samples and placed
Packit cb6d3d
     * them into verified fragments, but not yet merged them into
Packit cb6d3d
     * the verified root.  We'll check that before we actually
Packit cb6d3d
     * try to read data from the drive.
Packit cb6d3d
     */
Packit cb6d3d
Packit cb6d3d
    if (p->enable&(PARANOIA_MODE_VERIFY|PARANOIA_MODE_OVERLAP)){
Packit cb6d3d
Packit cb6d3d
      /* We need to make sure our memory consumption doesn't grow
Packit cb6d3d
       * to the size of the whole CD.  But at the same time, we
Packit cb6d3d
       * need to hang onto some of the verified data (even perhaps
Packit cb6d3d
       * data that's already been returned by paranoia_read()) in
Packit cb6d3d
       * order to verify and accurately position future samples.
Packit cb6d3d
       *
Packit cb6d3d
       * Therefore, we free some of the verified data that we
Packit cb6d3d
       * no longer need.
Packit cb6d3d
       */
Packit cb6d3d
      i_paranoia_trim(p,beginword,endword);
Packit cb6d3d
      recover_cache(p);
Packit cb6d3d
Packit cb6d3d
      if (rb(root)!=-1 && p->root.lastsector)
Packit cb6d3d
	i_end_case(p, endword+(MAX_SECTOR_OVERLAP*CD_FRAMEWORDS),
Packit cb6d3d
			callback);
Packit cb6d3d
      else
Packit cb6d3d
Packit cb6d3d
	/* Merge as many verified fragments into the verified root
Packit cb6d3d
	 * as we need to satisfy the pending request.  We may
Packit cb6d3d
	 * not have all the fragments we need, in which case we'll
Packit cb6d3d
	 * read data from the CD further below.
Packit cb6d3d
	 */
Packit cb6d3d
	i_stage2(p, beginword,
Packit cb6d3d
		      endword+(MAX_SECTOR_OVERLAP*CD_FRAMEWORDS),
Packit cb6d3d
		      callback);
Packit cb6d3d
    } else
Packit cb6d3d
      i_end_case(p,endword+(MAX_SECTOR_OVERLAP*CD_FRAMEWORDS),
Packit cb6d3d
		 callback); /* only trips if we're already done */
Packit cb6d3d
Packit cb6d3d
#if TRACE_PARANOIA
Packit cb6d3d
    fprintf(stderr, "- Root is now [%ld-%ld] silencebegin=%ld\n",
Packit cb6d3d
	    rb(root), re(root), root->silencebegin);
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
    /* If we were able to fill the verified root with data already
Packit cb6d3d
     * in memory, we don't need to read any more data from the drive.
Packit cb6d3d
     */
Packit cb6d3d
    if (!(rb(root)==-1 || rb(root)>beginword ||
Packit cb6d3d
	 re(root)
Packit cb6d3d
      break;
Packit cb6d3d
Packit cb6d3d
    /* Hmm, need more.  Read another block */
Packit cb6d3d
Packit cb6d3d
    {
Packit cb6d3d
      /* Read many sectors, encompassing at least the requested words.
Packit cb6d3d
       *
Packit cb6d3d
       * The returned c_block encapsulates these sectors' data and
Packit cb6d3d
       * sector number.  The sectors come come from multiple low-level
Packit cb6d3d
       * read requests, and words which were near the boundaries of
Packit cb6d3d
       * those read requests are marked with FLAGS_EDGE.
Packit cb6d3d
       */
Packit cb6d3d
      c_block_t *new=i_read_c_block(p,beginword,endword,callback);
Packit cb6d3d
Packit cb6d3d
      if (new){
Packit cb6d3d
	if (p->enable&(PARANOIA_MODE_OVERLAP|PARANOIA_MODE_VERIFY)){
Packit cb6d3d
Packit cb6d3d
	  /* If we need to verify these samples, send them to
Packit cb6d3d
	   * stage 1 verification, which will add verified samples
Packit cb6d3d
	   * to the set of verified fragments.  Verified fragments
Packit cb6d3d
	   * will be merged into the verified root during stage 2
Packit cb6d3d
	   * overlap analysis.
Packit cb6d3d
	   */
Packit cb6d3d
	  if (p->enable&PARANOIA_MODE_VERIFY)
Packit cb6d3d
	    i_stage1(p,new,callback);
Packit cb6d3d
Packit cb6d3d
	  /* If we're only doing overlapping reads (no stage 1
Packit cb6d3d
	   * verification), consider each low-level read in the
Packit cb6d3d
	   * c_block to be a verified fragment.  We exclude the
Packit cb6d3d
	   * edges from these fragments to enforce the requirement
Packit cb6d3d
	   * that we overlap the reads by the minimum amount.
Packit cb6d3d
	   * These fragments will be merged into the verified
Packit cb6d3d
	   * root during stage 2 overlap analysis.
Packit cb6d3d
	   */
Packit cb6d3d
	  else{
Packit cb6d3d
	    /* just make v_fragments from the boundary information. */
Packit cb6d3d
	    long begin=0,end=0;
Packit cb6d3d
Packit cb6d3d
	    while (begin
Packit cb6d3d
	      while (begin<cs(new) && (new->flags[begin]&FLAGS_EDGE))begin++;
Packit cb6d3d
	      end=begin+1;
Packit cb6d3d
	      while (end<cs(new) && (new->flags[end]&FLAGS_EDGE)==0)end++;
Packit cb6d3d
	      {
Packit cb6d3d
		new_v_fragment(p,new,begin+cb(new),
Packit cb6d3d
			       end+cb(new),
Packit cb6d3d
			       (new->lastsector && cb(new)+end==ce(new)));
Packit cb6d3d
	      }
Packit cb6d3d
	      begin=end;
Packit cb6d3d
	    }
Packit cb6d3d
	  }
Packit cb6d3d
Packit cb6d3d
	} else {
Packit cb6d3d
Packit cb6d3d
	  /* If we're not doing any overlapping reads or verification
Packit cb6d3d
	   * of data, skip over the stage 1 and stage 2 verification and
Packit cb6d3d
	   * promote this c_block directly to the current "verified" root.
Packit cb6d3d
	   */
Packit cb6d3d
Packit cb6d3d
	  if (p->root.vector)i_cblock_destructor(p->root.vector);
Packit cb6d3d
	  free_elem(new->e,0);
Packit cb6d3d
	  p->root.vector=new;
Packit cb6d3d
Packit cb6d3d
	  i_end_case(p,endword+(MAX_SECTOR_OVERLAP*CD_FRAMEWORDS),
Packit cb6d3d
			  callback);
Packit cb6d3d
Packit cb6d3d
	}
Packit cb6d3d
      }else{
Packit cb6d3d
Packit cb6d3d
#ifdef ENOMEDIUM
Packit cb6d3d
	/* Was the medium removed or the device closed out from
Packit cb6d3d
	   under us? */
Packit cb6d3d
	if(errno==ENOMEDIUM) return NULL;
Packit cb6d3d
#endif
Packit cb6d3d
Packit cb6d3d
      }
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* Are we doing lots of retries?  **************************************/
Packit cb6d3d
Packit cb6d3d
    /* ???: To be studied
Packit cb6d3d
     */
Packit cb6d3d
Packit cb6d3d
    /* Check unaddressable sectors first.  There's no backoff here;
Packit cb6d3d
       jiggle and minimum backseek handle that for us */
Packit cb6d3d
Packit cb6d3d
    if (rb(root)!=-1 && lastend+588
Packit cb6d3d
						 half a sector */
Packit cb6d3d
      lastend=re(root);
Packit cb6d3d
      retry_count=0;
Packit cb6d3d
    } else {
Packit cb6d3d
      /* increase overlap or bail */
Packit cb6d3d
      retry_count++;
Packit cb6d3d
Packit cb6d3d
      /* The better way to do this is to look at how many actual
Packit cb6d3d
	 matches we're getting and what kind of gap */
Packit cb6d3d
Packit cb6d3d
      if (retry_count%5==0){
Packit cb6d3d
	if (p->dynoverlap==MAX_SECTOR_OVERLAP*CD_FRAMEWORDS ||
Packit cb6d3d
	   retry_count==max_retries){
Packit cb6d3d
	  if (!(p->enable&PARANOIA_MODE_NEVERSKIP))
Packit cb6d3d
	    verify_skip_case(p,callback);
Packit cb6d3d
	  retry_count=0;
Packit cb6d3d
	} else {
Packit cb6d3d
	  if (p->stage1.offpoints!=-1){ /* hack */
Packit cb6d3d
	    p->dynoverlap*=1.5;
Packit cb6d3d
	    if (p->dynoverlap>MAX_SECTOR_OVERLAP*CD_FRAMEWORDS)
Packit cb6d3d
	      p->dynoverlap=MAX_SECTOR_OVERLAP*CD_FRAMEWORDS;
Packit cb6d3d
	    if (callback)
Packit cb6d3d
	      (*callback)(p->dynoverlap,PARANOIA_CB_OVERLAP);
Packit cb6d3d
	  }
Packit cb6d3d
	}
Packit cb6d3d
      }
Packit cb6d3d
    }
Packit cb6d3d
Packit cb6d3d
    /* Having read data from the drive and placed it into verified
Packit cb6d3d
     * fragments, we now loop back to try to extend the root with
Packit cb6d3d
     * the newly loaded data.  Alternatively, if the root already
Packit cb6d3d
     * contains the needed data, we'll just fall through.
Packit cb6d3d
     */
Packit cb6d3d
Packit cb6d3d
  } /* end while */
Packit cb6d3d
  p->cursor++;
Packit cb6d3d
Packit cb6d3d
  /* Return a pointer into the verified root.  Thus, the caller
Packit cb6d3d
   * must NOT free the returned pointer!
Packit cb6d3d
   */
Packit cb6d3d
  return(rv(root)+(beginword-rb(root)));
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
/* a temporary hack */
Packit cb6d3d
void
Packit cb6d3d
cdio_paranoia_overlapset(cdrom_paranoia_t *p, long int overlap)
Packit cb6d3d
{
Packit cb6d3d
  p->dynoverlap=overlap*CD_FRAMEWORDS;
Packit cb6d3d
  p->stage1.offpoints=-1;
Packit cb6d3d
}
Packit cb6d3d
Packit cb6d3d
extern const char *cdio_paranoia_version(void){
Packit cb6d3d
  return LIBCDIO_PARANOIA_VERSION;
Packit cb6d3d
}