1
/********************************************************************
3
* THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
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. *
9
* THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
10
* BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
12
********************************************************************
14
function: PCM data vector blocking, windowing and dis/reassembly
16
********************************************************************/
22
#include "ivorbiscodec.h"
23
#include "codec_internal.h"
29
static int ilog(unsigned int v){
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
53
<--------------- W ---------------->
54
| | .. ______________ |
56
|___.'___/`. | ---_____|
57
|_______|__|_______|_________________|
58
| >|Sl|< |<------ Sr ----->|endW
59
| | |endSl |beginSr |endSr
61
mult[0] |beginSl mult[n]
63
<-------------- lW ----------------->
65
: .............. ___ | |
67
:.....''' |/`....\|...|
68
:.........................|___|___|___|
77
/* block abstraction setup *********************************************/
83
int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
84
memset(vb,0,sizeof(*vb));
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 */
97
struct alloc_chain *link=(struct alloc_chain *)_ogg_malloc(sizeof(*link));
98
vb->totaluse+=vb->localtop;
100
link->ptr=vb->localstore;
103
/* highly conservative */
104
vb->localalloc=bytes;
105
vb->localstore=_ogg_malloc(vb->localalloc);
109
void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
115
/* reap the chain, pull the ripcord */
116
void _vorbis_block_ripcord(vorbis_block *vb){
118
struct alloc_chain *reap=vb->reap;
120
struct alloc_chain *next=reap->next;
121
_ogg_free(reap->ptr);
122
memset(reap,0,sizeof(*reap));
126
/* consolidate storage */
128
vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
129
vb->localalloc+=vb->totaluse;
133
/* pull the ripcord */
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));
146
static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){
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)));
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 */
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));
175
for(i=0;i<vi->channels;i++)
176
v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
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 */
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]);
194
int vorbis_synthesis_restart(vorbis_dsp_state *v){
195
vorbis_info *vi=v->vi;
196
codec_setup_info *ci;
198
if(!v->backend_state)return -1;
203
v->centerW=ci->blocksizes[1]/2;
204
v->pcm_current=v->centerW;
209
((private_state *)(v->backend_state))->sample_count=-1;
214
int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
216
vorbis_synthesis_restart(v);
221
void vorbis_dsp_clear(vorbis_dsp_state *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;
229
for(i=0;i<vi->channels;i++)
230
if(v->pcm[i])_ogg_free(v->pcm[i]);
232
if(v->pcmret)_ogg_free(v->pcmret);
235
/* free mode lookups; these are actually vorbis_look_mapping structs */
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]);
245
if(b->mode)_ogg_free(b->mode);
249
memset(v,0,sizeof(*v));
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). */
257
int 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;
263
if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
269
if((v->sequence==-1)||
270
(v->sequence+1 != vb->sequence)){
271
v->granulepos=-1; /* out of sequence; lose count */
275
v->sequence=vb->sequence;
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;
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 */
298
/* overlap/add PCM */
300
for(j=0;j<vi->channels;j++){
301
/* the overlap/add section */
305
ogg_int32_t *pcm=v->pcm[j]+prevCenter;
306
ogg_int32_t *p=vb->pcm[j];
311
ogg_int32_t *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
312
ogg_int32_t *p=vb->pcm[j];
319
ogg_int32_t *pcm=v->pcm[j]+prevCenter;
320
ogg_int32_t *p=vb->pcm[j]+n1/2-n0/2;
323
for(;i<n1/2+n0/2;i++)
327
ogg_int32_t *pcm=v->pcm[j]+prevCenter;
328
ogg_int32_t *p=vb->pcm[j];
334
/* the copy section */
336
ogg_int32_t *pcm=v->pcm[j]+thisCenter;
337
ogg_int32_t *p=vb->pcm[j]+n;
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 */
352
if(v->pcm_returned==-1){
353
v->pcm_returned=thisCenter;
354
v->pcm_current=thisCenter;
356
v->pcm_returned=prevCenter;
357
v->pcm_current=prevCenter+
358
ci->blocksizes[v->lW]/4+
359
ci->blocksizes[v->W]/4;
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.
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 */
375
if(b->sample_count==-1){
378
b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
381
if(v->granulepos==-1){
382
if(vb->granulepos!=-1){ /* only set if we have a position to set to */
384
v->granulepos=vb->granulepos;
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 */
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 */
397
v->pcm_current-=(b->sample_count-v->granulepos);
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;
409
v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
410
if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
412
if(v->granulepos>vb->granulepos){
413
long extra=v->granulepos-vb->granulepos;
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;
427
/* Update, cleanup */
429
if(vb->eofflag)v->eofflag=1;
433
/* pcm==NULL indicates we just want the pending samples, no more */
434
int 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){
439
for(i=0;i<vi->channels;i++)
440
v->pcmret[i]=v->pcm[i]+v->pcm_returned;
443
return(v->pcm_current-v->pcm_returned);
448
int 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;