Line | Count | Source |
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 | | |
29 | 3.63k | static int ilog(unsigned int v){ |
30 | 3.63k | int ret=0; |
31 | 3.63k | if(v)--v; |
32 | 4.51k | while(v){ |
33 | 880 | ret++; |
34 | 880 | v>>=1; |
35 | 880 | } |
36 | 3.63k | return(ret); |
37 | 3.63k | } |
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 | 3.06M | #define WORD_ALIGN 8 |
81 | | #endif |
82 | | |
83 | 3.59k | int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ |
84 | 3.59k | memset(vb,0,sizeof(*vb)); |
85 | 3.59k | vb->vd=v; |
86 | 3.59k | vb->localalloc=0; |
87 | 3.59k | vb->localstore=NULL; |
88 | | |
89 | 3.59k | return(0); |
90 | 3.59k | } |
91 | | |
92 | 1.53M | void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ |
93 | 1.53M | bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); |
94 | 1.53M | if(bytes+vb->localtop>vb->localalloc){ |
95 | | /* can't just _ogg_realloc... there are outstanding pointers */ |
96 | 169k | if(vb->localstore){ |
97 | 167k | struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link)); |
98 | 167k | vb->totaluse+=vb->localtop; |
99 | 167k | link->next=vb->reap; |
100 | 167k | link->ptr=vb->localstore; |
101 | 167k | vb->reap=link; |
102 | 167k | } |
103 | | /* highly conservative */ |
104 | 169k | vb->localalloc=bytes; |
105 | 169k | vb->localstore=_ogg_malloc(vb->localalloc); |
106 | 169k | vb->localtop=0; |
107 | 169k | } |
108 | 1.53M | { |
109 | 1.53M | void *ret=(void *)(((char *)vb->localstore)+vb->localtop); |
110 | 1.53M | vb->localtop+=bytes; |
111 | 1.53M | return ret; |
112 | 1.53M | } |
113 | 1.53M | } |
114 | | |
115 | | /* reap the chain, pull the ripcord */ |
116 | 51.8k | void _vorbis_block_ripcord(vorbis_block *vb){ |
117 | | /* reap the chain */ |
118 | 51.8k | struct alloc_chain *reap=vb->reap; |
119 | 218k | while(reap){ |
120 | 167k | struct alloc_chain *next=reap->next; |
121 | 167k | _ogg_free(reap->ptr); |
122 | 167k | memset(reap,0,sizeof(*reap)); |
123 | 167k | _ogg_free(reap); |
124 | 167k | reap=next; |
125 | 167k | } |
126 | | /* consolidate storage */ |
127 | 51.8k | if(vb->totaluse){ |
128 | 3.00k | vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); |
129 | 3.00k | vb->localalloc+=vb->totaluse; |
130 | 3.00k | vb->totaluse=0; |
131 | 3.00k | } |
132 | | |
133 | | /* pull the ripcord */ |
134 | 51.8k | vb->localtop=0; |
135 | 51.8k | vb->reap=NULL; |
136 | 51.8k | } |
137 | | |
138 | 4.30k | int vorbis_block_clear(vorbis_block *vb){ |
139 | 4.30k | _vorbis_block_ripcord(vb); |
140 | 4.30k | if(vb->localstore)_ogg_free(vb->localstore); |
141 | | |
142 | 4.30k | memset(vb,0,sizeof(*vb)); |
143 | 4.30k | return(0); |
144 | 4.30k | } |
145 | | |
146 | 3.63k | static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){ |
147 | 3.63k | int i; |
148 | 3.63k | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; |
149 | 3.63k | private_state *b=NULL; |
150 | | |
151 | 3.63k | if(ci==NULL) return 1; |
152 | | |
153 | 3.63k | memset(v,0,sizeof(*v)); |
154 | 3.63k | b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b))); |
155 | | |
156 | 3.63k | v->vi=vi; |
157 | 3.63k | b->modebits=ilog(ci->modes); |
158 | | |
159 | | /* Vorbis I uses only window type 0 */ |
160 | 3.63k | b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2); |
161 | 3.63k | b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2); |
162 | | |
163 | | /* finish the codebooks */ |
164 | 3.63k | if(!ci->fullbooks){ |
165 | 3.63k | ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); |
166 | 9.56k | for(i=0;i<ci->books;i++){ |
167 | 5.97k | if(ci->book_param[i]==NULL) |
168 | 0 | goto abort_books; |
169 | 5.97k | if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])) |
170 | 37 | goto abort_books; |
171 | | /* decode codebooks are now standalone after init */ |
172 | 5.93k | vorbis_staticbook_destroy(ci->book_param[i]); |
173 | 5.93k | ci->book_param[i]=NULL; |
174 | 5.93k | } |
175 | 3.63k | } |
176 | | |
177 | 3.59k | v->pcm_storage=ci->blocksizes[1]; |
178 | 3.59k | v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm)); |
179 | 3.59k | v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret)); |
180 | 259k | for(i=0;i<vi->channels;i++) |
181 | 256k | 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 | 3.59k | v->lW=0; /* previous window size */ |
186 | 3.59k | v->W=0; /* current window size */ |
187 | | |
188 | | /* initialize all the mapping/backend lookups */ |
189 | 3.59k | b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode)); |
190 | 9.23k | for(i=0;i<ci->modes;i++){ |
191 | 5.63k | int mapnum=ci->mode_param[i]->mapping; |
192 | 5.63k | int maptype=ci->map_type[mapnum]; |
193 | 5.63k | b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i], |
194 | 5.63k | ci->map_param[mapnum]); |
195 | 5.63k | } |
196 | 3.59k | return 0; |
197 | 37 | abort_books: |
198 | 749 | for(i=0;i<ci->books;i++){ |
199 | 712 | if(ci->book_param[i]!=NULL){ |
200 | 364 | vorbis_staticbook_destroy(ci->book_param[i]); |
201 | 364 | ci->book_param[i]=NULL; |
202 | 364 | } |
203 | 712 | } |
204 | 37 | vorbis_dsp_clear(v); |
205 | 37 | return -1; |
206 | 3.63k | } |
207 | | |
208 | 3.59k | int vorbis_synthesis_restart(vorbis_dsp_state *v){ |
209 | 3.59k | vorbis_info *vi=v->vi; |
210 | 3.59k | codec_setup_info *ci; |
211 | | |
212 | 3.59k | if(!v->backend_state)return -1; |
213 | 3.59k | if(!vi)return -1; |
214 | 3.59k | ci=vi->codec_setup; |
215 | 3.59k | if(!ci)return -1; |
216 | | |
217 | 3.59k | v->centerW=ci->blocksizes[1]/2; |
218 | 3.59k | v->pcm_current=v->centerW; |
219 | | |
220 | 3.59k | v->pcm_returned=-1; |
221 | 3.59k | v->granulepos=-1; |
222 | 3.59k | v->sequence=-1; |
223 | 3.59k | ((private_state *)(v->backend_state))->sample_count=-1; |
224 | | |
225 | 3.59k | return(0); |
226 | 3.59k | } |
227 | | |
228 | 3.63k | int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ |
229 | 3.63k | if(_vds_init(v,vi))return 1; |
230 | 3.59k | vorbis_synthesis_restart(v); |
231 | | |
232 | 3.59k | return 0; |
233 | 3.63k | } |
234 | | |
235 | 4.34k | void vorbis_dsp_clear(vorbis_dsp_state *v){ |
236 | 4.34k | int i; |
237 | 4.34k | if(v){ |
238 | 4.34k | vorbis_info *vi=v->vi; |
239 | 4.34k | codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL); |
240 | 4.34k | private_state *b=(private_state *)v->backend_state; |
241 | | |
242 | 4.34k | if(v->pcm){ |
243 | 259k | for(i=0;i<vi->channels;i++) |
244 | 256k | if(v->pcm[i])_ogg_free(v->pcm[i]); |
245 | 3.59k | _ogg_free(v->pcm); |
246 | 3.59k | if(v->pcmret)_ogg_free(v->pcmret); |
247 | 3.59k | } |
248 | | |
249 | | /* free mode lookups; these are actually vorbis_look_mapping structs */ |
250 | 4.34k | if(ci){ |
251 | 9.40k | for(i=0;i<ci->modes;i++){ |
252 | 5.77k | int mapnum=ci->mode_param[i]->mapping; |
253 | 5.77k | int maptype=ci->map_type[mapnum]; |
254 | 5.77k | if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]); |
255 | 5.77k | } |
256 | 3.63k | } |
257 | | |
258 | 4.34k | if(b){ |
259 | 3.63k | if(b->mode)_ogg_free(b->mode); |
260 | 3.63k | _ogg_free(b); |
261 | 3.63k | } |
262 | | |
263 | 4.34k | memset(v,0,sizeof(*v)); |
264 | 4.34k | } |
265 | 4.34k | } |
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 | | |
271 | 18.6k | int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ |
272 | 18.6k | vorbis_info *vi=v->vi; |
273 | 18.6k | codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; |
274 | 18.6k | private_state *b=v->backend_state; |
275 | 18.6k | int i,j; |
276 | | |
277 | 18.6k | if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); |
278 | | |
279 | 17.4k | v->lW=v->W; |
280 | 17.4k | v->W=vb->W; |
281 | 17.4k | v->nW=-1; |
282 | | |
283 | 17.4k | if((v->sequence==-1)|| |
284 | 15.1k | (v->sequence+1 != vb->sequence)){ |
285 | 8.86k | v->granulepos=-1; /* out of sequence; lose count */ |
286 | 8.86k | b->sample_count=-1; |
287 | 8.86k | } |
288 | | |
289 | 17.4k | v->sequence=vb->sequence; |
290 | | |
291 | 17.4k | if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly |
292 | | was called on block */ |
293 | 17.4k | int n=ci->blocksizes[v->W]/2; |
294 | 17.4k | int n0=ci->blocksizes[0]/2; |
295 | 17.4k | int n1=ci->blocksizes[1]/2; |
296 | | |
297 | 17.4k | int thisCenter; |
298 | 17.4k | int prevCenter; |
299 | | |
300 | 17.4k | if(v->centerW){ |
301 | 9.28k | thisCenter=n1; |
302 | 9.28k | prevCenter=0; |
303 | 9.28k | }else{ |
304 | 8.13k | thisCenter=0; |
305 | 8.13k | prevCenter=n1; |
306 | 8.13k | } |
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 | 1.40M | for(j=0;j<vi->channels;j++){ |
315 | | /* the overlap/add section */ |
316 | 1.38M | if(v->lW){ |
317 | 545k | if(v->W){ |
318 | | /* large/large */ |
319 | 542k | ogg_int32_t *pcm=v->pcm[j]+prevCenter; |
320 | 542k | ogg_int32_t *p=vb->pcm[j]; |
321 | 895M | for(i=0;i<n1;i++) |
322 | 894M | pcm[i]+=p[i]; |
323 | 542k | }else{ |
324 | | /* large/small */ |
325 | 2.57k | ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; |
326 | 2.57k | ogg_int32_t *p=vb->pcm[j]; |
327 | 437k | for(i=0;i<n0;i++) |
328 | 434k | pcm[i]+=p[i]; |
329 | 2.57k | } |
330 | 842k | }else{ |
331 | 842k | if(v->W){ |
332 | | /* small/large */ |
333 | 85.6k | ogg_int32_t *pcm=v->pcm[j]+prevCenter; |
334 | 85.6k | ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2; |
335 | 15.6M | for(i=0;i<n0;i++) |
336 | 15.6M | pcm[i]+=p[i]; |
337 | 16.5M | for(;i<n1/2+n0/2;i++) |
338 | 16.5M | pcm[i]=p[i]; |
339 | 757k | }else{ |
340 | | /* small/small */ |
341 | 757k | ogg_int32_t *pcm=v->pcm[j]+prevCenter; |
342 | 757k | ogg_int32_t *p=vb->pcm[j]; |
343 | 1.09G | for(i=0;i<n0;i++) |
344 | 1.09G | pcm[i]+=p[i]; |
345 | 757k | } |
346 | 842k | } |
347 | | |
348 | | /* the copy section */ |
349 | 1.38M | { |
350 | 1.38M | ogg_int32_t *pcm=v->pcm[j]+thisCenter; |
351 | 1.38M | ogg_int32_t *p=vb->pcm[j]+n; |
352 | 2.03G | for(i=0;i<n;i++) |
353 | 2.03G | pcm[i]=p[i]; |
354 | 1.38M | } |
355 | 1.38M | } |
356 | | |
357 | 17.4k | if(v->centerW) |
358 | 9.28k | v->centerW=0; |
359 | 8.13k | else |
360 | 8.13k | 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 | 17.4k | if(v->pcm_returned==-1){ |
367 | 2.26k | v->pcm_returned=thisCenter; |
368 | 2.26k | v->pcm_current=thisCenter; |
369 | 15.1k | }else{ |
370 | 15.1k | v->pcm_returned=prevCenter; |
371 | 15.1k | v->pcm_current=prevCenter+ |
372 | 15.1k | ci->blocksizes[v->lW]/4+ |
373 | 15.1k | ci->blocksizes[v->W]/4; |
374 | 15.1k | } |
375 | | |
376 | 17.4k | } |
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 | 17.4k | if(b->sample_count==-1){ |
390 | 8.86k | b->sample_count=0; |
391 | 8.86k | }else{ |
392 | 8.56k | b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; |
393 | 8.56k | } |
394 | | |
395 | 17.4k | if(v->granulepos==-1){ |
396 | 16.0k | if(vb->granulepos!=-1){ /* only set if we have a position to set to */ |
397 | | |
398 | 4.59k | v->granulepos=vb->granulepos; |
399 | | |
400 | | /* is this a short page? */ |
401 | 4.59k | 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 | 2.51k | 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 | 2.51k | if(extra<0) |
411 | 19 | extra=0; |
412 | | |
413 | 2.51k | 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 | 1.25k | if(extra > v->pcm_current - v->pcm_returned) |
424 | 1.22k | extra = v->pcm_current - v->pcm_returned; |
425 | | |
426 | 1.25k | v->pcm_current-=extra; |
427 | 1.25k | }else{ |
428 | | /* trim the beginning */ |
429 | 1.25k | v->pcm_returned+=extra; |
430 | 1.25k | if(v->pcm_returned>v->pcm_current) |
431 | 674 | v->pcm_returned=v->pcm_current; |
432 | 1.25k | } |
433 | | |
434 | 2.51k | } |
435 | | |
436 | 4.59k | } |
437 | 16.0k | }else{ |
438 | 1.36k | v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; |
439 | 1.36k | if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ |
440 | | |
441 | 860 | if(v->granulepos>vb->granulepos){ |
442 | 637 | long extra=v->granulepos-vb->granulepos; |
443 | | |
444 | 637 | if(extra) |
445 | 637 | 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 | 410 | if(extra > v->pcm_current - v->pcm_returned) |
452 | 329 | 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 | 410 | if(extra<0) |
459 | 79 | extra=0; |
460 | | |
461 | 410 | v->pcm_current-=extra; |
462 | | |
463 | 410 | } /* else {Shouldn't happen *unless* the bitstream is out of |
464 | | spec. Either way, believe the bitstream } */ |
465 | 637 | } /* else {Shouldn't happen *unless* the bitstream is out of |
466 | | spec. Either way, believe the bitstream } */ |
467 | 860 | v->granulepos=vb->granulepos; |
468 | 860 | } |
469 | 1.36k | } |
470 | | |
471 | | /* Update, cleanup */ |
472 | | |
473 | 17.4k | if(vb->eofflag)v->eofflag=1; |
474 | 17.4k | return(0); |
475 | 18.6k | } |
476 | | |
477 | | /* pcm==NULL indicates we just want the pending samples, no more */ |
478 | 1.02M | int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){ |
479 | 1.02M | vorbis_info *vi=v->vi; |
480 | 1.02M | if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){ |
481 | 975k | if(pcm){ |
482 | 960k | int i; |
483 | 221M | for(i=0;i<vi->channels;i++) |
484 | 220M | v->pcmret[i]=v->pcm[i]+v->pcm_returned; |
485 | 960k | *pcm=v->pcmret; |
486 | 960k | } |
487 | 975k | return(v->pcm_current-v->pcm_returned); |
488 | 975k | } |
489 | 49.7k | return(0); |
490 | 1.02M | } |
491 | | |
492 | 960k | int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){ |
493 | 960k | if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL); |
494 | 960k | v->pcm_returned+=bytes; |
495 | 960k | return(0); |
496 | 960k | } |
497 | | |