1 /***
2  * CopyPolicy: GNU Public License 2 applies
3  * Copyright (C) by Monty (xiphmont@mit.edu)
4  *
5  * Gapa analysis support code for paranoia
6  *
7  ***/
8 
9 #include <string.h>
10 #include "p_block.h"
11 #include "cdda_paranoia.h"
12 #include "gap.h"
13 
14 /**** Gap analysis code ***************************************************/
15 
i_paranoia_overlap_r(int16_t * buffA,int16_t * buffB,long offsetA,long offsetB)16 long i_paranoia_overlap_r(int16_t *buffA,int16_t *buffB,
17 			  long offsetA, long offsetB){
18   long beginA=offsetA;
19   long beginB=offsetB;
20 
21   for(;beginA>=0 && beginB>=0;beginA--,beginB--)
22     if(buffA[beginA]!=buffB[beginB])break;
23   beginA++;
24   beginB++;
25 
26   return(offsetA-beginA);
27 }
28 
i_paranoia_overlap_f(int16_t * buffA,int16_t * buffB,long offsetA,long offsetB,long sizeA,long sizeB)29 long i_paranoia_overlap_f(int16_t *buffA,int16_t *buffB,
30 			  long offsetA, long offsetB,
31 			  long sizeA,long sizeB){
32   long endA=offsetA;
33   long endB=offsetB;
34 
35   for(;endA<sizeA && endB<sizeB;endA++,endB++)
36     if(buffA[endA]!=buffB[endB])break;
37 
38   return(endA-offsetA);
39 }
40 
i_stutter_or_gap(int16_t * A,int16_t * B,long offA,long offB,long gap)41 int i_stutter_or_gap(int16_t *A, int16_t *B,long offA, long offB,
42 		     long gap){
43   long a1=offA;
44   long b1=offB;
45 
46   if(a1<0){
47     b1-=a1;
48     gap+=a1;
49     a1=0;
50   }
51 
52   return(memcmp(A+a1,B+b1,gap*2));
53 }
54 
55 /* riftv is the first value into the rift -> or <- */
i_analyze_rift_f(int16_t * A,int16_t * B,long sizeA,long sizeB,long aoffset,long boffset,long * matchA,long * matchB,long * matchC)56 void i_analyze_rift_f(int16_t *A,int16_t *B,
57 		      long sizeA, long sizeB,
58 		      long aoffset, long boffset,
59 		      long *matchA,long *matchB,long *matchC){
60 
61   long apast=sizeA-aoffset;
62   long bpast=sizeB-boffset;
63   long i;
64 
65   *matchA=0, *matchB=0, *matchC=0;
66 
67   /* Look for three possible matches... (A) Ariftv->B, (B) Briftv->A and
68      (c) AB->AB. */
69 
70   for(i=0;;i++){
71     if(i<bpast) /* A */
72       if(i_paranoia_overlap_f(A,B,aoffset,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){
73 	*matchA=i;
74 	break;
75       }
76 
77     if(i<apast){ /* B */
78       if(i_paranoia_overlap_f(A,B,aoffset+i,boffset,sizeA,sizeB)>=MIN_WORDS_RIFT){
79 	*matchB=i;
80 	break;
81       }
82       if(i<bpast) /* C */
83 	if(i_paranoia_overlap_f(A,B,aoffset+i,boffset+i,sizeA,sizeB)>=MIN_WORDS_RIFT){
84 	  *matchC=i;
85 	  break;
86 	}
87     }else
88       if(i>=bpast)break;
89 
90   }
91 
92   if(*matchA==0 && *matchB==0 && *matchC==0)return;
93 
94   if(*matchC)return;
95   if(*matchA){
96     if(i_stutter_or_gap(A,B,aoffset-*matchA,boffset,*matchA))
97       return;
98     *matchB=-*matchA; /* signify we need to remove n bytes from B */
99     *matchA=0;
100     return;
101   }else{
102     if(i_stutter_or_gap(B,A,boffset-*matchB,aoffset,*matchB))
103       return;
104     *matchA=-*matchB;
105     *matchB=0;
106     return;
107   }
108 }
109 
110 /* riftv must be first even val of rift moving back */
111 
i_analyze_rift_r(int16_t * A,int16_t * B,long sizeA,long sizeB,long aoffset,long boffset,long * matchA,long * matchB,long * matchC)112 void i_analyze_rift_r(int16_t *A,int16_t *B,
113 		      long sizeA, long sizeB,
114 		      long aoffset, long boffset,
115 		      long *matchA,long *matchB,long *matchC){
116 
117   long apast=aoffset+1;
118   long bpast=boffset+1;
119   long i;
120 
121   *matchA=0, *matchB=0, *matchC=0;
122 
123   /* Look for three possible matches... (A) Ariftv->B, (B) Briftv->A and
124      (c) AB->AB. */
125 
126   for(i=0;;i++){
127     if(i<bpast) /* A */
128       if(i_paranoia_overlap_r(A,B,aoffset,boffset-i)>=MIN_WORDS_RIFT){
129 	*matchA=i;
130 	break;
131       }
132     if(i<apast){ /* B */
133       if(i_paranoia_overlap_r(A,B,aoffset-i,boffset)>=MIN_WORDS_RIFT){
134 	*matchB=i;
135 	break;
136       }
137       if(i<bpast) /* C */
138 	if(i_paranoia_overlap_r(A,B,aoffset-i,boffset-i)>=MIN_WORDS_RIFT){
139 	  *matchC=i;
140 	  break;
141 	}
142     }else
143       if(i>=bpast)break;
144 
145   }
146 
147   if(*matchA==0 && *matchB==0 && *matchC==0)return;
148 
149   if(*matchC)return;
150 
151   if(*matchA){
152     if(i_stutter_or_gap(A,B,aoffset+1,boffset-*matchA+1,*matchA))
153       return;
154     *matchB=-*matchA; /* signify we need to remove n bytes from B */
155     *matchA=0;
156     return;
157   }else{
158     if(i_stutter_or_gap(B,A,boffset+1,aoffset-*matchB+1,*matchB))
159       return;
160     *matchA=-*matchB;
161     *matchB=0;
162     return;
163   }
164 }
165 
analyze_rift_silence_f(int16_t * A,int16_t * B,long sizeA,long sizeB,long aoffset,long boffset,long * matchA,long * matchB)166 void  analyze_rift_silence_f(int16_t *A,int16_t *B,long sizeA,long sizeB,
167 			     long aoffset, long boffset,
168 			     long *matchA, long *matchB){
169   *matchA=-1;
170   *matchB=-1;
171 
172   sizeA=prna_min(sizeA,aoffset+MIN_WORDS_RIFT);
173   sizeB=prna_min(sizeB,boffset+MIN_WORDS_RIFT);
174 
175   aoffset++;
176   boffset++;
177 
178   while(aoffset<sizeA){
179     if(A[aoffset]!=A[aoffset-1]){
180       *matchA=0;
181       break;
182     }
183     aoffset++;
184   }
185 
186   while(boffset<sizeB){
187     if(B[boffset]!=B[boffset-1]){
188       *matchB=0;
189       break;
190     }
191     boffset++;
192   }
193 }
194