misc/libtremor/res012.c
changeset 5170 f7e49eff3708
equal deleted inserted replaced
5169:e353ca78d28b 5170:f7e49eff3708
       
     1 /********************************************************************
       
     2  *                                                                  *
       
     3  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
       
     4  *                                                                  *
       
     5  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
       
     6  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
       
     7  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
       
     8  *                                                                  *
       
     9  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002    *
       
    10  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
       
    11  *                                                                  *
       
    12  ********************************************************************
       
    13 
       
    14  function: residue backend 0, 1 and 2 implementation
       
    15 
       
    16  ********************************************************************/
       
    17 
       
    18 #include <stdlib.h>
       
    19 #include <string.h>
       
    20 #include <math.h>
       
    21 #include "ogg.h"
       
    22 #include "ivorbiscodec.h"
       
    23 #include "codec_internal.h"
       
    24 #include "registry.h"
       
    25 #include "codebook.h"
       
    26 #include "misc.h"
       
    27 #include "os.h"
       
    28 #include "block.h"
       
    29 
       
    30 typedef struct {
       
    31   vorbis_info_residue0 *info;
       
    32   int         map;
       
    33   
       
    34   int         parts;
       
    35   int         stages;
       
    36   codebook   *fullbooks;
       
    37   codebook   *phrasebook;
       
    38   codebook ***partbooks;
       
    39 
       
    40   int         partvals;
       
    41   int       **decodemap;
       
    42 
       
    43 } vorbis_look_residue0;
       
    44 
       
    45 void res0_free_info(vorbis_info_residue *i){
       
    46   vorbis_info_residue0 *info=(vorbis_info_residue0 *)i;
       
    47   if(info){
       
    48     memset(info,0,sizeof(*info));
       
    49     _ogg_free(info);
       
    50   }
       
    51 }
       
    52 
       
    53 void res0_free_look(vorbis_look_residue *i){
       
    54   int j;
       
    55   if(i){
       
    56 
       
    57     vorbis_look_residue0 *look=(vorbis_look_residue0 *)i;
       
    58 
       
    59     for(j=0;j<look->parts;j++)
       
    60       if(look->partbooks[j])_ogg_free(look->partbooks[j]);
       
    61     _ogg_free(look->partbooks);
       
    62     for(j=0;j<look->partvals;j++)
       
    63       _ogg_free(look->decodemap[j]);
       
    64     _ogg_free(look->decodemap);
       
    65 
       
    66     memset(look,0,sizeof(*look));
       
    67     _ogg_free(look);
       
    68   }
       
    69 }
       
    70 
       
    71 static int ilog(unsigned int v){
       
    72   int ret=0;
       
    73   while(v){
       
    74     ret++;
       
    75     v>>=1;
       
    76   }
       
    77   return(ret);
       
    78 }
       
    79 
       
    80 static int icount(unsigned int v){
       
    81   int ret=0;
       
    82   while(v){
       
    83     ret+=v&1;
       
    84     v>>=1;
       
    85   }
       
    86   return(ret);
       
    87 }
       
    88 
       
    89 /* vorbis_info is for range checking */
       
    90 vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){
       
    91   int j,acc=0;
       
    92   vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info));
       
    93   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
       
    94 
       
    95   info->begin=oggpack_read(opb,24);
       
    96   info->end=oggpack_read(opb,24);
       
    97   info->grouping=oggpack_read(opb,24)+1;
       
    98   info->partitions=oggpack_read(opb,6)+1;
       
    99   info->groupbook=oggpack_read(opb,8);
       
   100 
       
   101   for(j=0;j<info->partitions;j++){
       
   102     int cascade=oggpack_read(opb,3);
       
   103     if(oggpack_read(opb,1))
       
   104       cascade|=(oggpack_read(opb,5)<<3);
       
   105     info->secondstages[j]=cascade;
       
   106 
       
   107     acc+=icount(cascade);
       
   108   }
       
   109   for(j=0;j<acc;j++)
       
   110     info->booklist[j]=oggpack_read(opb,8);
       
   111 
       
   112   if(info->groupbook>=ci->books)goto errout;
       
   113   for(j=0;j<acc;j++)
       
   114     if(info->booklist[j]>=ci->books)goto errout;
       
   115 
       
   116   return(info);
       
   117  errout:
       
   118   res0_free_info(info);
       
   119   return(NULL);
       
   120 }
       
   121 
       
   122 vorbis_look_residue *res0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm,
       
   123 			  vorbis_info_residue *vr){
       
   124   vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr;
       
   125   vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look));
       
   126   codec_setup_info     *ci=(codec_setup_info *)vd->vi->codec_setup;
       
   127 
       
   128   int j,k,acc=0;
       
   129   int dim;
       
   130   int maxstage=0;
       
   131   look->info=info;
       
   132   look->map=vm->mapping;
       
   133 
       
   134   look->parts=info->partitions;
       
   135   look->fullbooks=ci->fullbooks;
       
   136   look->phrasebook=ci->fullbooks+info->groupbook;
       
   137   dim=look->phrasebook->dim;
       
   138 
       
   139   look->partbooks=(codebook ***)_ogg_calloc(look->parts,sizeof(*look->partbooks));
       
   140 
       
   141   for(j=0;j<look->parts;j++){
       
   142     int stages=ilog(info->secondstages[j]);
       
   143     if(stages){
       
   144       if(stages>maxstage)maxstage=stages;
       
   145       look->partbooks[j]=(codebook **)_ogg_calloc(stages,sizeof(*look->partbooks[j]));
       
   146       for(k=0;k<stages;k++)
       
   147 	if(info->secondstages[j]&(1<<k)){
       
   148 	  look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++];
       
   149 #ifdef TRAIN_RES
       
   150 	  look->training_data[k][j]=calloc(look->partbooks[j][k]->entries,
       
   151 					   sizeof(***look->training_data));
       
   152 #endif
       
   153 	}
       
   154     }
       
   155   }
       
   156 
       
   157   look->partvals=look->parts;
       
   158   for(j=1;j<dim;j++)look->partvals*=look->parts;
       
   159   look->stages=maxstage;
       
   160   look->decodemap=(int **)_ogg_malloc(look->partvals*sizeof(*look->decodemap));
       
   161   for(j=0;j<look->partvals;j++){
       
   162     long val=j;
       
   163     long mult=look->partvals/look->parts;
       
   164     look->decodemap[j]=(int *)_ogg_malloc(dim*sizeof(*look->decodemap[j]));
       
   165     for(k=0;k<dim;k++){
       
   166       long deco=val/mult;
       
   167       val-=deco*mult;
       
   168       mult/=look->parts;
       
   169       look->decodemap[j][k]=deco;
       
   170     }
       
   171   }
       
   172 
       
   173   return(look);
       
   174 }
       
   175 
       
   176 
       
   177 /* a truncated packet here just means 'stop working'; it's not an error */
       
   178 static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl,
       
   179 		      ogg_int32_t **in,int ch,
       
   180 		      long (*decodepart)(codebook *, ogg_int32_t *, 
       
   181 					 oggpack_buffer *,int,int)){
       
   182 
       
   183   long i,j,k,l,s;
       
   184   vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
       
   185   vorbis_info_residue0 *info=look->info;
       
   186 
       
   187   /* move all this setup out later */
       
   188   int samples_per_partition=info->grouping;
       
   189   int partitions_per_word=look->phrasebook->dim;
       
   190   int max=vb->pcmend>>1;
       
   191   int end=(info->end<max?info->end:max);
       
   192   int n=end-info->begin;
       
   193 
       
   194   if(n>0){
       
   195     int partvals=n/samples_per_partition;
       
   196     int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
       
   197     int ***partword=(int ***)alloca(ch*sizeof(*partword));
       
   198     
       
   199     for(j=0;j<ch;j++)
       
   200       partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j]));
       
   201     
       
   202     for(s=0;s<look->stages;s++){
       
   203       
       
   204       /* each loop decodes on partition codeword containing 
       
   205 	 partitions_pre_word partitions */
       
   206       for(i=0,l=0;i<partvals;l++){
       
   207 	if(s==0){
       
   208 	  /* fetch the partition word for each channel */
       
   209 	  for(j=0;j<ch;j++){
       
   210 	    int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
       
   211 	    if(temp==-1)goto eopbreak;
       
   212 	    partword[j][l]=look->decodemap[temp];
       
   213 	    if(partword[j][l]==NULL)goto errout;
       
   214 	  }
       
   215 	}
       
   216 	
       
   217 	/* now we decode residual values for the partitions */
       
   218 	for(k=0;k<partitions_per_word && i<partvals;k++,i++)
       
   219 	  for(j=0;j<ch;j++){
       
   220 	    long offset=info->begin+i*samples_per_partition;
       
   221 	    if(info->secondstages[partword[j][l][k]]&(1<<s)){
       
   222 	      codebook *stagebook=look->partbooks[partword[j][l][k]][s];
       
   223 	      if(stagebook){
       
   224 		if(decodepart(stagebook,in[j]+offset,&vb->opb,
       
   225 			      samples_per_partition,-8)==-1)goto eopbreak;
       
   226 	      }
       
   227 	    }
       
   228 	  }
       
   229       } 
       
   230     }
       
   231   }
       
   232  errout:
       
   233  eopbreak:
       
   234   return(0);
       
   235 }
       
   236 
       
   237 int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl,
       
   238 		 ogg_int32_t **in,int *nonzero,int ch){
       
   239   int i,used=0;
       
   240   for(i=0;i<ch;i++)
       
   241     if(nonzero[i])
       
   242       in[used++]=in[i];
       
   243   if(used)
       
   244     return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add));
       
   245   else
       
   246     return(0);
       
   247 }
       
   248 
       
   249 int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl,
       
   250 		 ogg_int32_t **in,int *nonzero,int ch){
       
   251   int i,used=0;
       
   252   for(i=0;i<ch;i++)
       
   253     if(nonzero[i])
       
   254       in[used++]=in[i];
       
   255   if(used)
       
   256     return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add));
       
   257   else
       
   258     return(0);
       
   259 }
       
   260 
       
   261 /* duplicate code here as speed is somewhat more important */
       
   262 int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl,
       
   263 		 ogg_int32_t **in,int *nonzero,int ch){
       
   264   long i,k,l,s;
       
   265   vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
       
   266   vorbis_info_residue0 *info=look->info;
       
   267 
       
   268   /* move all this setup out later */
       
   269   int samples_per_partition=info->grouping;
       
   270   int partitions_per_word=look->phrasebook->dim;
       
   271   int max=(vb->pcmend*ch)>>1;
       
   272   int end=(info->end<max?info->end:max);
       
   273   int n=end-info->begin;
       
   274 
       
   275   if(n>0){
       
   276     
       
   277     int partvals=n/samples_per_partition;
       
   278     int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
       
   279     int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword));
       
   280     int beginoff=info->begin/ch;
       
   281     
       
   282     for(i=0;i<ch;i++)if(nonzero[i])break;
       
   283     if(i==ch)return(0); /* no nonzero vectors */
       
   284     
       
   285     samples_per_partition/=ch;
       
   286     
       
   287     for(s=0;s<look->stages;s++){
       
   288       for(i=0,l=0;i<partvals;l++){
       
   289 	
       
   290 	if(s==0){
       
   291 	  /* fetch the partition word */
       
   292 	  int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
       
   293 	  if(temp==-1)goto eopbreak;
       
   294 	  partword[l]=look->decodemap[temp];
       
   295 	  if(partword[l]==NULL)goto errout;
       
   296 	}
       
   297 
       
   298 	/* now we decode residual values for the partitions */
       
   299 	for(k=0;k<partitions_per_word && i<partvals;k++,i++)
       
   300 	  if(info->secondstages[partword[l][k]]&(1<<s)){
       
   301 	    codebook *stagebook=look->partbooks[partword[l][k]][s];
       
   302 	    
       
   303 	    if(stagebook){
       
   304 	      if(vorbis_book_decodevv_add(stagebook,in,
       
   305 					  i*samples_per_partition+beginoff,ch,
       
   306 					  &vb->opb,
       
   307 					  samples_per_partition,-8)==-1)
       
   308 		goto eopbreak;
       
   309 	    }
       
   310 	  }
       
   311       } 
       
   312     }
       
   313   }
       
   314  errout:
       
   315  eopbreak:
       
   316   return(0);
       
   317 }
       
   318 
       
   319 
       
   320 vorbis_func_residue residue0_exportbundle={
       
   321   &res0_unpack,
       
   322   &res0_look,
       
   323   &res0_free_info,
       
   324   &res0_free_look,
       
   325   &res0_inverse
       
   326 };
       
   327 
       
   328 vorbis_func_residue residue1_exportbundle={
       
   329   &res0_unpack,
       
   330   &res0_look,
       
   331   &res0_free_info,
       
   332   &res0_free_look,
       
   333   &res1_inverse
       
   334 };
       
   335 
       
   336 vorbis_func_residue residue2_exportbundle={
       
   337   &res0_unpack,
       
   338   &res0_look,
       
   339   &res0_free_info,
       
   340   &res0_free_look,
       
   341   &res2_inverse
       
   342 };