Recude iram usage for the Vorbis decoder a little. Makes it possible to build with...
[kugel-rb.git] / apps / codecs / Tremor / block.c
blobac19f3a3170fbe5c17281a49b56f1d2326b9513f
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 "config-tremor.h"
19 #include <stdio.h>
20 #include <string.h>
21 #include "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;
36 return(ret);
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
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);
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;
103 /* highly conservative */
104 vb->localalloc=bytes;
105 vb->localstore=_ogg_malloc(vb->localalloc);
106 vb->localtop=0;
109 void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
110 vb->localtop+=bytes;
111 return ret;
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;
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;
133 /* pull the ripcord */
134 vb->localtop=0;
135 vb->reap=NULL;
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);
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 memset(v,0,sizeof(*v));
152 b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
154 v->vi=vi;
155 b->modebits=ilog(ci->modes);
157 /* Vorbis I uses only window type 0 */
158 b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2);
159 b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2);
161 /* finish the codebooks */
162 if(!ci->fullbooks){
163 ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
164 for(i=0;i<ci->books;i++){
165 vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]);
166 /* decode codebooks are now standalone after init */
167 vorbis_staticbook_destroy(ci->book_param[i]);
168 ci->book_param[i]=NULL;
172 v->pcm_storage=ci->blocksizes[1];
173 v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm));
174 v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret));
176 for(i=0;i<vi->channels;i++)
177 v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
180 /* all 1 (large block) or 0 (small block) */
181 /* explicitly set for the sake of clarity */
182 v->lW=0; /* previous window size */
183 v->W=0; /* current window size */
185 /* initialize all the mapping/backend lookups */
186 b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode));
187 for(i=0;i<ci->modes;i++){
188 int mapnum=ci->mode_param[i]->mapping;
189 int maptype=ci->map_type[mapnum];
190 b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
191 ci->map_param[mapnum]);
193 return(0);
196 int vorbis_synthesis_restart(vorbis_dsp_state *v){
197 vorbis_info *vi=v->vi;
198 codec_setup_info *ci;
200 if(!v->backend_state)return -1;
201 if(!vi)return -1;
202 ci=vi->codec_setup;
203 if(!ci)return -1;
205 v->centerW=ci->blocksizes[1]/2;
206 v->pcm_current=v->centerW;
208 v->pcm_returned=-1;
209 v->granulepos=-1;
210 v->sequence=-1;
211 ((private_state *)(v->backend_state))->sample_count=-1;
213 return(0);
216 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
217 _vds_init(v,vi);
218 vorbis_synthesis_restart(v);
220 return(0);
223 void vorbis_dsp_clear(vorbis_dsp_state *v){
224 int i;
225 if(v){
226 vorbis_info *vi=v->vi;
227 codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
228 private_state *b=(private_state *)v->backend_state;
230 if(v->pcm){
231 for(i=0;i<vi->channels;i++)
232 if(v->pcm[i])_ogg_free(v->pcm[i]);
233 _ogg_free(v->pcm);
234 if(v->pcmret)_ogg_free(v->pcmret);
237 /* free mode lookups; these are actually vorbis_look_mapping structs */
238 if(ci){
239 for(i=0;i<ci->modes;i++){
240 int mapnum=ci->mode_param[i]->mapping;
241 int maptype=ci->map_type[mapnum];
242 if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
246 if(b){
247 if(b->mode)_ogg_free(b->mode);
248 _ogg_free(b);
251 memset(v,0,sizeof(*v));
255 /* Unlike in analysis, the window is only partially applied for each
256 block. The time domain envelope is not yet handled at the point of
257 calling (as it relies on the previous block). */
259 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb) ICODE_ATTR;
260 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
261 vorbis_info *vi=v->vi;
262 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
263 private_state *b=v->backend_state;
264 #ifdef CPU_COLDFIRE
265 int j;
266 #else
267 int i,j;
268 #endif
270 if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
272 v->lW=v->W;
273 v->W=vb->W;
274 v->nW=-1;
276 if((v->sequence==-1)||
277 (v->sequence+1 != vb->sequence)){
278 v->granulepos=-1; /* out of sequence; lose count */
279 b->sample_count=-1;
282 v->sequence=vb->sequence;
284 if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
285 was called on block */
286 int n=ci->blocksizes[v->W]/2;
287 int n0=ci->blocksizes[0]/2;
288 int n1=ci->blocksizes[1]/2;
290 int thisCenter;
291 int prevCenter;
293 if(v->centerW){
294 thisCenter=n1;
295 prevCenter=0;
296 }else{
297 thisCenter=0;
298 prevCenter=n1;
301 /* v->pcm is now used like a two-stage double buffer. We don't want
302 to have to constantly shift *or* adjust memory usage. Don't
303 accept a new block until the old is shifted out */
305 /* overlap/add PCM */
307 for(j=0;j<vi->channels;j++){
308 /* the overlap/add section */
309 if(v->lW){
310 if(v->W){
311 /* large/large */
312 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
313 ogg_int32_t *p=vb->pcm[j];
314 #ifdef CPU_COLDFIRE
315 mcf5249_vect_add(pcm, p, n1);
316 #else
317 for(i=0;i<n1;i++)
318 pcm[i]+=p[i];
319 #endif
320 }else{
321 /* large/small */
322 ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
323 ogg_int32_t *p=vb->pcm[j];
324 #ifdef CPU_COLDFIRE
325 mcf5249_vect_add(pcm, p, n0);
326 #else
327 for(i=0;i<n0;i++)
328 pcm[i]+=p[i];
329 #endif
331 }else{
332 if(v->W){
333 /* small/large */
334 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
335 ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
336 #ifdef CPU_COLDFIRE
337 mcf5249_vect_add(pcm, p, n0);
338 mcf5249_vect_copy(&pcm[n0], &p[n0], n1/2-n0/2);
339 #else
340 for(i=0;i<n0;i++)
341 pcm[i]+=p[i];
342 for(;i<n1/2+n0/2;i++)
343 pcm[i]=p[i];
344 #endif
345 }else{
346 /* small/small */
347 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
348 ogg_int32_t *p=vb->pcm[j];
349 #ifdef CPU_COLDFIRE
350 mcf5249_vect_add(pcm, p, n0);
351 #else
352 for(i=0;i<n0;i++)
353 pcm[i]+=p[i];
354 #endif
358 /* the copy section */
360 ogg_int32_t *pcm=v->pcm[j]+thisCenter;
361 ogg_int32_t *p=vb->pcm[j]+n;
362 #ifdef CPU_COLDFIRE
363 mcf5249_vect_copy(pcm, p, n);
364 #else
365 for(i=0;i<n;i++)
366 pcm[i]=p[i];
367 #endif
371 if(v->centerW)
372 v->centerW=0;
373 else
374 v->centerW=n1;
376 /* deal with initial packet state; we do this using the explicit
377 pcm_returned==-1 flag otherwise we're sensitive to first block
378 being short or long */
380 if(v->pcm_returned==-1){
381 v->pcm_returned=thisCenter;
382 v->pcm_current=thisCenter;
383 }else{
384 v->pcm_returned=prevCenter;
385 v->pcm_current=prevCenter+
386 ci->blocksizes[v->lW]/4+
387 ci->blocksizes[v->W]/4;
392 /* track the frame number... This is for convenience, but also
393 making sure our last packet doesn't end with added padding. If
394 the last packet is partial, the number of samples we'll have to
395 return will be past the vb->granulepos.
397 This is not foolproof! It will be confused if we begin
398 decoding at the last page after a seek or hole. In that case,
399 we don't have a starting point to judge where the last frame
400 is. For this reason, vorbisfile will always try to make sure
401 it reads the last two marked pages in proper sequence */
403 if(b->sample_count==-1){
404 b->sample_count=0;
405 }else{
406 b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
409 if(v->granulepos==-1){
410 if(vb->granulepos!=-1){ /* only set if we have a position to set to */
412 v->granulepos=vb->granulepos;
414 /* is this a short page? */
415 if(b->sample_count>v->granulepos){
416 /* corner case; if this is both the first and last audio page,
417 then spec says the end is cut, not beginning */
418 if(vb->eofflag){
419 /* trim the end */
420 /* no preceeding granulepos; assume we started at zero (we'd
421 have to in a short single-page stream) */
422 /* granulepos could be -1 due to a seek, but that would result
423 in a long coun`t, not short count */
425 v->pcm_current-=(b->sample_count-v->granulepos);
426 }else{
427 /* trim the beginning */
428 v->pcm_returned+=(b->sample_count-v->granulepos);
429 if(v->pcm_returned>v->pcm_current)
430 v->pcm_returned=v->pcm_current;
436 }else{
437 v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
438 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
440 if(v->granulepos>vb->granulepos){
441 long extra=v->granulepos-vb->granulepos;
443 if(extra)
444 if(vb->eofflag){
445 /* partial last frame. Strip the extra samples off */
446 v->pcm_current-=extra;
447 } /* else {Shouldn't happen *unless* the bitstream is out of
448 spec. Either way, believe the bitstream } */
449 } /* else {Shouldn't happen *unless* the bitstream is out of
450 spec. Either way, believe the bitstream } */
451 v->granulepos=vb->granulepos;
455 /* Update, cleanup */
457 if(vb->eofflag)v->eofflag=1;
458 return(0);
461 /* pcm==NULL indicates we just want the pending samples, no more */
462 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm) ICODE_ATTR;
463 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){
464 vorbis_info *vi=v->vi;
465 if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
466 if(pcm){
467 int i;
468 for(i=0;i<vi->channels;i++)
469 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
470 *pcm=v->pcmret;
472 return(v->pcm_current-v->pcm_returned);
474 return(0);
477 int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
478 if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
479 v->pcm_returned+=bytes;
480 return(0);