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