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/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 
ilog(unsigned int v)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 
vorbis_block_init(vorbis_dsp_state * v,vorbis_block * vb)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 
_vorbis_block_alloc(vorbis_block * vb,long bytes)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 */
_vorbis_block_ripcord(vorbis_block * vb)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 
vorbis_block_clear(vorbis_block * vb)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 
_vds_init(vorbis_dsp_state * v,vorbis_info * vi)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   if(ci==NULL) return 1;
152 
153   memset(v,0,sizeof(*v));
154   b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
155 
156   v->vi=vi;
157   b->modebits=ilog(ci->modes);
158 
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);
162 
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   }
176 
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]));
182 
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 */
187 
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 }
207 
vorbis_synthesis_restart(vorbis_dsp_state * v)208 int vorbis_synthesis_restart(vorbis_dsp_state *v){
209   vorbis_info *vi=v->vi;
210   codec_setup_info *ci;
211 
212   if(!v->backend_state)return -1;
213   if(!vi)return -1;
214   ci=vi->codec_setup;
215   if(!ci)return -1;
216 
217   v->centerW=ci->blocksizes[1]/2;
218   v->pcm_current=v->centerW;
219 
220   v->pcm_returned=-1;
221   v->granulepos=-1;
222   v->sequence=-1;
223   ((private_state *)(v->backend_state))->sample_count=-1;
224 
225   return(0);
226 }
227 
vorbis_synthesis_init(vorbis_dsp_state * v,vorbis_info * vi)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);
231 
232   return 0;
233 }
234 
vorbis_dsp_clear(vorbis_dsp_state * v)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;
241 
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     }
248 
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     }
257 
258     if(b){
259       if(b->mode)_ogg_free(b->mode);
260       _ogg_free(b);
261     }
262 
263     memset(v,0,sizeof(*v));
264   }
265 }
266 
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). */
270 
vorbis_synthesis_blockin(vorbis_dsp_state * v,vorbis_block * vb)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;
276 
277   if(v->pcm_current>v->pcm_returned  && v->pcm_returned!=-1)return(OV_EINVAL);
278 
279   v->lW=v->W;
280   v->W=vb->W;
281   v->nW=-1;
282 
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   }
288 
289   v->sequence=vb->sequence;
290 
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;
296 
297     int thisCenter;
298     int prevCenter;
299 
300     if(v->centerW){
301       thisCenter=n1;
302       prevCenter=0;
303     }else{
304       thisCenter=0;
305       prevCenter=n1;
306     }
307 
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 */
311 
312     /* overlap/add PCM */
313 
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       }
347 
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     }
356 
357     if(v->centerW)
358       v->centerW=0;
359     else
360       v->centerW=n1;
361 
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 */
365 
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     }
375 
376   }
377 
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.
382 
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 */
388 
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   }
394 
395   if(v->granulepos==-1){
396     if(vb->granulepos!=-1){ /* only set if we have a position to set to */
397 
398       v->granulepos=vb->granulepos;
399 
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;
405 
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;
412 
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 */
419 
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;
425 
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 	}
433 
434       }
435 
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){
440 
441       if(v->granulepos>vb->granulepos){
442 	long extra=v->granulepos-vb->granulepos;
443 
444 	if(extra)
445 	  if(vb->eofflag){
446 	    /* partial last frame.  Strip the extra samples off */
447 
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;
453 
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;
460 
461             v->pcm_current-=extra;
462 
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   }
470 
471   /* Update, cleanup */
472 
473   if(vb->eofflag)v->eofflag=1;
474   return(0);
475 }
476 
477 /* pcm==NULL indicates we just want the pending samples, no more */
vorbis_synthesis_pcmout(vorbis_dsp_state * v,ogg_int32_t *** pcm)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 }
491 
vorbis_synthesis_read(vorbis_dsp_state * v,int bytes)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 }
497 
498