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 | 6.16M | #define WORD_ALIGN 8 |
75 | | #endif |
76 | | |
77 | 986 | int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){ |
78 | 986 | int i; |
79 | 986 | memset(vb,0,sizeof(*vb)); |
80 | 986 | vb->vd=v; |
81 | 986 | vb->localalloc=0; |
82 | 986 | vb->localstore=NULL; |
83 | 986 | 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 | 986 | return(0); |
100 | 986 | } |
101 | | |
102 | 3.08M | void *_vorbis_block_alloc(vorbis_block *vb,long bytes){ |
103 | 3.08M | bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1); |
104 | 3.08M | if(bytes+vb->localtop>vb->localalloc){ |
105 | | /* can't just _ogg_realloc... there are outstanding pointers */ |
106 | 120k | if(vb->localstore){ |
107 | 119k | struct alloc_chain *link=_ogg_malloc(sizeof(*link)); |
108 | 119k | vb->totaluse+=vb->localtop; |
109 | 119k | link->next=vb->reap; |
110 | 119k | link->ptr=vb->localstore; |
111 | 119k | vb->reap=link; |
112 | 119k | } |
113 | | /* highly conservative */ |
114 | 120k | vb->localalloc=bytes; |
115 | 120k | vb->localstore=_ogg_malloc(vb->localalloc); |
116 | 120k | vb->localtop=0; |
117 | 120k | } |
118 | 3.08M | { |
119 | 3.08M | void *ret=(void *)(((char *)vb->localstore)+vb->localtop); |
120 | 3.08M | vb->localtop+=bytes; |
121 | 3.08M | return ret; |
122 | 3.08M | } |
123 | 3.08M | } |
124 | | |
125 | | /* reap the chain, pull the ripcord */ |
126 | 131k | void _vorbis_block_ripcord(vorbis_block *vb){ |
127 | | /* reap the chain */ |
128 | 131k | struct alloc_chain *reap=vb->reap; |
129 | 251k | while(reap){ |
130 | 119k | struct alloc_chain *next=reap->next; |
131 | 119k | _ogg_free(reap->ptr); |
132 | 119k | memset(reap,0,sizeof(*reap)); |
133 | 119k | _ogg_free(reap); |
134 | 119k | reap=next; |
135 | 119k | } |
136 | | /* consolidate storage */ |
137 | 131k | if(vb->totaluse){ |
138 | 1.96k | vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc); |
139 | 1.96k | vb->localalloc+=vb->totaluse; |
140 | 1.96k | vb->totaluse=0; |
141 | 1.96k | } |
142 | | |
143 | | /* pull the ripcord */ |
144 | 131k | vb->localtop=0; |
145 | 131k | vb->reap=NULL; |
146 | 131k | } |
147 | | |
148 | 1.92k | int vorbis_block_clear(vorbis_block *vb){ |
149 | 1.92k | int i; |
150 | 1.92k | vorbis_block_internal *vbi=vb->internal; |
151 | | |
152 | 1.92k | _vorbis_block_ripcord(vb); |
153 | 1.92k | if(vb->localstore)_ogg_free(vb->localstore); |
154 | | |
155 | 1.92k | 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 | 1.92k | memset(vb,0,sizeof(*vb)); |
163 | 1.92k | return(0); |
164 | 1.92k | } |
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 | 986 | static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ |
171 | 986 | int i; |
172 | 986 | codec_setup_info *ci=vi->codec_setup; |
173 | 986 | private_state *b=NULL; |
174 | 986 | int hs; |
175 | | |
176 | 986 | if(ci==NULL|| |
177 | 986 | ci->modes<=0|| |
178 | 986 | ci->blocksizes[0]<64|| |
179 | 986 | ci->blocksizes[1]<ci->blocksizes[0]){ |
180 | 0 | return 1; |
181 | 0 | } |
182 | 986 | hs=ci->halfrate_flag; |
183 | | |
184 | 986 | memset(v,0,sizeof(*v)); |
185 | 986 | b=v->backend_state=_ogg_calloc(1,sizeof(*b)); |
186 | | |
187 | 986 | v->vi=vi; |
188 | 986 | b->modebits=ov_ilog(ci->modes-1); |
189 | | |
190 | 986 | b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0])); |
191 | 986 | b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1])); |
192 | | |
193 | | /* MDCT is tranform 0 */ |
194 | | |
195 | 986 | b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup)); |
196 | 986 | b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup)); |
197 | 986 | mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs); |
198 | 986 | 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 | 986 | b->window[0]=ov_ilog(ci->blocksizes[0])-7; |
208 | 986 | b->window[1]=ov_ilog(ci->blocksizes[1])-7; |
209 | | |
210 | 986 | 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 | 986 | }else{ |
234 | | /* finish the codebooks */ |
235 | 986 | if(ci->decbooks==NULL) |
236 | 0 | goto abort_books; |
237 | 1.91k | for(i=0;i<ci->books;i++){ |
238 | 986 | if(vorbis_book_init_decode(ci->decbooks+i)) |
239 | 56 | goto abort_books; |
240 | 986 | } |
241 | 986 | } |
242 | | |
243 | | /* initialize the storage vectors. blocksize[1] is small for encode, |
244 | | but the correct size for decode */ |
245 | 930 | v->pcm_storage=ci->blocksizes[1]; |
246 | 930 | v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm)); |
247 | 930 | v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret)); |
248 | 930 | { |
249 | 930 | int i; |
250 | 94.2k | for(i=0;i<vi->channels;i++) |
251 | 93.2k | v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); |
252 | 930 | } |
253 | | |
254 | | /* all 1 (large block) or 0 (small block) */ |
255 | | /* explicitly set for the sake of clarity */ |
256 | 930 | v->lW=0; /* previous window size */ |
257 | 930 | v->W=0; /* current window size */ |
258 | | |
259 | | /* all vector indexes */ |
260 | 930 | v->centerW=ci->blocksizes[1]/2; |
261 | | |
262 | 930 | v->pcm_current=v->centerW; |
263 | | |
264 | | /* initialize all the backend lookups */ |
265 | 930 | b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr)); |
266 | 930 | b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue)); |
267 | | |
268 | 1.86k | for(i=0;i<ci->floors;i++) |
269 | 930 | b->flr[i]=_floor_P[ci->floor_type[i]]-> |
270 | 930 | look(v,ci->floor_param[i]); |
271 | | |
272 | 2.78k | for(i=0;i<ci->residues;i++) |
273 | 1.85k | b->residue[i]=_residue_P[ci->residue_type[i]]-> |
274 | 1.85k | look(v,ci->residue_param[i]); |
275 | | |
276 | 930 | return 0; |
277 | 56 | abort_books: |
278 | 112 | for(i=0;i<ci->books;i++){ |
279 | 56 | 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 | 56 | if(ci->decbooks!=NULL){ |
284 | 56 | vorbis_decbook_clear(ci->decbooks+i); |
285 | 56 | } |
286 | 56 | } |
287 | 56 | if(ci->decbooks!=NULL){ |
288 | 56 | _ogg_free(ci->decbooks); |
289 | 56 | ci->decbooks=NULL; |
290 | 56 | } |
291 | 56 | vorbis_dsp_clear(v); |
292 | 56 | return -1; |
293 | 986 | } |
294 | | |
295 | | /* arbitrary settings and spec-mandated numbers get filled in here */ |
296 | 0 | int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){ |
297 | 0 | private_state *b=NULL; |
298 | |
|
299 | 0 | if(_vds_shared_init(v,vi,1))return 1; |
300 | 0 | b=v->backend_state; |
301 | 0 | b->psy_g_look=_vp_global_look(vi); |
302 | | |
303 | | /* Initialize the envelope state storage */ |
304 | 0 | b->ve=_ogg_calloc(1,sizeof(*b->ve)); |
305 | 0 | _ve_envelope_init(b->ve,vi); |
306 | |
|
307 | 0 | vorbis_bitrate_init(vi,&b->bms); |
308 | | |
309 | | /* compressed audio packets start after the headers |
310 | | with sequence number 3 */ |
311 | 0 | v->sequence=3; |
312 | |
|
313 | 0 | return(0); |
314 | 0 | } |
315 | | |
316 | 2.03k | void vorbis_dsp_clear(vorbis_dsp_state *v){ |
317 | 2.03k | int i; |
318 | 2.03k | if(v){ |
319 | 2.03k | vorbis_info *vi=v->vi; |
320 | 2.03k | codec_setup_info *ci=(vi?vi->codec_setup:NULL); |
321 | 2.03k | private_state *b=v->backend_state; |
322 | | |
323 | 2.03k | if(b){ |
324 | | |
325 | 986 | if(b->ve){ |
326 | 0 | _ve_envelope_clear(b->ve); |
327 | 0 | _ogg_free(b->ve); |
328 | 0 | } |
329 | | |
330 | 986 | if(b->transform[0]){ |
331 | 986 | mdct_clear(b->transform[0][0]); |
332 | 986 | _ogg_free(b->transform[0][0]); |
333 | 986 | _ogg_free(b->transform[0]); |
334 | 986 | } |
335 | 986 | if(b->transform[1]){ |
336 | 986 | mdct_clear(b->transform[1][0]); |
337 | 986 | _ogg_free(b->transform[1][0]); |
338 | 986 | _ogg_free(b->transform[1]); |
339 | 986 | } |
340 | | |
341 | 986 | if(b->flr){ |
342 | 930 | if(ci) |
343 | 1.86k | for(i=0;i<ci->floors;i++) |
344 | 930 | _floor_P[ci->floor_type[i]]-> |
345 | 930 | free_look(b->flr[i]); |
346 | 930 | _ogg_free(b->flr); |
347 | 930 | } |
348 | 986 | if(b->residue){ |
349 | 930 | if(ci) |
350 | 2.78k | for(i=0;i<ci->residues;i++) |
351 | 1.85k | _residue_P[ci->residue_type[i]]-> |
352 | 1.85k | free_look(b->residue[i]); |
353 | 930 | _ogg_free(b->residue); |
354 | 930 | } |
355 | 986 | if(b->psy){ |
356 | 0 | if(ci) |
357 | 0 | for(i=0;i<ci->psys;i++) |
358 | 0 | _vp_psy_clear(b->psy+i); |
359 | 0 | _ogg_free(b->psy); |
360 | 0 | } |
361 | | |
362 | 986 | if(b->psy_g_look)_vp_global_free(b->psy_g_look); |
363 | 986 | vorbis_bitrate_clear(&b->bms); |
364 | | |
365 | 986 | drft_clear(&b->fft_look[0]); |
366 | 986 | drft_clear(&b->fft_look[1]); |
367 | | |
368 | 986 | } |
369 | | |
370 | 2.03k | if(v->pcm){ |
371 | 930 | if(vi) |
372 | 94.2k | for(i=0;i<vi->channels;i++) |
373 | 93.2k | if(v->pcm[i])_ogg_free(v->pcm[i]); |
374 | 930 | _ogg_free(v->pcm); |
375 | 930 | if(v->pcmret)_ogg_free(v->pcmret); |
376 | 930 | } |
377 | | |
378 | 2.03k | if(b){ |
379 | | /* free header, header1, header2 */ |
380 | 986 | if(b->header)_ogg_free(b->header); |
381 | 986 | if(b->header1)_ogg_free(b->header1); |
382 | 986 | if(b->header2)_ogg_free(b->header2); |
383 | 986 | _ogg_free(b); |
384 | 986 | } |
385 | | |
386 | 2.03k | memset(v,0,sizeof(*v)); |
387 | 2.03k | } |
388 | 2.03k | } |
389 | | |
390 | 0 | float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){ |
391 | 0 | int i; |
392 | 0 | vorbis_info *vi=v->vi; |
393 | 0 | private_state *b=v->backend_state; |
394 | | |
395 | | /* free header, header1, header2 */ |
396 | 0 | if(b->header) { |
397 | 0 | _ogg_free(b->header); |
398 | 0 | b->header=NULL; |
399 | 0 | } |
400 | 0 | if(b->header1) { |
401 | 0 | _ogg_free(b->header1); |
402 | 0 | b->header1=NULL; |
403 | 0 | } |
404 | 0 | if(b->header2) { |
405 | 0 | _ogg_free(b->header2); |
406 | 0 | b->header2=NULL; |
407 | 0 | } |
408 | | |
409 | | /* Do we have enough storage space for the requested buffer? If not, |
410 | | expand the PCM (and envelope) storage */ |
411 | |
|
412 | 0 | if(v->pcm_current+vals>=v->pcm_storage){ |
413 | 0 | v->pcm_storage=v->pcm_current+vals*2; |
414 | |
|
415 | 0 | for(i=0;i<vi->channels;i++){ |
416 | 0 | v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i])); |
417 | 0 | } |
418 | 0 | } |
419 | |
|
420 | 0 | for(i=0;i<vi->channels;i++) |
421 | 0 | v->pcmret[i]=v->pcm[i]+v->pcm_current; |
422 | |
|
423 | 0 | return(v->pcmret); |
424 | 0 | } |
425 | | |
426 | 0 | static void _preextrapolate_helper(vorbis_dsp_state *v){ |
427 | 0 | int i; |
428 | 0 | int order=16; |
429 | 0 | float *lpc=alloca(order*sizeof(*lpc)); |
430 | 0 | float *work=alloca(v->pcm_current*sizeof(*work)); |
431 | 0 | long j; |
432 | 0 | v->preextrapolate=1; |
433 | |
|
434 | 0 | if(v->pcm_current-v->centerW>order*2){ /* safety */ |
435 | 0 | for(i=0;i<v->vi->channels;i++){ |
436 | | /* need to run the extrapolation in reverse! */ |
437 | 0 | for(j=0;j<v->pcm_current;j++) |
438 | 0 | work[j]=v->pcm[i][v->pcm_current-j-1]; |
439 | | |
440 | | /* prime as above */ |
441 | 0 | 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 | 0 | vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order, |
456 | 0 | order, |
457 | 0 | work+v->pcm_current-v->centerW, |
458 | 0 | v->centerW); |
459 | |
|
460 | 0 | for(j=0;j<v->pcm_current;j++) |
461 | 0 | v->pcm[i][v->pcm_current-j-1]=work[j]; |
462 | |
|
463 | 0 | } |
464 | 0 | } |
465 | 0 | } |
466 | | |
467 | | |
468 | | /* call with val<=0 to set eof */ |
469 | | |
470 | 0 | int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ |
471 | 0 | vorbis_info *vi=v->vi; |
472 | 0 | codec_setup_info *ci=vi->codec_setup; |
473 | |
|
474 | 0 | if(vals<=0){ |
475 | 0 | int order=32; |
476 | 0 | int i; |
477 | 0 | float *lpc=alloca(order*sizeof(*lpc)); |
478 | | |
479 | | /* if it wasn't done earlier (very short sample) */ |
480 | 0 | if(!v->preextrapolate) |
481 | 0 | _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 | 0 | vorbis_analysis_buffer(v,ci->blocksizes[1]*3); |
490 | 0 | v->eofflag=v->pcm_current; |
491 | 0 | v->pcm_current+=ci->blocksizes[1]*3; |
492 | |
|
493 | 0 | for(i=0;i<vi->channels;i++){ |
494 | 0 | if(v->eofflag>order*2){ |
495 | | /* extrapolate with LPC to fill in */ |
496 | 0 | long n; |
497 | | |
498 | | /* make a predictor filter */ |
499 | 0 | n=v->eofflag; |
500 | 0 | if(n>ci->blocksizes[1])n=ci->blocksizes[1]; |
501 | 0 | vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order); |
502 | | |
503 | | /* run the predictor filter */ |
504 | 0 | vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order, |
505 | 0 | v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag); |
506 | 0 | }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 | 0 | } |
515 | 0 | }else{ |
516 | |
|
517 | 0 | if(v->pcm_current+vals>v->pcm_storage) |
518 | 0 | return(OV_EINVAL); |
519 | | |
520 | 0 | 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 | 0 | if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) |
526 | 0 | _preextrapolate_helper(v); |
527 | |
|
528 | 0 | } |
529 | 0 | return(0); |
530 | 0 | } |
531 | | |
532 | | /* do the deltas, envelope shaping, pre-echo and determine the size of |
533 | | the next block on which to continue analysis */ |
534 | 0 | int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ |
535 | 0 | int i; |
536 | 0 | vorbis_info *vi=v->vi; |
537 | 0 | codec_setup_info *ci=vi->codec_setup; |
538 | 0 | private_state *b=v->backend_state; |
539 | 0 | vorbis_look_psy_global *g=b->psy_g_look; |
540 | 0 | long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext; |
541 | 0 | vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; |
542 | | |
543 | | /* check to see if we're started... */ |
544 | 0 | if(!v->preextrapolate)return(0); |
545 | | |
546 | | /* check to see if we're done... */ |
547 | 0 | 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 | 0 | { |
557 | 0 | long bp=_ve_envelope_search(v); |
558 | 0 | if(bp==-1){ |
559 | |
|
560 | 0 | if(v->eofflag==0)return(0); /* not enough data currently to search for a |
561 | | full long block */ |
562 | 0 | v->nW=0; |
563 | 0 | }else{ |
564 | |
|
565 | 0 | if(ci->blocksizes[0]==ci->blocksizes[1]) |
566 | 0 | v->nW=0; |
567 | 0 | else |
568 | 0 | v->nW=bp; |
569 | 0 | } |
570 | 0 | } |
571 | | |
572 | 0 | centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4; |
573 | |
|
574 | 0 | { |
575 | | /* center of next block + next block maximum right side. */ |
576 | |
|
577 | 0 | long blockbound=centerNext+ci->blocksizes[v->nW]/2; |
578 | 0 | 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 | 0 | } |
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 | 0 | _vorbis_block_ripcord(vb); |
593 | 0 | vb->lW=v->lW; |
594 | 0 | vb->W=v->W; |
595 | 0 | vb->nW=v->nW; |
596 | |
|
597 | 0 | if(v->W){ |
598 | 0 | if(!v->lW || !v->nW){ |
599 | 0 | vbi->blocktype=BLOCKTYPE_TRANSITION; |
600 | | /*fprintf(stderr,"-");*/ |
601 | 0 | }else{ |
602 | 0 | vbi->blocktype=BLOCKTYPE_LONG; |
603 | | /*fprintf(stderr,"_");*/ |
604 | 0 | } |
605 | 0 | }else{ |
606 | 0 | if(_ve_envelope_mark(v)){ |
607 | 0 | vbi->blocktype=BLOCKTYPE_IMPULSE; |
608 | | /*fprintf(stderr,"|");*/ |
609 | |
|
610 | 0 | }else{ |
611 | 0 | vbi->blocktype=BLOCKTYPE_PADDING; |
612 | | /*fprintf(stderr,".");*/ |
613 | |
|
614 | 0 | } |
615 | 0 | } |
616 | |
|
617 | 0 | vb->vd=v; |
618 | 0 | vb->sequence=v->sequence++; |
619 | 0 | vb->granulepos=v->granulepos; |
620 | 0 | 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 | 0 | if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax; |
627 | 0 | g->ampmax=_vp_ampmax_decay(g->ampmax,v); |
628 | 0 | vbi->ampmax=g->ampmax; |
629 | |
|
630 | 0 | vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); |
631 | 0 | vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels); |
632 | 0 | for(i=0;i<vi->channels;i++){ |
633 | 0 | vbi->pcmdelay[i]= |
634 | 0 | _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); |
635 | 0 | memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); |
636 | 0 | 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 | 0 | } |
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 | 0 | if(v->eofflag){ |
650 | 0 | if(v->centerW>=v->eofflag){ |
651 | 0 | v->eofflag=-1; |
652 | 0 | vb->eofflag=1; |
653 | 0 | return(1); |
654 | 0 | } |
655 | 0 | } |
656 | | |
657 | | /* advance storage vectors and clean up */ |
658 | 0 | { |
659 | 0 | int new_centerNext=ci->blocksizes[1]/2; |
660 | 0 | int movementW=centerNext-new_centerNext; |
661 | |
|
662 | 0 | if(movementW>0){ |
663 | |
|
664 | 0 | _ve_envelope_shift(b->ve,movementW); |
665 | 0 | v->pcm_current-=movementW; |
666 | |
|
667 | 0 | for(i=0;i<vi->channels;i++) |
668 | 0 | memmove(v->pcm[i],v->pcm[i]+movementW, |
669 | 0 | v->pcm_current*sizeof(*v->pcm[i])); |
670 | | |
671 | |
|
672 | 0 | v->lW=v->W; |
673 | 0 | v->W=v->nW; |
674 | 0 | v->centerW=new_centerNext; |
675 | |
|
676 | 0 | if(v->eofflag){ |
677 | 0 | v->eofflag-=movementW; |
678 | 0 | if(v->eofflag<=0)v->eofflag=-1; |
679 | | /* do not add padding to end of stream! */ |
680 | 0 | if(v->centerW>=v->eofflag){ |
681 | 0 | v->granulepos+=movementW-(v->centerW-v->eofflag); |
682 | 0 | }else{ |
683 | 0 | v->granulepos+=movementW; |
684 | 0 | } |
685 | 0 | }else{ |
686 | 0 | v->granulepos+=movementW; |
687 | 0 | } |
688 | 0 | } |
689 | 0 | } |
690 | | |
691 | | /* done */ |
692 | 0 | return(1); |
693 | 0 | } |
694 | | |
695 | 930 | int vorbis_synthesis_restart(vorbis_dsp_state *v){ |
696 | 930 | vorbis_info *vi=v->vi; |
697 | 930 | codec_setup_info *ci; |
698 | 930 | int hs; |
699 | | |
700 | 930 | if(!v->backend_state)return -1; |
701 | 930 | if(!vi)return -1; |
702 | 930 | ci=vi->codec_setup; |
703 | 930 | if(!ci)return -1; |
704 | 930 | hs=ci->halfrate_flag; |
705 | | |
706 | 930 | v->centerW=ci->blocksizes[1]>>(hs+1); |
707 | 930 | v->pcm_current=v->centerW>>hs; |
708 | | |
709 | 930 | v->pcm_returned=-1; |
710 | 930 | v->granulepos=-1; |
711 | 930 | v->sequence=-1; |
712 | 930 | v->eofflag=0; |
713 | 930 | ((private_state *)(v->backend_state))->sample_count=-1; |
714 | | |
715 | 930 | return(0); |
716 | 930 | } |
717 | | |
718 | 986 | int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){ |
719 | 986 | if(_vds_shared_init(v,vi,0)){ |
720 | 56 | vorbis_dsp_clear(v); |
721 | 56 | return 1; |
722 | 56 | } |
723 | 930 | vorbis_synthesis_restart(v); |
724 | 930 | return 0; |
725 | 986 | } |
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 | 122k | int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){ |
732 | 122k | vorbis_info *vi=v->vi; |
733 | 122k | codec_setup_info *ci=vi->codec_setup; |
734 | 122k | private_state *b=v->backend_state; |
735 | 122k | int hs=ci->halfrate_flag; |
736 | 122k | int i,j; |
737 | | |
738 | 122k | if(!vb)return(OV_EINVAL); |
739 | 122k | if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL); |
740 | | |
741 | 122k | v->lW=v->W; |
742 | 122k | v->W=vb->W; |
743 | 122k | v->nW=-1; |
744 | | |
745 | 122k | if((v->sequence==-1)|| |
746 | 122k | (v->sequence+1 != vb->sequence)){ |
747 | 122k | v->granulepos=-1; /* out of sequence; lose count */ |
748 | 122k | b->sample_count=-1; |
749 | 122k | } |
750 | | |
751 | 122k | v->sequence=vb->sequence; |
752 | | |
753 | 122k | if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly |
754 | | was called on block */ |
755 | 122k | int n=ci->blocksizes[v->W]>>(hs+1); |
756 | 122k | int n0=ci->blocksizes[0]>>(hs+1); |
757 | 122k | int n1=ci->blocksizes[1]>>(hs+1); |
758 | | |
759 | 122k | int thisCenter; |
760 | 122k | int prevCenter; |
761 | | |
762 | 122k | v->glue_bits+=vb->glue_bits; |
763 | 122k | v->time_bits+=vb->time_bits; |
764 | 122k | v->floor_bits+=vb->floor_bits; |
765 | 122k | v->res_bits+=vb->res_bits; |
766 | | |
767 | 122k | if(v->centerW){ |
768 | 61.5k | thisCenter=n1; |
769 | 61.5k | prevCenter=0; |
770 | 61.5k | }else{ |
771 | 61.1k | thisCenter=0; |
772 | 61.1k | prevCenter=n1; |
773 | 61.1k | } |
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 | 2.77M | for(j=0;j<vi->channels;j++){ |
780 | | /* the overlap/add section */ |
781 | 2.64M | if(v->lW){ |
782 | 54.5k | if(v->W){ |
783 | | /* large/large */ |
784 | 49.6k | const float *w=_vorbis_window_get(b->window[1]-hs); |
785 | 49.6k | float *pcm=v->pcm[j]+prevCenter; |
786 | 49.6k | float *p=vb->pcm[j]; |
787 | 169M | for(i=0;i<n1;i++) |
788 | 169M | pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i]; |
789 | 49.6k | }else{ |
790 | | /* large/small */ |
791 | 4.86k | const float *w=_vorbis_window_get(b->window[0]-hs); |
792 | 4.86k | float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2; |
793 | 4.86k | float *p=vb->pcm[j]; |
794 | 315k | for(i=0;i<n0;i++) |
795 | 311k | pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; |
796 | 4.86k | } |
797 | 2.59M | }else{ |
798 | 2.59M | if(v->W){ |
799 | | /* small/large */ |
800 | 11.1k | const float *w=_vorbis_window_get(b->window[0]-hs); |
801 | 11.1k | float *pcm=v->pcm[j]+prevCenter; |
802 | 11.1k | float *p=vb->pcm[j]+n1/2-n0/2; |
803 | 2.53M | for(i=0;i<n0;i++) |
804 | 2.51M | pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; |
805 | 18.5M | for(;i<n1/2+n0/2;i++) |
806 | 18.5M | pcm[i]=p[i]; |
807 | 2.58M | }else{ |
808 | | /* small/small */ |
809 | 2.58M | const float *w=_vorbis_window_get(b->window[0]-hs); |
810 | 2.58M | float *pcm=v->pcm[j]+prevCenter; |
811 | 2.58M | float *p=vb->pcm[j]; |
812 | 336M | for(i=0;i<n0;i++) |
813 | 334M | pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i]; |
814 | 2.58M | } |
815 | 2.59M | } |
816 | | |
817 | | /* the copy section */ |
818 | 2.64M | { |
819 | 2.64M | float *pcm=v->pcm[j]+thisCenter; |
820 | 2.64M | float *p=vb->pcm[j]+n; |
821 | 546M | for(i=0;i<n;i++) |
822 | 543M | pcm[i]=p[i]; |
823 | 2.64M | } |
824 | 2.64M | } |
825 | | |
826 | 122k | if(v->centerW) |
827 | 61.5k | v->centerW=0; |
828 | 61.1k | else |
829 | 61.1k | 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 | 122k | if(v->pcm_returned==-1){ |
836 | 900 | v->pcm_returned=thisCenter; |
837 | 900 | v->pcm_current=thisCenter; |
838 | 121k | }else{ |
839 | 121k | v->pcm_returned=prevCenter; |
840 | 121k | v->pcm_current=prevCenter+ |
841 | 121k | ((ci->blocksizes[v->lW]/4+ |
842 | 121k | ci->blocksizes[v->W]/4)>>hs); |
843 | 121k | } |
844 | | |
845 | 122k | } |
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 | 122k | if(b->sample_count==-1){ |
859 | 122k | b->sample_count=0; |
860 | 122k | }else{ |
861 | 0 | b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; |
862 | 0 | } |
863 | | |
864 | 122k | if(v->granulepos==-1){ |
865 | 122k | if(vb->granulepos!=-1){ /* only set if we have a position to set to */ |
866 | | |
867 | 122k | v->granulepos=vb->granulepos; |
868 | | |
869 | | /* is this a short page? */ |
870 | 122k | 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 | 0 | 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 | 0 | if(extra<0) |
880 | 0 | extra=0; |
881 | |
|
882 | 0 | 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 | 0 | if(extra > (v->pcm_current - v->pcm_returned)<<hs) |
893 | 0 | extra = (v->pcm_current - v->pcm_returned)<<hs; |
894 | |
|
895 | 0 | v->pcm_current-=extra>>hs; |
896 | 0 | }else{ |
897 | | /* trim the beginning */ |
898 | 0 | v->pcm_returned+=extra>>hs; |
899 | 0 | if(v->pcm_returned>v->pcm_current) |
900 | 0 | v->pcm_returned=v->pcm_current; |
901 | 0 | } |
902 | |
|
903 | 0 | } |
904 | | |
905 | 122k | } |
906 | 122k | }else{ |
907 | 0 | v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4; |
908 | 0 | if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){ |
909 | |
|
910 | 0 | if(v->granulepos>vb->granulepos){ |
911 | 0 | long extra=v->granulepos-vb->granulepos; |
912 | |
|
913 | 0 | if(extra) |
914 | 0 | 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 | 0 | if(extra > (v->pcm_current - v->pcm_returned)<<hs) |
921 | 0 | 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 | 0 | if(extra<0) |
928 | 0 | extra=0; |
929 | |
|
930 | 0 | v->pcm_current-=extra>>hs; |
931 | 0 | } /* else {Shouldn't happen *unless* the bitstream is out of |
932 | | spec. Either way, believe the bitstream } */ |
933 | 0 | } /* else {Shouldn't happen *unless* the bitstream is out of |
934 | | spec. Either way, believe the bitstream } */ |
935 | 0 | v->granulepos=vb->granulepos; |
936 | 0 | } |
937 | 0 | } |
938 | | |
939 | | /* Update, cleanup */ |
940 | | |
941 | 122k | if(vb->eofflag)v->eofflag=1; |
942 | 122k | return(0); |
943 | | |
944 | 122k | } |
945 | | |
946 | | /* pcm==NULL indicates we just want the pending samples, no more */ |
947 | 253k | int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){ |
948 | 253k | vorbis_info *vi=v->vi; |
949 | | |
950 | 253k | if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){ |
951 | 121k | if(pcm){ |
952 | 121k | int i; |
953 | 2.67M | for(i=0;i<vi->channels;i++) |
954 | 2.55M | v->pcmret[i]=v->pcm[i]+v->pcm_returned; |
955 | 121k | *pcm=v->pcmret; |
956 | 121k | } |
957 | 121k | return(v->pcm_current-v->pcm_returned); |
958 | 121k | } |
959 | 131k | return(0); |
960 | 253k | } |
961 | | |
962 | 121k | int vorbis_synthesis_read(vorbis_dsp_state *v,int n){ |
963 | 121k | if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL); |
964 | 121k | v->pcm_returned+=n; |
965 | 121k | return(0); |
966 | 121k | } |
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 | } |