media/libtremor/lib/tremor_block.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  ********************************************************************
    14  function: PCM data vector blocking, windowing and dis/reassembly
    16  ********************************************************************/
    18 #include <stdio.h>
    19 #include <stdlib.h>
    20 #include <string.h>
    21 #include <ogg/ogg.h>
    22 #include "ivorbiscodec.h"
    23 #include "codec_internal.h"
    25 #include "window.h"
    26 #include "registry.h"
    27 #include "misc.h"
    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 }
    39 /* pcm accumulator examples (not exhaustive):
    41  <-------------- lW ---------------->
    42                    <--------------- W ---------------->
    43 :            .....|.....       _______________         |
    44 :        .'''     |     '''_---      |       |\        |
    45 :.....'''         |_____--- '''......|       | \_______|
    46 :.................|__________________|_______|__|______|
    47                   |<------ Sl ------>|      > Sr <     |endW
    48                   |beginSl           |endSl  |  |endSr   
    49                   |beginW            |endlW  |beginSr
    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]
    63  <-------------- lW ----------------->
    64                           |<--W-->|                               
    65 :            ..............  ___  |   |                    
    66 :        .'''             |`/   \ |   |                       
    67 :.....'''                 |/`....\|...|                    
    68 :.........................|___|___|___|                  
    69                           |Sl |Sr |endW    
    70                           |   |   |endSr
    71                           |   |beginSr
    72                           |   |endSl
    73 			  |beginSl
    74 			  |beginW
    75 */
    77 /* block abstraction setup *********************************************/
    79 #ifndef WORD_ALIGN
    80 #define WORD_ALIGN 8
    81 #endif
    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;
    89   return(0);
    90 }
    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 }
   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   }
   133   /* pull the ripcord */
   134   vb->localtop=0;
   135   vb->reap=NULL;
   136 }
   138 int vorbis_block_clear(vorbis_block *vb){
   139   _vorbis_block_ripcord(vb);
   140   if(vb->localstore)_ogg_free(vb->localstore);
   142   memset(vb,0,sizeof(*vb));
   143   return(0);
   144 }
   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;
   151   if(ci==NULL) return 1;
   153   memset(v,0,sizeof(*v));
   154   b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
   156   v->vi=vi;
   157   b->modebits=ilog(ci->modes);
   159   /* Vorbis I uses only window type 0 */
   160   b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2);
   161   b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2);
   163   /* finish the codebooks */
   164   if(!ci->fullbooks){
   165     ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
   166     for(i=0;i<ci->books;i++){
   167       if(ci->book_param[i]==NULL)
   168         goto abort_books;
   169       if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]))
   170         goto abort_books;
   171       /* decode codebooks are now standalone after init */
   172       vorbis_staticbook_destroy(ci->book_param[i]);
   173       ci->book_param[i]=NULL;
   174     }
   175   }
   177   v->pcm_storage=ci->blocksizes[1];
   178   v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm));
   179   v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret));
   180   for(i=0;i<vi->channels;i++)
   181     v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
   183   /* all 1 (large block) or 0 (small block) */
   184   /* explicitly set for the sake of clarity */
   185   v->lW=0; /* previous window size */
   186   v->W=0;  /* current window size */
   188   /* initialize all the mapping/backend lookups */
   189   b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode));
   190   for(i=0;i<ci->modes;i++){
   191     int mapnum=ci->mode_param[i]->mapping;
   192     int maptype=ci->map_type[mapnum];
   193     b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
   194 					 ci->map_param[mapnum]);
   195   }
   196   return 0;
   197 abort_books:
   198   for(i=0;i<ci->books;i++){
   199     if(ci->book_param[i]!=NULL){
   200       vorbis_staticbook_destroy(ci->book_param[i]);
   201       ci->book_param[i]=NULL;
   202     }
   203   }
   204   vorbis_dsp_clear(v);
   205   return -1;
   206 }
   208 int vorbis_synthesis_restart(vorbis_dsp_state *v){
   209   vorbis_info *vi=v->vi;
   210   codec_setup_info *ci;
   212   if(!v->backend_state)return -1;
   213   if(!vi)return -1;
   214   ci=vi->codec_setup;
   215   if(!ci)return -1;
   217   v->centerW=ci->blocksizes[1]/2;
   218   v->pcm_current=v->centerW;
   220   v->pcm_returned=-1;
   221   v->granulepos=-1;
   222   v->sequence=-1;
   223   ((private_state *)(v->backend_state))->sample_count=-1;
   225   return(0);
   226 }
   228 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
   229   if(_vds_init(v,vi))return 1;
   230   vorbis_synthesis_restart(v);
   232   return 0;
   233 }
   235 void vorbis_dsp_clear(vorbis_dsp_state *v){
   236   int i;
   237   if(v){
   238     vorbis_info *vi=v->vi;
   239     codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
   240     private_state *b=(private_state *)v->backend_state;
   242     if(v->pcm){
   243       for(i=0;i<vi->channels;i++)
   244 	if(v->pcm[i])_ogg_free(v->pcm[i]);
   245       _ogg_free(v->pcm);
   246       if(v->pcmret)_ogg_free(v->pcmret);
   247     }
   249     /* free mode lookups; these are actually vorbis_look_mapping structs */
   250     if(ci){
   251       for(i=0;i<ci->modes;i++){
   252 	int mapnum=ci->mode_param[i]->mapping;
   253 	int maptype=ci->map_type[mapnum];
   254 	if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
   255       }
   256     }
   258     if(b){
   259       if(b->mode)_ogg_free(b->mode);    
   260       _ogg_free(b);
   261     }
   263     memset(v,0,sizeof(*v));
   264   }
   265 }
   267 /* Unlike in analysis, the window is only partially applied for each
   268    block.  The time domain envelope is not yet handled at the point of
   269    calling (as it relies on the previous block). */
   271 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
   272   vorbis_info *vi=v->vi;
   273   codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
   274   private_state *b=v->backend_state;
   275   int i,j;
   277   if(v->pcm_current>v->pcm_returned  && v->pcm_returned!=-1)return(OV_EINVAL);
   279   v->lW=v->W;
   280   v->W=vb->W;
   281   v->nW=-1;
   283   if((v->sequence==-1)||
   284      (v->sequence+1 != vb->sequence)){
   285     v->granulepos=-1; /* out of sequence; lose count */
   286     b->sample_count=-1;
   287   }
   289   v->sequence=vb->sequence;
   291   if(vb->pcm){  /* no pcm to process if vorbis_synthesis_trackonly 
   292                    was called on block */
   293     int n=ci->blocksizes[v->W]/2;
   294     int n0=ci->blocksizes[0]/2;
   295     int n1=ci->blocksizes[1]/2;
   297     int thisCenter;
   298     int prevCenter;
   300     if(v->centerW){
   301       thisCenter=n1;
   302       prevCenter=0;
   303     }else{
   304       thisCenter=0;
   305       prevCenter=n1;
   306     }
   308     /* v->pcm is now used like a two-stage double buffer.  We don't want
   309        to have to constantly shift *or* adjust memory usage.  Don't
   310        accept a new block until the old is shifted out */
   312     /* overlap/add PCM */
   314     for(j=0;j<vi->channels;j++){
   315       /* the overlap/add section */
   316       if(v->lW){
   317 	if(v->W){
   318 	  /* large/large */
   319 	  ogg_int32_t *pcm=v->pcm[j]+prevCenter;
   320 	  ogg_int32_t *p=vb->pcm[j];
   321 	  for(i=0;i<n1;i++)
   322 	    pcm[i]+=p[i];
   323 	}else{
   324 	  /* large/small */
   325 	  ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
   326 	  ogg_int32_t *p=vb->pcm[j];
   327 	  for(i=0;i<n0;i++)
   328 	    pcm[i]+=p[i];
   329 	}
   330       }else{
   331 	if(v->W){
   332 	  /* small/large */
   333 	  ogg_int32_t *pcm=v->pcm[j]+prevCenter;
   334 	  ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
   335 	  for(i=0;i<n0;i++)
   336 	    pcm[i]+=p[i];
   337 	  for(;i<n1/2+n0/2;i++)
   338 	    pcm[i]=p[i];
   339 	}else{
   340 	  /* small/small */
   341 	  ogg_int32_t *pcm=v->pcm[j]+prevCenter;
   342 	  ogg_int32_t *p=vb->pcm[j];
   343 	  for(i=0;i<n0;i++)
   344 	    pcm[i]+=p[i];
   345 	}
   346       }
   348       /* the copy section */
   349       {
   350 	ogg_int32_t *pcm=v->pcm[j]+thisCenter;
   351 	ogg_int32_t *p=vb->pcm[j]+n;
   352 	for(i=0;i<n;i++)
   353 	  pcm[i]=p[i];
   354       }
   355     }
   357     if(v->centerW)
   358       v->centerW=0;
   359     else
   360       v->centerW=n1;
   362     /* deal with initial packet state; we do this using the explicit
   363        pcm_returned==-1 flag otherwise we're sensitive to first block
   364        being short or long */
   366     if(v->pcm_returned==-1){
   367       v->pcm_returned=thisCenter;
   368       v->pcm_current=thisCenter;
   369     }else{
   370       v->pcm_returned=prevCenter;
   371       v->pcm_current=prevCenter+
   372 	ci->blocksizes[v->lW]/4+
   373 	ci->blocksizes[v->W]/4;
   374     }
   376   }
   378   /* track the frame number... This is for convenience, but also
   379      making sure our last packet doesn't end with added padding.  If
   380      the last packet is partial, the number of samples we'll have to
   381      return will be past the vb->granulepos.
   383      This is not foolproof!  It will be confused if we begin
   384      decoding at the last page after a seek or hole.  In that case,
   385      we don't have a starting point to judge where the last frame
   386      is.  For this reason, vorbisfile will always try to make sure
   387      it reads the last two marked pages in proper sequence */
   389   if(b->sample_count==-1){
   390     b->sample_count=0;
   391   }else{
   392     b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
   393   }
   395   if(v->granulepos==-1){
   396     if(vb->granulepos!=-1){ /* only set if we have a position to set to */
   398       v->granulepos=vb->granulepos;
   400       /* is this a short page? */
   401       if(b->sample_count>v->granulepos){
   402 	/* corner case; if this is both the first and last audio page,
   403 	   then spec says the end is cut, not beginning */
   404 	long extra=b->sample_count-vb->granulepos;
   406         /* we use ogg_int64_t for granule positions because a
   407            uint64 isn't universally available.  Unfortunately,
   408            that means granposes can be 'negative' and result in
   409            extra being negative */
   410         if(extra<0)
   411           extra=0;
   413 	if(vb->eofflag){
   414 	  /* trim the end */
   415 	  /* no preceeding granulepos; assume we started at zero (we'd
   416 	     have to in a short single-page stream) */
   417 	  /* granulepos could be -1 due to a seek, but that would result
   418 	     in a long coun`t, not short count */
   420           /* Guard against corrupt/malicious frames that set EOP and
   421              a backdated granpos; don't rewind more samples than we
   422              actually have */
   423           if(extra > v->pcm_current - v->pcm_returned)
   424             extra = v->pcm_current - v->pcm_returned;
   426 	  v->pcm_current-=extra;
   427 	}else{
   428 	  /* trim the beginning */
   429 	  v->pcm_returned+=extra;
   430 	  if(v->pcm_returned>v->pcm_current)
   431 	    v->pcm_returned=v->pcm_current;
   432 	}
   434       }
   436     }
   437   }else{
   438     v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
   439     if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
   441       if(v->granulepos>vb->granulepos){
   442 	long extra=v->granulepos-vb->granulepos;
   444 	if(extra)
   445 	  if(vb->eofflag){
   446 	    /* partial last frame.  Strip the extra samples off */
   448             /* Guard against corrupt/malicious frames that set EOP and
   449                a backdated granpos; don't rewind more samples than we
   450                actually have */
   451             if(extra > v->pcm_current - v->pcm_returned)
   452               extra = v->pcm_current - v->pcm_returned;
   454             /* we use ogg_int64_t for granule positions because a
   455                uint64 isn't universally available.  Unfortunately,
   456                that means granposes can be 'negative' and result in
   457                extra being negative */
   458             if(extra<0)
   459               extra=0;
   461             v->pcm_current-=extra;
   463 	  } /* else {Shouldn't happen *unless* the bitstream is out of
   464 	       spec.  Either way, believe the bitstream } */
   465       } /* else {Shouldn't happen *unless* the bitstream is out of
   466 	   spec.  Either way, believe the bitstream } */
   467       v->granulepos=vb->granulepos;
   468     }
   469   }
   471   /* Update, cleanup */
   473   if(vb->eofflag)v->eofflag=1;
   474   return(0);
   475 }
   477 /* pcm==NULL indicates we just want the pending samples, no more */
   478 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){
   479   vorbis_info *vi=v->vi;
   480   if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
   481     if(pcm){
   482       int i;
   483       for(i=0;i<vi->channels;i++)
   484 	v->pcmret[i]=v->pcm[i]+v->pcm_returned;
   485       *pcm=v->pcmret;
   486     }
   487     return(v->pcm_current-v->pcm_returned);
   488   }
   489   return(0);
   490 }
   492 int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
   493   if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
   494   v->pcm_returned+=bytes;
   495   return(0);
   496 }

mercurial