misc/libtremor/tremor/dsp.c
changeset 7851 d4bda0201cae
parent 7850 fcbb024090a4
child 7852 d25ffc7271d5
equal deleted inserted replaced
7850:fcbb024090a4 7851:d4bda0201cae
     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-2003    *
       
    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 <stdlib.h> 
       
    19 #include "ogg.h"
       
    20 #include "mdct.h"
       
    21 #include "ivorbiscodec.h"
       
    22 #include "codec_internal.h"
       
    23 #include "misc.h"
       
    24 #include "window_lookup.h"
       
    25 
       
    26 int vorbis_dsp_restart(vorbis_dsp_state *v){
       
    27   if(!v)return -1;
       
    28   {
       
    29     vorbis_info *vi=v->vi;
       
    30     codec_setup_info *ci;
       
    31     
       
    32     if(!vi)return -1;
       
    33     ci=vi->codec_setup;
       
    34     if(!ci)return -1;
       
    35     
       
    36     v->out_end=-1;
       
    37     v->out_begin=-1;
       
    38 
       
    39     v->granulepos=-1;
       
    40     v->sequence=-1;
       
    41     v->sample_count=-1;
       
    42   }
       
    43   return 0;
       
    44 }
       
    45 
       
    46 vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){
       
    47   int i;
       
    48 
       
    49   vorbis_dsp_state *v=_ogg_calloc(1,sizeof(*v));
       
    50   codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
       
    51 
       
    52   v->vi=vi;
       
    53   
       
    54   v->work=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->work));
       
    55   v->mdctright=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->mdctright));
       
    56   for(i=0;i<vi->channels;i++){
       
    57     v->work[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>1)*
       
    58 					  sizeof(*v->work[i]));
       
    59     v->mdctright[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>2)*
       
    60 					       sizeof(*v->mdctright[i]));
       
    61   }
       
    62 
       
    63   v->lW=0; /* previous window size */
       
    64   v->W=0;  /* current window size */
       
    65 
       
    66   vorbis_dsp_restart(v);
       
    67   return v;
       
    68 }
       
    69 
       
    70 void vorbis_dsp_destroy(vorbis_dsp_state *v){
       
    71   int i;
       
    72   if(v){
       
    73     vorbis_info *vi=v->vi;
       
    74 
       
    75     if(v->work){
       
    76       for(i=0;i<vi->channels;i++)
       
    77         if(v->work[i])_ogg_free(v->work[i]);
       
    78       _ogg_free(v->work);
       
    79     }
       
    80     if(v->mdctright){
       
    81       for(i=0;i<vi->channels;i++)
       
    82         if(v->mdctright[i])_ogg_free(v->mdctright[i]);
       
    83       _ogg_free(v->mdctright);
       
    84     }
       
    85 
       
    86     _ogg_free(v);
       
    87   }
       
    88 }
       
    89 
       
    90 static LOOKUP_T *_vorbis_window(int left){
       
    91   switch(left){
       
    92   case 32:
       
    93     return vwin64;
       
    94   case 64:
       
    95     return vwin128;
       
    96   case 128:
       
    97     return vwin256;
       
    98   case 256:
       
    99     return vwin512;
       
   100   case 512:
       
   101     return vwin1024;
       
   102   case 1024:
       
   103     return vwin2048;
       
   104   case 2048:
       
   105     return vwin4096;
       
   106 #ifndef LIMIT_TO_64kHz
       
   107   case 4096:
       
   108     return vwin8192;
       
   109 #endif
       
   110   default:
       
   111     return(0);
       
   112   }
       
   113 }
       
   114 
       
   115 /* pcm==0 indicates we just want the pending samples, no more */
       
   116 int vorbis_dsp_pcmout(vorbis_dsp_state *v,ogg_int16_t *pcm,int samples){
       
   117   vorbis_info *vi=v->vi;
       
   118   codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
       
   119   if(v->out_begin>-1 && v->out_begin<v->out_end){
       
   120     int n=v->out_end-v->out_begin;
       
   121     if(pcm){
       
   122       int i;
       
   123       if(n>samples)n=samples;
       
   124       for(i=0;i<vi->channels;i++)
       
   125 	mdct_unroll_lap(ci->blocksizes[0],ci->blocksizes[1],
       
   126 			v->lW,v->W,v->work[i],v->mdctright[i],
       
   127 			_vorbis_window(ci->blocksizes[0]>>1),
       
   128 			_vorbis_window(ci->blocksizes[1]>>1),
       
   129 			pcm+i,vi->channels,
       
   130 			v->out_begin,v->out_begin+n);
       
   131     }
       
   132     return(n);
       
   133   }
       
   134   return(0);
       
   135 }
       
   136 
       
   137 int vorbis_dsp_read(vorbis_dsp_state *v,int s){
       
   138   if(s && v->out_begin+s>v->out_end)return(OV_EINVAL);
       
   139   v->out_begin+=s;
       
   140   return(0);
       
   141 }
       
   142 
       
   143 long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
       
   144   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
       
   145   oggpack_buffer       opb;
       
   146   int                  mode;
       
   147   int modebits=0;
       
   148   int v=ci->modes;
       
   149  
       
   150   oggpack_readinit(&opb,op->packet);
       
   151 
       
   152   /* Check the packet type */
       
   153   if(oggpack_read(&opb,1)!=0){
       
   154     /* Oops.  This is not an audio data packet */
       
   155     return(OV_ENOTAUDIO);
       
   156   }
       
   157 
       
   158   while(v>1){
       
   159     modebits++;
       
   160     v>>=1;
       
   161   }
       
   162 
       
   163   /* read our mode and pre/post windowsize */
       
   164   mode=oggpack_read(&opb,modebits);
       
   165   if(mode==-1)return(OV_EBADPACKET);
       
   166   return(ci->blocksizes[ci->mode_param[mode].blockflag]);
       
   167 }
       
   168 
       
   169 
       
   170 static int ilog(ogg_uint32_t v){
       
   171   int ret=0;
       
   172   if(v)--v;
       
   173   while(v){
       
   174     ret++;
       
   175     v>>=1;
       
   176   }
       
   177   return(ret);
       
   178 }
       
   179 
       
   180 int vorbis_dsp_synthesis(vorbis_dsp_state *vd,ogg_packet *op,int decodep){
       
   181   vorbis_info          *vi=vd->vi;
       
   182   codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
       
   183   int                   mode,i;
       
   184 
       
   185   oggpack_readinit(&vd->opb,op->packet);
       
   186 
       
   187   /* Check the packet type */
       
   188   if(oggpack_read(&vd->opb,1)!=0){
       
   189     /* Oops.  This is not an audio data packet */
       
   190     return OV_ENOTAUDIO ;
       
   191   }
       
   192 
       
   193   /* read our mode and pre/post windowsize */
       
   194   mode=oggpack_read(&vd->opb,ilog(ci->modes));
       
   195   if(mode==-1 || mode>=ci->modes) return OV_EBADPACKET;
       
   196 
       
   197   /* shift information we still need from last window */
       
   198   vd->lW=vd->W;
       
   199   vd->W=ci->mode_param[mode].blockflag;
       
   200   for(i=0;i<vi->channels;i++)
       
   201     mdct_shift_right(ci->blocksizes[vd->lW],vd->work[i],vd->mdctright[i]);
       
   202   
       
   203   if(vd->W){
       
   204     int temp;
       
   205     oggpack_read(&vd->opb,1);
       
   206     temp=oggpack_read(&vd->opb,1);
       
   207     if(temp==-1) return OV_EBADPACKET;
       
   208   }
       
   209   
       
   210   /* packet decode and portions of synthesis that rely on only this block */
       
   211   if(decodep){
       
   212     mapping_inverse(vd,ci->map_param+ci->mode_param[mode].mapping);
       
   213 
       
   214     if(vd->out_begin==-1){
       
   215       vd->out_begin=0;
       
   216       vd->out_end=0;
       
   217     }else{
       
   218       vd->out_begin=0;
       
   219       vd->out_end=ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
       
   220     }
       
   221   }
       
   222 
       
   223   /* track the frame number... This is for convenience, but also
       
   224      making sure our last packet doesn't end with added padding.
       
   225      
       
   226      This is not foolproof!  It will be confused if we begin
       
   227      decoding at the last page after a seek or hole.  In that case,
       
   228      we don't have a starting point to judge where the last frame
       
   229      is.  For this reason, vorbisfile will always try to make sure
       
   230      it reads the last two marked pages in proper sequence */
       
   231   
       
   232   /* if we're out of sequence, dump granpos tracking until we sync back up */
       
   233   if(vd->sequence==-1 || vd->sequence+1 != op->packetno-3){
       
   234     /* out of sequence; lose count */
       
   235     vd->granulepos=-1;
       
   236     vd->sample_count=-1;
       
   237   }
       
   238   
       
   239   vd->sequence=op->packetno;
       
   240   vd->sequence=vd->sequence-3;
       
   241   
       
   242   if(vd->sample_count==-1){
       
   243     vd->sample_count=0;
       
   244   }else{
       
   245     vd->sample_count+=
       
   246       ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
       
   247   }
       
   248   
       
   249   if(vd->granulepos==-1){
       
   250     if(op->granulepos!=-1){ /* only set if we have a
       
   251 			       position to set to */
       
   252       
       
   253       vd->granulepos=op->granulepos;
       
   254       
       
   255       /* is this a short page? */
       
   256       if(vd->sample_count>vd->granulepos){
       
   257 	/* corner case; if this is both the first and last audio page,
       
   258 	   then spec says the end is cut, not beginning */
       
   259 	if(op->e_o_s){
       
   260 	  /* trim the end */
       
   261 	  /* no preceeding granulepos; assume we started at zero (we'd
       
   262 	     have to in a short single-page stream) */
       
   263 	  /* granulepos could be -1 due to a seek, but that would result
       
   264 	     in a long coun t, not short count */
       
   265 	  
       
   266 	  vd->out_end-=vd->sample_count-vd->granulepos;
       
   267 	}else{
       
   268 	  /* trim the beginning */
       
   269 	  vd->out_begin+=vd->sample_count-vd->granulepos;
       
   270 	  if(vd->out_begin>vd->out_end)
       
   271 	    vd->out_begin=vd->out_end;
       
   272 	}
       
   273 	
       
   274       }
       
   275       
       
   276     }
       
   277   }else{
       
   278     vd->granulepos+=
       
   279       ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
       
   280     if(op->granulepos!=-1 && vd->granulepos!=op->granulepos){
       
   281       
       
   282       if(vd->granulepos>op->granulepos){
       
   283 	long extra=vd->granulepos-op->granulepos;
       
   284 	
       
   285 	if(extra)
       
   286 	  if(op->e_o_s){
       
   287 	    /* partial last frame.  Strip the extra samples off */
       
   288 	    vd->out_end-=extra;
       
   289 	  } /* else {Shouldn't happen *unless* the bitstream is out of
       
   290 	       spec.  Either way, believe the bitstream } */
       
   291       } /* else {Shouldn't happen *unless* the bitstream is out of
       
   292 	   spec.  Either way, believe the bitstream } */
       
   293       vd->granulepos=op->granulepos;
       
   294     }
       
   295   }
       
   296 
       
   297   return(0);
       
   298 }