Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / libparanoia / gap.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)gap.c    1.12 04/02/18 J. Schilling from cdparanoia-III-alpha9.8 */
14 /*
15  *      Modifications to make the code portable Copyright (c) 2002 J. Schilling
16  */
17 /*
18  * CopyPolicy: GNU Public License 2 applies
19  * Copyright (C) by Monty (xiphmont@mit.edu)
20  *
21  * Gapa analysis support code for paranoia
22  *
23  */
24
25 #include <mconfig.h>
26 #include <standard.h>
27 #include <utypes.h>
28 #include <strdefs.h>
29 #include "p_block.h"
30 #include "cdda_paranoia.h"
31 #include "gap.h"
32
33 long i_paranoia_overlap_r(Int16_t * buffA, Int16_t * buffB, long offsetA, 
34                                                                   long offsetB);
35 long i_paranoia_overlap_f(Int16_t * buffA, Int16_t * buffB, long offsetA, 
36                                                                   long offsetB, long sizeA, long sizeB);
37 int i_stutter_or_gap(Int16_t * A, Int16_t * B, long offA, long offB, long gap);
38 void i_analyze_rift_f(Int16_t * A, Int16_t * B, 
39                                                     long sizeA, long sizeB, 
40                                                          long aoffset, long boffset, 
41                                                          long *matchA, long *matchB, long *matchC);
42 void i_analyze_rift_r(Int16_t * A, Int16_t * B,
43                       long sizeA, long sizeB,
44                       long aoffset, long boffset,
45                       long *matchA, long *matchB, long *matchC);
46 void analyze_rift_silence_f(Int16_t * A, Int16_t * B,
47                             long sizeA, long sizeB,
48                             long aoffset, long boffset,
49                             long *matchA, long *matchB);
50
51 /*
52  * Gap analysis code
53  */
54 long i_paranoia_overlap_r(Int16_t *buffA, Int16_t *buffB, long offsetA, 
55                           long offsetB)
56 {
57         long            beginA = offsetA;
58         long            beginB = offsetB;
59
60         for (; beginA >= 0 && beginB >= 0; beginA--, beginB--)
61                 if (buffA[beginA] != buffB[beginB])
62                         break;
63         beginA++;
64         beginB++;
65
66         return (offsetA - beginA);
67 }
68
69 long i_paranoia_overlap_f(Int16_t *buffA, Int16_t *buffB, long offsetA, 
70                           long offsetB, long sizeA, long sizeB)
71 {
72         long            endA = offsetA;
73         long            endB = offsetB;
74
75         for (; endA < sizeA && endB < sizeB; endA++, endB++)
76                 if (buffA[endA] != buffB[endB])
77                         break;
78
79         return (endA - offsetA);
80 }
81
82 int i_stutter_or_gap(Int16_t *A, Int16_t *B, long offA, long offB, long gap)
83 {
84         long            a1 = offA;
85         long            b1 = offB;
86
87         if (a1 < 0) {
88                 b1 -= a1;
89                 gap += a1;
90                 a1 = 0;
91         }
92         return (memcmp(A + a1, B + b1, gap * 2));
93 }
94
95 /*
96  * riftv is the first value into the rift -> or <-
97  */
98 void i_analyze_rift_f(Int16_t *A, Int16_t *B, long sizeA, long sizeB,
99                       long aoffset, long boffset, long *matchA, long *matchB, 
100                       long *matchC)
101 {
102
103         long            apast = sizeA - aoffset;
104         long            bpast = sizeB - boffset;
105         long            i;
106
107         *matchA = 0, *matchB = 0, *matchC = 0;
108
109         /*
110          * Look for three possible matches... (A) Ariftv->B,
111          * (B) Briftv->A and (c) AB->AB.
112          */
113         for (i = 0; ; i++) {
114                 if (i < bpast)  /* A */
115                         if (i_paranoia_overlap_f(A, B, aoffset, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) {
116                                 *matchA = i;
117                                 break;
118                         }
119                 if (i < apast) {        /* B */
120                         if (i_paranoia_overlap_f(A, B, aoffset + i, boffset, sizeA, sizeB) >= MIN_WORDS_RIFT) {
121                                 *matchB = i;
122                                 break;
123                         }
124                         if (i < bpast)  /* C */
125                                 if (i_paranoia_overlap_f(A, B, aoffset + i, boffset + i, sizeA, sizeB) >= MIN_WORDS_RIFT) {
126                                         *matchC = i;
127                                         break;
128                                 }
129                 } else if (i >= bpast)
130                         break;
131
132         }
133
134         if (*matchA == 0 && *matchB == 0 && *matchC == 0)
135                 return;
136
137         if (*matchC)
138                 return;
139         if (*matchA) {
140                 if (i_stutter_or_gap(A, B, aoffset - *matchA, boffset, *matchA))
141                         return;
142                 *matchB = -*matchA;     /* signify we need to remove n bytes */
143                                         /* from B */
144                 *matchA = 0;
145                 return;
146         } else {
147                 if (i_stutter_or_gap(B, A, boffset - *matchB, aoffset, *matchB))
148                         return;
149                 *matchA = -*matchB;
150                 *matchB = 0;
151                 return;
152         }
153 }
154
155 /*
156  * riftv must be first even val of rift moving back
157  */
158 void i_analyze_rift_r(Int16_t *A, Int16_t *B, long sizeA, long sizeB, 
159                       long aoffset, long boffset, long *matchA, long *matchB, 
160                       long *matchC)
161 {
162
163         long            apast = aoffset + 1;
164         long            bpast = boffset + 1;
165         long            i;
166
167         *matchA = 0, *matchB = 0, *matchC = 0;
168
169         /*
170          * Look for three possible matches... (A) Ariftv->B, (B) Briftv->A and
171          * (c) AB->AB.
172          */
173         for (i = 0; ; i++) {
174                 if (i < bpast)  /* A */
175                         if (i_paranoia_overlap_r(A, B, aoffset, boffset - i) >= MIN_WORDS_RIFT) {
176                                 *matchA = i;
177                                 break;
178                         }
179                 if (i < apast) {        /* B */
180                         if (i_paranoia_overlap_r(A, B, aoffset - i, boffset) >= MIN_WORDS_RIFT) {
181                                 *matchB = i;
182                                 break;
183                         }
184                         if (i < bpast)  /* C */
185                                 if (i_paranoia_overlap_r(A, B, aoffset - i, boffset - i) >= MIN_WORDS_RIFT) {
186                                         *matchC = i;
187                                         break;
188                                 }
189                 } else if (i >= bpast)
190                         break;
191
192         }
193
194         if (*matchA == 0 && *matchB == 0 && *matchC == 0)
195                 return;
196
197         if (*matchC)
198                 return;
199
200         if (*matchA) {
201                 if (i_stutter_or_gap(A, B, aoffset + 1, boffset - *matchA + 1, *matchA))
202                         return;
203                 *matchB = -*matchA;     /* signify we need to remove n bytes */
204                                         /* from B */
205                 *matchA = 0;
206                 return;
207         } else {
208                 if (i_stutter_or_gap(B, A, boffset + 1, aoffset - *matchB + 1, *matchB))
209                         return;
210                 *matchA = -*matchB;
211                 *matchB = 0;
212                 return;
213         }
214 }
215
216 void analyze_rift_silence_f(Int16_t *A, Int16_t *B, long sizeA, long sizeB, 
217                             long aoffset, long boffset, long *matchA, 
218                             long *matchB)
219 {
220         *matchA = -1;
221         *matchB = -1;
222
223         sizeA = min(sizeA, aoffset + MIN_WORDS_RIFT);
224         sizeB = min(sizeB, boffset + MIN_WORDS_RIFT);
225
226         aoffset++;
227         boffset++;
228
229         while (aoffset < sizeA) {
230                 if (A[aoffset] != A[aoffset - 1]) {
231                         *matchA = 0;
232                         break;
233                 }
234                 aoffset++;
235         }
236
237         while (boffset < sizeB) {
238                 if (B[boffset] != B[boffset - 1]) {
239                         *matchB = 0;
240                         break;
241                 }
242                 boffset++;
243         }
244 }