annotate src/libvorbis-1.3.3/lib/block.c @ 169:223a55898ab9 tip default

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