diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-12-31 05:04:42 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-12-31 05:04:42 +0400 |
commit | 71dc8760ff4de5f365330d1bc571d934deb54af9 (patch) | |
tree | 7346d42a282562a3937d82307012b5857d642ce6 /libparanoia/gap.c | |
download | cdrkit-941fb342494d2b61ef5fd1870a4fa695d1c7fc69.tar.gz |
Imported Upstream version 1.1.11upstream/1.1.11upstream
Diffstat (limited to 'libparanoia/gap.c')
-rw-r--r-- | libparanoia/gap.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/libparanoia/gap.c b/libparanoia/gap.c new file mode 100644 index 0000000..6bb1b92 --- /dev/null +++ b/libparanoia/gap.c @@ -0,0 +1,244 @@ +/* + * This file has been modified for the cdrkit suite. + * + * The behaviour and appearence of the program code below can differ to a major + * extent from the version distributed by the original author(s). + * + * For details, see Changelog file distributed with the cdrkit package. If you + * received this file from another source then ask the distributing person for + * a log of modifications. + * + */ + +/* @(#)gap.c 1.12 04/02/18 J. Schilling from cdparanoia-III-alpha9.8 */ +/* + * 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" + +long i_paranoia_overlap_r(Int16_t * buffA, Int16_t * buffB, long offsetA, + long offsetB); +long i_paranoia_overlap_f(Int16_t * buffA, Int16_t * buffB, long offsetA, + long offsetB, long sizeA, long sizeB); +int i_stutter_or_gap(Int16_t * A, Int16_t * B, long offA, long offB, long gap); +void i_analyze_rift_f(Int16_t * A, Int16_t * B, + long sizeA, long sizeB, + long aoffset, long boffset, + long *matchA, long *matchB, long *matchC); +void i_analyze_rift_r(Int16_t * A, Int16_t * B, + long sizeA, long sizeB, + long aoffset, long boffset, + long *matchA, long *matchB, long *matchC); +void analyze_rift_silence_f(Int16_t * A, Int16_t * B, + long sizeA, long sizeB, + long aoffset, long boffset, + long *matchA, long *matchB); + +/* + * Gap analysis code + */ +long i_paranoia_overlap_r(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); +} + +long i_paranoia_overlap_f(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); +} + +int i_stutter_or_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 <- + */ +void i_analyze_rift_f(Int16_t *A, Int16_t *B, long sizeA, long sizeB, + long aoffset, long boffset, long *matchA, long *matchB, + long *matchC) +{ + + long apast = sizeA - aoffset; + long bpast = sizeB - boffset; + long i; + + *matchA = 0, *matchB = 0, *matchC = 0; + + /* + * Look for three possible matches... (A) Ariftv->B, + * (B) Briftv->A and (c) AB->AB. + */ + for (i = 0; ; i++) { + if (i < bpast) /* A */ + if (i_paranoia_overlap_f(A, B, aoffset, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) { + *matchA = i; + break; + } + if (i < apast) { /* B */ + if (i_paranoia_overlap_f(A, B, aoffset + i, boffset, sizeA, sizeB) >= MIN_WORDS_RIFT) { + *matchB = i; + break; + } + if (i < bpast) /* C */ + if (i_paranoia_overlap_f(A, B, aoffset + i, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) { + *matchC = i; + break; + } + } else if (i >= bpast) + break; + + } + + if (*matchA == 0 && *matchB == 0 && *matchC == 0) + return; + + if (*matchC) + return; + if (*matchA) { + if (i_stutter_or_gap(A, B, aoffset - *matchA, boffset, *matchA)) + return; + *matchB = -*matchA; /* signify we need to remove n bytes */ + /* from B */ + *matchA = 0; + return; + } else { + if (i_stutter_or_gap(B, A, boffset - *matchB, aoffset, *matchB)) + return; + *matchA = -*matchB; + *matchB = 0; + return; + } +} + +/* + * riftv must be first even val of rift moving back + */ +void i_analyze_rift_r(Int16_t *A, Int16_t *B, long sizeA, long sizeB, + long aoffset, long boffset, long *matchA, long *matchB, + long *matchC) +{ + + long apast = aoffset + 1; + long bpast = boffset + 1; + long i; + + *matchA = 0, *matchB = 0, *matchC = 0; + + /* + * Look 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; + } +} + +void analyze_rift_silence_f(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++; + } +} |