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
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 realloc... there are outstanding pointers */
96 if(vb->localstore){
97 struct alloc_chain *link=(struct alloc_chain *)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=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 free(reap->ptr);
122 memset(reap,0,sizeof(*reap));
123 free(reap);
124 reap=next;
125 }
126 /* consolidate storage */
127 if(vb->totaluse){
128 vb->localstore=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)
141 free(vb->localstore);
142
143 memset(vb,0,sizeof(*vb));
144 return(0);
145 }
146
_vds_init(vorbis_dsp_state * v,vorbis_info * vi)147 static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){
148 int i;
149 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
150 private_state *b=NULL;
151
152 if(ci==NULL) return 1;
153
154 memset(v,0,sizeof(*v));
155 b=(private_state *)(v->backend_state=calloc(1,sizeof(*b)));
156
157 v->vi=vi;
158 b->modebits=ilog(ci->modes);
159
160 /* Vorbis I uses only window type 0 */
161 b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2);
162 b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2);
163
164 /* finish the codebooks */
165 if(!ci->fullbooks){
166 ci->fullbooks=(codebook *)calloc(ci->books,sizeof(*ci->fullbooks));
167 for(i=0;i<ci->books;i++){
168 if(ci->book_param[i]==NULL)
169 goto abort_books;
170 if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]))
171 goto abort_books;
172 /* decode codebooks are now standalone after init */
173 vorbis_staticbook_destroy(ci->book_param[i]);
174 ci->book_param[i]=NULL;
175 }
176 }
177
178 v->pcm_storage=ci->blocksizes[1];
179 v->pcm=(int32_t **)malloc(vi->channels*sizeof(*v->pcm));
180 v->pcmret=(int32_t **)malloc(vi->channels*sizeof(*v->pcmret));
181 for(i=0;i<vi->channels;i++)
182 v->pcm[i]=(int32_t *)calloc(v->pcm_storage,sizeof(*v->pcm[i]));
183
184 /* all 1 (large block) or 0 (small block) */
185 /* explicitly set for the sake of clarity */
186 v->lW=0; /* previous window size */
187 v->W=0; /* current window size */
188
189 /* initialize all the mapping/backend lookups */
190 b->mode=(vorbis_look_mapping **)calloc(ci->modes,sizeof(*b->mode));
191 for(i=0;i<ci->modes;i++){
192 int mapnum=ci->mode_param[i]->mapping;
193 int maptype=ci->map_type[mapnum];
194 b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
195 ci->map_param[mapnum]);
196 }
197 return 0;
198 abort_books:
199 for(i=0;i<ci->books;i++){
200 if(ci->book_param[i]!=NULL){
201 vorbis_staticbook_destroy(ci->book_param[i]);
202 ci->book_param[i]=NULL;
203 }
204 }
205 vorbis_dsp_clear(v);
206 return -1;
207 }
208
vorbis_synthesis_restart(vorbis_dsp_state * v)209 int vorbis_synthesis_restart(vorbis_dsp_state *v){
210 vorbis_info *vi=v->vi;
211 codec_setup_info *ci;
212
213 if(!v->backend_state)return -1;
214 if(!vi)return -1;
215 ci=vi->codec_setup;
216 if(!ci)return -1;
217
218 v->centerW=ci->blocksizes[1]/2;
219 v->pcm_current=v->centerW;
220
221 v->pcm_returned=-1;
222 v->granulepos=-1;
223 v->sequence=-1;
224 ((private_state *)(v->backend_state))->sample_count=-1;
225
226 return(0);
227 }
228
vorbis_synthesis_init(vorbis_dsp_state * v,vorbis_info * vi)229 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
230 if(_vds_init(v,vi))return 1;
231 vorbis_synthesis_restart(v);
232
233 return 0;
234 }
235
vorbis_dsp_clear(vorbis_dsp_state * v)236 void vorbis_dsp_clear(vorbis_dsp_state *v){
237 int i;
238 if(v){
239 vorbis_info *vi=v->vi;
240 codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
241 private_state *b=(private_state *)v->backend_state;
242
243 if(v->pcm)
244 {
245 if(vi)
246 for(i=0;i<vi->channels;i++)
247 if(v->pcm[i])
248 free(v->pcm[i]);
249 free(v->pcm);
250 if(v->pcmret)
251 free(v->pcmret);
252 }
253
254 /* free mode lookups; these are actually vorbis_look_mapping structs */
255 if(ci){
256 for(i=0;i<ci->modes;i++){
257 int mapnum=ci->mode_param[i]->mapping;
258 int maptype=ci->map_type[mapnum];
259 if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
260 }
261 }
262
263 if(b)
264 {
265 if(b->mode)
266 free(b->mode);
267 free(b);
268 }
269
270 memset(v,0,sizeof(*v));
271 }
272 }
273
274 /* Unlike in analysis, the window is only partially applied for each
275 block. The time domain envelope is not yet handled at the point of
276 calling (as it relies on the previous block). */
277
vorbis_synthesis_blockin(vorbis_dsp_state * v,vorbis_block * vb)278 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
279 vorbis_info *vi=v->vi;
280 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
281 private_state *b=v->backend_state;
282 int i,j;
283
284 if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
285
286 v->lW=v->W;
287 v->W=vb->W;
288 v->nW=-1;
289
290 if((v->sequence==-1)||
291 (v->sequence+1 != vb->sequence)){
292 v->granulepos=-1; /* out of sequence; lose count */
293 b->sample_count=-1;
294 }
295
296 v->sequence=vb->sequence;
297
298 if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
299 was called on block */
300 int n=ci->blocksizes[v->W]/2;
301 int n0=ci->blocksizes[0]/2;
302 int n1=ci->blocksizes[1]/2;
303
304 int thisCenter;
305 int prevCenter;
306
307 if(v->centerW){
308 thisCenter=n1;
309 prevCenter=0;
310 }else{
311 thisCenter=0;
312 prevCenter=n1;
313 }
314
315 /* v->pcm is now used like a two-stage double buffer. We don't want
316 to have to constantly shift *or* adjust memory usage. Don't
317 accept a new block until the old is shifted out */
318
319 /* overlap/add PCM */
320
321 for(j=0;j<vi->channels;j++){
322 /* the overlap/add section */
323 if(v->lW){
324 if(v->W){
325 /* large/large */
326 int32_t *pcm=v->pcm[j]+prevCenter;
327 int32_t *p=vb->pcm[j];
328 for(i=0;i<n1;i++)
329 pcm[i]+=p[i];
330 }else{
331 /* large/small */
332 int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
333 int32_t *p=vb->pcm[j];
334 for(i=0;i<n0;i++)
335 pcm[i]+=p[i];
336 }
337 }else{
338 if(v->W){
339 /* small/large */
340 int32_t *pcm=v->pcm[j]+prevCenter;
341 int32_t *p=vb->pcm[j]+n1/2-n0/2;
342 for(i=0;i<n0;i++)
343 pcm[i]+=p[i];
344 for(;i<n1/2+n0/2;i++)
345 pcm[i]=p[i];
346 }else{
347 /* small/small */
348 int32_t *pcm=v->pcm[j]+prevCenter;
349 int32_t *p=vb->pcm[j];
350 for(i=0;i<n0;i++)
351 pcm[i]+=p[i];
352 }
353 }
354
355 /* the copy section */
356 {
357 int32_t *pcm=v->pcm[j]+thisCenter;
358 int32_t *p=vb->pcm[j]+n;
359 for(i=0;i<n;i++)
360 pcm[i]=p[i];
361 }
362 }
363
364 if(v->centerW)
365 v->centerW=0;
366 else
367 v->centerW=n1;
368
369 /* deal with initial packet state; we do this using the explicit
370 pcm_returned==-1 flag otherwise we're sensitive to first block
371 being short or long */
372
373 if(v->pcm_returned==-1){
374 v->pcm_returned=thisCenter;
375 v->pcm_current=thisCenter;
376 }else{
377 v->pcm_returned=prevCenter;
378 v->pcm_current=prevCenter+
379 ci->blocksizes[v->lW]/4+
380 ci->blocksizes[v->W]/4;
381 }
382
383 }
384
385 /* track the frame number... This is for convenience, but also
386 making sure our last packet doesn't end with added padding. If
387 the last packet is partial, the number of samples we'll have to
388 return will be past the vb->granulepos.
389
390 This is not foolproof! It will be confused if we begin
391 decoding at the last page after a seek or hole. In that case,
392 we don't have a starting point to judge where the last frame
393 is. For this reason, vorbisfile will always try to make sure
394 it reads the last two marked pages in proper sequence */
395
396 if(b->sample_count==-1){
397 b->sample_count=0;
398 }else{
399 b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
400 }
401
402 if(v->granulepos==-1){
403 if(vb->granulepos!=-1){ /* only set if we have a position to set to */
404
405 v->granulepos=vb->granulepos;
406
407 /* is this a short page? */
408 if(b->sample_count>v->granulepos){
409 /* corner case; if this is both the first and last audio page,
410 then spec says the end is cut, not beginning */
411 long extra=b->sample_count-vb->granulepos;
412
413 /* we use int64_t for granule positions because a
414 uint64 isn't universally available. Unfortunately,
415 that means granposes can be 'negative' and result in
416 extra being negative */
417 if(extra<0)
418 extra=0;
419
420 if(vb->eofflag){
421 /* trim the end */
422 /* no preceeding granulepos; assume we started at zero (we'd
423 have to in a short single-page stream) */
424 /* granulepos could be -1 due to a seek, but that would result
425 in a long coun`t, not short count */
426
427 /* Guard against corrupt/malicious frames that set EOP and
428 a backdated granpos; don't rewind more samples than we
429 actually have */
430 if(extra > v->pcm_current - v->pcm_returned)
431 extra = v->pcm_current - v->pcm_returned;
432
433 v->pcm_current-=extra;
434 }else{
435 /* trim the beginning */
436 v->pcm_returned+=extra;
437 if(v->pcm_returned>v->pcm_current)
438 v->pcm_returned=v->pcm_current;
439 }
440
441 }
442
443 }
444 }else{
445 v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
446 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
447
448 if(v->granulepos>vb->granulepos){
449 long extra=v->granulepos-vb->granulepos;
450
451 if(extra)
452 if(vb->eofflag){
453 /* partial last frame. Strip the extra samples off */
454
455 /* Guard against corrupt/malicious frames that set EOP and
456 a backdated granpos; don't rewind more samples than we
457 actually have */
458 if(extra > v->pcm_current - v->pcm_returned)
459 extra = v->pcm_current - v->pcm_returned;
460
461 /* we use int64_t for granule positions because a
462 uint64 isn't universally available. Unfortunately,
463 that means granposes can be 'negative' and result in
464 extra being negative */
465 if(extra<0)
466 extra=0;
467
468 v->pcm_current-=extra;
469
470 } /* else {Shouldn't happen *unless* the bitstream is out of
471 spec. Either way, believe the bitstream } */
472 } /* else {Shouldn't happen *unless* the bitstream is out of
473 spec. Either way, believe the bitstream } */
474 v->granulepos=vb->granulepos;
475 }
476 }
477
478 /* Update, cleanup */
479
480 if(vb->eofflag)v->eofflag=1;
481 return(0);
482 }
483
484 /* pcm==NULL indicates we just want the pending samples, no more */
vorbis_synthesis_pcmout(vorbis_dsp_state * v,int32_t *** pcm)485 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,int32_t ***pcm){
486 vorbis_info *vi=v->vi;
487 if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
488 if(pcm){
489 int i;
490 for(i=0;i<vi->channels;i++)
491 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
492 *pcm=v->pcmret;
493 }
494 return(v->pcm_current-v->pcm_returned);
495 }
496 return(0);
497 }
498
vorbis_synthesis_read(vorbis_dsp_state * v,int bytes)499 int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
500 if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
501 v->pcm_returned+=bytes;
502 return(0);
503 }
504
505