1
/********************************************************************
3
* THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
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. *
9
********************************************************************
11
function: PCM data vector blocking, windowing and dis/reassembly
13
********************************************************************/
19
#include "ivorbiscodec.h"
20
#include "codec_internal.h"
26
static int ilog(unsigned int v){
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
50
<--------------- W ---------------->
51
| | .. ______________ |
53
|___.'___/`. | ---_____|
54
|_______|__|_______|_________________|
55
| >|Sl|< |<------ Sr ----->|endW
56
| | |endSl |beginSr |endSr
58
mult[0] |beginSl mult[n]
60
<-------------- lW ----------------->
62
: .............. ___ | |
64
:.....''' |/`....\|...|
65
:.........................|___|___|___|
74
/* block abstraction setup *********************************************/
80
int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
81
memset(vb,0,sizeof(*vb));
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 */
94
struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link));
95
vb->totaluse+=vb->localtop;
97
link->ptr=vb->localstore;
100
/* highly conservative */
101
vb->localalloc=bytes;
102
vb->localstore=_ogg_malloc(vb->localalloc);
106
void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
112
/* reap the chain, pull the ripcord */
113
void _vorbis_block_ripcord(vorbis_block *vb){
115
struct alloc_chain *reap=vb->reap;
117
struct alloc_chain *next=reap->next;
118
_ogg_free(reap->ptr);
119
memset(reap,0,sizeof(*reap));
123
/* consolidate storage */
125
vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
126
vb->localalloc+=vb->totaluse;
130
/* pull the ripcord */
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));
143
int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
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)));
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 */
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]);
201
void vorbis_dsp_clear(vorbis_dsp_state *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;
209
for(i=0;i<vi->channels;i++)
210
if(v->pcm[i])_ogg_free(v->pcm[i]);
212
if(v->pcmret)_ogg_free(v->pcmret);
215
/* free mode lookups; these are actually vorbis_look_mapping structs */
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]);
225
if(b->mode)_ogg_free(b->mode);
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;
242
if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
248
if(v->sequence+1 != vb->sequence)v->granulepos=-1; /* out of sequence;
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;
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 */
280
ogg_int32_t *pcm=v->pcm[j]+prevCenter;
281
ogg_int32_t *p=vb->pcm[j];
286
ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
287
ogg_int32_t *p=vb->pcm[j];
294
ogg_int32_t *pcm=v->pcm[j]+prevCenter;
295
ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
298
for(;i<n1/2+n0/2;i++)
302
ogg_int32_t *pcm=v->pcm[j]+prevCenter;
303
ogg_int32_t *p=vb->pcm[j];
309
/* the copy section */
311
ogg_int32_t *pcm=v->pcm[j]+thisCenter;
312
ogg_int32_t *p=vb->pcm[j]+n;
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;
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){
352
v->granulepos=vb->granulepos;
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;
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;
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){
395
for(i=0;i<vi->channels;i++)
396
v->pcmret[i]=v->pcm[i]+v->pcm_returned;
399
return(v->pcm_current-v->pcm_returned);
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;