overlap.c
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:4k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

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