summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/vorbis/tremor/block.c
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/vorbis/tremor/block.c') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/vorbis/tremor/block.c453
1 files changed, 453 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/vorbis/tremor/block.c b/core/multimedia/opieplayer/vorbis/tremor/block.c
new file mode 100644
index 0000000..8949253
--- a/dev/null
+++ b/core/multimedia/opieplayer/vorbis/tremor/block.c
@@ -0,0 +1,453 @@
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
29static 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
83int 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
92void *_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;
102 }
103 /* highly conservative */
104 vb->localalloc=bytes;
105 vb->localstore=_ogg_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 */
116void _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;
125 }
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;
131 }
132
133 /* pull the ripcord */
134 vb->localtop=0;
135 vb->reap=NULL;
136}
137
138int vorbis_block_clear(vorbis_block *vb){
139 _vorbis_block_ripcord(vb);
140 if(vb->localstore)_ogg_free(vb->localstore);
141
142 memset(vb,0,sizeof(*vb));
143 return(0);
144}
145
146static 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;
150
151 memset(v,0,sizeof(*v));
152 b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b)));
153
154 v->vi=vi;
155 b->modebits=ilog(ci->modes);
156
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);
160
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;
169 }
170 }
171
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));
175 for(i=0;i<vi->channels;i++)
176 v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
177
178 /* all 1 (large block) or 0 (small block) */
179 /* explicitly set for the sake of clarity */
180 v->lW=0; /* previous window size */
181 v->W=0; /* current window size */
182
183 /* initialize all the mapping/backend lookups */
184 b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode));
185 for(i=0;i<ci->modes;i++){
186 int mapnum=ci->mode_param[i]->mapping;
187 int maptype=ci->map_type[mapnum];
188 b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i],
189 ci->map_param[mapnum]);
190 }
191 return(0);
192}
193
194int vorbis_synthesis_restart(vorbis_dsp_state *v){
195 vorbis_info *vi=v->vi;
196 codec_setup_info *ci;
197
198 if(!v->backend_state)return -1;
199 if(!vi)return -1;
200 ci=vi->codec_setup;
201 if(!ci)return -1;
202
203 v->centerW=ci->blocksizes[1]/2;
204 v->pcm_current=v->centerW;
205
206 v->pcm_returned=-1;
207 v->granulepos=-1;
208 v->sequence=-1;
209 ((private_state *)(v->backend_state))->sample_count=-1;
210
211 return(0);
212}
213
214int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
215 _vds_init(v,vi);
216 vorbis_synthesis_restart(v);
217
218 return(0);
219}
220
221void vorbis_dsp_clear(vorbis_dsp_state *v){
222 int i;
223 if(v){
224 vorbis_info *vi=v->vi;
225 codec_setup_info *ci=(codec_setup_info *)(vi?vi->codec_setup:NULL);
226 private_state *b=(private_state *)v->backend_state;
227
228 if(v->pcm){
229 for(i=0;i<vi->channels;i++)
230 if(v->pcm[i])_ogg_free(v->pcm[i]);
231 _ogg_free(v->pcm);
232 if(v->pcmret)_ogg_free(v->pcmret);
233 }
234
235 /* free mode lookups; these are actually vorbis_look_mapping structs */
236 if(ci){
237 for(i=0;i<ci->modes;i++){
238 int mapnum=ci->mode_param[i]->mapping;
239 int maptype=ci->map_type[mapnum];
240 if(b && b->mode)_mapping_P[maptype]->free_look(b->mode[i]);
241 }
242 }
243
244 if(b){
245 if(b->mode)_ogg_free(b->mode);
246 _ogg_free(b);
247 }
248
249 memset(v,0,sizeof(*v));
250 }
251}
252
253/* Unlike in analysis, the window is only partially applied for each
254 block. The time domain envelope is not yet handled at the point of
255 calling (as it relies on the previous block). */
256
257int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
258 vorbis_info *vi=v->vi;
259 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
260 private_state *b=v->backend_state;
261 int i,j;
262
263 if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
264
265 v->lW=v->W;
266 v->W=vb->W;
267 v->nW=-1;
268
269 if((v->sequence==-1)||
270 (v->sequence+1 != vb->sequence)){
271 v->granulepos=-1; /* out of sequence; lose count */
272 b->sample_count=-1;
273 }
274
275 v->sequence=vb->sequence;
276
277 if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
278 was called on block */
279 int n=ci->blocksizes[v->W]/2;
280 int n0=ci->blocksizes[0]/2;
281 int n1=ci->blocksizes[1]/2;
282
283 int thisCenter;
284 int prevCenter;
285
286 if(v->centerW){
287 thisCenter=n1;
288 prevCenter=0;
289 }else{
290 thisCenter=0;
291 prevCenter=n1;
292 }
293
294 /* v->pcm is now used like a two-stage double buffer. We don't want
295 to have to constantly shift *or* adjust memory usage. Don't
296 accept a new block until the old is shifted out */
297
298 /* overlap/add PCM */
299
300 for(j=0;j<vi->channels;j++){
301 /* the overlap/add section */
302 if(v->lW){
303 if(v->W){
304 /* large/large */
305 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
306 ogg_int32_t *p=vb->pcm[j];
307 for(i=0;i<n1;i++)
308 pcm[i]+=p[i];
309 }else{
310 /* large/small */
311 ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
312 ogg_int32_t *p=vb->pcm[j];
313 for(i=0;i<n0;i++)
314 pcm[i]+=p[i];
315 }
316 }else{
317 if(v->W){
318 /* small/large */
319 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
320 ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
321 for(i=0;i<n0;i++)
322 pcm[i]+=p[i];
323 for(;i<n1/2+n0/2;i++)
324 pcm[i]=p[i];
325 }else{
326 /* small/small */
327 ogg_int32_t *pcm=v->pcm[j]+prevCenter;
328 ogg_int32_t *p=vb->pcm[j];
329 for(i=0;i<n0;i++)
330 pcm[i]+=p[i];
331 }
332 }
333
334 /* the copy section */
335 {
336 ogg_int32_t *pcm=v->pcm[j]+thisCenter;
337 ogg_int32_t *p=vb->pcm[j]+n;
338 for(i=0;i<n;i++)
339 pcm[i]=p[i];
340 }
341 }
342
343 if(v->centerW)
344 v->centerW=0;
345 else
346 v->centerW=n1;
347
348 /* deal with initial packet state; we do this using the explicit
349 pcm_returned==-1 flag otherwise we're sensitive to first block
350 being short or long */
351
352 if(v->pcm_returned==-1){
353 v->pcm_returned=thisCenter;
354 v->pcm_current=thisCenter;
355 }else{
356 v->pcm_returned=prevCenter;
357 v->pcm_current=prevCenter+
358 ci->blocksizes[v->lW]/4+
359 ci->blocksizes[v->W]/4;
360 }
361
362 }
363
364 /* track the frame number... This is for convenience, but also
365 making sure our last packet doesn't end with added padding. If
366 the last packet is partial, the number of samples we'll have to
367 return will be past the vb->granulepos.
368
369 This is not foolproof! It will be confused if we begin
370 decoding at the last page after a seek or hole. In that case,
371 we don't have a starting point to judge where the last frame
372 is. For this reason, vorbisfile will always try to make sure
373 it reads the last two marked pages in proper sequence */
374
375 if(b->sample_count==-1){
376 b->sample_count=0;
377 }else{
378 b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
379 }
380
381 if(v->granulepos==-1){
382 if(vb->granulepos!=-1){ /* only set if we have a position to set to */
383
384 v->granulepos=vb->granulepos;
385
386 /* is this a short page? */
387 if(b->sample_count>v->granulepos){
388 /* corner case; if this is both the first and last audio page,
389 then spec says the end is cut, not beginning */
390 if(vb->eofflag){
391 /* trim the end */
392 /* no preceeding granulepos; assume we started at zero (we'd
393 have to in a short single-page stream) */
394 /* granulepos could be -1 due to a seek, but that would result
395 in a long coun`t, not short count */
396
397 v->pcm_current-=(b->sample_count-v->granulepos);
398 }else{
399 /* trim the beginning */
400 v->pcm_returned+=(b->sample_count-v->granulepos);
401 if(v->pcm_returned>v->pcm_current)
402 v->pcm_returned=v->pcm_current;
403 }
404
405 }
406
407 }
408 }else{
409 v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
410 if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
411
412 if(v->granulepos>vb->granulepos){
413 long extra=v->granulepos-vb->granulepos;
414
415 if(extra)
416 if(vb->eofflag){
417 /* partial last frame. Strip the extra samples off */
418 v->pcm_current-=extra;
419 } /* else {Shouldn't happen *unless* the bitstream is out of
420 spec. Either way, believe the bitstream } */
421 } /* else {Shouldn't happen *unless* the bitstream is out of
422 spec. Either way, believe the bitstream } */
423 v->granulepos=vb->granulepos;
424 }
425 }
426
427 /* Update, cleanup */
428
429 if(vb->eofflag)v->eofflag=1;
430 return(0);
431}
432
433/* pcm==NULL indicates we just want the pending samples, no more */
434int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm){
435 vorbis_info *vi=v->vi;
436 if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
437 if(pcm){
438 int i;
439 for(i=0;i<vi->channels;i++)
440 v->pcmret[i]=v->pcm[i]+v->pcm_returned;
441 *pcm=v->pcmret;
442 }
443 return(v->pcm_current-v->pcm_returned);
444 }
445 return(0);
446}
447
448int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
449 if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
450 v->pcm_returned+=bytes;
451 return(0);
452}
453