⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floor1.c

📁 OGG文件格式音频数解压缩SDK.现在OGG文件格式在一些游戏开发中使用的比较多.
💻 C
📖 第 1 页 / 共 2 页
字号:
static void fit_line(lsfit_acc *a,int fits,int *y0,int *y1){
  ogg_int32_t x=0,y=0,x2=0,y2=0,xy=0,n=0,an=0,i;
  ogg_int32_t x0=a[0].x0;
  ogg_int32_t x1=a[fits-1].x1;

  for(i=0;i<fits;i++){
    x+=a[i].xa;
    y+=a[i].ya;
    x2+=a[i].x2a;
    y2+=a[i].y2a;
    xy+=a[i].xya;
    an+=a[i].an;
  }

  if(*y0>=0){
    x+=   x0;
    y+=  *y0;
    x2+=  x0 *  x0;
    y2+= *y0 * *y0;
    xy+= *y0 *  x0;
    an++;
  }

  if(*y1>=0){
    x+=   x1;
    y+=  *y1;
    x2+=  x1 *  x1;
    y2+= *y1 * *y1;
    xy+= *y1 *  x1;
    an++;
  }
  
  if(an){
    /* need 64 bit multiplies, which C doesn't give portably as int */
    float fx=(float)x;
    float fy=(float)y;
    float fx2=(float)x2;
    float fxy=(float)xy;
    float denom=1.0f/(an*fx2-fx*fx);
    float a=(fy*fx2-fxy*fx)*denom;
    float b=(an*fxy-fx*fy)*denom;
    *y0 = (int)ogg_rint(a+b*x0);
    *y1 = (int)ogg_rint(a+b*x1);

    /* limit to our range! */
    if(*y0>1023)*y0=1023;
    if(*y1>1023)*y1=1023;
    if(*y0<0)*y0=0;
    if(*y1<0)*y1=0;

  }else{
    *y0=0;
    *y1=0;
  }
}

/*static void fit_line_point(lsfit_acc *a,int fits,int *y0,int *y1){
  ogg_int32_t y=0;
  int i;

  for(i=0;i<fits && y==0;i++)
    y+=a[i].ya;
  
  *y0=*y1=y;
  }*/

static int inspect_error(int x0,int x1,int y0,int y1,const float *mask,
			 const float *mdct,
			 vorbis_info_floor1 *info){
  int dy=y1-y0;
  int adx=x1-x0;
  int ady=abs(dy);
  int base=dy/adx;
  int sy=(dy<0?base-1:base+1);
  int x=x0;
  int y=y0;
  int err=0;
  int val=vorbis_dBquant(mask+x);
  int mse=0;
  int n=0;

  ady-=abs(base*adx);
  
  mse=(y-val);
  mse*=mse;
  n++;
  if(mdct[x]+info->twofitatten>=mask[x]){
    if(y+info->maxover<val)return(1);
    if(y-info->maxunder>val)return(1);
  }

  while(++x<x1){
    err=err+ady;
    if(err>=adx){
      err-=adx;
      y+=sy;
    }else{
      y+=base;
    }

    val=vorbis_dBquant(mask+x);
    mse+=((y-val)*(y-val));
    n++;
    if(mdct[x]+info->twofitatten>=mask[x]){
      if(val){
	if(y+info->maxover<val)return(1);
	if(y-info->maxunder>val)return(1);
      }
    }
  }
  
  if(info->maxover*info->maxover/n>info->maxerr)return(0);
  if(info->maxunder*info->maxunder/n>info->maxerr)return(0);
  if(mse/n>info->maxerr)return(1);
  return(0);
}

static int post_Y(int *A,int *B,int pos){
  if(A[pos]<0)
    return B[pos];
  if(B[pos]<0)
    return A[pos];

  return (A[pos]+B[pos])>>1;
}

//static int seq=0;
#if 0
int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look,
			  const float *logmdct,   /* in */
			  const float *logmask){

  ogg_int32_t i,j;
  vorbis_info_floor1 *info=look->vi;
  ogg_int32_t n=look->n;
  ogg_int32_t posts=look->posts;
  ogg_int32_t nonzero=0;
  lsfit_acc fits[VIF_POSIT+1];
  int fit_valueA[VIF_POSIT+2]; /* index by range list position */
  int fit_valueB[VIF_POSIT+2]; /* index by range list position */

  int loneighbor[VIF_POSIT+2]; /* sorted index of range list position (+2) */
  int hineighbor[VIF_POSIT+2]; 
  int *output=NULL;
  int memo[VIF_POSIT+2];

  for(i=0;i<posts;i++)fit_valueA[i]=-200; /* mark all unused */
  for(i=0;i<posts;i++)fit_valueB[i]=-200; /* mark all unused */
  for(i=0;i<posts;i++)loneighbor[i]=0; /* 0 for the implicit 0 post */
  for(i=0;i<posts;i++)hineighbor[i]=1; /* 1 for the implicit post at n */
  for(i=0;i<posts;i++)memo[i]=-1;      /* no neighbor yet */

  /* quantize the relevant floor points and collect them into line fit
     structures (one per minimal division) at the same time */
  if(posts==0){
    nonzero+=accumulate_fit(logmask,logmdct,0,n,fits,n,info);
  }else{
    for(i=0;i<posts-1;i++)
      nonzero+=accumulate_fit(logmask,logmdct,look->sorted_index[i],
			      look->sorted_index[i+1],fits+i,
			      n,info);
  }
  
  if(nonzero){
    /* start by fitting the implicit base case.... */
    int y0=-200;
    int y1=-200;
    fit_line(fits,posts-1,&y0,&y1);

    fit_valueA[0]=y0;
    fit_valueB[0]=y0;
    fit_valueB[1]=y1;
    fit_valueA[1]=y1;

    /* Non degenerate case */
    /* start progressive splitting.  This is a greedy, non-optimal
       algorithm, but simple and close enough to the best
       answer. */
    for(i=2;i<posts;i++){
      int sortpos=look->reverse_index[i];
      int ln=loneighbor[sortpos];
      int hn=hineighbor[sortpos];
      
      /* eliminate repeat searches of a particular range with a memo */
      if(memo[ln]!=hn){
	/* haven't performed this error search yet */
	int lsortpos=look->reverse_index[ln];
	int hsortpos=look->reverse_index[hn];
	memo[ln]=hn;
		
	{
	  /* A note: we want to bound/minimize *local*, not global, error */
	  int lx=info->postlist[ln];
	  int hx=info->postlist[hn];	  
	  int ly=post_Y(fit_valueA,fit_valueB,ln);
	  int hy=post_Y(fit_valueA,fit_valueB,hn);
	  
	  if(ly==-1 || hy==-1){
	    exit(1);
	  }

	  if(inspect_error(lx,hx,ly,hy,logmask,logmdct,info)){
	    /* outside error bounds/begin search area.  Split it. */
	    int ly0=-200;
	    int ly1=-200;
	    int hy0=-200;
	    int hy1=-200;
	    fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1);
	    fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1);
	    
	    /* store new edge values */
	    fit_valueB[ln]=ly0;
	    if(ln==0)fit_valueA[ln]=ly0;
	    fit_valueA[i]=ly1;
	    fit_valueB[i]=hy0;
	    fit_valueA[hn]=hy1;
	    if(hn==1)fit_valueB[hn]=hy1;
	    
	    if(ly1>=0 || hy0>=0){
	      /* store new neighbor values */
	      for(j=sortpos-1;j>=0;j--)
		if(hineighbor[j]==hn)
		  hineighbor[j]=i;
		else
		  break;
	      for(j=sortpos+1;j<posts;j++)
		if(loneighbor[j]==ln)
		  loneighbor[j]=i;
		else
		  break;
	      
	    }
	  }else{
	    
	    fit_valueA[i]=-200;
	    fit_valueB[i]=-200;
	  }
	}
      }
    }
  
    output=_vorbis_block_alloc(vb,sizeof(*output)*posts);
    
    output[0]=post_Y(fit_valueA,fit_valueB,0);
    output[1]=post_Y(fit_valueA,fit_valueB,1);
    
    /* fill in posts marked as not using a fit; we will zero
       back out to 'unused' when encoding them so long as curve
       interpolation doesn't force them into use */
    for(i=2;i<posts;i++){
      int ln=look->loneighbor[i-2];
      int hn=look->hineighbor[i-2];
      int x0=info->postlist[ln];
      int x1=info->postlist[hn];
      int y0=output[ln];
      int y1=output[hn];
      
      int predicted=render_point(x0,x1,y0,y1,info->postlist[i]);
      int vx=post_Y(fit_valueA,fit_valueB,i);
      
      if(vx>=0 && predicted!=vx){ 
	output[i]=vx;
      }else{
	output[i]= predicted|0x8000;
      }
    }
  }

  return(output);
  
}
		
int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor1 *look,
			  int *A,int *B,
			  int del){

  ogg_int32_t i;
  ogg_int32_t posts=look->posts;
  int *output=NULL;
  
  if(A && B){
    output=_vorbis_block_alloc(vb,sizeof(*output)*posts);
    
    for(i=0;i<posts;i++){
      output[i]=((65536-del)*(A[i]&0x7fff)+del*(B[i]&0x7fff)+32768)>>16;
      if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000;
    }
  }

  return(output);
}
#endif

static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
  vorbis_info_floor1 *info=look->vi;
  codec_setup_info   *ci=vb->vd->vi->codec_setup;
  
  int i,j,k;
  codebook *books=ci->fullbooks;   

  /* unpack wrapped/predicted values from stream */
  if(oggpack_read(&vb->opb,1)==1){
    int *fit_value=_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value));

    fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1));
    fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1));

    /* partition by partition */
    for(i=0,j=2;i<info->partitions;i++){
      int class=info->partitionclass[i];
      int cdim=info->class_dim[class];
      int csubbits=info->class_subs[class];
      int csub=1<<csubbits;
      int cval=0;

      /* decode the partition's first stage cascade value */
      if(csubbits){
	cval=vorbis_book_decode(books+info->class_book[class],&vb->opb);

	if(cval==-1)goto eop;
      }

      for(k=0;k<cdim;k++){
	int book=info->class_subbook[class][cval&(csub-1)];
	cval>>=csubbits;
	if(book>=0){
	  if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1)
	    goto eop;
	}else{
	  fit_value[j+k]=0;
	}
      }
      j+=cdim;
    }

    /* unwrap positive values and reconsitute via linear interpolation */
    for(i=2;i<look->posts;i++){
      int predicted=render_point(info->postlist[look->loneighbor[i-2]],
				 info->postlist[look->hineighbor[i-2]],
				 fit_value[look->loneighbor[i-2]],
				 fit_value[look->hineighbor[i-2]],
				 info->postlist[i]);
      int hiroom=look->quant_q-predicted;
      int loroom=predicted;
      int room=(hiroom<loroom?hiroom:loroom)<<1;
      int val=fit_value[i];

      if(val){
	if(val>=room){
	  if(hiroom>loroom){
	    val = val-loroom;
	  }else{
	    val = -1-(val-hiroom);
	  }
	}else{
	  if(val&1){
	    val= -((val+1)>>1);
	  }else{
	    val>>=1;
	  }
	}

	fit_value[i]=val+predicted;
	fit_value[look->loneighbor[i-2]]&=0x7fff;
	fit_value[look->hineighbor[i-2]]&=0x7fff;

      }else{
	fit_value[i]=predicted|0x8000;
      }
	
    }

    return(fit_value);
  }
 eop:
  return(NULL);
}

static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo,
			  float *out){
  vorbis_look_floor1 *look=(vorbis_look_floor1 *)in;
  vorbis_info_floor1 *info=look->vi;

  codec_setup_info   *ci=vb->vd->vi->codec_setup;
  int                  n=ci->blocksizes[vb->W]/2;
  int j;

  if(memo){
    /* render the lines */
    int *fit_value=(int *)memo;
    int hx=0;
    int lx=0;
    int ly=fit_value[0]*info->mult;
    for(j=1;j<look->posts;j++){
      int current=look->forward_index[j];
      int hy=fit_value[current]&0x7fff;
      if(hy==fit_value[current]){
	
	hy*=info->mult;
	hx=info->postlist[current];
	
	render_line(lx,hx,ly,hy,out);
	
	lx=hx;
	ly=hy;
      }
    }
    for(j=hx;j<n;j++)out[j]*=FLOOR1_fromdB_LOOKUP[ly]; /* be certain */    
    return(1);
  }
  memset(out,0,sizeof(*out)*n);
  return(0);
}

/* export hooks */
vorbis_func_floor floor1_exportbundle=
{
    NULL, //&floor1_pack,
    &floor1_unpack,
    &floor1_look,
    &floor1_free_info,
    &floor1_free_look,
    &floor1_inverse1,
    &floor1_inverse2
};


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -