
Packit 
cb6d3d 
/*


Packit 
cb6d3d 
Copyright (C) 2004, 2008, 2011 Rocky Bernstein <rocky@gnu.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 
* Gap analysis support code for paranoia


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 
#include "p_block.h"


Packit 
cb6d3d 
#include <cdio/paranoia/paranoia.h>


Packit 
cb6d3d 
#include "gap.h"


Packit 
cb6d3d 
#include <string.h>


Packit 
cb6d3d 


Packit 
cb6d3d 
/**** Gap analysis code ***************************************************/


Packit 
cb6d3d 


Packit 
cb6d3d 
/* ===========================================================================


Packit 
cb6d3d 
* i_paranoia_overlap_r (internal)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function seeks backward through two vectors (starting at the given


Packit 
cb6d3d 
* offsets) to determine how many consecutive samples agree. It returns


Packit 
cb6d3d 
* the number of matching samples, which may be 0.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Unlike its sibling, i_paranoia_overlap_f, this function doesn't need to


Packit 
cb6d3d 
* be given the size of the vectors (all vectors stop at offset 0).


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function is used by i_analyze_rift_r() below to find where a


Packit 
cb6d3d 
* leading rift ends.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
long int


Packit 
cb6d3d 
i_paranoia_overlap_r(int16_t *buffA,int16_t *buffB,


Packit 
cb6d3d 
long offsetA, long offsetB)


Packit 
cb6d3d 
{


Packit 
cb6d3d 
long beginA=offsetA;


Packit 
cb6d3d 
long beginB=offsetB;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Start at the given offsets and work our way backwards until we hit


Packit 
cb6d3d 
* the beginning of one of the vectors.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
for( ; beginA>=0 && beginB>=0; beginA,beginB )


Packit 
cb6d3d 
if (buffA[beginA] != buffB[beginB]) break;


Packit 
cb6d3d 


Packit 
cb6d3d 
return(offsetAbeginA);


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 


Packit 
cb6d3d 
/* ===========================================================================


Packit 
cb6d3d 
* i_paranoia_overlap_f (internal)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function seeks forward through two vectors (starting at the given


Packit 
cb6d3d 
* offsets) to determine how many consecutive samples agree. It returns


Packit 
cb6d3d 
* the number of matching samples, which may be 0.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Unlike its sibling, i_paranoia_overlap_r, this function needs to given


Packit 
cb6d3d 
* the size of the vectors.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function is used by i_analyze_rift_f() below to find where a


Packit 
cb6d3d 
* trailing rift ends.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
long int


Packit 
cb6d3d 
i_paranoia_overlap_f(int16_t *buffA,int16_t *buffB,


Packit 
cb6d3d 
long offsetA, long offsetB,


Packit 
cb6d3d 
long sizeA,long sizeB)


Packit 
cb6d3d 
{


Packit 
cb6d3d 
long endA=offsetA;


Packit 
cb6d3d 
long endB=offsetB;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Start at the given offsets and work our way forward until we hit


Packit 
cb6d3d 
* the end of one of the vectors.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
for(;endA


Packit 
cb6d3d 
if(buffA[endA]!=buffB[endB])break;


Packit 
cb6d3d 


Packit 
cb6d3d 
return(endAoffsetA);


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 


Packit 
cb6d3d 
/* ===========================================================================


Packit 
cb6d3d 
* i_stutter_or_gap (internal)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function compares (gap) samples of two vectors at the given offsets.


Packit 
cb6d3d 
* It returns 0 if all the samples are identical, or nonzero if they differ.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This is used by i_analyze_rift_[rf] below to determine whether a rift


Packit 
cb6d3d 
* contains samples dropped by the other vector (that should be inserted),


Packit 
cb6d3d 
* or whether the rift contains a stutter (that should be dropped). See


Packit 
cb6d3d 
* i_analyze_rift_[rf] for more details.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
int


Packit 
cb6d3d 
i_stutter_or_gap(int16_t *A, int16_t *B,long offA, long offB, long int gap)


Packit 
cb6d3d 
{


Packit 
cb6d3d 
long a1=offA;


Packit 
cb6d3d 
long b1=offB;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* If the rift was so big that there aren't enough samples in the other


Packit 
cb6d3d 
* vector to compare against the full gap, then just compare what we


Packit 
cb6d3d 
* have available. E.g.:


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* (5678)(newly matching run ...)


Packit 
cb6d3d 
* (... 12345678) (345678) (newly matching run ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* In this case, a1 would be 2, since we'd want to compare 6 samples


Packit 
cb6d3d 
* against a vector that had only 4. So we start 2 samples later, and


Packit 
cb6d3d 
* compare the 4 available samples.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Again, this approach to identifying stutters is simply a heuristic,


Packit 
cb6d3d 
* so this may not produce correct results in all cases.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(a1<0){


Packit 
cb6d3d 
/* Note that a1 is negative, so we're increasing b1 and decreasing (gap).


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
b1=a1;


Packit 
cb6d3d 
gap+=a1;


Packit 
cb6d3d 
a1=0;


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Note that we don't have an equivalent adjustment for leading rifts.


Packit 
cb6d3d 
* Thus, it's possible for the following memcmp() to run off the end


Packit 
cb6d3d 
* of A. See the bug note in i_analyze_rift_r().


Packit 
cb6d3d 
*/


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Multiply gap by 2 because samples are 2 bytes long and memcmp compares


Packit 
cb6d3d 
* at the byte level.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
return(memcmp(A+a1,B+b1,gap*2));


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
/* riftv is the first value into the rift > or < */


Packit 
cb6d3d 


Packit 
cb6d3d 


Packit 
cb6d3d 
/* ===========================================================================


Packit 
cb6d3d 
* i_analyze_rift_f (internal)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function examines a trailing rift to see how far forward the rift goes


Packit 
cb6d3d 
* and to determine what kind of rift it is. This function is called by


Packit 
cb6d3d 
* i_stage2_each() when a trailing rift is detected. (aoffset,boffset) are


Packit 
cb6d3d 
* the offsets into (A,B) of the first mismatching sample.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function returns:


Packit 
cb6d3d 
* matchA > 0 if there are (matchA) samples missing from A


Packit 
cb6d3d 
* matchA < 0 if there are (matchA) duplicate samples (stuttering) in A


Packit 
cb6d3d 
* matchB > 0 if there are (matchB) samples missing from B


Packit 
cb6d3d 
* matchB < 0 if there are (matchB) duplicate samples in B


Packit 
cb6d3d 
* matchC != 0 if there are (matchC) samples of garbage, after which


Packit 
cb6d3d 
* both A and B are in sync again


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
void


Packit 
cb6d3d 
i_analyze_rift_f(int16_t *A,int16_t *B,


Packit 
cb6d3d 
long sizeA, long sizeB,


Packit 
cb6d3d 
long aoffset, long boffset,


Packit 
cb6d3d 
long *matchA,long *matchB,long *matchC)


Packit 
cb6d3d 
{


Packit 
cb6d3d 


Packit 
cb6d3d 
long apast=sizeAaoffset;


Packit 
cb6d3d 
long bpast=sizeBboffset;


Packit 
cb6d3d 
long i;


Packit 
cb6d3d 


Packit 
cb6d3d 
*matchA=0, *matchB=0, *matchC=0;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Look forward to see where we regain agreement between vectors


Packit 
cb6d3d 
* A and B (of at least MIN_WORDS_RIFT samples). We look for one of


Packit 
cb6d3d 
* the following possible matches:


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* edge


Packit 
cb6d3d 
* v


Packit 
cb6d3d 
* (1) (... A matching run)(aoffset matches ...)


Packit 
cb6d3d 
* (... B matching run) (rift) (boffset+i matches ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* (2) (... A matching run) (rift) (aoffset+i matches ...)


Packit 
cb6d3d 
* (... B matching run)(boffset matches ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* (3) (... A matching run) (rift) (aoffset+i matches ...)


Packit 
cb6d3d 
* (... B matching run) (rift) (boffset+i matches ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Anything that doesn't match one of these three is too corrupt to


Packit 
cb6d3d 
* for us to recover from. E.g.:


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* (... A matching run) (rift) (eventual match ...)


Packit 
cb6d3d 
* (... B matching run) (big rift) (eventual match ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* We won't find the eventual match, since we wouldn't be sure how


Packit 
cb6d3d 
* to fix the rift.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 


Packit 
cb6d3d 
for(i=1;;i++){


Packit 
cb6d3d 
/* Search for whatever case we hit first, so as to end up with the


Packit 
cb6d3d 
* smallest rift.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Don't search for (1) past the end of B */


Packit 
cb6d3d 
if (i


Packit 
cb6d3d 


Packit 
cb6d3d 
/* See if we match case (1) above, which either means that A dropped


Packit 
cb6d3d 
* samples at the rift, or that B stuttered.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i_paranoia_overlap_f(A,B,aoffset,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){


Packit 
cb6d3d 
*matchA=i;


Packit 
cb6d3d 
break;


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Don't search for (2) or (3) past the end of A */


Packit 
cb6d3d 
if (i


Packit 
cb6d3d 


Packit 
cb6d3d 
/* See if we match case (2) above, which either means that B dropped


Packit 
cb6d3d 
* samples at the rift, or that A stuttered.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i_paranoia_overlap_f(A,B,aoffset+i,boffset,sizeA,sizeB)>=MIN_WORDS_RIFT){


Packit 
cb6d3d 
*matchB=i;


Packit 
cb6d3d 
break;


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Don't search for (3) past the end of B */


Packit 
cb6d3d 
if (i


Packit 
cb6d3d 


Packit 
cb6d3d 
/* See if we match case (3) above, which means that a fixedlength


Packit 
cb6d3d 
* rift of samples is getting read unreliably.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i_paranoia_overlap_f(A,B,aoffset+i,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){


Packit 
cb6d3d 
*matchC=i;


Packit 
cb6d3d 
break;


Packit 
cb6d3d 
}


Packit 
cb6d3d 
}else


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Stop searching when we've reached the end of both vectors.


Packit 
cb6d3d 
* In theory we could stop when there aren't MIN_WORDS_RIFT samples


Packit 
cb6d3d 
* left in both vectors, but this case should happen fairly rarely.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i>=bpast)break;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Try the search again with a larger tentative rift. */


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
if(*matchA==0 && *matchB==0 && *matchC==0)return;


Packit 
cb6d3d 


Packit 
cb6d3d 
if(*matchC)return;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* For case (1) or (2), we need to determine whether the rift contains


Packit 
cb6d3d 
* samples dropped by the other vector (that should be inserted), or


Packit 
cb6d3d 
* whether the rift contains a stutter (that should be dropped). To


Packit 
cb6d3d 
* distinguish, we check the contents of the rift against the good samples


Packit 
cb6d3d 
* just before the rift. If the contents match, then the rift contains


Packit 
cb6d3d 
* a stutter.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* A stutter in the second vector:


Packit 
cb6d3d 
* (...good samples... 1234)(567 ...newly matched run...)


Packit 
cb6d3d 
* (...good samples... 1234) (1234)  (567 ...newly matched run)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Samples missing from the first vector:


Packit 
cb6d3d 
* (...good samples... 1234)(901 ...newly matched run...)


Packit 
cb6d3d 
* (...good samples... 1234) (5678) (901 ...newly matched run...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Of course, there's no theoretical guarantee that a nonstutter


Packit 
cb6d3d 
* truly represents missing samples, but given that we're dealing with


Packit 
cb6d3d 
* verified fragments in stage 2, we can have some confidence that this


Packit 
cb6d3d 
* is the case.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(*matchA){


Packit 
cb6d3d 
/* For case (1), we need to determine whether A dropped samples at the


Packit 
cb6d3d 
* rift or whether B stuttered.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* If the rift doesn't match the good samples in A (and hence in B),


Packit 
cb6d3d 
* it's not a stutter, and the rift should be inserted into A.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i_stutter_or_gap(A,B,aoffset*matchA,boffset,*matchA))


Packit 
cb6d3d 
return;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* It is a stutter, so we need to signal that we need to remove


Packit 
cb6d3d 
* (matchA) bytes from B.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
*matchB = *matchA;


Packit 
cb6d3d 
*matchA=0;


Packit 
cb6d3d 
return;


Packit 
cb6d3d 


Packit 
cb6d3d 
}else{


Packit 
cb6d3d 
/* Case (2) is the inverse of case (1) above. */


Packit 
cb6d3d 
if(i_stutter_or_gap(B,A,boffset*matchB,aoffset,*matchB))


Packit 
cb6d3d 
return;


Packit 
cb6d3d 


Packit 
cb6d3d 
*matchA = *matchB;


Packit 
cb6d3d 
*matchB=0;


Packit 
cb6d3d 
return;


Packit 
cb6d3d 
}


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 


Packit 
cb6d3d 
/* riftv must be first even val of rift moving back */


Packit 
cb6d3d 


Packit 
cb6d3d 
/* ===========================================================================


Packit 
cb6d3d 
* i_analyze_rift_r (internal)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function examines a leading rift to see how far back the rift goes


Packit 
cb6d3d 
* and to determine what kind of rift it is. This function is called by


Packit 
cb6d3d 
* i_stage2_each() when a leading rift is detected. (aoffset,boffset) are


Packit 
cb6d3d 
* the offsets into (A,B) of the first mismatching sample.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function returns:


Packit 
cb6d3d 
* matchA > 0 if there are (matchA) samples missing from A


Packit 
cb6d3d 
* matchA < 0 if there are (matchA) duplicate samples (stuttering) in A


Packit 
cb6d3d 
* matchB > 0 if there are (matchB) samples missing from B


Packit 
cb6d3d 
* matchB < 0 if there are (matchB) duplicate samples in B


Packit 
cb6d3d 
* matchC != 0 if there are (matchC) samples of garbage, after which


Packit 
cb6d3d 
* both A and B are in sync again


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
void


Packit 
cb6d3d 
i_analyze_rift_r(int16_t *A,int16_t *B,


Packit 
cb6d3d 
long sizeA, long sizeB,


Packit 
cb6d3d 
long aoffset, long boffset,


Packit 
cb6d3d 
long *matchA,long *matchB,long *matchC)


Packit 
cb6d3d 
{


Packit 
cb6d3d 


Packit 
cb6d3d 
long apast=aoffset+1;


Packit 
cb6d3d 
long bpast=boffset+1;


Packit 
cb6d3d 
long i;


Packit 
cb6d3d 


Packit 
cb6d3d 
*matchA=0, *matchB=0, *matchC=0;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Look backward to see where we regain agreement between vectors


Packit 
cb6d3d 
* A and B (of at least MIN_WORDS_RIFT samples). We look for one of


Packit 
cb6d3d 
* the following possible matches:


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* edge


Packit 
cb6d3d 
* v


Packit 
cb6d3d 
* (1) (... aoffset matches)(A matching run ...)


Packit 
cb6d3d 
* (... boffseti matches) (rift) (B matching run ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* (2) (... aoffseti matches) (rift) (A matching run ...)


Packit 
cb6d3d 
* (... boffset matches)(B matching run ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* (3) (... aoffseti matches) (rift) (A matching run ...)


Packit 
cb6d3d 
* (... boffseti matches) (rift) (B matching run ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Anything that doesn't match one of these three is too corrupt to


Packit 
cb6d3d 
* for us to recover from. E.g.:


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* (... eventual match) (rift) (A matching run ...)


Packit 
cb6d3d 
* (... eventual match)  (big rift) (B matching run ...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* We won't find the eventual match, since we wouldn't be sure how


Packit 
cb6d3d 
* to fix the rift.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 


Packit 
cb6d3d 
for(i=1;;i++){


Packit 
cb6d3d 
/* Search for whatever case we hit first, so as to end up with the


Packit 
cb6d3d 
* smallest rift.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Don't search for (1) past the beginning of B */


Packit 
cb6d3d 
if (i


Packit 
cb6d3d 


Packit 
cb6d3d 
/* See if we match case (1) above, which either means that A dropped


Packit 
cb6d3d 
* samples at the rift, or that B stuttered.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i_paranoia_overlap_r(A,B,aoffset,boffseti)>=MIN_WORDS_RIFT){


Packit 
cb6d3d 
*matchA=i;


Packit 
cb6d3d 
break;


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Don't search for (2) or (3) past the beginning of A */


Packit 
cb6d3d 
if (i


Packit 
cb6d3d 


Packit 
cb6d3d 
/* See if we match case (2) above, which either means that B dropped


Packit 
cb6d3d 
* samples at the rift, or that A stuttered.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i_paranoia_overlap_r(A,B,aoffseti,boffset)>=MIN_WORDS_RIFT){


Packit 
cb6d3d 
*matchB=i;


Packit 
cb6d3d 
break;


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Don't search for (3) past the beginning of B */


Packit 
cb6d3d 
if (i


Packit 
cb6d3d 


Packit 
cb6d3d 
/* See if we match case (3) above, which means that a fixedlength


Packit 
cb6d3d 
* rift of samples is getting read unreliably.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i_paranoia_overlap_r(A,B,aoffseti,boffseti)>=MIN_WORDS_RIFT){


Packit 
cb6d3d 
*matchC=i;


Packit 
cb6d3d 
break;


Packit 
cb6d3d 
}


Packit 
cb6d3d 
}else


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Stop searching when we've reached the end of both vectors.


Packit 
cb6d3d 
* In theory we could stop when there aren't MIN_WORDS_RIFT samples


Packit 
cb6d3d 
* left in both vectors, but this case should happen fairly rarely.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i>=bpast)break;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Try the search again with a larger tentative rift. */


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
if(*matchA==0 && *matchB==0 && *matchC==0)return;


Packit 
cb6d3d 


Packit 
cb6d3d 
if(*matchC)return;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* For case (1) or (2), we need to determine whether the rift contains


Packit 
cb6d3d 
* samples dropped by the other vector (that should be inserted), or


Packit 
cb6d3d 
* whether the rift contains a stutter (that should be dropped). To


Packit 
cb6d3d 
* distinguish, we check the contents of the rift against the good samples


Packit 
cb6d3d 
* just after the rift. If the contents match, then the rift contains


Packit 
cb6d3d 
* a stutter.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* A stutter in the second vector:


Packit 
cb6d3d 
* (...newly matched run... 234)(5678 ...good samples...)


Packit 
cb6d3d 
* (...newly matched run... 234) (5678) (5678 ...good samples...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Samples missing from the first vector:


Packit 
cb6d3d 
* (...newly matched run... 890)(5678 ...good samples...)


Packit 
cb6d3d 
* (...newly matched run... 890) (1234) (5678 ...good samples...)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Of course, there's no theoretical guarantee that a nonstutter


Packit 
cb6d3d 
* truly represents missing samples, but given that we're dealing with


Packit 
cb6d3d 
* verified fragments in stage 2, we can have some confidence that this


Packit 
cb6d3d 
* is the case.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 


Packit 
cb6d3d 
if(*matchA){


Packit 
cb6d3d 
/* For case (1), we need to determine whether A dropped samples at the


Packit 
cb6d3d 
* rift or whether B stuttered.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* If the rift doesn't match the good samples in A (and hence in B),


Packit 
cb6d3d 
* it's not a stutter, and the rift should be inserted into A.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* ???BUG??? It's possible for aoffset+1+*matchA to be > sizeA, in


Packit 
cb6d3d 
* which case the comparison in i_stutter_or_gap() will extend beyond


Packit 
cb6d3d 
* the bounds of A. Thankfully, this isn't writing data and thus


Packit 
cb6d3d 
* trampling memory, but it's still a memory access error that should


Packit 
cb6d3d 
* be fixed.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This bug is not fixed yet.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
if(i_stutter_or_gap(A,B,aoffset+1,boffset*matchA+1,*matchA))


Packit 
cb6d3d 
return;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* It is a stutter, so we need to signal that we need to remove


Packit 
cb6d3d 
* (matchA) bytes from B.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
*matchB = *matchA;


Packit 
cb6d3d 
*matchA=0;


Packit 
cb6d3d 
return;


Packit 
cb6d3d 


Packit 
cb6d3d 
}else{


Packit 
cb6d3d 
/* Case (2) is the inverse of case (1) above. */


Packit 
cb6d3d 
if(i_stutter_or_gap(B,A,boffset+1,aoffset*matchB+1,*matchB))


Packit 
cb6d3d 
return;


Packit 
cb6d3d 


Packit 
cb6d3d 
*matchA = *matchB;


Packit 
cb6d3d 
*matchB=0;


Packit 
cb6d3d 
return;


Packit 
cb6d3d 
}


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 


Packit 
cb6d3d 
/* ===========================================================================


Packit 
cb6d3d 
* analyze_rift_silence_f (internal)


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function examines the fragment and root from the rift onward to


Packit 
cb6d3d 
* see if they have a rift's worth of silence (or if they end with silence).


Packit 
cb6d3d 
* It sets (*matchA) to 1 if A's rift is silence, (*matchB) to 1 if B's


Packit 
cb6d3d 
* rift is silence, and sets them to 0 otherwise.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Note that, unlike every other function in cdparanoia, this function


Packit 
cb6d3d 
* considers any repeated value to be silence (which, in effect, it is).


Packit 
cb6d3d 
* All other functions only consider repeated zeroes to be silence.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* ??? Is this function name just a misnomer, as it's really looking for


Packit 
cb6d3d 
* repeated garbage?


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* This function is called by i_stage2_each() if it runs into a trailing rift


Packit 
cb6d3d 
* that i_analyze_rift_f couldn't diagnose. This checks for another variant:


Packit 
cb6d3d 
* where one vector has silence and the other doesn't. We then assume


Packit 
cb6d3d 
* that the silence (and anything following it) is garbage.


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Note that while this function checks both A and B for silence, the caller


Packit 
cb6d3d 
* assumes that only one or the other has silence.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
void


Packit 
cb6d3d 
analyze_rift_silence_f(int16_t *A,int16_t *B,long sizeA,long sizeB,


Packit 
cb6d3d 
long aoffset, long boffset,


Packit 
cb6d3d 
long *matchA, long *matchB)


Packit 
cb6d3d 
{


Packit 
cb6d3d 
*matchA=1;


Packit 
cb6d3d 
*matchB=1;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Search for MIN_WORDS_RIFT samples, or to the end of the vector,


Packit 
cb6d3d 
* whichever comes first.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
sizeA=min(sizeA,aoffset+MIN_WORDS_RIFT);


Packit 
cb6d3d 
sizeB=min(sizeB,boffset+MIN_WORDS_RIFT);


Packit 
cb6d3d 


Packit 
cb6d3d 
aoffset++;


Packit 
cb6d3d 
boffset++;


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Check whether A has only "silence" within the search range. Note


Packit 
cb6d3d 
* that "silence" here is a single, repeated value (zero or not).


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
while(aoffset


Packit 
cb6d3d 
if(A[aoffset]!=A[aoffset1]){


Packit 
cb6d3d 
*matchA=0;


Packit 
cb6d3d 
break;


Packit 
cb6d3d 
}


Packit 
cb6d3d 
aoffset++;


Packit 
cb6d3d 
}


Packit 
cb6d3d 


Packit 
cb6d3d 
/* Check whether B has only "silence" within the search range. Note


Packit 
cb6d3d 
* that "silence" here is a single, repeated value (zero or not).


Packit 
cb6d3d 
*


Packit 
cb6d3d 
* Also note that while the caller assumes that only matchA or matchB


Packit 
cb6d3d 
* is set, we check both vectors here.


Packit 
cb6d3d 
*/


Packit 
cb6d3d 
while(boffset


Packit 
cb6d3d 
if(B[boffset]!=B[boffset1]){


Packit 
cb6d3d 
*matchB=0;


Packit 
cb6d3d 
break;


Packit 
cb6d3d 
}


Packit 
cb6d3d 
boffset++;


Packit 
cb6d3d 
}


Packit 
cb6d3d 
}
