Line | Count | Source |
1 | | /******************************************************************** |
2 | | * * |
3 | | * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * |
4 | | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
5 | | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
6 | | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
7 | | * * |
8 | | * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 * |
9 | | * by the Xiph.Org Foundation https://xiph.org/ * |
10 | | * * |
11 | | ******************************************************************** |
12 | | |
13 | | function: PCM data vector blocking, windowing and dis/reassembly |
14 | | |
15 | | Handle windowing, overlap-add, etc of the PCM vectors. This is made |
16 | | more amusing by Vorbis' current two allowed block sizes. |
17 | | |
18 | | ********************************************************************/ |
19 | | |
20 | | #include <stdio.h> |
21 | | #include <stdlib.h> |
22 | | #include <string.h> |
23 | | #include <ogg/ogg.h> |
24 | | #include "vorbis/codec.h" |
25 | | #include "codec_internal.h" |
26 | | |
27 | | #include "window.h" |
28 | | #include "mdct.h" |
29 | | #include "lpc.h" |
30 | | #include "registry.h" |
31 | | #include "misc.h" |
32 | | |
33 | | /* pcm accumulator examples (not exhaustive): |
34 | | |
35 | | <-------------- lW ----------------> |
36 | | <--------------- W ----------------> |
37 | | : .....|..... _______________ | |
38 | | : .''' | '''_--- | |\ | |
39 | | :.....''' |_____--- '''......| | \_______| |
40 | | :.................|__________________|_______|__|______| |
41 | | |<------ Sl ------>| > Sr < |endW |
42 | | |beginSl |endSl | |endSr |
43 | | |beginW |endlW |beginSr |
44 | | |
45 | | |
46 | | |< lW >| |
47 | | <--------------- W ----------------> |
48 | | | | .. ______________ | |
49 | | | | ' `/ | ---_ | |
50 | | |___.'___/`. | ---_____| |
51 | | |_______|__|_______|_________________| |
52 | | | >|Sl|< |<------ Sr ----->|endW |
53 | | | | |endSl |beginSr |endSr |
54 | | |beginW | |endlW |
55 | | mult[0] |beginSl mult[n] |
56 | | |
57 | | <-------------- lW -----------------> |
58 | | |<--W-->| |
59 | | : .............. ___ | | |
60 | | : .''' |`/ \ | | |
61 | | :.....''' |/`....\|...| |
62 | | :.........................|___|___|___| |
63 | | |Sl |Sr |endW |
64 | | | | |endSr |
65 | | | |beginSr |
66 | | | |endSl |
67 | | |beginSl |
68 | | |beginW |
69 | | */ |
70 | | |
71 | | /* block abstraction setup *********************************************/ |
72 | | |
73 | | #ifndef WORD_ALIGN |
74 | 7.95M | #define WORD_ALIGN 8 |
75 | | #endif |
76 | | |
77 | 11.0k | int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ |
78 | 11.0k | int i; |
79 | 11.0k | memset(vb,0,sizeof(*vb)); |
80 | 11.0k | vb->vd=v; |
81 | 11.0k | vb->localalloc=0; |
82 | 11.0k | vb->localstore=NULL; |
83 | 11.0k | if(v->analysisp){ |
84 | 2.21k | vorbis_block_internal *vbi= |
85 | 2.21k | vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal)); |
86 | 2.21k | vbi->ampmax=-9999; |
87 | | |
88 | 35.3k | for(i=0;i<PACKETBLOBS;i++){ |
89 | 33.1k | if(i==PACKETBLOBS/2){ |
90 | 2.21k | vbi->packetblob[i]=&vb->opb; |
91 | 30.9k | }else{ |
92 | 30.9k | vbi->packetblob[i]= |
93 | 30.9k | _ogg_calloc(1,sizeof(oggpack_buffer)); |
94 | 30.9k | } |
95 | 33.1k | oggpack_writeinit(vbi->packetblob[i]); |
96 | 33.1k | } |
97 | 2.21k | } |
98 | | |
99 | 11.0k | return(0); |
100 | 11.0k | } |
101 | | |
102 | 3.97M | void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ |
103 | 3.97M | bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); |
104 | 3.97M | if(bytes+vb->localtop>vb->localalloc){ |
105 | | /* can't just _ogg_realloc... there are outstanding pointers */ |
106 | 492k | if(vb->localstore){ |
107 | 484k | struct alloc_chain *link=_ogg_malloc(sizeof(*link)); |
108 | 484k | vb->totaluse+=vb->localtop; |
109 | 484k | link->next=vb->reap; |
110 | 484k | link->ptr=vb->localstore; |
111 | 484k | vb->reap=link; |
112 | 484k | } |
113 | | /* highly conservative */ |
114 | 492k | vb->localalloc=bytes; |
115 | 492k | vb->localstore=_ogg_malloc(vb->localalloc); |
116 | 492k | vb->localtop=0; |
117 | 492k | } |
118 | 3.97M | { |
119 | 3.97M | void *ret=(void *)(((char *)vb->localstore)+vb->localtop); |
120 | 3.97M | vb->localtop+=bytes; |
121 | 3.97M | return ret; |
122 | 3.97M | } |
123 | 3.97M | } |
124 | | |
125 | | /* reap the chain, pull the ripcord */ |
126 | 1.62M | void _vorbis_block_ripcord(vorbis_block *vb){ |
127 | | /* reap the chain */ |
128 | 1.62M | struct alloc_chain *reap=vb->reap; |
129 | 2.11M | while(reap){ |
130 | 484k | struct alloc_chain *next=reap->next; |
131 | 484k | _ogg_free(reap->ptr); |
132 | 484k | memset(reap,0,sizeof(*reap)); |
133 | 484k | _ogg_free(reap); |
134 | 484k | reap=next; |
135 | 484k | } |
136 | | /* consolidate storage */ |
137 | 1.62M | if(vb->totaluse){ |
138 | 9.34k | vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); |
139 | 9.34k | vb->localalloc+=vb->totaluse; |
140 | 9.34k | vb->totaluse=0; |
141 | 9.34k | } |
142 | | |
143 | | /* pull the ripcord */ |
144 | 1.62M | vb->localtop=0; |
145 | 1.62M | vb->reap=NULL; |
146 | 1.62M | } |
147 | | |
148 | 14.0k | int vorbis_block_clear(vorbis_block *vb){ |
149 | 14.0k | int i; |
150 | 14.0k | vorbis_block_internal *vbi=vb->internal; |
151 | | |
152 | 14.0k | _vorbis_block_ripcord(vb); |
153 | 14.0k | if(vb->localstore)_ogg_free(vb->localstore); |
154 | | |
155 | 14.0k | if(vbi){ |
156 | 35.3k | for(i=0;i<PACKETBLOBS;i++){ |
157 | 33.1k | oggpack_writeclear(vbi->packetblob[i]); |
158 | 33.1k | if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]); |
159 | 33.1k | } |
160 | 2.21k | _ogg_free(vbi); |
161 | 2.21k | } |
162 | 14.0k | memset(vb,0,sizeof(*vb)); |
163 | 14.0k | return(0); |
164 | 14.0k | } |
165 | | |
166 | | /* Analysis side code, but directly related to blocking. Thus it's |
167 | | here and not in analysis.c (which is for analysis transforms only). |
168 | | The init is here because some of it is shared */ |
169 | | |
170 | 11.1k | static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ |
171 | 11.1k | int i; |
172 | 11.1k | codec_setup_info *ci=vi->codec_setup; |
173 | 11.1k | private_state *b=NULL; |
174 | 11.1k | int hs; |
175 | | |
176 | 11.1k | if(ci==NULL|| |
177 | 11.1k | ci->modes<=0|| |
178 | 11.1k | ci->blocksizes[0]<64|| |
179 | 11.1k | ci->blocksizes[1]<ci->blocksizes[0]){ |
180 | 0 | return 1; |
181 | 0 | } |
182 | 11.1k | hs=ci->halfrate_flag; |
183 | | |
184 | 11.1k | memset(v,0,sizeof(*v)); |
185 | 11.1k | b=v->backend_state=_ogg_calloc(1,sizeof(*b)); |
186 | | |
187 | 11.1k | v->vi=vi; |
188 | 11.1k | b->modebits=ov_ilog(ci->modes-1); |
189 | | |
190 | 11.1k | b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0])); |
191 | 11.1k | b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1])); |
192 | | |
193 | | /* MDCT is tranform 0 */ |
194 | | |
195 | 11.1k | b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup)); |
196 | 11.1k | b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup)); |
197 | 11.1k | mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs); |
198 | 11.1k | mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs); |
199 | | |
200 | | /* Vorbis I uses only window type 0 */ |
201 | | /* note that the correct computation below is technically: |
202 | | b->window[0]=ov_ilog(ci->blocksizes[0]-1)-6; |
203 | | b->window[1]=ov_ilog(ci->blocksizes[1]-1)-6; |
204 | | but since blocksizes are always powers of two, |
205 | | the below is equivalent. |
206 | | */ |
207 | 11.1k | b->window[0]=ov_ilog(ci->blocksizes[0])-7; |
208 | 11.1k | b->window[1]=ov_ilog(ci->blocksizes[1])-7; |
209 | | |
210 | 11.1k | if(encp){ /* encode/decode differ here */ |
211 | | |
212 | | /* analysis always needs an fft */ |
213 | 2.21k | drft_init(&b->fft_look[0],ci->blocksizes[0]); |
214 | 2.21k | drft_init(&b->fft_look[1],ci->blocksizes[1]); |
215 | | |
216 | | /* finish the codebooks */ |
217 | 2.21k | if(!ci->fullbooks){ |
218 | 2.21k | ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); |
219 | 81.1k | for(i=0;i<ci->books;i++) |
220 | 78.8k | vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]); |
221 | 2.21k | } |
222 | | |
223 | 2.21k | b->psy=_ogg_calloc(ci->psys,sizeof(*b->psy)); |
224 | 10.2k | for(i=0;i<ci->psys;i++){ |
225 | 8.04k | _vp_psy_init(b->psy+i, |
226 | 8.04k | ci->psy_param[i], |
227 | 8.04k | &ci->psy_g_param, |
228 | 8.04k | ci->blocksizes[ci->psy_param[i]->blockflag]/2, |
229 | 8.04k | vi->rate); |
230 | 8.04k | } |
231 | | |
232 | 2.21k | v->analysisp=1; |
233 | 8.92k | }else{ |
234 | | /* finish the codebooks */ |
235 | 8.92k | if(ci->decbooks==NULL) |
236 | 0 | goto abort_books; |
237 | 26.5k | for(i=0;i<ci->books;i++){ |
238 | 17.7k | if(vorbis_book_init_decode(ci->decbooks+i)) |
239 | 122 | goto abort_books; |
240 | 17.7k | } |
241 | 8.92k | } |
242 | | |
243 | | /* initialize the storage vectors. blocksize[1] is small for encode, |
244 | | but the correct size for decode */ |
245 | 11.0k | v->pcm_storage=ci->blocksizes[1]; |
246 | 11.0k | v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm)); |
247 | 11.0k | v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret)); |
248 | 11.0k | { |
249 | 11.0k | int i; |
250 | 704k | for(i=0;i<vi->channels;i++) |
251 | 693k | v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); |
252 | 11.0k | } |
253 | | |
254 | | /* all 1 (large block) or 0 (small block) */ |
255 | | /* explicitly set for the sake of clarity */ |
256 | 11.0k | v->lW=0; /* previous window size */ |
257 | 11.0k | v->W=0; /* current window size */ |
258 | | |
259 | | /* all vector indexes */ |
260 | 11.0k | v->centerW=ci->blocksizes[1]/2; |
261 | | |
262 | 11.0k | v->pcm_current=v->centerW; |
263 | | |
264 | | /* initialize all the backend lookups */ |
265 | 11.0k | b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr)); |
266 | 11.0k | b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue)); |
267 | | |
268 | 25.1k | for(i=0;i<ci->floors;i++) |
269 | 14.1k | b->flr[i]=_floor_P[ci->floor_type[i]]-> |
270 | 14.1k | look(v,ci->floor_param[i]); |
271 | | |
272 | 25.6k | for(i=0;i<ci->residues;i++) |
273 | 14.6k | b->residue[i]=_residue_P[ci->residue_type[i]]-> |
274 | 14.6k | look(v,ci->residue_param[i]); |
275 | | |
276 | 11.0k | return 0; |
277 | 122 | abort_books: |
278 | 1.04k | for(i=0;i<ci->books;i++){ |
279 | 919 | if(ci->book_param[i]!=NULL){ |
280 | 0 | vorbis_staticbook_destroy(ci->book_param[i]); |
281 | 0 | ci->book_param[i]=NULL; |
282 | 0 | } |
283 | 919 | if(ci->decbooks!=NULL){ |
284 | 919 | vorbis_decbook_clear(ci->decbooks+i); |
285 | 919 | } |
286 | 919 | } |
287 | 122 | if(ci->decbooks!=NULL){ |
288 | 122 | _ogg_free(ci->decbooks); |
289 | 122 | ci->decbooks=NULL; |
290 | 122 | } |
291 | 122 | vorbis_dsp_clear(v); |
292 | 122 | return -1; |
293 | 11.1k | } |
294 | | |
295 | | /* arbitrary settings and spec-mandated numbers get filled in here */ |
296 | 2.21k | int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ |
297 | 2.21k | private_state *b=NULL; |
298 | | |
299 | 2.21k | if(_vds_shared_init(v,vi,1))return 1; |
300 | 2.21k | b=v->backend_state; |
301 | 2.21k | b->psy_g_look=_vp_global_look(vi); |
302 | | |
303 | | /* Initialize the envelope state storage */ |
304 | 2.21k | b->ve=_ogg_calloc(1,sizeof(*b->ve)); |
305 | 2.21k | _ve_envelope_init(b->ve,vi); |
306 | | |
307 | 2.21k | vorbis_bitrate_init(vi,&b->bms); |
308 | | |
309 | | /* compressed audio packets start after the headers |
310 | | with sequence number 3 */ |
311 | 2.21k | v->sequence=3; |
312 | | |
313 | 2.21k | return(0); |
314 | 2.21k | } |
315 | | |
316 | 14.3k | void vorbis_dsp_clear(vorbis_dsp_state *v){ |
317 | 14.3k | int i; |
318 | 14.3k | if(v){ |
319 | 14.3k | vorbis_info *vi=v->vi; |
320 | 14.3k | codec_setup_info *ci=(vi?vi->codec_setup:NULL); |
321 | 14.3k | private_state *b=v->backend_state; |
322 | | |
323 | 14.3k | if(b){ |
324 | | |
325 | 11.1k | if(b->ve){ |
326 | 2.21k | _ve_envelope_clear(b->ve); |
327 | 2.21k | _ogg_free(b->ve); |
328 | 2.21k | } |
329 | | |
330 | 11.1k | if(b->transform[0]){ |
331 | 11.1k | mdct_clear(b->transform[0][0]); |
332 | 11.1k | _ogg_free(b->transform[0][0]); |
333 | 11.1k | _ogg_free(b->transform[0]); |
334 | 11.1k | } |
335 | 11.1k | if(b->transform[1]){ |
336 | 11.1k | mdct_clear(b->transform[1][0]); |
337 | 11.1k | _ogg_free(b->transform[1][0]); |
338 | 11.1k | _ogg_free(b->transform[1]); |
339 | 11.1k | } |
340 | | |
341 | 11.1k | if(b->flr){ |
342 | 11.0k | if(ci) |
343 | 25.1k | for(i=0;i<ci->floors;i++) |
344 | 14.1k | _floor_P[ci->floor_type[i]]-> |
345 | 14.1k | free_look(b->flr[i]); |
346 | 11.0k | _ogg_free(b->flr); |
347 | 11.0k | } |
348 | 11.1k | if(b->residue){ |
349 | 11.0k | if(ci) |
350 | 25.6k | for(i=0;i<ci->residues;i++) |
351 | 14.6k | _residue_P[ci->residue_type[i]]-> |
352 | 14.6k | free_look(b->residue[i]); |
353 | 11.0k | _ogg_free(b->residue); |
354 | 11.0k | } |
355 | 11.1k | if(b->psy){ |
356 | 2.21k | if(ci) |
357 | 10.2k | for(i=0;i<ci->psys;i++) |
358 | 8.04k | _vp_psy_clear(b->psy+i); |
359 | 2.21k | _ogg_free(b->psy); |
360 | 2.21k | } |
361 | | |
362 | 11.1k | if(b->psy_g_look)_vp_global_free(b->psy_g_look); |
363 | 11.1k | vorbis_bitrate_clear(&b->bms); |
364 | | |
365 | 11.1k | drft_clear(&b->fft_look[0]); |
366 | 11.1k | drft_clear(&b->fft_look[1]); |
367 | | |
368 | 11.1k | } |
369 | | |
370 | 14.3k | if(v->pcm){ |
371 | 11.0k | if(vi) |
372 | 704k | for(i=0;i<vi->channels;i++) |
373 | 693k | if(v->pcm[i])_ogg_free(v->pcm[i]); |
374 | 11.0k | _ogg_free(v->pcm); |
375 | 11.0k | if(v->pcmret)_ogg_free(v->pcmret); |
376 | 11.0k | } |
377 | | |
378 | 14.3k | if(b){ |
379 | | /* free header, header1, header2 */ |
380 | 11.1k | if(b->header)_ogg_free(b->header); |
381 | 11.1k | if(b->header1)_ogg_free(b->header1); |
382 | 11.1k | if(b->header2)_ogg_free(b->header2); |
383 | 11.1k | _ogg_free(b); |
384 | 11.1k | } |
385 | | |
386 | 14.3k | memset(v,0,sizeof(*v)); |
387 | 14.3k | } |
388 | 14.3k | } |
389 | | |
390 | 14.7k | float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){ |
391 | 14.7k | int i; |
392 | 14.7k | vorbis_info *vi=v->vi; |
393 | 14.7k | private_state *b=v->backend_state; |
394 | | |
395 | | /* free header, header1, header2 */ |
396 | 14.7k | if(b->header) { |
397 | 2.21k | _ogg_free(b->header); |
398 | 2.21k | b->header=NULL; |
399 | 2.21k | } |
400 | 14.7k | if(b->header1) { |
401 | 2.21k | _ogg_free(b->header1); |
402 | 2.21k | b->header1=NULL; |
403 | 2.21k | } |
404 | 14.7k | if(b->header2) { |
405 | 2.21k | _ogg_free(b->header2); |
406 | 2.21k | b->header2=NULL; |
407 | 2.21k | } |
408 | | |
409 | | /* Do we have enough storage space for the requested buffer? If not, |
410 | | expand the PCM (and envelope) storage */ |
411 | | |
412 | 14.7k | if(v->pcm_current+vals>=v->pcm_storage){ |
413 | 5.05k | v->pcm_storage=v->pcm_current+vals*2; |
414 | | |
415 | 20.4k | for(i=0;i<vi->channels;i++){ |
416 | 15.3k | v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i])); |
417 | 15.3k | } |
418 | 5.05k | } |
419 | | |
420 | 43.2k | for(i=0;i<vi->channels;i++) |
421 | 28.5k | v->pcmret[i]=v->pcm[i]+v->pcm_current; |
422 | | |
423 | 14.7k | return(v->pcmret); |
424 | 14.7k | } |
425 | | |
426 | 2.21k | static void _preextrapolate_helper(vorbis_dsp_state *v){ |
427 | 2.21k | int i; |
428 | 2.21k | int order=16; |
429 | 2.21k | float *lpc=alloca(order*sizeof(*lpc)); |
430 | 2.21k | float *work=alloca(v->pcm_current*sizeof(*work)); |
431 | 2.21k | long j; |
432 | 2.21k | v->preextrapolate=1; |
433 | | |
434 | 2.21k | if(v->pcm_current-v->centerW>order*2){ /* safety */ |
435 | 5.43k | for(i=0;i<v->vi->channels;i++){ |
436 | | /* need to run the extrapolation in reverse! */ |
437 | 9.37M | for(j=0;j<v->pcm_current;j++) |
438 | 9.36M | work[j]=v->pcm[i][v->pcm_current-j-1]; |
439 | | |
440 | | /* prime as above */ |
441 | 4.08k | vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order); |
442 | | |
443 | | #if 0 |
444 | | if(v->vi->channels==2){ |
445 | | if(i==0) |
446 | | _analysis_output("predataL",0,work,v->pcm_current-v->centerW,0,0,0); |
447 | | else |
448 | | _analysis_output("predataR",0,work,v->pcm_current-v->centerW,0,0,0); |
449 | | }else{ |
450 | | _analysis_output("predata",0,work,v->pcm_current-v->centerW,0,0,0); |
451 | | } |
452 | | #endif |
453 | | |
454 | | /* run the predictor filter */ |
455 | 4.08k | vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order, |
456 | 4.08k | order, |
457 | 4.08k | work+v->pcm_current-v->centerW, |
458 | 4.08k | v->centerW); |
459 | | |
460 | 9.37M | for(j=0;j<v->pcm_current;j++) |
461 | 9.36M | v->pcm[i][v->pcm_current-j-1]=work[j]; |
462 | | |
463 | 4.08k | } |
464 | 1.34k | } |
465 | 2.21k | } |
466 | | |
467 | | |
468 | | /* call with val<=0 to set eof */ |
469 | | |
470 | 14.7k | int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ |
471 | 14.7k | vorbis_info *vi=v->vi; |
472 | 14.7k | codec_setup_info *ci=vi->codec_setup; |
473 | | |
474 | 14.7k | if(vals<=0){ |
475 | 2.21k | int order=32; |
476 | 2.21k | int i; |
477 | 2.21k | float *lpc=alloca(order*sizeof(*lpc)); |
478 | | |
479 | | /* if it wasn't done earlier (very short sample) */ |
480 | 2.21k | if(!v->preextrapolate) |
481 | 1.64k | _preextrapolate_helper(v); |
482 | | |
483 | | /* We're encoding the end of the stream. Just make sure we have |
484 | | [at least] a few full blocks of zeroes at the end. */ |
485 | | /* actually, we don't want zeroes; that could drop a large |
486 | | amplitude off a cliff, creating spread spectrum noise that will |
487 | | suck to encode. Extrapolate for the sake of cleanliness. */ |
488 | | |
489 | 2.21k | vorbis_analysis_buffer(v,ci->blocksizes[1]*3); |
490 | 2.21k | v->eofflag=v->pcm_current; |
491 | 2.21k | v->pcm_current+=ci->blocksizes[1]*3; |
492 | | |
493 | 8.92k | for(i=0;i<vi->channels;i++){ |
494 | 6.71k | if(v->eofflag>order*2){ |
495 | | /* extrapolate with LPC to fill in */ |
496 | 6.71k | long n; |
497 | | |
498 | | /* make a predictor filter */ |
499 | 6.71k | n=v->eofflag; |
500 | 6.71k | if(n>ci->blocksizes[1])n=ci->blocksizes[1]; |
501 | 6.71k | vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order); |
502 | | |
503 | | /* run the predictor filter */ |
504 | 6.71k | vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order, |
505 | 6.71k | v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag); |
506 | 6.71k | }else{ |
507 | | /* not enough data to extrapolate (unlikely to happen due to |
508 | | guarding the overlap, but bulletproof in case that |
509 | | assumtion goes away). zeroes will do. */ |
510 | 0 | memset(v->pcm[i]+v->eofflag,0, |
511 | 0 | (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i])); |
512 | |
|
513 | 0 | } |
514 | 6.71k | } |
515 | 12.5k | }else{ |
516 | | |
517 | 12.5k | if(v->pcm_current+vals>v->pcm_storage) |
518 | 0 | return(OV_EINVAL); |
519 | | |
520 | 12.5k | v->pcm_current+=vals; |
521 | | |
522 | | /* we may want to reverse extrapolate the beginning of a stream |
523 | | too... in case we're beginning on a cliff! */ |
524 | | /* clumsy, but simple. It only runs once, so simple is good. */ |
525 | 12.5k | if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) |
526 | 570 | _preextrapolate_helper(v); |
527 | | |
528 | 12.5k | } |
529 | 14.7k | return(0); |
530 | 14.7k | } |
531 | | |
532 | | /* do the deltas, envelope shaping, pre-echo and determine the size of |
533 | | the next block on which to continue analysis */ |
534 | 77.1k | int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ |
535 | 77.1k | int i; |
536 | 77.1k | vorbis_info *vi=v->vi; |
537 | 77.1k | codec_setup_info *ci=vi->codec_setup; |
538 | 77.1k | private_state *b=v->backend_state; |
539 | 77.1k | vorbis_look_psy_global *g=b->psy_g_look; |
540 | 77.1k | long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext; |
541 | 77.1k | vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; |
542 | | |
543 | | /* check to see if we're started... */ |
544 | 77.1k | if(!v->preextrapolate)return(0); |
545 | | |
546 | | /* check to see if we're done... */ |
547 | 74.6k | if(v->eofflag==-1)return(0); |
548 | | |
549 | | /* By our invariant, we have lW, W and centerW set. Search for |
550 | | the next boundary so we can determine nW (the next window size) |
551 | | which lets us compute the shape of the current block's window */ |
552 | | |
553 | | /* we do an envelope search even on a single blocksize; we may still |
554 | | be throwing more bits at impulses, and envelope search handles |
555 | | marking impulses too. */ |
556 | 72.4k | { |
557 | 72.4k | long bp=_ve_envelope_search(v); |
558 | 72.4k | if(bp==-1){ |
559 | | |
560 | 9.80k | if(v->eofflag==0)return(0); /* not enough data currently to search for a |
561 | | full long block */ |
562 | 0 | v->nW=0; |
563 | 62.6k | }else{ |
564 | | |
565 | 62.6k | if(ci->blocksizes[0]==ci->blocksizes[1]) |
566 | 13.3k | v->nW=0; |
567 | 49.2k | else |
568 | 49.2k | v->nW=bp; |
569 | 62.6k | } |
570 | 72.4k | } |
571 | | |
572 | 62.6k | centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4; |
573 | | |
574 | 62.6k | { |
575 | | /* center of next block + next block maximum right side. */ |
576 | | |
577 | 62.6k | long blockbound=centerNext+ci->blocksizes[v->nW]/2; |
578 | 62.6k | if(v->pcm_current<blockbound)return(0); /* not enough data yet; |
579 | | although this check is |
580 | | less strict that the |
581 | | _ve_envelope_search, |
582 | | the search is not run |
583 | | if we only use one |
584 | | block size */ |
585 | | |
586 | | |
587 | 62.6k | } |
588 | | |
589 | | /* fill in the block. Note that for a short window, lW and nW are *short* |
590 | | regardless of actual settings in the stream */ |
591 | | |
592 | 62.4k | _vorbis_block_ripcord(vb); |
593 | 62.4k | vb->lW=v->lW; |
594 | 62.4k | vb->W=v->W; |
595 | 62.4k | vb->nW=v->nW; |
596 | | |
597 | 62.4k | if(v->W){ |
598 | 3.31k | if(!v->lW || !v->nW){ |
599 | 1.63k | vbi->blocktype=BLOCKTYPE_TRANSITION; |
600 | | /*fprintf(stderr,"-");*/ |
601 | 1.67k | }else{ |
602 | 1.67k | vbi->blocktype=BLOCKTYPE_LONG; |
603 | | /*fprintf(stderr,"_");*/ |
604 | 1.67k | } |
605 | 59.0k | }else{ |
606 | 59.0k | if(_ve_envelope_mark(v)){ |
607 | 39.3k | vbi->blocktype=BLOCKTYPE_IMPULSE; |
608 | | /*fprintf(stderr,"|");*/ |
609 | | |
610 | 39.3k | }else{ |
611 | 19.7k | vbi->blocktype=BLOCKTYPE_PADDING; |
612 | | /*fprintf(stderr,".");*/ |
613 | | |
614 | 19.7k | } |
615 | 59.0k | } |
616 | | |
617 | 62.4k | vb->vd=v; |
618 | 62.4k | vb->sequence=v->sequence++; |
619 | 62.4k | vb->granulepos=v->granulepos; |
620 | 62.4k | vb->pcmend=ci->blocksizes[v->W]; |
621 | | |
622 | | /* copy the vectors; this uses the local storage in vb */ |
623 | | |
624 | | /* this tracks 'strongest peak' for later psychoacoustics */ |
625 | | /* moved to the global psy state; clean this mess up */ |
626 | 62.4k | if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax; |
627 | 62.4k | g->ampmax=_vp_ampmax_decay(g->ampmax,v); |
628 | 62.4k | vbi->ampmax=g->ampmax; |
629 | | |
630 | 62.4k | vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); |
631 | 62.4k | vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels); |
632 | 168k | for(i=0;i<vi->channels;i++){ |
633 | 105k | vbi->pcmdelay[i]= |
634 | 105k | _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); |
635 | 105k | memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); |
636 | 105k | vb->pcm[i]=vbi->pcmdelay[i]+beginW; |
637 | | |
638 | | /* before we added the delay |
639 | | vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); |
640 | | memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i])); |
641 | | */ |
642 | | |
643 | 105k | } |
644 | | |
645 | | /* handle eof detection: eof==0 means that we've not yet received EOF |
646 | | eof>0 marks the last 'real' sample in pcm[] |
647 | | eof<0 'no more to do'; doesn't get here */ |
648 | | |
649 | 62.4k | if(v->eofflag){ |
650 | 8.88k | if(v->centerW>=v->eofflag){ |
651 | 2.21k | v->eofflag=-1; |
652 | 2.21k | vb->eofflag=1; |
653 | 2.21k | return(1); |
654 | 2.21k | } |
655 | 8.88k | } |
656 | | |
657 | | /* advance storage vectors and clean up */ |
658 | 60.1k | { |
659 | 60.1k | int new_centerNext=ci->blocksizes[1]/2; |
660 | 60.1k | int movementW=centerNext-new_centerNext; |
661 | | |
662 | 60.1k | if(movementW>0){ |
663 | | |
664 | 60.1k | _ve_envelope_shift(b->ve,movementW); |
665 | 60.1k | v->pcm_current-=movementW; |
666 | | |
667 | 159k | for(i=0;i<vi->channels;i++) |
668 | 99.1k | memmove(v->pcm[i],v->pcm[i]+movementW, |
669 | 99.1k | v->pcm_current*sizeof(*v->pcm[i])); |
670 | | |
671 | | |
672 | 60.1k | v->lW=v->W; |
673 | 60.1k | v->W=v->nW; |
674 | 60.1k | v->centerW=new_centerNext; |
675 | | |
676 | 60.1k | if(v->eofflag){ |
677 | 6.67k | v->eofflag-=movementW; |
678 | 6.67k | if(v->eofflag<=0)v->eofflag=-1; |
679 | | /* do not add padding to end of stream! */ |
680 | 6.67k | if(v->centerW>=v->eofflag){ |
681 | 2.10k | v->granulepos+=movementW-(v->centerW-v->eofflag); |
682 | 4.56k | }else{ |
683 | 4.56k | v->granulepos+=movementW; |
684 | 4.56k | } |
685 | 53.5k | }else{ |
686 | 53.5k | v->granulepos+=movementW; |
687 | 53.5k | } |
688 | 60.1k | } |
689 | 60.1k | } |
690 | | |
691 | | /* done */ |
692 | 60.1k | return(1); |
693 | 62.4k | } |
694 | | |
695 | 8.79k | int vorbis_synthesis_restart(vorbis_dsp_state *v){ |
696 | 8.79k | vorbis_info *vi=v->vi; |
697 | 8.79k | codec_setup_info *ci; |
698 | 8.79k | int hs; |
699 | | |
700 | 8.79k | if(!v->backend_state)return -1; |
701 | 8.79k | if(!vi)return -1; |
702 | 8.79k | ci=vi->codec_setup; |
703 | 8.79k | if(!ci)return -1; |
704 | 8.79k | hs=ci->halfrate_flag; |
705 | | |
706 | 8.79k | v->centerW=ci->blocksizes[1]>>(hs+1); |
707 | 8.79k | v->pcm_current=v->centerW>>hs; |
708 | | |
709 | 8.79k | v->pcm_returned=-1; |
710 | 8.79k | v->granulepos=-1; |
711 | 8.79k | v->sequence=-1; |
712 | 8.79k | v->eofflag=0; |
713 | 8.79k | ((private_state *)(v->backend_state))->sample_count=-1; |
714 | | |
715 | 8.79k | return(0); |
716 | 8.79k | } |
717 | | |
718 | 8.92k | int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ |
719 | 8.92k | if(_vds_shared_init(v,vi,0)){ |
720 | 122 | vorbis_dsp_clear(v); |
721 | 122 | return 1; |
722 | 122 | } |
723 | 8.79k | vorbis_synthesis_restart(v); |
724 | 8.79k | return 0; |
725 | 8.92k | } |
726 | | |
727 | | /* Unlike in analysis, the window is only partially applied for each |
728 | | block. The time domain envelope is not yet handled at the point of |
729 | | calling (as it relies on the previous block). */ |
730 | | |
731 | 106k | int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ |
732 | 106k | vorbis_info *vi=v->vi; |
733 | 106k | codec_setup_info *ci=vi->codec_setup; |
734 | 106k | private_state *b=v->backend_state; |
735 | 106k | int hs=ci->halfrate_flag; |
736 | 106k | int i,j; |
737 | | |
738 | 106k | if(!vb)return(OV_EINVAL); |
739 | 106k | if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); |
740 | | |
741 | 95.4k | v->lW=v->W; |
742 | 95.4k | v->W=vb->W; |
743 | 95.4k | v->nW=-1; |
744 | | |
745 | 95.4k | if((v->sequence==-1)|| |
746 | 89.8k | (v->sequence+1 != vb->sequence)){ |
747 | 63.7k | v->granulepos=-1; /* out of sequence; lose count */ |
748 | 63.7k | b->sample_count=-1; |
749 | 63.7k | } |
750 | | |
751 | 95.4k | v->sequence=vb->sequence; |
752 | | |
753 | 95.4k | if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly |
754 | | was called on block */ |
755 | 95.4k | int n=ci->blocksizes[v->W]>>(hs+1); |
756 | 95.4k | int n0=ci->blocksizes[0]>>(hs+1); |
757 | 95.4k | int n1=ci->blocksizes[1]>>(hs+1); |
758 | | |
759 | 95.4k | int thisCenter; |
760 | 95.4k | int prevCenter; |
761 | | |
762 | 95.4k | v->glue_bits+=vb->glue_bits; |
763 | 95.4k | v->time_bits+=vb->time_bits; |
764 | 95.4k | v->floor_bits+=vb->floor_bits; |
765 | 95.4k | v->res_bits+=vb->res_bits; |
766 | | |
767 | 95.4k | if(v->centerW){ |
768 | 49.0k | thisCenter=n1; |
769 | 49.0k | prevCenter=0; |
770 | 49.0k | }else{ |
771 | 46.3k | thisCenter=0; |
772 | 46.3k | prevCenter=n1; |
773 | 46.3k | } |
774 | | |
775 | | /* v->pcm is now used like a two-stage double buffer. We don't want |
776 | | to have to constantly shift *or* adjust memory usage. Don't |
777 | | accept a new block until the old is shifted out */ |
778 | | |
779 | 1.86M | for(j=0;j<vi->channels;j++){ |
780 | | /* the overlap/add section */ |
781 | 1.76M | if(v->lW){ |
782 | 854k | if(v->W){ |
783 | | /* large/large */ |
784 | 851k | const float *w=_vorbis_window_get(b->window[1]-hs); |
785 | 851k | float *pcm=v->pcm[j]+prevCenter; |
786 | 851k | float *p=vb->pcm[j]; |
787 | 1.00G | for(i=0;i<n1;i++) |
788 | 1.00G | pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i]; |
789 | 851k | }else{ |
790 | | /* large/small */ |
791 | 3.01k | const float *w=_vorbis_window_get(b->window[0]-hs); |
792 | 3.01k | float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; |
793 | 3.01k | float *p=vb->pcm[j]; |
794 | 341k | for(i=0;i<n0;i++) |
795 | 338k | pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; |
796 | 3.01k | } |
797 | 914k | }else{ |
798 | 914k | if(v->W){ |
799 | | /* small/large */ |
800 | 222k | const float *w=_vorbis_window_get(b->window[0]-hs); |
801 | 222k | float *pcm=v->pcm[j]+prevCenter; |
802 | 222k | float *p=vb->pcm[j]+n1/2-n0/2; |
803 | 72.7M | for(i=0;i<n0;i++) |
804 | 72.5M | pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; |
805 | 73.3M | for(;i<n1/2+n0/2;i++) |
806 | 73.1M | pcm[i]=p[i]; |
807 | 692k | }else{ |
808 | | /* small/small */ |
809 | 692k | const float *w=_vorbis_window_get(b->window[0]-hs); |
810 | 692k | float *pcm=v->pcm[j]+prevCenter; |
811 | 692k | float *p=vb->pcm[j]; |
812 | 194M | for(i=0;i<n0;i++) |
813 | 193M | pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; |
814 | 692k | } |
815 | 914k | } |
816 | | |
817 | | /* the copy section */ |
818 | 1.76M | { |
819 | 1.76M | float *pcm=v->pcm[j]+thisCenter; |
820 | 1.76M | float *p=vb->pcm[j]+n; |
821 | 1.41G | for(i=0;i<n;i++) |
822 | 1.41G | pcm[i]=p[i]; |
823 | 1.76M | } |
824 | 1.76M | } |
825 | | |
826 | 95.4k | if(v->centerW) |
827 | 49.0k | v->centerW=0; |
828 | 46.3k | else |
829 | 46.3k | v->centerW=n1; |
830 | | |
831 | | /* deal with initial packet state; we do this using the explicit |
832 | | pcm_returned==-1 flag otherwise we're sensitive to first block |
833 | | being short or long */ |
834 | | |
835 | 95.4k | if(v->pcm_returned==-1){ |
836 | 5.58k | v->pcm_returned=thisCenter; |
837 | 5.58k | v->pcm_current=thisCenter; |
838 | 89.8k | }else{ |
839 | 89.8k | v->pcm_returned=prevCenter; |
840 | 89.8k | v->pcm_current=prevCenter+ |
841 | 89.8k | ((ci->blocksizes[v->lW]/4+ |
842 | 89.8k | ci->blocksizes[v->W]/4)>>hs); |
843 | 89.8k | } |
844 | | |
845 | 95.4k | } |
846 | | |
847 | | /* track the frame number... This is for convenience, but also |
848 | | making sure our last packet doesn't end with added padding. If |
849 | | the last packet is partial, the number of samples we'll have to |
850 | | return will be past the vb->granulepos. |
851 | | |
852 | | This is not foolproof! It will be confused if we begin |
853 | | decoding at the last page after a seek or hole. In that case, |
854 | | we don't have a starting point to judge where the last frame |
855 | | is. For this reason, vorbisfile will always try to make sure |
856 | | it reads the last two marked pages in proper sequence */ |
857 | | |
858 | 95.4k | if(b->sample_count==-1){ |
859 | 63.7k | b->sample_count=0; |
860 | 63.7k | }else{ |
861 | 31.7k | b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; |
862 | 31.7k | } |
863 | | |
864 | 95.4k | if(v->granulepos==-1){ |
865 | 83.2k | if(vb->granulepos!=-1){ /* only set if we have a position to set to */ |
866 | | |
867 | 14.2k | v->granulepos=vb->granulepos; |
868 | | |
869 | | /* is this a short page? */ |
870 | 14.2k | if(b->sample_count>v->granulepos){ |
871 | | /* corner case; if this is both the first and last audio page, |
872 | | then spec says the end is cut, not beginning */ |
873 | 4.99k | long extra=b->sample_count-vb->granulepos; |
874 | | |
875 | | /* we use ogg_int64_t for granule positions because a |
876 | | uint64 isn't universally available. Unfortunately, |
877 | | that means granposes can be 'negative' and result in |
878 | | extra being negative */ |
879 | 4.99k | if(extra<0) |
880 | 55 | extra=0; |
881 | | |
882 | 4.99k | if(vb->eofflag){ |
883 | | /* trim the end */ |
884 | | /* no preceding granulepos; assume we started at zero (we'd |
885 | | have to in a short single-page stream) */ |
886 | | /* granulepos could be -1 due to a seek, but that would result |
887 | | in a long count, not short count */ |
888 | | |
889 | | /* Guard against corrupt/malicious frames that set EOP and |
890 | | a backdated granpos; don't rewind more samples than we |
891 | | actually have */ |
892 | 2.43k | if(extra > (v->pcm_current - v->pcm_returned)<<hs) |
893 | 2.29k | extra = (v->pcm_current - v->pcm_returned)<<hs; |
894 | | |
895 | 2.43k | v->pcm_current-=extra>>hs; |
896 | 2.55k | }else{ |
897 | | /* trim the beginning */ |
898 | 2.55k | v->pcm_returned+=extra>>hs; |
899 | 2.55k | if(v->pcm_returned>v->pcm_current) |
900 | 983 | v->pcm_returned=v->pcm_current; |
901 | 2.55k | } |
902 | | |
903 | 4.99k | } |
904 | | |
905 | 14.2k | } |
906 | 83.2k | }else{ |
907 | 12.2k | v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; |
908 | 12.2k | if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ |
909 | | |
910 | 2.14k | if(v->granulepos>vb->granulepos){ |
911 | 1.39k | long extra=v->granulepos-vb->granulepos; |
912 | | |
913 | 1.39k | if(extra) |
914 | 1.39k | if(vb->eofflag){ |
915 | | /* partial last frame. Strip the extra samples off */ |
916 | | |
917 | | /* Guard against corrupt/malicious frames that set EOP and |
918 | | a backdated granpos; don't rewind more samples than we |
919 | | actually have */ |
920 | 870 | if(extra > (v->pcm_current - v->pcm_returned)<<hs) |
921 | 353 | extra = (v->pcm_current - v->pcm_returned)<<hs; |
922 | | |
923 | | /* we use ogg_int64_t for granule positions because a |
924 | | uint64 isn't universally available. Unfortunately, |
925 | | that means granposes can be 'negative' and result in |
926 | | extra being negative */ |
927 | 870 | if(extra<0) |
928 | 84 | extra=0; |
929 | | |
930 | 870 | v->pcm_current-=extra>>hs; |
931 | 870 | } /* else {Shouldn't happen *unless* the bitstream is out of |
932 | | spec. Either way, believe the bitstream } */ |
933 | 1.39k | } /* else {Shouldn't happen *unless* the bitstream is out of |
934 | | spec. Either way, believe the bitstream } */ |
935 | 2.14k | v->granulepos=vb->granulepos; |
936 | 2.14k | } |
937 | 12.2k | } |
938 | | |
939 | | /* Update, cleanup */ |
940 | | |
941 | 95.4k | if(vb->eofflag)v->eofflag=1; |
942 | 95.4k | return(0); |
943 | | |
944 | 106k | } |
945 | | |
946 | | /* pcm==NULL indicates we just want the pending samples, no more */ |
947 | 907k | int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){ |
948 | 907k | vorbis_info *vi=v->vi; |
949 | | |
950 | 907k | if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){ |
951 | 650k | if(pcm){ |
952 | 556k | int i; |
953 | 87.9M | for(i=0;i<vi->channels;i++) |
954 | 87.3M | v->pcmret[i]=v->pcm[i]+v->pcm_returned; |
955 | 556k | *pcm=v->pcmret; |
956 | 556k | } |
957 | 650k | return(v->pcm_current-v->pcm_returned); |
958 | 650k | } |
959 | 256k | return(0); |
960 | 907k | } |
961 | | |
962 | 556k | int vorbis_synthesis_read(vorbis_dsp_state *v,int n){ |
963 | 556k | if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL); |
964 | 556k | v->pcm_returned+=n; |
965 | 556k | return(0); |
966 | 556k | } |
967 | | |
968 | | /* intended for use with a specific vorbisfile feature; we want access |
969 | | to the [usually synthetic/postextrapolated] buffer and lapping at |
970 | | the end of a decode cycle, specifically, a half-short-block worth. |
971 | | This funtion works like pcmout above, except it will also expose |
972 | | this implicit buffer data not normally decoded. */ |
973 | 0 | int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){ |
974 | 0 | vorbis_info *vi=v->vi; |
975 | 0 | codec_setup_info *ci=vi->codec_setup; |
976 | 0 | int hs=ci->halfrate_flag; |
977 | |
|
978 | 0 | int n=ci->blocksizes[v->W]>>(hs+1); |
979 | 0 | int n0=ci->blocksizes[0]>>(hs+1); |
980 | 0 | int n1=ci->blocksizes[1]>>(hs+1); |
981 | 0 | int i,j; |
982 | |
|
983 | 0 | if(v->pcm_returned<0)return 0; |
984 | | |
985 | | /* our returned data ends at pcm_returned; because the synthesis pcm |
986 | | buffer is a two-fragment ring, that means our data block may be |
987 | | fragmented by buffering, wrapping or a short block not filling |
988 | | out a buffer. To simplify things, we unfragment if it's at all |
989 | | possibly needed. Otherwise, we'd need to call lapout more than |
990 | | once as well as hold additional dsp state. Opt for |
991 | | simplicity. */ |
992 | | |
993 | | /* centerW was advanced by blockin; it would be the center of the |
994 | | *next* block */ |
995 | 0 | if(v->centerW==n1){ |
996 | | /* the data buffer wraps; swap the halves */ |
997 | | /* slow, sure, small */ |
998 | 0 | for(j=0;j<vi->channels;j++){ |
999 | 0 | float *p=v->pcm[j]; |
1000 | 0 | for(i=0;i<n1;i++){ |
1001 | 0 | float temp=p[i]; |
1002 | 0 | p[i]=p[i+n1]; |
1003 | 0 | p[i+n1]=temp; |
1004 | 0 | } |
1005 | 0 | } |
1006 | |
|
1007 | 0 | v->pcm_current-=n1; |
1008 | 0 | v->pcm_returned-=n1; |
1009 | 0 | v->centerW=0; |
1010 | 0 | } |
1011 | | |
1012 | | /* solidify buffer into contiguous space */ |
1013 | 0 | if((v->lW^v->W)==1){ |
1014 | | /* long/short or short/long */ |
1015 | 0 | for(j=0;j<vi->channels;j++){ |
1016 | 0 | float *s=v->pcm[j]; |
1017 | 0 | float *d=v->pcm[j]+(n1-n0)/2; |
1018 | 0 | for(i=(n1+n0)/2-1;i>=0;--i) |
1019 | 0 | d[i]=s[i]; |
1020 | 0 | } |
1021 | 0 | v->pcm_returned+=(n1-n0)/2; |
1022 | 0 | v->pcm_current+=(n1-n0)/2; |
1023 | 0 | }else{ |
1024 | 0 | if(v->lW==0){ |
1025 | | /* short/short */ |
1026 | 0 | for(j=0;j<vi->channels;j++){ |
1027 | 0 | float *s=v->pcm[j]; |
1028 | 0 | float *d=v->pcm[j]+n1-n0; |
1029 | 0 | for(i=n0-1;i>=0;--i) |
1030 | 0 | d[i]=s[i]; |
1031 | 0 | } |
1032 | 0 | v->pcm_returned+=n1-n0; |
1033 | 0 | v->pcm_current+=n1-n0; |
1034 | 0 | } |
1035 | 0 | } |
1036 | |
|
1037 | 0 | if(pcm){ |
1038 | 0 | int i; |
1039 | 0 | for(i=0;i<vi->channels;i++) |
1040 | 0 | v->pcmret[i]=v->pcm[i]+v->pcm_returned; |
1041 | 0 | *pcm=v->pcmret; |
1042 | 0 | } |
1043 | |
|
1044 | 0 | return(n1+n-v->pcm_returned); |
1045 | |
|
1046 | 0 | } |
1047 | | |
1048 | 0 | const float *vorbis_window(vorbis_dsp_state *v,int W){ |
1049 | 0 | vorbis_info *vi=v->vi; |
1050 | 0 | codec_setup_info *ci=vi->codec_setup; |
1051 | 0 | int hs=ci->halfrate_flag; |
1052 | 0 | private_state *b=v->backend_state; |
1053 | |
|
1054 | 0 | if(b->window[W]-1<0)return NULL; |
1055 | 0 | return _vorbis_window_get(b->window[W]-hs); |
1056 | 0 | } |