589 lines
18 KiB
C
589 lines
18 KiB
C
|
/* @(#)gap.c 1.18 09/07/11 J. Schilling from cdparanoia-III-alpha9.8 */
|
||
|
#include <schily/mconfig.h>
|
||
|
#ifndef lint
|
||
|
static UConst char sccsid[] =
|
||
|
"@(#)gap.c 1.18 09/07/11 J. Schilling from cdparanoia-III-alpha9.8";
|
||
|
|
||
|
#endif
|
||
|
/*
|
||
|
* CopyPolicy: GNU Lesser General Public License v2.1 applies
|
||
|
* Copyright (C) 1997-2001,2008 by Monty (xiphmont@mit.edu)
|
||
|
* Copyright (C) 2002-2009 by J. Schilling
|
||
|
*
|
||
|
* Gap analysis support code for paranoia
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <schily/standard.h>
|
||
|
#include <schily/utypes.h>
|
||
|
#include <schily/string.h>
|
||
|
#include "p_block.h"
|
||
|
#include "cdda_paranoia.h"
|
||
|
#include "gap.h"
|
||
|
|
||
|
EXPORT long i_paranoia_overlap_r __PR((Int16_t * buffA, Int16_t * buffB,
|
||
|
long offsetA, long offsetB));
|
||
|
EXPORT long i_paranoia_overlap_f __PR((Int16_t * buffA, Int16_t * buffB,
|
||
|
long offsetA, long offsetB,
|
||
|
long sizeA, long sizeB));
|
||
|
EXPORT int i_stutter_or_gap __PR((Int16_t * A, Int16_t * B,
|
||
|
long offA, long offB,
|
||
|
long gap));
|
||
|
EXPORT void i_analyze_rift_f __PR((Int16_t * A, Int16_t * B,
|
||
|
long sizeA, long sizeB,
|
||
|
long aoffset, long boffset,
|
||
|
long *matchA, long *matchB,
|
||
|
long *matchC));
|
||
|
EXPORT void i_analyze_rift_r __PR((Int16_t * A, Int16_t * B,
|
||
|
long sizeA, long sizeB,
|
||
|
long aoffset, long boffset,
|
||
|
long *matchA, long *matchB,
|
||
|
long *matchC));
|
||
|
|
||
|
EXPORT void analyze_rift_silence_f __PR((Int16_t * A, Int16_t * B,
|
||
|
long sizeA, long sizeB,
|
||
|
long aoffset, long boffset,
|
||
|
long *matchA, long *matchB));
|
||
|
|
||
|
/*
|
||
|
* Gap analysis code
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* i_paranoia_overlap_r (internal)
|
||
|
*
|
||
|
* This function seeks backward through two vectors (starting at the given
|
||
|
* offsets) to determine how many consecutive samples agree. It returns
|
||
|
* the number of matching samples, which may be 0.
|
||
|
*
|
||
|
* Unlike its sibling, i_paranoia_overlap_f, this function doesn't need to
|
||
|
* be given the size of the vectors (all vectors stop at offset 0).
|
||
|
*
|
||
|
* This function is used by i_analyze_rift_r() below to find where a
|
||
|
* leading rift ends.
|
||
|
*/
|
||
|
EXPORT long
|
||
|
i_paranoia_overlap_r(buffA, buffB, offsetA, offsetB)
|
||
|
Int16_t *buffA;
|
||
|
Int16_t *buffB;
|
||
|
long offsetA;
|
||
|
long offsetB;
|
||
|
{
|
||
|
long beginA = offsetA;
|
||
|
long beginB = offsetB;
|
||
|
|
||
|
/*
|
||
|
* Start at the given offsets and work our way backwards until we hit
|
||
|
* the beginning of one of the vectors.
|
||
|
*/
|
||
|
for (; beginA >= 0 && beginB >= 0; beginA--, beginB--)
|
||
|
if (buffA[beginA] != buffB[beginB])
|
||
|
break;
|
||
|
|
||
|
return (offsetA - beginA);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* i_paranoia_overlap_f (internal)
|
||
|
*
|
||
|
* This function seeks forward through two vectors (starting at the given
|
||
|
* offsets) to determine how many consecutive samples agree. It returns
|
||
|
* the number of matching samples, which may be 0.
|
||
|
*
|
||
|
* Unlike its sibling, i_paranoia_overlap_r, this function needs to given
|
||
|
* the size of the vectors.
|
||
|
*
|
||
|
* This function is used by i_analyze_rift_f() below to find where a
|
||
|
* trailing rift ends.
|
||
|
*/
|
||
|
EXPORT long
|
||
|
i_paranoia_overlap_f(buffA, buffB, offsetA, offsetB, sizeA, sizeB)
|
||
|
Int16_t *buffA;
|
||
|
Int16_t *buffB;
|
||
|
long offsetA;
|
||
|
long offsetB;
|
||
|
long sizeA;
|
||
|
long sizeB;
|
||
|
{
|
||
|
long endA = offsetA;
|
||
|
long endB = offsetB;
|
||
|
|
||
|
/*
|
||
|
* Start at the given offsets and work our way forward until we hit
|
||
|
* the end of one of the vectors.
|
||
|
*/
|
||
|
for (; endA < sizeA && endB < sizeB; endA++, endB++)
|
||
|
if (buffA[endA] != buffB[endB])
|
||
|
break;
|
||
|
|
||
|
return (endA - offsetA);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* i_stutter_or_gap (internal)
|
||
|
*
|
||
|
* This function compares (gap) samples of two vectors at the given offsets.
|
||
|
* It returns 0 if all the samples are identical, or nonzero if they differ.
|
||
|
*
|
||
|
* This is used by i_analyze_rift_[rf] below to determine whether a rift
|
||
|
* contains samples dropped by the other vector (that should be inserted),
|
||
|
* or whether the rift contains a stutter (that should be dropped). See
|
||
|
* i_analyze_rift_[rf] for more details.
|
||
|
*/
|
||
|
EXPORT int
|
||
|
i_stutter_or_gap(A, B, offA, offB, gap)
|
||
|
Int16_t *A;
|
||
|
Int16_t *B;
|
||
|
long offA;
|
||
|
long offB;
|
||
|
long gap;
|
||
|
{
|
||
|
long a1 = offA;
|
||
|
long b1 = offB;
|
||
|
|
||
|
/* BEGIN CSTYLED */
|
||
|
/*
|
||
|
* If the rift was so big that there aren't enough samples in the other
|
||
|
* vector to compare against the full gap, then just compare what we
|
||
|
* have available. E.g.:
|
||
|
*
|
||
|
* (5678)|(newly matching run ...)
|
||
|
* (... 12345678)| (345678) |(newly matching run ...)
|
||
|
*
|
||
|
* In this case, a1 would be -2, since we'd want to compare 6 samples
|
||
|
* against a vector that had only 4. So we start 2 samples later, and
|
||
|
* compare the 4 available samples.
|
||
|
*
|
||
|
* Again, this approach to identifying stutters is simply a heuristic,
|
||
|
* so this may not produce correct results in all cases.
|
||
|
*/
|
||
|
/* END CSTYLED */
|
||
|
if (a1 < 0) {
|
||
|
/*
|
||
|
* Note that a1 is negative, so we're increasing b1 and decreasing (gap).
|
||
|
*/
|
||
|
b1 -= a1;
|
||
|
gap += a1;
|
||
|
a1 = 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Note that we don't have an equivalent adjustment for leading rifts.
|
||
|
* Thus, it's possible for the following memcmp() to run off the end
|
||
|
* of A. See the bug note in i_analyze_rift_r().
|
||
|
*
|
||
|
* Multiply gap by 2 because samples are 2 bytes long and memcmp compares
|
||
|
* at the byte level.
|
||
|
*/
|
||
|
return (memcmp(A + a1, B + b1, gap * 2));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* riftv is the first value into the rift -> or <-
|
||
|
*
|
||
|
* i_analyze_rift_f (internal)
|
||
|
*
|
||
|
* This function examines a trailing rift to see how far forward the rift goes
|
||
|
* and to determine what kind of rift it is. This function is called by
|
||
|
* i_stage2_each() when a trailing rift is detected. (aoffset,boffset) are
|
||
|
* the offsets into (A,B) of the first mismatching sample.
|
||
|
*
|
||
|
* This function returns:
|
||
|
* matchA > 0 if there are (matchA) samples missing from A
|
||
|
* matchA < 0 if there are (-matchA) duplicate samples (stuttering) in A
|
||
|
* matchB > 0 if there are (matchB) samples missing from B
|
||
|
* matchB < 0 if there are (-matchB) duplicate samples in B
|
||
|
* matchC != 0 if there are (matchC) samples of garbage, after which
|
||
|
* both A and B are in sync again
|
||
|
*/
|
||
|
EXPORT void
|
||
|
i_analyze_rift_f(A, B, sizeA, sizeB, aoffset, boffset, matchA, matchB, matchC)
|
||
|
Int16_t *A;
|
||
|
Int16_t *B;
|
||
|
long sizeA;
|
||
|
long sizeB;
|
||
|
long aoffset;
|
||
|
long boffset;
|
||
|
long *matchA;
|
||
|
long *matchB;
|
||
|
long *matchC;
|
||
|
{
|
||
|
|
||
|
long apast = sizeA - aoffset;
|
||
|
long bpast = sizeB - boffset;
|
||
|
long i;
|
||
|
|
||
|
*matchA = 0, *matchB = 0, *matchC = 0;
|
||
|
|
||
|
/* BEGIN CSTYLED */
|
||
|
/*
|
||
|
* Look forward to see where we regain agreement between vectors
|
||
|
* A and B (of at least MIN_WORDS_RIFT samples). We look for one of
|
||
|
* the following possible matches:
|
||
|
*
|
||
|
* edge
|
||
|
* v
|
||
|
* (1) (... A matching run)|(aoffset matches ...)
|
||
|
* (... B matching run)| (rift) |(boffset+i matches ...)
|
||
|
*
|
||
|
* (2) (... A matching run)| (rift) |(aoffset+i matches ...)
|
||
|
* (... B matching run)|(boffset matches ...)
|
||
|
*
|
||
|
* (3) (... A matching run)| (rift) |(aoffset+i matches ...)
|
||
|
* (... B matching run)| (rift) |(boffset+i matches ...)
|
||
|
*
|
||
|
* Anything that doesn't match one of these three is too corrupt to
|
||
|
* for us to recover from. E.g.:
|
||
|
*
|
||
|
* (... A matching run)| (rift) |(eventual match ...)
|
||
|
* (... B matching run)| (big rift) |(eventual match ...)
|
||
|
*
|
||
|
* We won't find the eventual match, since we wouldn't be sure how
|
||
|
* to fix the rift.
|
||
|
*/
|
||
|
/* END CSTYLED */
|
||
|
for (i = 0; ; i++) {
|
||
|
/*
|
||
|
* Search for whatever case we hit first, so as to end up with the
|
||
|
* smallest rift.
|
||
|
*/
|
||
|
if (i < bpast) { /* Don't search for (1) past the end of B */
|
||
|
/*
|
||
|
* See if we match case (1) above, which either means that A dropped
|
||
|
* samples at the rift, or that B stuttered.
|
||
|
*/
|
||
|
if (i_paranoia_overlap_f(A, B, aoffset, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) {
|
||
|
*matchA = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (i < apast) { /* Don't search for (2) or (3) past the beginning of A */
|
||
|
/*
|
||
|
* See if we match case (2) above, which either means that B dropped
|
||
|
* samples at the rift, or that A stuttered.
|
||
|
*/
|
||
|
if (i_paranoia_overlap_f(A, B, aoffset + i, boffset, sizeA, sizeB) >= MIN_WORDS_RIFT) {
|
||
|
*matchB = i;
|
||
|
break;
|
||
|
}
|
||
|
if (i < bpast) /* Don't search for (3) past the end of B */
|
||
|
/*
|
||
|
* See if we match case (3) above, which means that a fixed-length
|
||
|
* rift of samples is getting read unreliably.
|
||
|
*/
|
||
|
if (i_paranoia_overlap_f(A, B, aoffset + i, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) {
|
||
|
*matchC = i;
|
||
|
break;
|
||
|
}
|
||
|
} else if (i >= bpast) {
|
||
|
/*
|
||
|
* Stop searching when we've reached the end of both vectors.
|
||
|
* In theory we could stop when there aren't MIN_WORDS_RIFT samples
|
||
|
* left in both vectors, but this case should happen fairly rarely.
|
||
|
*/
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (*matchA == 0 && *matchB == 0 && *matchC == 0)
|
||
|
return;
|
||
|
|
||
|
if (*matchC)
|
||
|
return;
|
||
|
|
||
|
/* BEGIN CSTYLED */
|
||
|
/*
|
||
|
* For case (1) or (2), we need to determine whether the rift contains
|
||
|
* samples dropped by the other vector (that should be inserted), or
|
||
|
* whether the rift contains a stutter (that should be dropped). To
|
||
|
* distinguish, we check the contents of the rift against the good samples
|
||
|
* just before the rift. If the contents match, then the rift contains
|
||
|
* a stutter.
|
||
|
*
|
||
|
* A stutter in the second vector:
|
||
|
* (...good samples... 1234)|(567 ...newly matched run...)
|
||
|
* (...good samples... 1234)| (1234) | (567 ...newly matched run)
|
||
|
*
|
||
|
* Samples missing from the first vector:
|
||
|
* (...good samples... 1234)|(901 ...newly matched run...)
|
||
|
* (...good samples... 1234)| (5678) |(901 ...newly matched run...)
|
||
|
*
|
||
|
* Of course, there's no theoretical guarantee that a non-stutter
|
||
|
* truly represents missing samples, but given that we're dealing with
|
||
|
* verified fragments in stage 2, we can have some confidence that this
|
||
|
* is the case.
|
||
|
*/
|
||
|
/* END CSTYLED */
|
||
|
if (*matchA) {
|
||
|
/*
|
||
|
* For case (1), we need to determine whether A dropped samples at the
|
||
|
* rift or whether B stuttered.
|
||
|
*
|
||
|
* If the rift doesn't match the good samples in A (and hence in B),
|
||
|
* it's not a stutter, and the rift should be inserted into A.
|
||
|
*/
|
||
|
if (i_stutter_or_gap(A, B, aoffset - *matchA, boffset, *matchA))
|
||
|
return;
|
||
|
*matchB = -*matchA; /* signify we need to remove n bytes */
|
||
|
/* from B */
|
||
|
*matchA = 0;
|
||
|
return;
|
||
|
} else {
|
||
|
/*
|
||
|
* Case (2) is the inverse of case (1) above.
|
||
|
*/
|
||
|
if (i_stutter_or_gap(B, A, boffset - *matchB, aoffset, *matchB))
|
||
|
return;
|
||
|
*matchA = -*matchB;
|
||
|
*matchB = 0;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* riftv must be first even val of rift moving back
|
||
|
*
|
||
|
* i_analyze_rift_r (internal)
|
||
|
*
|
||
|
* This function examines a leading rift to see how far back the rift goes
|
||
|
* and to determine what kind of rift it is. This function is called by
|
||
|
* i_stage2_each() when a leading rift is detected. (aoffset,boffset) are
|
||
|
* the offsets into (A,B) of the first mismatching sample.
|
||
|
*
|
||
|
* This function returns:
|
||
|
* matchA > 0 if there are (matchA) samples missing from A
|
||
|
* matchA < 0 if there are (-matchA) duplicate samples (stuttering) in A
|
||
|
* matchB > 0 if there are (matchB) samples missing from B
|
||
|
* matchB < 0 if there are (-matchB) duplicate samples in B
|
||
|
* matchC != 0 if there are (matchC) samples of garbage, after which
|
||
|
* both A and B are in sync again
|
||
|
*/
|
||
|
EXPORT void
|
||
|
i_analyze_rift_r(A, B, sizeA, sizeB, aoffset, boffset, matchA, matchB, matchC)
|
||
|
Int16_t *A;
|
||
|
Int16_t *B;
|
||
|
long sizeA;
|
||
|
long sizeB;
|
||
|
long aoffset;
|
||
|
long boffset;
|
||
|
long *matchA;
|
||
|
long *matchB;
|
||
|
long *matchC;
|
||
|
{
|
||
|
|
||
|
long apast = aoffset + 1;
|
||
|
long bpast = boffset + 1;
|
||
|
long i;
|
||
|
|
||
|
*matchA = 0, *matchB = 0, *matchC = 0;
|
||
|
|
||
|
/* BEGIN CSTYLED */
|
||
|
/*
|
||
|
* Look backward to see where we regain agreement between vectors
|
||
|
* A and B (of at least MIN_WORDS_RIFT samples). We look for one of
|
||
|
* the following possible matches:
|
||
|
*
|
||
|
* edge
|
||
|
* v
|
||
|
* (1) (... aoffset matches)|(A matching run ...)
|
||
|
* (... boffset-i matches)| (rift) |(B matching run ...)
|
||
|
*
|
||
|
* (2) (... aoffset-i matches)| (rift) |(A matching run ...)
|
||
|
* (... boffset matches)|(B matching run ...)
|
||
|
*
|
||
|
* (3) (... aoffset-i matches)| (rift) |(A matching run ...)
|
||
|
* (... boffset-i matches)| (rift) |(B matching run ...)
|
||
|
*
|
||
|
* Anything that doesn't match one of these three is too corrupt to
|
||
|
* for us to recover from. E.g.:
|
||
|
*
|
||
|
* (... eventual match)| (rift) |(A matching run ...)
|
||
|
* (... eventual match) | (big rift) |(B matching run ...)
|
||
|
*
|
||
|
* We won't find the eventual match, since we wouldn't be sure how
|
||
|
* to fix the rift.
|
||
|
*/
|
||
|
/* END CSTYLED */
|
||
|
for (i = 0; ; i++) {
|
||
|
/*
|
||
|
* Search for whatever case we hit first, so as to end up with the
|
||
|
* smallest rift.
|
||
|
*/
|
||
|
if (i < bpast) { /* Don't search for (1) past the beginning of B */
|
||
|
/*
|
||
|
* See if we match case (1) above, which either means that A dropped
|
||
|
* samples at the rift, or that B stuttered.
|
||
|
*/
|
||
|
if (i_paranoia_overlap_r(A, B, aoffset, boffset - i) >= MIN_WORDS_RIFT) {
|
||
|
*matchA = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (i < apast) { /* Don't search for (2) or (3) past the beginning of A */
|
||
|
/*
|
||
|
* See if we match case (2) above, which either means that B dropped
|
||
|
* samples at the rift, or that A stuttered.
|
||
|
*/
|
||
|
if (i_paranoia_overlap_r(A, B, aoffset - i, boffset) >= MIN_WORDS_RIFT) {
|
||
|
*matchB = i;
|
||
|
break;
|
||
|
}
|
||
|
if (i < bpast) { /* Don't search for (3) past the beginning of B */
|
||
|
/*
|
||
|
* See if we match case (3) above, which means that a fixed-length
|
||
|
* rift of samples is getting read unreliably.
|
||
|
*/
|
||
|
if (i_paranoia_overlap_r(A, B, aoffset - i, boffset - i) >= MIN_WORDS_RIFT) {
|
||
|
*matchC = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} else if (i >= bpast) {
|
||
|
/*
|
||
|
* Stop searching when we've reached the end of both vectors.
|
||
|
* In theory we could stop when there aren't MIN_WORDS_RIFT samples
|
||
|
* left in both vectors, but this case should happen fairly rarely.
|
||
|
*/
|
||
|
break;
|
||
|
}
|
||
|
/*
|
||
|
* Try the search again with a larger tentative rift.
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
if (*matchA == 0 && *matchB == 0 && *matchC == 0)
|
||
|
return;
|
||
|
|
||
|
if (*matchC)
|
||
|
return;
|
||
|
|
||
|
/* BEGIN CSTYLED */
|
||
|
/*
|
||
|
* For case (1) or (2), we need to determine whether the rift contains
|
||
|
* samples dropped by the other vector (that should be inserted), or
|
||
|
* whether the rift contains a stutter (that should be dropped). To
|
||
|
* distinguish, we check the contents of the rift against the good samples
|
||
|
* just after the rift. If the contents match, then the rift contains
|
||
|
* a stutter.
|
||
|
*
|
||
|
* A stutter in the second vector:
|
||
|
* (...newly matched run... 234)|(5678 ...good samples...)
|
||
|
* (...newly matched run... 234)| (5678) |(5678 ...good samples...)
|
||
|
*
|
||
|
* Samples missing from the first vector:
|
||
|
* (...newly matched run... 890)|(5678 ...good samples...)
|
||
|
* (...newly matched run... 890)| (1234) |(5678 ...good samples...)
|
||
|
*
|
||
|
* Of course, there's no theoretical guarantee that a non-stutter
|
||
|
* truly represents missing samples, but given that we're dealing with
|
||
|
* verified fragments in stage 2, we can have some confidence that this
|
||
|
* is the case.
|
||
|
*/
|
||
|
/* END CSTYLED */
|
||
|
if (*matchA) {
|
||
|
/*
|
||
|
* For case (1), we need to determine whether A dropped samples at the
|
||
|
* rift or whether B stuttered.
|
||
|
*
|
||
|
* If the rift doesn't match the good samples in A (and hence in B),
|
||
|
* it's not a stutter, and the rift should be inserted into A.
|
||
|
*
|
||
|
* ???BUG??? It's possible for aoffset+1+*matchA to be > sizeA, in
|
||
|
* which case the comparison in i_stutter_or_gap() will extend beyond
|
||
|
* the bounds of A. Thankfully, this isn't writing data and thus
|
||
|
* trampling memory, but it's still a memory access error that should
|
||
|
* be fixed.
|
||
|
*
|
||
|
* This bug is not fixed yet.
|
||
|
*/
|
||
|
if (i_stutter_or_gap(A, B, aoffset + 1, boffset - *matchA + 1, *matchA))
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* It is a stutter, so we need to signal that we need to remove
|
||
|
* (matchA) bytes from B.
|
||
|
*/
|
||
|
*matchB = -*matchA; /* signify we need to remove n bytes */
|
||
|
/* from B */
|
||
|
*matchA = 0;
|
||
|
return;
|
||
|
} else {
|
||
|
/*
|
||
|
* Case (2) is the inverse of case (1) above.
|
||
|
*/
|
||
|
if (i_stutter_or_gap(B, A, boffset + 1, aoffset - *matchB + 1, *matchB))
|
||
|
return;
|
||
|
*matchA = -*matchB;
|
||
|
*matchB = 0;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* analyze_rift_silence_f (internal)
|
||
|
*
|
||
|
* This function examines the fragment and root from the rift onward to
|
||
|
* see if they have a rift's worth of silence (or if they end with silence).
|
||
|
* It sets (*matchA) to -1 if A's rift is silence, (*matchB) to -1 if B's
|
||
|
* rift is silence, and sets them to 0 otherwise.
|
||
|
*
|
||
|
* Note that, unlike every other function in cdparanoia, this function
|
||
|
* considers any repeated value to be silence (which, in effect, it is).
|
||
|
* All other functions only consider repeated zeroes to be silence.
|
||
|
*
|
||
|
* This function is called by i_stage2_each() if it runs into a trailing rift
|
||
|
* that i_analyze_rift_f couldn't diagnose. This checks for another variant:
|
||
|
* where one vector has silence and the other doesn't. We then assume
|
||
|
* that the silence (and anything following it) is garbage.
|
||
|
*
|
||
|
* Note that while this function checks both A and B for silence, the caller
|
||
|
* assumes that only one or the other has silence.
|
||
|
*/
|
||
|
EXPORT void
|
||
|
analyze_rift_silence_f(A, B, sizeA, sizeB, aoffset, boffset, matchA, matchB)
|
||
|
Int16_t *A;
|
||
|
Int16_t *B;
|
||
|
long sizeA;
|
||
|
long sizeB;
|
||
|
long aoffset;
|
||
|
long boffset;
|
||
|
long *matchA;
|
||
|
long *matchB;
|
||
|
{
|
||
|
*matchA = -1;
|
||
|
*matchB = -1;
|
||
|
|
||
|
sizeA = min(sizeA, aoffset + MIN_WORDS_RIFT);
|
||
|
sizeB = min(sizeB, boffset + MIN_WORDS_RIFT);
|
||
|
|
||
|
aoffset++;
|
||
|
boffset++;
|
||
|
|
||
|
/*
|
||
|
* Check whether A has only "silence" within the search range. Note
|
||
|
* that "silence" here is a single, repeated value (zero or not).
|
||
|
*/
|
||
|
while (aoffset < sizeA) {
|
||
|
if (A[aoffset] != A[aoffset - 1]) {
|
||
|
*matchA = 0;
|
||
|
break;
|
||
|
}
|
||
|
aoffset++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Check whether B has only "silence" within the search range. Note
|
||
|
* that "silence" here is a single, repeated value (zero or not).
|
||
|
*
|
||
|
* Also note that while the caller assumes that only matchA or matchB
|
||
|
* is set, we check both vectors here.
|
||
|
*/
|
||
|
while (boffset < sizeB) {
|
||
|
if (B[boffset] != B[boffset - 1]) {
|
||
|
*matchB = 0;
|
||
|
break;
|
||
|
}
|
||
|
boffset++;
|
||
|
}
|
||
|
}
|