lcd-m6sp.c: remove \r
[kugel-rb.git] / apps / codecs / libtremor / block.c
blobb4ca8f3f110d0662786dbf93ad8b01a5075a2585
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"
28 //#include <codecs/lib/codeclib.h>
30 static int ilog(unsigned int v){
31 int ret=0;
32 if(v)--v;
33 while(v){
34 ret++;
35 v>>=1;
37 return(ret);
40 static ogg_int32_t* _pcmp [CHANNELS] IBSS_ATTR;
41 static ogg_int32_t* _pcmbp[CHANNELS] IBSS_ATTR;
42 static ogg_int32_t* _pcmret[CHANNELS] IBSS_ATTR;
44 /* pcm accumulator examples (not exhaustive):
46 <-------------- lW ---------------->
47 <--------------- W ---------------->
48 : .....|..... _______________ |
49 : .''' | '''_--- | |\ |
50 :.....''' |_____--- '''......| | \_______|
51 :.................|__________________|_______|__|______|
52 |<------ Sl ------>| > Sr < |endW
53 |beginSl |endSl | |endSr
54 |beginW |endlW |beginSr
57 |< lW >|
58 <--------------- W ---------------->
59 | | .. ______________ |
60 | | ' `/ | ---_ |
61 |___.'___/`. | ---_____|
62 |_______|__|_______|_________________|
63 | >|Sl|< |<------ Sr ----->|endW
64 | | |endSl |beginSr |endSr
65 |beginW | |endlW
66 mult[0] |beginSl mult[n]
68 <-------------- lW ----------------->
69 |<--W-->|
70 : .............. ___ | |
71 : .''' |`/ \ | |
72 :.....''' |/`....\|...|
73 :.........................|___|___|___|
74 |Sl |Sr |endW
75 | | |endSr
76 | |beginSr
77 | |endSl
78 |beginSl
79 |beginW
82 /* block abstraction setup *********************************************/
84 #ifndef WORD_ALIGN
85 #define WORD_ALIGN 8
86 #endif
88 int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
89 memset(vb,0,sizeof(*vb));
90 vb->vd=v;
91 vb->localalloc=0;
92 vb->localstore=NULL;
94 return(0);
97 void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
98 bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
99 if(bytes+vb->localtop>vb->localalloc){
100 /* can't just _ogg_realloc... there are outstanding pointers */
101 if(vb->localstore){
102 struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link));
103 vb->totaluse+=vb->localtop;
104 link->next=vb->reap;
105 link->ptr=vb->localstore;
106 vb->reap=link;
108 /* highly conservative */
109 vb->localalloc=bytes;
110 vb->localstore=_ogg_malloc(vb->localalloc);
111 vb->localtop=0;
114 void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
115 vb->localtop+=bytes;
116 return ret;
120 /* reap the chain, pull the ripcord */
121 void _vorbis_block_ripcord(vorbis_block *vb){
122 /* reap the chain */
123 struct alloc_chain *reap=vb->reap;
124 while(reap){
125 struct alloc_chain *next=reap->next;
126 _ogg_free(reap->ptr);
127 memset(reap,0,sizeof(*reap));
128 _ogg_free(reap);
129 reap=next;
131 /* consolidate storage */
132 if(vb->totaluse){
133 vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
134 vb->localalloc+=vb->totaluse;
135 vb->totaluse=0;
138 /* pull the ripcord */
139 vb->localtop=0;
140 vb->reap=NULL;
143 int vorbis_block_clear(vorbis_block *vb){
144 _vorbis_block_ripcord(vb);
145 if(vb->localstore)_ogg_free(vb->localstore);
147 memset(vb,0,sizeof(*vb));
148 return(0);
151 static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){
152 int i;
153 long b_size[2];
154 LOOKUP_TNC *iramposw;
156 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
157 private_state *b=NULL;
159 memset(v,0,sizeof(*v));
160 v->reset_pcmb=true;
161 b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
163 v->vi=vi;
164 b->modebits=ilog(ci->modes);
166 /* allocate IRAM buffer for the PCM data generated by synthesis */
167 iram_malloc_init();
168 v->first_pcm=(ogg_int32_t *)iram_malloc(vi->channels*ci->blocksizes[1]*sizeof(ogg_int32_t));
169 /* when can't allocate IRAM buffer, allocate normal RAM buffer */
170 if(v->first_pcm == NULL){
171 v->first_pcm=(ogg_int32_t *)_ogg_malloc(vi->channels*ci->blocksizes[1]*sizeof(ogg_int32_t));
174 v->centerW=0;
176 /* Vorbis I uses only window type 0 */
177 b_size[0]=ci->blocksizes[0]/2;
178 b_size[1]=ci->blocksizes[1]/2;
179 b->window[0]=_vorbis_window(0,b_size[0]);
180 b->window[1]=_vorbis_window(0,b_size[1]);
182 /* allocate IRAM buffer for window tables too, if sufficient iram available */
183 /* give preference to the larger window over the smaller window
184 (on the assumption that both windows are equally likely used) */
185 for(i=1; i>=0; i--){
186 iramposw=(LOOKUP_TNC *)iram_malloc(b_size[i]*sizeof(LOOKUP_TNC));
187 if(iramposw!=NULL) {
188 memcpy(iramposw, b->window[i], b_size[i]*sizeof(LOOKUP_TNC));
189 b->window[i]=iramposw;
193 /* finish the codebooks */
194 if(!ci->fullbooks){
195 ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
196 for(i=0;i<ci->books;i++){
197 vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]);
198 /* decode codebooks are now standalone after init */
199 vorbis_staticbook_destroy(ci->book_param[i]);
200 ci->book_param[i]=NULL;
204 /* if we can get away with it, put a double buffer into IRAM too, so that
205 overlap-add runs iram-to-iram and we avoid needing to memcpy */
206 v->pcm_storage=ci->blocksizes[1];
207 v->pcm=_pcmp;
208 v->pcmret=_pcmret;
209 v->pcmb=_pcmbp;
211 _pcmp[0]=NULL;
212 _pcmp[1]=NULL;
213 _pcmbp[0]=NULL;
214 _pcmbp[1]=NULL;
215 if(NULL != (v->iram_double_pcm = iram_malloc(vi->channels*v->pcm_storage*sizeof(ogg_int32_t))))
217 /* one-time initialisation at codec start or on switch from
218 blocksizes greater than IRAM_PCM_END to sizes that fit */
219 for(i=0;i<vi->channels;i++)
220 v->pcm[i]=&v->iram_double_pcm[i*v->pcm_storage];
222 else
224 /* one-time initialisation at codec start or on switch from
225 blocksizes that fit in IRAM_PCM_END to those that don't */
226 for(i=0;i<vi->channels;i++)
227 v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
230 /* all 1 (large block) or 0 (small block) */
231 /* explicitly set for the sake of clarity */
232 v->lW=0; /* previous window size */
233 v->W=0; /* current window size */
235 /* initialize all the mapping/backend lookups */
236 b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode));
237 for(i=0;i<ci->modes;i++){
238 int mapnum=ci->mode_param[i]->mapping;
239 int maptype=ci->map_type[mapnum];
240 b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
241 ci->map_param[mapnum]);
244 return(0);
247 int vorbis_synthesis_restart(vorbis_dsp_state *v){
248 vorbis_info *vi=v->vi;
249 codec_setup_info *ci;
250 int i;
252 if(!v->backend_state)return -1;
253 if(!vi)return -1;
254 ci=vi->codec_setup;
255 if(!ci)return -1;
257 v->centerW=0;
258 v->pcm_current=0;
260 v->pcm_returned=-1;
261 v->granulepos=-1;
262 v->sequence=-1;
263 ((private_state *)(v->backend_state))->sample_count=-1;
265 /* indicate to synthesis code that buffer pointers no longer valid
266 (if we're using double pcm buffer) and will need to reset them */
267 v->reset_pcmb = true;
268 /* also reset our copy of the double buffer pointers if we have one */
269 if(v->iram_double_pcm)
270 for(i=0;i<vi->channels;i++)
271 v->pcm[i]=&v->iram_double_pcm[i*v->pcm_storage];
273 return(0);
276 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
277 _vds_init(v,vi);
278 vorbis_synthesis_restart(v);
280 return(0);
283 void vorbis_dsp_clear(vorbis_dsp_state *v){
284 int i;
285 if(v){
286 vorbis_info *vi=v->vi;
287 codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
288 private_state *b=(private_state *)v->backend_state;
290 if(NULL == v->iram_double_pcm && vi != NULL)
292 /* pcm buffer came from oggmalloc rather than iram */
293 for(i=0;i<vi->channels;i++)
294 if(v->pcm[i])_ogg_free(v->pcm[i]);
297 /* free mode lookups; these are actually vorbis_look_mapping structs */
298 if(ci){
299 for(i=0;i<ci->modes;i++){
300 int mapnum=ci->mode_param[i]->mapping;
301 int maptype=ci->map_type[mapnum];
302 if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
306 if(b){
307 if(b->mode)_ogg_free(b->mode);
308 _ogg_free(b);
311 memset(v,0,sizeof(*v));
315 /* Unlike in analysis, the window is only partially applied for each
316 block. The time domain envelope is not yet handled at the point of
317 calling (as it relies on the previous block). */
319 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb)
320 ICODE_ATTR;
321 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
322 vorbis_info *vi=v->vi;
323 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
324 private_state *b=v->backend_state;
325 int j;
326 bool iram_pcm_doublebuffer = (NULL != v->iram_double_pcm);
328 if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
330 v->lW=v->W;
331 v->W=vb->W;
332 v->nW=-1;
334 if((v->sequence==-1)||
335 (v->sequence+1 != vb->sequence)){
336 v->granulepos=-1; /* out of sequence; lose count */
337 b->sample_count=-1;
340 v->sequence=vb->sequence;
341 int n=ci->blocksizes[v->W]/2;
342 int ln=ci->blocksizes[v->lW]/2;
344 if(LIKELY(vb->pcm)){ /* no pcm to process if vorbis_synthesis_trackonly
345 was called on block */
346 int prevCenter;
347 int n0=ci->blocksizes[0]/2;
348 int n1=ci->blocksizes[1]/2;
350 if(iram_pcm_doublebuffer)
352 prevCenter = ln;
354 else
356 prevCenter = v->centerW;
357 v->centerW = n1 - v->centerW;
360 /* overlap/add PCM */
361 /* nb nothing to overlap with on first block so don't bother */
362 if(LIKELY(v->pcm_returned!=-1))
364 for(j=0;j<vi->channels;j++)
366 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
367 ogg_int32_t *p=vb->pcm[j];
369 /* the overlap/add section */
370 if(v->lW == v->W)
372 /* large/large or small/small */
373 vect_add_right_left(pcm,p,n);
374 v->pcmb[j]=pcm;
376 else if (!v->W)
378 /* large/small */
379 vect_add_right_left(pcm + (n1-n0)/2, p, n0);
380 v->pcmb[j]=pcm;
382 else
384 /* small/large */
385 p += (n1-n0)/2;
386 vect_add_left_right(p,pcm,n0);
387 v->pcmb[j]=p;
392 /* the copy section */
393 if(iram_pcm_doublebuffer)
395 /* just flip the pointers over as we have a double buffer in iram */
396 ogg_int32_t *p;
397 p=v->pcm[0];
398 v->pcm[0]=vb->pcm[0];
399 vb->pcm[0] = p;
400 p=v->pcm[1];
401 v->pcm[1]=vb->pcm[1];
402 vb->pcm[1] = p;
404 else
406 for(j=0;j<vi->channels;j++)
408 /* at best only vb->pcm is in iram, and that's where we do the
409 synthesis, so we copy out the right-hand subframe of last
410 synthesis into (noniram) local buffer so we can still do
411 synth in iram */
412 vect_copy(v->pcm[j]+v->centerW, vb->pcm[j]+n, n);
416 /* deal with initial packet state; we do this using the explicit
417 pcm_returned==-1 flag otherwise we're sensitive to first block
418 being short or long */
420 if(v->pcm_returned==-1){
421 v->pcm_returned=0;
422 v->pcm_current=0;
423 }else{
424 v->pcm_returned=0;
425 v->pcm_current=(n+ln)/2;
430 /* track the frame number... This is for convenience, but also
431 making sure our last packet doesn't end with added padding. If
432 the last packet is partial, the number of samples we'll have to
433 return will be past the vb->granulepos.
435 This is not foolproof! It will be confused if we begin
436 decoding at the last page after a seek or hole. In that case,
437 we don't have a starting point to judge where the last frame
438 is. For this reason, vorbisfile will always try to make sure
439 it reads the last two marked pages in proper sequence */
441 if(b->sample_count==-1){
442 b->sample_count=0;
443 }else{
444 b->sample_count+=(n+ln)/2;
447 if(v->granulepos==-1){
448 if(vb->granulepos!=-1){ /* only set if we have a position to set to */
450 v->granulepos=vb->granulepos;
452 /* is this a short page? */
453 if(b->sample_count>v->granulepos){
454 /* corner case; if this is both the first and last audio page,
455 then spec says the end is cut, not beginning */
456 if(vb->eofflag){
457 /* trim the end */
458 /* no preceeding granulepos; assume we started at zero (we'd
459 have to in a short single-page stream) */
460 /* granulepos could be -1 due to a seek, but that would result
461 in a long coun`t, not short count */
463 v->pcm_current-=(b->sample_count-v->granulepos);
464 }else{
465 /* trim the beginning */
466 v->pcm_returned+=(b->sample_count-v->granulepos);
467 if(v->pcm_returned>v->pcm_current)
468 v->pcm_returned=v->pcm_current;
474 }else{
475 v->granulepos+=(n+ln)/2;
476 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
478 if(v->granulepos>vb->granulepos){
479 long extra=v->granulepos-vb->granulepos;
481 if(extra)
482 if(vb->eofflag){
483 /* partial last frame. Strip the extra samples off */
484 v->pcm_current-=extra;
485 } /* else {Shouldn't happen *unless* the bitstream is out of
486 spec. Either way, believe the bitstream } */
487 } /* else {Shouldn't happen *unless* the bitstream is out of
488 spec. Either way, believe the bitstream } */
489 v->granulepos=vb->granulepos;
493 /* Update, cleanup */
495 if(vb->eofflag)v->eofflag=1;
496 return(0);
499 /* pcm==NULL indicates we just want the pending samples, no more */
500 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm) ICODE_ATTR;
501 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){
502 vorbis_info *vi=v->vi;
503 if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
504 if(pcm){
505 int i;
506 for(i=0;i<vi->channels;i++)
507 v->pcmret[i]=v->pcmb[i]+v->pcm_returned;
508 *pcm=v->pcmret;
510 return(v->pcm_current-v->pcm_returned);
512 return(0);
515 int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
516 if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
517 v->pcm_returned+=bytes;
518 return(0);