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
;