/* @(#)gap.c 1.12 04/02/18 J. Schilling from cdparanoia-III-alpha9.8 */
#ifndef lint
static char sccsid[] =
"@(#)gap.c 1.12 04/02/18 J. Schilling from cdparanoia-III-alpha9.8";
#endif
/*
* Modifications to make the code portable Copyright (c) 2002 J. Schilling
*/
/*
* CopyPolicy: GNU Public License 2 applies
* Copyright (C) by Monty (xiphmont@mit.edu)
*
* Gapa analysis support code for paranoia
*
*/
#include <mconfig.h>
#include <standard.h>
#include <utypes.h>
#include <strdefs.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
*/
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;
for (; beginA >= 0 && beginB >= 0; beginA--, beginB--)
if (buffA[beginA] != buffB[beginB])
break;
beginA++;
beginB++;
return (offsetA - beginA);
}
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;
for (; endA < sizeA && endB < sizeB; endA++, endB++)
if (buffA[endA] != buffB[endB])
break;
return (endA - offsetA);
}
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;
if (a1 < 0) {
b1 -= a1;
gap += a1;
a1 = 0;
}
return (memcmp(A + a1, B + b1, gap * 2));
}
/*
* riftv is the first value into the rift -> or <-
*/
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;
/*
* Look for three possible matches... (A) Ariftv->B,
* (B) Briftv->A and (c) AB->AB.
*/
for (i = 0; ; i++) {
if (i < bpast) /* A */
if (i_paranoia_overlap_f(A, B, aoffset, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) {
*matchA = i;
break;
}
if (i < apast) { /* B */
if (i_paranoia_overlap_f(A, B, aoffset + i, boffset, sizeA, sizeB) >= MIN_WORDS_RIFT) {
*matchB = i;
break;
}
if (i < bpast) /* C */
if (i_paranoia_overlap_f(A, B, aoffset + i, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) {
*matchC = i;
break;
}
} else if (i >= bpast)
break;
}
if (*matchA == 0 && *matchB == 0 && *matchC == 0)
return;
if (*matchC)
return;
if (*matchA) {
if (i_stutter_or_gap(A, B, aoffset - *matchA, boffset, *matchA))
return;
*matchB = -*matchA; /* signify we need to remove n bytes */
/* from B */
*matchA = 0;
return;
} else {
if (i_stutter_or_gap(B, A, boffset - *matchB, aoffset, *matchB))
return;
*matchA = -*matchB;
*matchB = 0;
return;
}
}
/*
* riftv must be first even val of rift moving back
*/
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;
/*
* Look for three possible matches... (A) Ariftv->B, (B) Briftv->A and
* (c) AB->AB.
*/
for (i = 0; ; i++) {
if (i < bpast) /* A */
if (i_paranoia_overlap_r(A, B, aoffset, boffset - i) >= MIN_WORDS_RIFT) {
*matchA = i;
break;
}
if (i < apast) { /* B */
if (i_paranoia_overlap_r(A, B, aoffset - i, boffset) >= MIN_WORDS_RIFT) {
*matchB = i;
break;
}
if (i < bpast) /* C */
if (i_paranoia_overlap_r(A, B, aoffset - i, boffset - i) >= MIN_WORDS_RIFT) {
*matchC = i;
break;
}
} else if (i >= bpast)
break;
}
if (*matchA == 0 && *matchB == 0 && *matchC == 0)
return;
if (*matchC)
return;
if (*matchA) {
if (i_stutter_or_gap(A, B, aoffset + 1, boffset - *matchA + 1, *matchA))
return;
*matchB = -*matchA; /* signify we need to remove n bytes */
/* from B */
*matchA = 0;
return;
} else {
if (i_stutter_or_gap(B, A, boffset + 1, aoffset - *matchB + 1, *matchB))
return;
*matchA = -*matchB;
*matchB = 0;
return;
}
}
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++;
while (aoffset < sizeA) {
if (A[aoffset] != A[aoffset - 1]) {
*matchA = 0;
break;
}
aoffset++;
}
while (boffset < sizeB) {
if (B[boffset] != B[boffset - 1]) {
*matchB = 0;
break;
}
boffset++;
}
}
syntax highlighted by Code2HTML, v. 0.9.1