2 * This file has been modified for the cdrkit suite.
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).
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.
13 /* @(#)overlap.c 1.11 04/02/20 J. Schilling from cdparanoia-III-alpha9.8 */
15 * Modifications to make the code portable Copyright (c) 2002 J. Schilling
18 * CopyPolicy: GNU Public License 2 applies
19 * Copyright (C) by Monty (xiphmont@mit.edu)
21 * Statistic code and cache management for overlap settings
30 #include "cdda_paranoia.h"
34 void paranoia_resetcache(cdrom_paranoia *p);
35 void paranoia_resetall(cdrom_paranoia *p);
36 void i_paranoia_trim(cdrom_paranoia *p, long beginword, long endword);
37 void offset_adjust_settings(cdrom_paranoia *p, void (*callback)(long, int));
38 void offset_add_value(cdrom_paranoia *p, offsets *o, long value,
39 void (*callback)(long, int));
42 * Internal cache management
44 void paranoia_resetcache(cdrom_paranoia *p)
46 c_block *c = c_first(p);
61 void paranoia_resetall(cdrom_paranoia *p)
63 p->root.returnedlimit = 0;
65 p->root.lastsector = 0;
68 i_cblock_destructor(p->root.vector);
69 p->root.vector = NULL;
71 paranoia_resetcache(p);
74 void i_paranoia_trim(cdrom_paranoia *p, long beginword, long endword)
76 root_block *root = &(p->root);
78 if (root->vector != NULL) {
79 long target = beginword - p->maxdynoverlap;
80 long rbegin = cb(root->vector);
81 long rend = ce(root->vector);
83 if (rbegin > beginword)
86 if (rbegin + p->maxdynoverlap < beginword) {
87 if (target + MIN_WORDS_OVERLAP > rend)
91 long offset = target - rbegin;
93 c_removef(root->vector, offset);
96 c_block *c = c_first(p);
99 c_block *next = c_next(c);
101 if (ce(c) < beginword - p->maxdynoverlap)
112 i_cblock_destructor(root->vector);
114 root->returnedlimit = -1;
115 root->lastsector = 0;
120 * Statistical and heuristic[al? :-] management
122 void offset_adjust_settings(cdrom_paranoia *p, void (*callback)(long, int))
124 if (p->stage2.offpoints >= 10) {
126 * drift: look at the average offset value. If it's over one
127 * sector, frob it. We just want a little hysteresis [sp?]
129 long av = (p->stage2.offpoints ? p->stage2.offaccum / p->stage2.offpoints : 0);
131 if (abs(av) > p->dynoverlap / 4) {
132 av = (av / MIN_SECTOR_EPSILON) * MIN_SECTOR_EPSILON;
135 (*callback) (ce(p->root.vector), PARANOIA_CB_DRIFT);
139 * Adjust all the values in the cache otherwise we get
140 * a (potentially unstable) feedback loop
143 c_block *c = c_first(p);
144 v_fragment *v = v_first(p);
146 while (v && v->one) {
148 * safeguard beginning bounds case with
151 if (fb(v) < av || cb(v->one) < av) {
159 long adj = min(av, cb(c));
161 c_set(c, cb(c) - adj);
166 p->stage2.offaccum = 0;
167 p->stage2.offmin = 0;
168 p->stage2.offmax = 0;
169 p->stage2.offpoints = 0;
170 p->stage2.newpoints = 0;
171 p->stage2.offdiff = 0;
174 if (p->stage1.offpoints >= 10) {
176 * dynoverlap: we arbitrarily set it to 4x the running
177 * difference value, unless min/max are more
179 p->dynoverlap = (p->stage1.offpoints ? p->stage1.offdiff /
180 p->stage1.offpoints * 3 : CD_FRAMEWORDS);
182 if (p->dynoverlap < -p->stage1.offmin * 1.5)
183 p->dynoverlap = -p->stage1.offmin * 1.5;
185 if (p->dynoverlap < p->stage1.offmax * 1.5)
186 p->dynoverlap = p->stage1.offmax * 1.5;
188 if (p->dynoverlap < p->mindynoverlap)
189 p->dynoverlap = p->mindynoverlap;
190 if (p->dynoverlap > p->maxdynoverlap)
191 p->dynoverlap = p->maxdynoverlap;
194 (*callback) (p->dynoverlap, PARANOIA_CB_OVERLAP);
196 if (p->stage1.offpoints > 600) {
198 * bit of a bug; this routine is called too often
199 * due to the overlap mesh alg we use in stage 1
201 p->stage1.offpoints /= 1.2;
202 p->stage1.offaccum /= 1.2;
203 p->stage1.offdiff /= 1.2;
205 p->stage1.offmin = 0;
206 p->stage1.offmax = 0;
207 p->stage1.newpoints = 0;
211 void offset_add_value(cdrom_paranoia *p, offsets *o, long value,
212 void (*callback)(long, int))
214 if (o->offpoints != -1) {
216 o->offdiff += abs(value);
219 o->offaccum += value;
220 if (value < o->offmin)
222 if (value > o->offmax)
225 if (o->newpoints >= 10)
226 offset_adjust_settings(p, callback);