~ubuntu-branches/ubuntu/lucid/cdrdao/lucid

« back to all changes in this revision

Viewing changes to paranoia/overlap.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Suffield
  • Date: 2004-06-24 22:33:16 UTC
  • Revision ID: james.westby@ubuntu.com-20040624223316-534onzugaeeyq61j
Tags: upstream-1.1.9
ImportĀ upstreamĀ versionĀ 1.1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***
 
2
 * CopyPolicy: GNU Public License 2 applies
 
3
 * Copyright (C) by Monty (xiphmont@mit.edu)
 
4
 *
 
5
 * Statistic code and cache management for overlap settings
 
6
 *
 
7
 ***/
 
8
 
 
9
#include <stdlib.h>
 
10
#include <stdio.h>
 
11
#include <string.h>
 
12
#include "p_block.h"
 
13
#include "cdda_paranoia.h"
 
14
#include "overlap.h"
 
15
#include "isort.h"
 
16
 
 
17
/**** Internal cache management *****************************************/
 
18
 
 
19
void paranoia_resetcache(cdrom_paranoia *p){
 
20
  c_block *c=c_first(p);
 
21
  v_fragment *v;
 
22
 
 
23
  while(c){
 
24
    free_c_block(c);
 
25
    c=c_first(p);
 
26
  }
 
27
 
 
28
  v=v_first(p);
 
29
  while(v){
 
30
    free_v_fragment(v);
 
31
    v=v_first(p);
 
32
  }
 
33
}
 
34
 
 
35
void paranoia_resetall(cdrom_paranoia *p){
 
36
  p->root.returnedlimit=0;
 
37
  p->dyndrift=0;
 
38
  p->root.lastsector=0;
 
39
 
 
40
  if(p->root.vector){
 
41
    i_cblock_destructor(p->root.vector);
 
42
    p->root.vector=NULL;
 
43
  }
 
44
 
 
45
  paranoia_resetcache(p);
 
46
}
 
47
 
 
48
void i_paranoia_trim(cdrom_paranoia *p,long beginword,long endword){
 
49
  root_block *root=&(p->root);
 
50
  if(root->vector!=NULL){
 
51
    long target=beginword-MAX_SECTOR_OVERLAP*CD_FRAMEWORDS;
 
52
    long rbegin=cb(root->vector);
 
53
    long rend=ce(root->vector);
 
54
 
 
55
    if(rbegin>beginword)
 
56
      goto rootfree;
 
57
    
 
58
    if(rbegin+MAX_SECTOR_OVERLAP*CD_FRAMEWORDS<beginword){
 
59
      if(target+MIN_WORDS_OVERLAP>rend)
 
60
        goto rootfree;
 
61
 
 
62
      {
 
63
        long offset=target-rbegin;
 
64
        c_removef(root->vector,offset);
 
65
      }
 
66
    }
 
67
 
 
68
    {
 
69
      c_block *c=c_first(p);
 
70
      while(c){
 
71
        c_block *next=c_next(c);
 
72
        if(ce(c)<beginword-MAX_SECTOR_OVERLAP*CD_FRAMEWORDS)
 
73
          free_c_block(c);
 
74
        c=next;
 
75
      }
 
76
    }
 
77
 
 
78
  }
 
79
  return;
 
80
  
 
81
rootfree:
 
82
 
 
83
  i_cblock_destructor(root->vector);
 
84
  root->vector=NULL;
 
85
  root->returnedlimit=-1;
 
86
  root->lastsector=0;
 
87
  
 
88
}
 
89
 
 
90
/**** Statistical and heuristic[al? :-] management ************************/
 
91
 
 
92
void offset_adjust_settings(cdrom_paranoia *p, void(*callback)(long,int)){
 
93
  if(p->stage2.offpoints>=10){
 
94
    /* drift: look at the average offset value.  If it's over one
 
95
       sector, frob it.  We just want a little hysteresis [sp?]*/
 
96
    long av=(p->stage2.offpoints?p->stage2.offaccum/p->stage2.offpoints:0);
 
97
    
 
98
    if(abs(av)>p->dynoverlap/4){
 
99
      av=(av/MIN_SECTOR_EPSILON)*MIN_SECTOR_EPSILON;
 
100
      
 
101
      if(callback)(*callback)(ce(p->root.vector),PARANOIA_CB_DRIFT);
 
102
      p->dyndrift+=av;
 
103
      
 
104
      /* Adjust all the values in the cache otherwise we get a
 
105
         (potentially unstable) feedback loop */
 
106
      {
 
107
        c_block *c=c_first(p);
 
108
        v_fragment *v=v_first(p);
 
109
 
 
110
        while(v && v->one){
 
111
          /* safeguard beginning bounds case with a hammer */
 
112
          if(fb(v)<av || cb(v->one)<av){
 
113
            v->one=NULL;
 
114
          }else{
 
115
            fb(v)-=av;
 
116
          }
 
117
          v=v_next(v);
 
118
        }
 
119
        while(c){
 
120
          long adj=min(av,cb(c));
 
121
          c_set(c,cb(c)-adj);
 
122
          c=c_next(c);
 
123
        }
 
124
      }
 
125
 
 
126
      p->stage2.offaccum=0;
 
127
      p->stage2.offmin=0;
 
128
      p->stage2.offmax=0;
 
129
      p->stage2.offpoints=0;
 
130
      p->stage2.newpoints=0;
 
131
      p->stage2.offdiff=0;
 
132
    }
 
133
  }
 
134
 
 
135
  if(p->stage1.offpoints>=10){
 
136
    /* dynoverlap: we arbitrarily set it to 4x the running difference
 
137
       value, unless min/max are more */
 
138
 
 
139
    p->dynoverlap=(p->stage1.offpoints?p->stage1.offdiff/
 
140
                   p->stage1.offpoints*3:CD_FRAMEWORDS);
 
141
 
 
142
    if(p->dynoverlap<-p->stage1.offmin*1.5)
 
143
      p->dynoverlap=-p->stage1.offmin*1.5;
 
144
                                                     
 
145
    if(p->dynoverlap<p->stage1.offmax*1.5)
 
146
      p->dynoverlap=p->stage1.offmax*1.5;
 
147
 
 
148
    if(p->dynoverlap<MIN_SECTOR_EPSILON)p->dynoverlap=MIN_SECTOR_EPSILON;
 
149
    if(p->dynoverlap>MAX_SECTOR_OVERLAP*CD_FRAMEWORDS)
 
150
      p->dynoverlap=MAX_SECTOR_OVERLAP*CD_FRAMEWORDS;
 
151
                             
 
152
    if(callback)(*callback)(p->dynoverlap,PARANOIA_CB_OVERLAP);
 
153
 
 
154
    if(p->stage1.offpoints>600){ /* bit of a bug; this routine is
 
155
                                    called too often due to the overlap 
 
156
                                    mesh alg we use in stage 1 */
 
157
      p->stage1.offpoints/=1.2;
 
158
      p->stage1.offaccum/=1.2;
 
159
      p->stage1.offdiff/=1.2;
 
160
    }
 
161
    p->stage1.offmin=0;
 
162
    p->stage1.offmax=0;
 
163
    p->stage1.newpoints=0;
 
164
  }
 
165
}
 
166
 
 
167
void offset_add_value(cdrom_paranoia *p,offsets *o,long value,
 
168
                             void(*callback)(long,int)){
 
169
  if(o->offpoints!=-1){
 
170
 
 
171
    o->offdiff+=abs(value);
 
172
    o->offpoints++;
 
173
    o->newpoints++;
 
174
    o->offaccum+=value;
 
175
    if(value<o->offmin)o->offmin=value;
 
176
    if(value>o->offmax)o->offmax=value;
 
177
    
 
178
    if(o->newpoints>=10)offset_adjust_settings(p,callback);
 
179
  }
 
180
}
 
181