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