misc/libtremor/block.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: PCM data vector blocking, windowing and dis/reassembly
       
    15 
       
    16  ********************************************************************/
       
    17 
       
    18 #include <stdio.h>
       
    19 #include <stdlib.h>
       
    20 #include <string.h>
       
    21 #include "ogg.h"
       
    22 #include "ivorbiscodec.h"
       
    23 #include "codec_internal.h"
       
    24 
       
    25 #include "window.h"
       
    26 #include "registry.h"
       
    27 #include "misc.h"
       
    28 
       
    29 static int ilog(unsigned int v){
       
    30   int ret=0;
       
    31   if(v)--v;
       
    32   while(v){
       
    33     ret++;
       
    34     v>>=1;
       
    35   }
       
    36   return(ret);
       
    37 }
       
    38 
       
    39 /* pcm accumulator examples (not exhaustive):
       
    40 
       
    41  <-------------- lW ---------------->
       
    42                    <--------------- W ---------------->
       
    43 :            .....|.....       _______________         |
       
    44 :        .'''     |     '''_---      |       |\        |
       
    45 :.....'''         |_____--- '''......|       | \_______|
       
    46 :.................|__________________|_______|__|______|
       
    47                   |<------ Sl ------>|      > Sr <     |endW
       
    48                   |beginSl           |endSl  |  |endSr
       
    49                   |beginW            |endlW  |beginSr
       
    50 
       
    51 
       
    52                       |< lW >|
       
    53                    <--------------- W ---------------->
       
    54                   |   |  ..  ______________            |
       
    55                   |   | '  `/        |     ---_        |
       
    56                   |___.'___/`.       |         ---_____|
       
    57                   |_______|__|_______|_________________|
       
    58                   |      >|Sl|<      |<------ Sr ----->|endW
       
    59                   |       |  |endSl  |beginSr          |endSr
       
    60                   |beginW |  |endlW
       
    61                   mult[0] |beginSl                     mult[n]
       
    62 
       
    63  <-------------- lW ----------------->
       
    64                           |<--W-->|
       
    65 :            ..............  ___  |   |
       
    66 :        .'''             |`/   \ |   |
       
    67 :.....'''                 |/`....\|...|
       
    68 :.........................|___|___|___|
       
    69                           |Sl |Sr |endW
       
    70                           |   |   |endSr
       
    71                           |   |beginSr
       
    72                           |   |endSl
       
    73 			  |beginSl
       
    74 			  |beginW
       
    75 */
       
    76 
       
    77 /* block abstraction setup *********************************************/
       
    78 
       
    79 #ifndef WORD_ALIGN
       
    80 #define WORD_ALIGN 8
       
    81 #endif
       
    82 
       
    83 int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
       
    84   memset(vb,0,sizeof(*vb));
       
    85   vb->vd=v;
       
    86   vb->localalloc=0;
       
    87   vb->localstore=NULL;
       
    88 
       
    89   return(0);
       
    90 }
       
    91 
       
    92 void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
       
    93   bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
       
    94   if(bytes+vb->localtop>vb->localalloc){
       
    95     /* can't just _ogg_realloc... there are outstanding pointers */
       
    96     if(vb->localstore){
       
    97       struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link));
       
    98       vb->totaluse+=vb->localtop;
       
    99       link->next=vb->reap;
       
   100       link->ptr=vb->localstore;
       
   101       vb->reap=link;
       
   102     }
       
   103     /* highly conservative */
       
   104     vb->localalloc=bytes;
       
   105     vb->localstore=_ogg_malloc(vb->localalloc);
       
   106     vb->localtop=0;
       
   107   }
       
   108   {
       
   109     void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
       
   110     vb->localtop+=bytes;
       
   111     return ret;
       
   112   }
       
   113 }
       
   114 
       
   115 /* reap the chain, pull the ripcord */
       
   116 void _vorbis_block_ripcord(vorbis_block *vb){
       
   117   /* reap the chain */
       
   118   struct alloc_chain *reap=vb->reap;
       
   119   while(reap){
       
   120     struct alloc_chain *next=reap->next;
       
   121     _ogg_free(reap->ptr);
       
   122     memset(reap,0,sizeof(*reap));
       
   123     _ogg_free(reap);
       
   124     reap=next;
       
   125   }
       
   126   /* consolidate storage */
       
   127   if(vb->totaluse){
       
   128     vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
       
   129     vb->localalloc+=vb->totaluse;
       
   130     vb->totaluse=0;
       
   131   }
       
   132 
       
   133   /* pull the ripcord */
       
   134   vb->localtop=0;
       
   135   vb->reap=NULL;
       
   136 }
       
   137 
       
   138 int vorbis_block_clear(vorbis_block *vb){
       
   139   _vorbis_block_ripcord(vb);
       
   140   if(vb->localstore)_ogg_free(vb->localstore);
       
   141 
       
   142   memset(vb,0,sizeof(*vb));
       
   143   return(0);
       
   144 }
       
   145 
       
   146 static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){
       
   147   int i;
       
   148   codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
       
   149   private_state *b=NULL;
       
   150 
       
   151   memset(v,0,sizeof(*v));
       
   152   b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
       
   153 
       
   154   v->vi=vi;
       
   155   b->modebits=ilog(ci->modes);
       
   156 
       
   157   /* Vorbis I uses only window type 0 */
       
   158   b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2);
       
   159   b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2);
       
   160 
       
   161   /* finish the codebooks */
       
   162   if(!ci->fullbooks){
       
   163     ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
       
   164     for(i=0;i<ci->books;i++){
       
   165       vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]);
       
   166       /* decode codebooks are now standalone after init */
       
   167       vorbis_staticbook_destroy(ci->book_param[i]);
       
   168       ci->book_param[i]=NULL;
       
   169     }
       
   170   }
       
   171 
       
   172   v->pcm_storage=ci->blocksizes[1];
       
   173   v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm));
       
   174   v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret));
       
   175   for(i=0;i<vi->channels;i++)
       
   176     v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
       
   177 
       
   178   /* all 1 (large block) or 0 (small block) */
       
   179   /* explicitly set for the sake of clarity */
       
   180   v->lW=0; /* previous window size */
       
   181   v->W=0;  /* current window size */
       
   182 
       
   183   /* initialize all the mapping/backend lookups */
       
   184   b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode));
       
   185   for(i=0;i<ci->modes;i++){
       
   186     int mapnum=ci->mode_param[i]->mapping;
       
   187     int maptype=ci->map_type[mapnum];
       
   188     b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
       
   189 					 ci->map_param[mapnum]);
       
   190   }
       
   191   return(0);
       
   192 }
       
   193 
       
   194 int vorbis_synthesis_restart(vorbis_dsp_state *v){
       
   195   vorbis_info *vi=v->vi;
       
   196   codec_setup_info *ci;
       
   197 
       
   198   if(!v->backend_state)return -1;
       
   199   if(!vi)return -1;
       
   200   ci=vi->codec_setup;
       
   201   if(!ci)return -1;
       
   202 
       
   203   v->centerW=ci->blocksizes[1]/2;
       
   204   v->pcm_current=v->centerW;
       
   205 
       
   206   v->pcm_returned=-1;
       
   207   v->granulepos=-1;
       
   208   v->sequence=-1;
       
   209   ((private_state *)(v->backend_state))->sample_count=-1;
       
   210 
       
   211   return(0);
       
   212 }
       
   213 
       
   214 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
       
   215   _vds_init(v,vi);
       
   216   vorbis_synthesis_restart(v);
       
   217 
       
   218   return(0);
       
   219 }
       
   220 
       
   221 void vorbis_dsp_clear(vorbis_dsp_state *v){
       
   222   int i;
       
   223   if(v){
       
   224     vorbis_info *vi=v->vi;
       
   225     codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
       
   226     private_state *b=(private_state *)v->backend_state;
       
   227 
       
   228     if(v->pcm){
       
   229       for(i=0;i<vi->channels;i++)
       
   230 	if(v->pcm[i])_ogg_free(v->pcm[i]);
       
   231       _ogg_free(v->pcm);
       
   232       if(v->pcmret)_ogg_free(v->pcmret);
       
   233     }
       
   234 
       
   235     /* free mode lookups; these are actually vorbis_look_mapping structs */
       
   236     if(ci){
       
   237       for(i=0;i<ci->modes;i++){
       
   238 	int mapnum=ci->mode_param[i]->mapping;
       
   239 	int maptype=ci->map_type[mapnum];
       
   240 	if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
       
   241       }
       
   242     }
       
   243 
       
   244     if(b){
       
   245       if(b->mode)_ogg_free(b->mode);
       
   246       _ogg_free(b);
       
   247     }
       
   248 
       
   249     memset(v,0,sizeof(*v));
       
   250   }
       
   251 }
       
   252 
       
   253 /* Unlike in analysis, the window is only partially applied for each
       
   254    block.  The time domain envelope is not yet handled at the point of
       
   255    calling (as it relies on the previous block). */
       
   256 
       
   257 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
       
   258   vorbis_info *vi=v->vi;
       
   259   codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
       
   260   private_state *b=v->backend_state;
       
   261   int i,j;
       
   262 
       
   263   if(v->pcm_current>v->pcm_returned  && v->pcm_returned!=-1)return(OV_EINVAL);
       
   264 
       
   265   v->lW=v->W;
       
   266   v->W=vb->W;
       
   267   v->nW=-1;
       
   268 
       
   269   if((v->sequence==-1)||
       
   270      (v->sequence+1 != vb->sequence)){
       
   271     v->granulepos=-1; /* out of sequence; lose count */
       
   272     b->sample_count=-1;
       
   273   }
       
   274 
       
   275   v->sequence=vb->sequence;
       
   276 
       
   277   if(vb->pcm){  /* no pcm to process if vorbis_synthesis_trackonly
       
   278                    was called on block */
       
   279     int n=ci->blocksizes[v->W]/2;
       
   280     int n0=ci->blocksizes[0]/2;
       
   281     int n1=ci->blocksizes[1]/2;
       
   282 
       
   283     int thisCenter;
       
   284     int prevCenter;
       
   285 
       
   286     if(v->centerW){
       
   287       thisCenter=n1;
       
   288       prevCenter=0;
       
   289     }else{
       
   290       thisCenter=0;
       
   291       prevCenter=n1;
       
   292     }
       
   293 
       
   294     /* v->pcm is now used like a two-stage double buffer.  We don't want
       
   295        to have to constantly shift *or* adjust memory usage.  Don't
       
   296        accept a new block until the old is shifted out */
       
   297 
       
   298     /* overlap/add PCM */
       
   299 
       
   300     for(j=0;j<vi->channels;j++){
       
   301       /* the overlap/add section */
       
   302       if(v->lW){
       
   303 	if(v->W){
       
   304 	  /* large/large */
       
   305 	  ogg_int32_t *pcm=v->pcm[j]+prevCenter;
       
   306 	  ogg_int32_t *p=vb->pcm[j];
       
   307 	  for(i=0;i<n1;i++)
       
   308 	    pcm[i]+=p[i];
       
   309 	}else{
       
   310 	  /* large/small */
       
   311 	  ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
       
   312 	  ogg_int32_t *p=vb->pcm[j];
       
   313 	  for(i=0;i<n0;i++)
       
   314 	    pcm[i]+=p[i];
       
   315 	}
       
   316       }else{
       
   317 	if(v->W){
       
   318 	  /* small/large */
       
   319 	  ogg_int32_t *pcm=v->pcm[j]+prevCenter;
       
   320 	  ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
       
   321 	  for(i=0;i<n0;i++)
       
   322 	    pcm[i]+=p[i];
       
   323 	  for(;i<n1/2+n0/2;i++)
       
   324 	    pcm[i]=p[i];
       
   325 	}else{
       
   326 	  /* small/small */
       
   327 	  ogg_int32_t *pcm=v->pcm[j]+prevCenter;
       
   328 	  ogg_int32_t *p=vb->pcm[j];
       
   329 	  for(i=0;i<n0;i++)
       
   330 	    pcm[i]+=p[i];
       
   331 	}
       
   332       }
       
   333 
       
   334       /* the copy section */
       
   335       {
       
   336 	ogg_int32_t *pcm=v->pcm[j]+thisCenter;
       
   337 	ogg_int32_t *p=vb->pcm[j]+n;
       
   338 	for(i=0;i<n;i++)
       
   339 	  pcm[i]=p[i];
       
   340       }
       
   341     }
       
   342 
       
   343     if(v->centerW)
       
   344       v->centerW=0;
       
   345     else
       
   346       v->centerW=n1;
       
   347 
       
   348     /* deal with initial packet state; we do this using the explicit
       
   349        pcm_returned==-1 flag otherwise we're sensitive to first block
       
   350        being short or long */
       
   351 
       
   352     if(v->pcm_returned==-1){
       
   353       v->pcm_returned=thisCenter;
       
   354       v->pcm_current=thisCenter;
       
   355     }else{
       
   356       v->pcm_returned=prevCenter;
       
   357       v->pcm_current=prevCenter+
       
   358 	ci->blocksizes[v->lW]/4+
       
   359 	ci->blocksizes[v->W]/4;
       
   360     }
       
   361 
       
   362   }
       
   363 
       
   364   /* track the frame number... This is for convenience, but also
       
   365      making sure our last packet doesn't end with added padding.  If
       
   366      the last packet is partial, the number of samples we'll have to
       
   367      return will be past the vb->granulepos.
       
   368      
       
   369      This is not foolproof!  It will be confused if we begin
       
   370      decoding at the last page after a seek or hole.  In that case,
       
   371      we don't have a starting point to judge where the last frame
       
   372      is.  For this reason, vorbisfile will always try to make sure
       
   373      it reads the last two marked pages in proper sequence */
       
   374 
       
   375   if(b->sample_count==-1){
       
   376     b->sample_count=0;
       
   377   }else{
       
   378     b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
       
   379   }
       
   380 
       
   381   if(v->granulepos==-1){
       
   382     if(vb->granulepos!=-1){ /* only set if we have a position to set to */
       
   383 
       
   384       v->granulepos=vb->granulepos;
       
   385 
       
   386       /* is this a short page? */
       
   387       if(b->sample_count>v->granulepos){
       
   388 	/* corner case; if this is both the first and last audio page,
       
   389 	   then spec says the end is cut, not beginning */
       
   390 	if(vb->eofflag){
       
   391 	  /* trim the end */
       
   392 	  /* no preceeding granulepos; assume we started at zero (we'd
       
   393 	     have to in a short single-page stream) */
       
   394 	  /* granulepos could be -1 due to a seek, but that would result
       
   395 	     in a long coun`t, not short count */
       
   396 
       
   397 	  v->pcm_current-=(b->sample_count-v->granulepos);
       
   398 	}else{
       
   399 	  /* trim the beginning */
       
   400 	  v->pcm_returned+=(b->sample_count-v->granulepos);
       
   401 	  if(v->pcm_returned>v->pcm_current)
       
   402 	    v->pcm_returned=v->pcm_current;
       
   403 	}
       
   404 
       
   405       }
       
   406 
       
   407     }
       
   408   }else{
       
   409     v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
       
   410     if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
       
   411       
       
   412       if(v->granulepos>vb->granulepos){
       
   413 	long extra=v->granulepos-vb->granulepos;
       
   414 	
       
   415 	if(extra)
       
   416 	  if(vb->eofflag){
       
   417 	    /* partial last frame.  Strip the extra samples off */
       
   418 	    v->pcm_current-=extra;
       
   419 	  } /* else {Shouldn't happen *unless* the bitstream is out of
       
   420 	       spec.  Either way, believe the bitstream } */
       
   421       } /* else {Shouldn't happen *unless* the bitstream is out of
       
   422 	   spec.  Either way, believe the bitstream } */
       
   423       v->granulepos=vb->granulepos;
       
   424     }
       
   425   }
       
   426 
       
   427   /* Update, cleanup */
       
   428 
       
   429   if(vb->eofflag)v->eofflag=1;
       
   430   return(0);
       
   431 }
       
   432 
       
   433 /* pcm==NULL indicates we just want the pending samples, no more */
       
   434 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){
       
   435   vorbis_info *vi=v->vi;
       
   436   if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
       
   437     if(pcm){
       
   438       int i;
       
   439       for(i=0;i<vi->channels;i++)
       
   440 	v->pcmret[i]=v->pcm[i]+v->pcm_returned;
       
   441       *pcm=v->pcmret;
       
   442     }
       
   443     return(v->pcm_current-v->pcm_returned);
       
   444   }
       
   445   return(0);
       
   446 }
       
   447 
       
   448 int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
       
   449   if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
       
   450   v->pcm_returned+=bytes;
       
   451   return(0);
       
   452 }
       
   453