UltraSPARC T1 (Niagara) support, patch by Derek E. Lewis /dlewis (gobble) solnetworks...
[mplayer/glamo.git] / tremor / block.c
blob546b7567043f5a1503082bad9584cb327bb5684c
1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
4 * *
5 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
6 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
7 * ALL REDISTRIBUTION RIGHTS RESERVED. *
8 * *
9 ********************************************************************
11 function: PCM data vector blocking, windowing and dis/reassembly
13 ********************************************************************/
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include "ogg.h"
19 #include "ivorbiscodec.h"
20 #include "codec_internal.h"
22 #include "window.h"
23 #include "registry.h"
24 #include "misc.h"
26 static int ilog(unsigned int v){
27 int ret=0;
28 if(v)--v;
29 while(v){
30 ret++;
31 v>>=1;
33 return(ret);
36 /* pcm accumulator examples (not exhaustive):
38 <-------------- lW ---------------->
39 <--------------- W ---------------->
40 : .....|..... _______________ |
41 : .''' | '''_--- | |\ |
42 :.....''' |_____--- '''......| | \_______|
43 :.................|__________________|_______|__|______|
44 |<------ Sl ------>| > Sr < |endW
45 |beginSl |endSl | |endSr
46 |beginW |endlW |beginSr
49 |< lW >|
50 <--------------- W ---------------->
51 | | .. ______________ |
52 | | ' `/ | ---_ |
53 |___.'___/`. | ---_____|
54 |_______|__|_______|_________________|
55 | >|Sl|< |<------ Sr ----->|endW
56 | | |endSl |beginSr |endSr
57 |beginW | |endlW
58 mult[0] |beginSl mult[n]
60 <-------------- lW ----------------->
61 |<--W-->|
62 : .............. ___ | |
63 : .''' |`/ \ | |
64 :.....''' |/`....\|...|
65 :.........................|___|___|___|
66 |Sl |Sr |endW
67 | | |endSr
68 | |beginSr
69 | |endSl
70 |beginSl
71 |beginW
74 /* block abstraction setup *********************************************/
76 #ifndef WORD_ALIGN
77 #define WORD_ALIGN 8
78 #endif
80 int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
81 memset(vb,0,sizeof(*vb));
82 vb->vd=v;
83 vb->localalloc=0;
84 vb->localstore=NULL;
86 return(0);
89 void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
90 bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
91 if(bytes+vb->localtop>vb->localalloc){
92 /* can't just _ogg_realloc... there are outstanding pointers */
93 if(vb->localstore){
94 struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link));
95 vb->totaluse+=vb->localtop;
96 link->next=vb->reap;
97 link->ptr=vb->localstore;
98 vb->reap=link;
100 /* highly conservative */
101 vb->localalloc=bytes;
102 vb->localstore=_ogg_malloc(vb->localalloc);
103 vb->localtop=0;
106 void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
107 vb->localtop+=bytes;
108 return ret;
112 /* reap the chain, pull the ripcord */
113 void _vorbis_block_ripcord(vorbis_block *vb){
114 /* reap the chain */
115 struct alloc_chain *reap=vb->reap;
116 while(reap){
117 struct alloc_chain *next=reap->next;
118 _ogg_free(reap->ptr);
119 memset(reap,0,sizeof(*reap));
120 _ogg_free(reap);
121 reap=next;
123 /* consolidate storage */
124 if(vb->totaluse){
125 vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
126 vb->localalloc+=vb->totaluse;
127 vb->totaluse=0;
130 /* pull the ripcord */
131 vb->localtop=0;
132 vb->reap=NULL;
135 int vorbis_block_clear(vorbis_block *vb){
136 _vorbis_block_ripcord(vb);
137 if(vb->localstore)_ogg_free(vb->localstore);
139 memset(vb,0,sizeof(*vb));
140 return(0);
143 int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
144 int i;
145 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
146 backend_lookup_state *b=NULL;
148 memset(v,0,sizeof(*v));
149 b=(backend_lookup_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
151 v->vi=vi;
152 b->modebits=ilog(ci->modes);
154 /* Vorbis I uses only window type 0 */
155 b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2);
156 b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2);
158 /* finish the codebooks */
159 if(!ci->fullbooks){
160 ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
161 for(i=0;i<ci->books;i++){
162 vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]);
163 /* decode codebooks are now standalone after init */
164 vorbis_staticbook_destroy(ci->book_param[i]);
165 ci->book_param[i]=NULL;
169 v->pcm_storage=ci->blocksizes[1];
170 v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm));
171 v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret));
172 for(i=0;i<vi->channels;i++)
173 v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
175 /* all 1 (large block) or 0 (small block) */
176 /* explicitly set for the sake of clarity */
177 v->lW=0; /* previous window size */
178 v->W=0; /* current window size */
180 /* all vector indexes */
181 v->centerW=ci->blocksizes[1]/2;
183 v->pcm_current=v->centerW;
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]);
194 v->pcm_returned=-1;
195 v->granulepos=-1;
196 v->sequence=-1;
198 return(0);
201 void vorbis_dsp_clear(vorbis_dsp_state *v){
202 int i;
203 if(v){
204 vorbis_info *vi=v->vi;
205 codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
206 backend_lookup_state *b=(backend_lookup_state *)v->backend_state;
208 if(v->pcm){
209 for(i=0;i<vi->channels;i++)
210 if(v->pcm[i])_ogg_free(v->pcm[i]);
211 _ogg_free(v->pcm);
212 if(v->pcmret)_ogg_free(v->pcmret);
215 /* free mode lookups; these are actually vorbis_look_mapping structs */
216 if(ci){
217 for(i=0;i<ci->modes;i++){
218 int mapnum=ci->mode_param[i]->mapping;
219 int maptype=ci->map_type[mapnum];
220 if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
224 if(b){
225 if(b->mode)_ogg_free(b->mode);
226 _ogg_free(b);
229 memset(v,0,sizeof(*v));
233 /* Unlike in analysis, the window is only partially applied for each
234 block. The time domain envelope is not yet handled at the point of
235 calling (as it relies on the previous block). */
237 int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
238 vorbis_info *vi=v->vi;
239 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
240 int i,j;
242 if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
244 v->lW=v->W;
245 v->W=vb->W;
246 v->nW=-1;
248 if(v->sequence+1 != vb->sequence)v->granulepos=-1; /* out of sequence;
249 lose count */
251 v->sequence=vb->sequence;
254 int n=ci->blocksizes[v->W]/2;
255 int n0=ci->blocksizes[0]/2;
256 int n1=ci->blocksizes[1]/2;
258 int thisCenter;
259 int prevCenter;
261 if(v->centerW){
262 thisCenter=n1;
263 prevCenter=0;
264 }else{
265 thisCenter=0;
266 prevCenter=n1;
269 /* v->pcm is now used like a two-stage double buffer. We don't want
270 to have to constantly shift *or* adjust memory usage. Don't
271 accept a new block until the old is shifted out */
273 /* overlap/add PCM */
275 for(j=0;j<vi->channels;j++){
276 /* the overlap/add section */
277 if(v->lW){
278 if(v->W){
279 /* large/large */
280 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
281 ogg_int32_t *p=vb->pcm[j];
282 for(i=0;i<n1;i++)
283 pcm[i]+=p[i];
284 }else{
285 /* large/small */
286 ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
287 ogg_int32_t *p=vb->pcm[j];
288 for(i=0;i<n0;i++)
289 pcm[i]+=p[i];
291 }else{
292 if(v->W){
293 /* small/large */
294 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
295 ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
296 for(i=0;i<n0;i++)
297 pcm[i]+=p[i];
298 for(;i<n1/2+n0/2;i++)
299 pcm[i]=p[i];
300 }else{
301 /* small/small */
302 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
303 ogg_int32_t *p=vb->pcm[j];
304 for(i=0;i<n0;i++)
305 pcm[i]+=p[i];
309 /* the copy section */
311 ogg_int32_t *pcm=v->pcm[j]+thisCenter;
312 ogg_int32_t *p=vb->pcm[j]+n;
313 for(i=0;i<n;i++)
314 pcm[i]=p[i];
318 if(v->centerW)
319 v->centerW=0;
320 else
321 v->centerW=n1;
323 /* deal with initial packet state; we do this using the explicit
324 pcm_returned==-1 flag otherwise we're sensitive to first block
325 being short or long */
327 if(v->pcm_returned==-1){
328 v->pcm_returned=thisCenter;
329 v->pcm_current=thisCenter;
330 }else{
331 v->pcm_returned=prevCenter;
332 v->pcm_current=prevCenter+
333 ci->blocksizes[v->lW]/4+
334 ci->blocksizes[v->W]/4;
337 /* track the frame number... This is for convenience, but also
338 making sure our last packet doesn't end with added padding. If
339 the last packet is partial, the number of samples we'll have to
340 return will be past the vb->granulepos.
342 This is not foolproof! It will be confused if we begin
343 decoding at the last page after a seek or hole. In that case,
344 we don't have a starting point to judge where the last frame
345 is. For this reason, vorbisfile will always try to make sure
346 it reads the last two marked pages in proper sequence */
348 if(v->granulepos==-1)
349 if(vb->granulepos==-1){
350 v->granulepos=0;
351 }else{
352 v->granulepos=vb->granulepos;
354 else{
355 v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
356 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
358 if(v->granulepos>vb->granulepos){
359 long extra=v->granulepos-vb->granulepos;
361 if(vb->eofflag){
362 /* partial last frame. Strip the extra samples off */
363 v->pcm_current-=extra;
364 }else if(vb->sequence == 1){
365 /* ^^^ argh, this can be 1 from seeking! */
368 /* partial first frame. Discard extra leading samples */
369 v->pcm_returned+=extra;
370 if(v->pcm_returned>v->pcm_current)
371 v->pcm_returned=v->pcm_current;
375 }/* else{ Shouldn't happen *unless* the bitstream is out of
376 spec. Either way, believe the bitstream } */
377 v->granulepos=vb->granulepos;
381 /* Update, cleanup */
383 if(vb->eofflag)v->eofflag=1;
386 return(0);
389 /* pcm==NULL indicates we just want the pending samples, no more */
390 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){
391 vorbis_info *vi=v->vi;
392 if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
393 if(pcm){
394 int i;
395 for(i=0;i<vi->channels;i++)
396 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
397 *pcm=v->pcmret;
399 return(v->pcm_current-v->pcm_returned);
401 return(0);
404 int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
405 if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
406 v->pcm_returned+=bytes;
407 return(0);