vrshoot

diff libs/vorbis/block.c @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/vorbis/block.c	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,1046 @@
     1.4 +/********************************************************************
     1.5 + *                                                                  *
     1.6 + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
     1.7 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
     1.8 + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
     1.9 + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
    1.10 + *                                                                  *
    1.11 + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
    1.12 + * by the Xiph.Org Foundation http://www.xiph.org/                  *
    1.13 + *                                                                  *
    1.14 + ********************************************************************
    1.15 +
    1.16 + function: PCM data vector blocking, windowing and dis/reassembly
    1.17 + last mod: $Id: block.c 17561 2010-10-23 10:34:24Z xiphmont $
    1.18 +
    1.19 + Handle windowing, overlap-add, etc of the PCM vectors.  This is made
    1.20 + more amusing by Vorbis' current two allowed block sizes.
    1.21 +
    1.22 + ********************************************************************/
    1.23 +
    1.24 +#include <stdio.h>
    1.25 +#include <stdlib.h>
    1.26 +#include <string.h>
    1.27 +#include <ogg/ogg.h>
    1.28 +#include "vorbis/codec.h"
    1.29 +#include "codec_internal.h"
    1.30 +
    1.31 +#include "window.h"
    1.32 +#include "mdct.h"
    1.33 +#include "lpc.h"
    1.34 +#include "registry.h"
    1.35 +#include "misc.h"
    1.36 +
    1.37 +static int ilog2(unsigned int v){
    1.38 +  int ret=0;
    1.39 +  if(v)--v;
    1.40 +  while(v){
    1.41 +    ret++;
    1.42 +    v>>=1;
    1.43 +  }
    1.44 +  return(ret);
    1.45 +}
    1.46 +
    1.47 +/* pcm accumulator examples (not exhaustive):
    1.48 +
    1.49 + <-------------- lW ---------------->
    1.50 +                   <--------------- W ---------------->
    1.51 +:            .....|.....       _______________         |
    1.52 +:        .'''     |     '''_---      |       |\        |
    1.53 +:.....'''         |_____--- '''......|       | \_______|
    1.54 +:.................|__________________|_______|__|______|
    1.55 +                  |<------ Sl ------>|      > Sr <     |endW
    1.56 +                  |beginSl           |endSl  |  |endSr
    1.57 +                  |beginW            |endlW  |beginSr
    1.58 +
    1.59 +
    1.60 +                      |< lW >|
    1.61 +                   <--------------- W ---------------->
    1.62 +                  |   |  ..  ______________            |
    1.63 +                  |   | '  `/        |     ---_        |
    1.64 +                  |___.'___/`.       |         ---_____|
    1.65 +                  |_______|__|_______|_________________|
    1.66 +                  |      >|Sl|<      |<------ Sr ----->|endW
    1.67 +                  |       |  |endSl  |beginSr          |endSr
    1.68 +                  |beginW |  |endlW
    1.69 +                  mult[0] |beginSl                     mult[n]
    1.70 +
    1.71 + <-------------- lW ----------------->
    1.72 +                          |<--W-->|
    1.73 +:            ..............  ___  |   |
    1.74 +:        .'''             |`/   \ |   |
    1.75 +:.....'''                 |/`....\|...|
    1.76 +:.........................|___|___|___|
    1.77 +                          |Sl |Sr |endW
    1.78 +                          |   |   |endSr
    1.79 +                          |   |beginSr
    1.80 +                          |   |endSl
    1.81 +                          |beginSl
    1.82 +                          |beginW
    1.83 +*/
    1.84 +
    1.85 +/* block abstraction setup *********************************************/
    1.86 +
    1.87 +#ifndef WORD_ALIGN
    1.88 +#define WORD_ALIGN 8
    1.89 +#endif
    1.90 +
    1.91 +int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
    1.92 +  int i;
    1.93 +  memset(vb,0,sizeof(*vb));
    1.94 +  vb->vd=v;
    1.95 +  vb->localalloc=0;
    1.96 +  vb->localstore=NULL;
    1.97 +  if(v->analysisp){
    1.98 +    vorbis_block_internal *vbi=
    1.99 +      vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
   1.100 +    vbi->ampmax=-9999;
   1.101 +
   1.102 +    for(i=0;i<PACKETBLOBS;i++){
   1.103 +      if(i==PACKETBLOBS/2){
   1.104 +        vbi->packetblob[i]=&vb->opb;
   1.105 +      }else{
   1.106 +        vbi->packetblob[i]=
   1.107 +          _ogg_calloc(1,sizeof(oggpack_buffer));
   1.108 +      }
   1.109 +      oggpack_writeinit(vbi->packetblob[i]);
   1.110 +    }
   1.111 +  }
   1.112 +
   1.113 +  return(0);
   1.114 +}
   1.115 +
   1.116 +void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
   1.117 +  bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
   1.118 +  if(bytes+vb->localtop>vb->localalloc){
   1.119 +    /* can't just _ogg_realloc... there are outstanding pointers */
   1.120 +    if(vb->localstore){
   1.121 +      struct alloc_chain *link=_ogg_malloc(sizeof(*link));
   1.122 +      vb->totaluse+=vb->localtop;
   1.123 +      link->next=vb->reap;
   1.124 +      link->ptr=vb->localstore;
   1.125 +      vb->reap=link;
   1.126 +    }
   1.127 +    /* highly conservative */
   1.128 +    vb->localalloc=bytes;
   1.129 +    vb->localstore=_ogg_malloc(vb->localalloc);
   1.130 +    vb->localtop=0;
   1.131 +  }
   1.132 +  {
   1.133 +    void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
   1.134 +    vb->localtop+=bytes;
   1.135 +    return ret;
   1.136 +  }
   1.137 +}
   1.138 +
   1.139 +/* reap the chain, pull the ripcord */
   1.140 +void _vorbis_block_ripcord(vorbis_block *vb){
   1.141 +  /* reap the chain */
   1.142 +  struct alloc_chain *reap=vb->reap;
   1.143 +  while(reap){
   1.144 +    struct alloc_chain *next=reap->next;
   1.145 +    _ogg_free(reap->ptr);
   1.146 +    memset(reap,0,sizeof(*reap));
   1.147 +    _ogg_free(reap);
   1.148 +    reap=next;
   1.149 +  }
   1.150 +  /* consolidate storage */
   1.151 +  if(vb->totaluse){
   1.152 +    vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
   1.153 +    vb->localalloc+=vb->totaluse;
   1.154 +    vb->totaluse=0;
   1.155 +  }
   1.156 +
   1.157 +  /* pull the ripcord */
   1.158 +  vb->localtop=0;
   1.159 +  vb->reap=NULL;
   1.160 +}
   1.161 +
   1.162 +int vorbis_block_clear(vorbis_block *vb){
   1.163 +  int i;
   1.164 +  vorbis_block_internal *vbi=vb->internal;
   1.165 +
   1.166 +  _vorbis_block_ripcord(vb);
   1.167 +  if(vb->localstore)_ogg_free(vb->localstore);
   1.168 +
   1.169 +  if(vbi){
   1.170 +    for(i=0;i<PACKETBLOBS;i++){
   1.171 +      oggpack_writeclear(vbi->packetblob[i]);
   1.172 +      if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]);
   1.173 +    }
   1.174 +    _ogg_free(vbi);
   1.175 +  }
   1.176 +  memset(vb,0,sizeof(*vb));
   1.177 +  return(0);
   1.178 +}
   1.179 +
   1.180 +/* Analysis side code, but directly related to blocking.  Thus it's
   1.181 +   here and not in analysis.c (which is for analysis transforms only).
   1.182 +   The init is here because some of it is shared */
   1.183 +
   1.184 +static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){
   1.185 +  int i;
   1.186 +  codec_setup_info *ci=vi->codec_setup;
   1.187 +  private_state *b=NULL;
   1.188 +  int hs;
   1.189 +
   1.190 +  if(ci==NULL) return 1;
   1.191 +  hs=ci->halfrate_flag;
   1.192 +
   1.193 +  memset(v,0,sizeof(*v));
   1.194 +  b=v->backend_state=_ogg_calloc(1,sizeof(*b));
   1.195 +
   1.196 +  v->vi=vi;
   1.197 +  b->modebits=ilog2(ci->modes);
   1.198 +
   1.199 +  b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0]));
   1.200 +  b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1]));
   1.201 +
   1.202 +  /* MDCT is tranform 0 */
   1.203 +
   1.204 +  b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup));
   1.205 +  b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup));
   1.206 +  mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs);
   1.207 +  mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs);
   1.208 +
   1.209 +  /* Vorbis I uses only window type 0 */
   1.210 +  b->window[0]=ilog2(ci->blocksizes[0])-6;
   1.211 +  b->window[1]=ilog2(ci->blocksizes[1])-6;
   1.212 +
   1.213 +  if(encp){ /* encode/decode differ here */
   1.214 +
   1.215 +    /* analysis always needs an fft */
   1.216 +    drft_init(&b->fft_look[0],ci->blocksizes[0]);
   1.217 +    drft_init(&b->fft_look[1],ci->blocksizes[1]);
   1.218 +
   1.219 +    /* finish the codebooks */
   1.220 +    if(!ci->fullbooks){
   1.221 +      ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
   1.222 +      for(i=0;i<ci->books;i++)
   1.223 +        vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]);
   1.224 +    }
   1.225 +
   1.226 +    b->psy=_ogg_calloc(ci->psys,sizeof(*b->psy));
   1.227 +    for(i=0;i<ci->psys;i++){
   1.228 +      _vp_psy_init(b->psy+i,
   1.229 +                   ci->psy_param[i],
   1.230 +                   &ci->psy_g_param,
   1.231 +                   ci->blocksizes[ci->psy_param[i]->blockflag]/2,
   1.232 +                   vi->rate);
   1.233 +    }
   1.234 +
   1.235 +    v->analysisp=1;
   1.236 +  }else{
   1.237 +    /* finish the codebooks */
   1.238 +    if(!ci->fullbooks){
   1.239 +      ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
   1.240 +      for(i=0;i<ci->books;i++){
   1.241 +        if(ci->book_param[i]==NULL)
   1.242 +          goto abort_books;
   1.243 +        if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]))
   1.244 +          goto abort_books;
   1.245 +        /* decode codebooks are now standalone after init */
   1.246 +        vorbis_staticbook_destroy(ci->book_param[i]);
   1.247 +        ci->book_param[i]=NULL;
   1.248 +      }
   1.249 +    }
   1.250 +  }
   1.251 +
   1.252 +  /* initialize the storage vectors. blocksize[1] is small for encode,
   1.253 +     but the correct size for decode */
   1.254 +  v->pcm_storage=ci->blocksizes[1];
   1.255 +  v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm));
   1.256 +  v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret));
   1.257 +  {
   1.258 +    int i;
   1.259 +    for(i=0;i<vi->channels;i++)
   1.260 +      v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
   1.261 +  }
   1.262 +
   1.263 +  /* all 1 (large block) or 0 (small block) */
   1.264 +  /* explicitly set for the sake of clarity */
   1.265 +  v->lW=0; /* previous window size */
   1.266 +  v->W=0;  /* current window size */
   1.267 +
   1.268 +  /* all vector indexes */
   1.269 +  v->centerW=ci->blocksizes[1]/2;
   1.270 +
   1.271 +  v->pcm_current=v->centerW;
   1.272 +
   1.273 +  /* initialize all the backend lookups */
   1.274 +  b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr));
   1.275 +  b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue));
   1.276 +
   1.277 +  for(i=0;i<ci->floors;i++)
   1.278 +    b->flr[i]=_floor_P[ci->floor_type[i]]->
   1.279 +      look(v,ci->floor_param[i]);
   1.280 +
   1.281 +  for(i=0;i<ci->residues;i++)
   1.282 +    b->residue[i]=_residue_P[ci->residue_type[i]]->
   1.283 +      look(v,ci->residue_param[i]);
   1.284 +
   1.285 +  return 0;
   1.286 + abort_books:
   1.287 +  for(i=0;i<ci->books;i++){
   1.288 +    if(ci->book_param[i]!=NULL){
   1.289 +      vorbis_staticbook_destroy(ci->book_param[i]);
   1.290 +      ci->book_param[i]=NULL;
   1.291 +    }
   1.292 +  }
   1.293 +  vorbis_dsp_clear(v);
   1.294 +  return -1;
   1.295 +}
   1.296 +
   1.297 +/* arbitrary settings and spec-mandated numbers get filled in here */
   1.298 +int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
   1.299 +  private_state *b=NULL;
   1.300 +
   1.301 +  if(_vds_shared_init(v,vi,1))return 1;
   1.302 +  b=v->backend_state;
   1.303 +  b->psy_g_look=_vp_global_look(vi);
   1.304 +
   1.305 +  /* Initialize the envelope state storage */
   1.306 +  b->ve=_ogg_calloc(1,sizeof(*b->ve));
   1.307 +  _ve_envelope_init(b->ve,vi);
   1.308 +
   1.309 +  vorbis_bitrate_init(vi,&b->bms);
   1.310 +
   1.311 +  /* compressed audio packets start after the headers
   1.312 +     with sequence number 3 */
   1.313 +  v->sequence=3;
   1.314 +
   1.315 +  return(0);
   1.316 +}
   1.317 +
   1.318 +void vorbis_dsp_clear(vorbis_dsp_state *v){
   1.319 +  int i;
   1.320 +  if(v){
   1.321 +    vorbis_info *vi=v->vi;
   1.322 +    codec_setup_info *ci=(vi?vi->codec_setup:NULL);
   1.323 +    private_state *b=v->backend_state;
   1.324 +
   1.325 +    if(b){
   1.326 +
   1.327 +      if(b->ve){
   1.328 +        _ve_envelope_clear(b->ve);
   1.329 +        _ogg_free(b->ve);
   1.330 +      }
   1.331 +
   1.332 +      if(b->transform[0]){
   1.333 +        mdct_clear(b->transform[0][0]);
   1.334 +        _ogg_free(b->transform[0][0]);
   1.335 +        _ogg_free(b->transform[0]);
   1.336 +      }
   1.337 +      if(b->transform[1]){
   1.338 +        mdct_clear(b->transform[1][0]);
   1.339 +        _ogg_free(b->transform[1][0]);
   1.340 +        _ogg_free(b->transform[1]);
   1.341 +      }
   1.342 +
   1.343 +      if(b->flr){
   1.344 +        if(ci)
   1.345 +          for(i=0;i<ci->floors;i++)
   1.346 +            _floor_P[ci->floor_type[i]]->
   1.347 +              free_look(b->flr[i]);
   1.348 +        _ogg_free(b->flr);
   1.349 +      }
   1.350 +      if(b->residue){
   1.351 +        if(ci)
   1.352 +          for(i=0;i<ci->residues;i++)
   1.353 +            _residue_P[ci->residue_type[i]]->
   1.354 +              free_look(b->residue[i]);
   1.355 +        _ogg_free(b->residue);
   1.356 +      }
   1.357 +      if(b->psy){
   1.358 +        if(ci)
   1.359 +          for(i=0;i<ci->psys;i++)
   1.360 +            _vp_psy_clear(b->psy+i);
   1.361 +        _ogg_free(b->psy);
   1.362 +      }
   1.363 +
   1.364 +      if(b->psy_g_look)_vp_global_free(b->psy_g_look);
   1.365 +      vorbis_bitrate_clear(&b->bms);
   1.366 +
   1.367 +      drft_clear(&b->fft_look[0]);
   1.368 +      drft_clear(&b->fft_look[1]);
   1.369 +
   1.370 +    }
   1.371 +
   1.372 +    if(v->pcm){
   1.373 +      if(vi)
   1.374 +        for(i=0;i<vi->channels;i++)
   1.375 +          if(v->pcm[i])_ogg_free(v->pcm[i]);
   1.376 +      _ogg_free(v->pcm);
   1.377 +      if(v->pcmret)_ogg_free(v->pcmret);
   1.378 +    }
   1.379 +
   1.380 +    if(b){
   1.381 +      /* free header, header1, header2 */
   1.382 +      if(b->header)_ogg_free(b->header);
   1.383 +      if(b->header1)_ogg_free(b->header1);
   1.384 +      if(b->header2)_ogg_free(b->header2);
   1.385 +      _ogg_free(b);
   1.386 +    }
   1.387 +
   1.388 +    memset(v,0,sizeof(*v));
   1.389 +  }
   1.390 +}
   1.391 +
   1.392 +float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){
   1.393 +  int i;
   1.394 +  vorbis_info *vi=v->vi;
   1.395 +  private_state *b=v->backend_state;
   1.396 +
   1.397 +  /* free header, header1, header2 */
   1.398 +  if(b->header)_ogg_free(b->header);b->header=NULL;
   1.399 +  if(b->header1)_ogg_free(b->header1);b->header1=NULL;
   1.400 +  if(b->header2)_ogg_free(b->header2);b->header2=NULL;
   1.401 +
   1.402 +  /* Do we have enough storage space for the requested buffer? If not,
   1.403 +     expand the PCM (and envelope) storage */
   1.404 +
   1.405 +  if(v->pcm_current+vals>=v->pcm_storage){
   1.406 +    v->pcm_storage=v->pcm_current+vals*2;
   1.407 +
   1.408 +    for(i=0;i<vi->channels;i++){
   1.409 +      v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i]));
   1.410 +    }
   1.411 +  }
   1.412 +
   1.413 +  for(i=0;i<vi->channels;i++)
   1.414 +    v->pcmret[i]=v->pcm[i]+v->pcm_current;
   1.415 +
   1.416 +  return(v->pcmret);
   1.417 +}
   1.418 +
   1.419 +static void _preextrapolate_helper(vorbis_dsp_state *v){
   1.420 +  int i;
   1.421 +  int order=16;
   1.422 +  float *lpc=alloca(order*sizeof(*lpc));
   1.423 +  float *work=alloca(v->pcm_current*sizeof(*work));
   1.424 +  long j;
   1.425 +  v->preextrapolate=1;
   1.426 +
   1.427 +  if(v->pcm_current-v->centerW>order*2){ /* safety */
   1.428 +    for(i=0;i<v->vi->channels;i++){
   1.429 +      /* need to run the extrapolation in reverse! */
   1.430 +      for(j=0;j<v->pcm_current;j++)
   1.431 +        work[j]=v->pcm[i][v->pcm_current-j-1];
   1.432 +
   1.433 +      /* prime as above */
   1.434 +      vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order);
   1.435 +
   1.436 +#if 0
   1.437 +      if(v->vi->channels==2){
   1.438 +        if(i==0)
   1.439 +          _analysis_output("predataL",0,work,v->pcm_current-v->centerW,0,0,0);
   1.440 +        else
   1.441 +          _analysis_output("predataR",0,work,v->pcm_current-v->centerW,0,0,0);
   1.442 +      }else{
   1.443 +        _analysis_output("predata",0,work,v->pcm_current-v->centerW,0,0,0);
   1.444 +      }
   1.445 +#endif
   1.446 +
   1.447 +      /* run the predictor filter */
   1.448 +      vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order,
   1.449 +                         order,
   1.450 +                         work+v->pcm_current-v->centerW,
   1.451 +                         v->centerW);
   1.452 +
   1.453 +      for(j=0;j<v->pcm_current;j++)
   1.454 +        v->pcm[i][v->pcm_current-j-1]=work[j];
   1.455 +
   1.456 +    }
   1.457 +  }
   1.458 +}
   1.459 +
   1.460 +
   1.461 +/* call with val<=0 to set eof */
   1.462 +
   1.463 +int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
   1.464 +  vorbis_info *vi=v->vi;
   1.465 +  codec_setup_info *ci=vi->codec_setup;
   1.466 +
   1.467 +  if(vals<=0){
   1.468 +    int order=32;
   1.469 +    int i;
   1.470 +    float *lpc=alloca(order*sizeof(*lpc));
   1.471 +
   1.472 +    /* if it wasn't done earlier (very short sample) */
   1.473 +    if(!v->preextrapolate)
   1.474 +      _preextrapolate_helper(v);
   1.475 +
   1.476 +    /* We're encoding the end of the stream.  Just make sure we have
   1.477 +       [at least] a few full blocks of zeroes at the end. */
   1.478 +    /* actually, we don't want zeroes; that could drop a large
   1.479 +       amplitude off a cliff, creating spread spectrum noise that will
   1.480 +       suck to encode.  Extrapolate for the sake of cleanliness. */
   1.481 +
   1.482 +    vorbis_analysis_buffer(v,ci->blocksizes[1]*3);
   1.483 +    v->eofflag=v->pcm_current;
   1.484 +    v->pcm_current+=ci->blocksizes[1]*3;
   1.485 +
   1.486 +    for(i=0;i<vi->channels;i++){
   1.487 +      if(v->eofflag>order*2){
   1.488 +        /* extrapolate with LPC to fill in */
   1.489 +        long n;
   1.490 +
   1.491 +        /* make a predictor filter */
   1.492 +        n=v->eofflag;
   1.493 +        if(n>ci->blocksizes[1])n=ci->blocksizes[1];
   1.494 +        vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order);
   1.495 +
   1.496 +        /* run the predictor filter */
   1.497 +        vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order,
   1.498 +                           v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag);
   1.499 +      }else{
   1.500 +        /* not enough data to extrapolate (unlikely to happen due to
   1.501 +           guarding the overlap, but bulletproof in case that
   1.502 +           assumtion goes away). zeroes will do. */
   1.503 +        memset(v->pcm[i]+v->eofflag,0,
   1.504 +               (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i]));
   1.505 +
   1.506 +      }
   1.507 +    }
   1.508 +  }else{
   1.509 +
   1.510 +    if(v->pcm_current+vals>v->pcm_storage)
   1.511 +      return(OV_EINVAL);
   1.512 +
   1.513 +    v->pcm_current+=vals;
   1.514 +
   1.515 +    /* we may want to reverse extrapolate the beginning of a stream
   1.516 +       too... in case we're beginning on a cliff! */
   1.517 +    /* clumsy, but simple.  It only runs once, so simple is good. */
   1.518 +    if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1])
   1.519 +      _preextrapolate_helper(v);
   1.520 +
   1.521 +  }
   1.522 +  return(0);
   1.523 +}
   1.524 +
   1.525 +/* do the deltas, envelope shaping, pre-echo and determine the size of
   1.526 +   the next block on which to continue analysis */
   1.527 +int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
   1.528 +  int i;
   1.529 +  vorbis_info *vi=v->vi;
   1.530 +  codec_setup_info *ci=vi->codec_setup;
   1.531 +  private_state *b=v->backend_state;
   1.532 +  vorbis_look_psy_global *g=b->psy_g_look;
   1.533 +  long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext;
   1.534 +  vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
   1.535 +
   1.536 +  /* check to see if we're started... */
   1.537 +  if(!v->preextrapolate)return(0);
   1.538 +
   1.539 +  /* check to see if we're done... */
   1.540 +  if(v->eofflag==-1)return(0);
   1.541 +
   1.542 +  /* By our invariant, we have lW, W and centerW set.  Search for
   1.543 +     the next boundary so we can determine nW (the next window size)
   1.544 +     which lets us compute the shape of the current block's window */
   1.545 +
   1.546 +  /* we do an envelope search even on a single blocksize; we may still
   1.547 +     be throwing more bits at impulses, and envelope search handles
   1.548 +     marking impulses too. */
   1.549 +  {
   1.550 +    long bp=_ve_envelope_search(v);
   1.551 +    if(bp==-1){
   1.552 +
   1.553 +      if(v->eofflag==0)return(0); /* not enough data currently to search for a
   1.554 +                                     full long block */
   1.555 +      v->nW=0;
   1.556 +    }else{
   1.557 +
   1.558 +      if(ci->blocksizes[0]==ci->blocksizes[1])
   1.559 +        v->nW=0;
   1.560 +      else
   1.561 +        v->nW=bp;
   1.562 +    }
   1.563 +  }
   1.564 +
   1.565 +  centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4;
   1.566 +
   1.567 +  {
   1.568 +    /* center of next block + next block maximum right side. */
   1.569 +
   1.570 +    long blockbound=centerNext+ci->blocksizes[v->nW]/2;
   1.571 +    if(v->pcm_current<blockbound)return(0); /* not enough data yet;
   1.572 +                                               although this check is
   1.573 +                                               less strict that the
   1.574 +                                               _ve_envelope_search,
   1.575 +                                               the search is not run
   1.576 +                                               if we only use one
   1.577 +                                               block size */
   1.578 +
   1.579 +
   1.580 +  }
   1.581 +
   1.582 +  /* fill in the block.  Note that for a short window, lW and nW are *short*
   1.583 +     regardless of actual settings in the stream */
   1.584 +
   1.585 +  _vorbis_block_ripcord(vb);
   1.586 +  vb->lW=v->lW;
   1.587 +  vb->W=v->W;
   1.588 +  vb->nW=v->nW;
   1.589 +
   1.590 +  if(v->W){
   1.591 +    if(!v->lW || !v->nW){
   1.592 +      vbi->blocktype=BLOCKTYPE_TRANSITION;
   1.593 +      /*fprintf(stderr,"-");*/
   1.594 +    }else{
   1.595 +      vbi->blocktype=BLOCKTYPE_LONG;
   1.596 +      /*fprintf(stderr,"_");*/
   1.597 +    }
   1.598 +  }else{
   1.599 +    if(_ve_envelope_mark(v)){
   1.600 +      vbi->blocktype=BLOCKTYPE_IMPULSE;
   1.601 +      /*fprintf(stderr,"|");*/
   1.602 +
   1.603 +    }else{
   1.604 +      vbi->blocktype=BLOCKTYPE_PADDING;
   1.605 +      /*fprintf(stderr,".");*/
   1.606 +
   1.607 +    }
   1.608 +  }
   1.609 +
   1.610 +  vb->vd=v;
   1.611 +  vb->sequence=v->sequence++;
   1.612 +  vb->granulepos=v->granulepos;
   1.613 +  vb->pcmend=ci->blocksizes[v->W];
   1.614 +
   1.615 +  /* copy the vectors; this uses the local storage in vb */
   1.616 +
   1.617 +  /* this tracks 'strongest peak' for later psychoacoustics */
   1.618 +  /* moved to the global psy state; clean this mess up */
   1.619 +  if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax;
   1.620 +  g->ampmax=_vp_ampmax_decay(g->ampmax,v);
   1.621 +  vbi->ampmax=g->ampmax;
   1.622 +
   1.623 +  vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
   1.624 +  vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels);
   1.625 +  for(i=0;i<vi->channels;i++){
   1.626 +    vbi->pcmdelay[i]=
   1.627 +      _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
   1.628 +    memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
   1.629 +    vb->pcm[i]=vbi->pcmdelay[i]+beginW;
   1.630 +
   1.631 +    /* before we added the delay
   1.632 +       vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
   1.633 +       memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i]));
   1.634 +    */
   1.635 +
   1.636 +  }
   1.637 +
   1.638 +  /* handle eof detection: eof==0 means that we've not yet received EOF
   1.639 +                           eof>0  marks the last 'real' sample in pcm[]
   1.640 +                           eof<0  'no more to do'; doesn't get here */
   1.641 +
   1.642 +  if(v->eofflag){
   1.643 +    if(v->centerW>=v->eofflag){
   1.644 +      v->eofflag=-1;
   1.645 +      vb->eofflag=1;
   1.646 +      return(1);
   1.647 +    }
   1.648 +  }
   1.649 +
   1.650 +  /* advance storage vectors and clean up */
   1.651 +  {
   1.652 +    int new_centerNext=ci->blocksizes[1]/2;
   1.653 +    int movementW=centerNext-new_centerNext;
   1.654 +
   1.655 +    if(movementW>0){
   1.656 +
   1.657 +      _ve_envelope_shift(b->ve,movementW);
   1.658 +      v->pcm_current-=movementW;
   1.659 +
   1.660 +      for(i=0;i<vi->channels;i++)
   1.661 +        memmove(v->pcm[i],v->pcm[i]+movementW,
   1.662 +                v->pcm_current*sizeof(*v->pcm[i]));
   1.663 +
   1.664 +
   1.665 +      v->lW=v->W;
   1.666 +      v->W=v->nW;
   1.667 +      v->centerW=new_centerNext;
   1.668 +
   1.669 +      if(v->eofflag){
   1.670 +        v->eofflag-=movementW;
   1.671 +        if(v->eofflag<=0)v->eofflag=-1;
   1.672 +        /* do not add padding to end of stream! */
   1.673 +        if(v->centerW>=v->eofflag){
   1.674 +          v->granulepos+=movementW-(v->centerW-v->eofflag);
   1.675 +        }else{
   1.676 +          v->granulepos+=movementW;
   1.677 +        }
   1.678 +      }else{
   1.679 +        v->granulepos+=movementW;
   1.680 +      }
   1.681 +    }
   1.682 +  }
   1.683 +
   1.684 +  /* done */
   1.685 +  return(1);
   1.686 +}
   1.687 +
   1.688 +int vorbis_synthesis_restart(vorbis_dsp_state *v){
   1.689 +  vorbis_info *vi=v->vi;
   1.690 +  codec_setup_info *ci;
   1.691 +  int hs;
   1.692 +
   1.693 +  if(!v->backend_state)return -1;
   1.694 +  if(!vi)return -1;
   1.695 +  ci=vi->codec_setup;
   1.696 +  if(!ci)return -1;
   1.697 +  hs=ci->halfrate_flag;
   1.698 +
   1.699 +  v->centerW=ci->blocksizes[1]>>(hs+1);
   1.700 +  v->pcm_current=v->centerW>>hs;
   1.701 +
   1.702 +  v->pcm_returned=-1;
   1.703 +  v->granulepos=-1;
   1.704 +  v->sequence=-1;
   1.705 +  v->eofflag=0;
   1.706 +  ((private_state *)(v->backend_state))->sample_count=-1;
   1.707 +
   1.708 +  return(0);
   1.709 +}
   1.710 +
   1.711 +int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
   1.712 +  if(_vds_shared_init(v,vi,0)){
   1.713 +    vorbis_dsp_clear(v);
   1.714 +    return 1;
   1.715 +  }
   1.716 +  vorbis_synthesis_restart(v);
   1.717 +  return 0;
   1.718 +}
   1.719 +
   1.720 +/* Unlike in analysis, the window is only partially applied for each
   1.721 +   block.  The time domain envelope is not yet handled at the point of
   1.722 +   calling (as it relies on the previous block). */
   1.723 +
   1.724 +int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
   1.725 +  vorbis_info *vi=v->vi;
   1.726 +  codec_setup_info *ci=vi->codec_setup;
   1.727 +  private_state *b=v->backend_state;
   1.728 +  int hs=ci->halfrate_flag;
   1.729 +  int i,j;
   1.730 +
   1.731 +  if(!vb)return(OV_EINVAL);
   1.732 +  if(v->pcm_current>v->pcm_returned  && v->pcm_returned!=-1)return(OV_EINVAL);
   1.733 +
   1.734 +  v->lW=v->W;
   1.735 +  v->W=vb->W;
   1.736 +  v->nW=-1;
   1.737 +
   1.738 +  if((v->sequence==-1)||
   1.739 +     (v->sequence+1 != vb->sequence)){
   1.740 +    v->granulepos=-1; /* out of sequence; lose count */
   1.741 +    b->sample_count=-1;
   1.742 +  }
   1.743 +
   1.744 +  v->sequence=vb->sequence;
   1.745 +
   1.746 +  if(vb->pcm){  /* no pcm to process if vorbis_synthesis_trackonly
   1.747 +                   was called on block */
   1.748 +    int n=ci->blocksizes[v->W]>>(hs+1);
   1.749 +    int n0=ci->blocksizes[0]>>(hs+1);
   1.750 +    int n1=ci->blocksizes[1]>>(hs+1);
   1.751 +
   1.752 +    int thisCenter;
   1.753 +    int prevCenter;
   1.754 +
   1.755 +    v->glue_bits+=vb->glue_bits;
   1.756 +    v->time_bits+=vb->time_bits;
   1.757 +    v->floor_bits+=vb->floor_bits;
   1.758 +    v->res_bits+=vb->res_bits;
   1.759 +
   1.760 +    if(v->centerW){
   1.761 +      thisCenter=n1;
   1.762 +      prevCenter=0;
   1.763 +    }else{
   1.764 +      thisCenter=0;
   1.765 +      prevCenter=n1;
   1.766 +    }
   1.767 +
   1.768 +    /* v->pcm is now used like a two-stage double buffer.  We don't want
   1.769 +       to have to constantly shift *or* adjust memory usage.  Don't
   1.770 +       accept a new block until the old is shifted out */
   1.771 +
   1.772 +    for(j=0;j<vi->channels;j++){
   1.773 +      /* the overlap/add section */
   1.774 +      if(v->lW){
   1.775 +        if(v->W){
   1.776 +          /* large/large */
   1.777 +          float *w=_vorbis_window_get(b->window[1]-hs);
   1.778 +          float *pcm=v->pcm[j]+prevCenter;
   1.779 +          float *p=vb->pcm[j];
   1.780 +          for(i=0;i<n1;i++)
   1.781 +            pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i];
   1.782 +        }else{
   1.783 +          /* large/small */
   1.784 +          float *w=_vorbis_window_get(b->window[0]-hs);
   1.785 +          float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
   1.786 +          float *p=vb->pcm[j];
   1.787 +          for(i=0;i<n0;i++)
   1.788 +            pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
   1.789 +        }
   1.790 +      }else{
   1.791 +        if(v->W){
   1.792 +          /* small/large */
   1.793 +          float *w=_vorbis_window_get(b->window[0]-hs);
   1.794 +          float *pcm=v->pcm[j]+prevCenter;
   1.795 +          float *p=vb->pcm[j]+n1/2-n0/2;
   1.796 +          for(i=0;i<n0;i++)
   1.797 +            pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
   1.798 +          for(;i<n1/2+n0/2;i++)
   1.799 +            pcm[i]=p[i];
   1.800 +        }else{
   1.801 +          /* small/small */
   1.802 +          float *w=_vorbis_window_get(b->window[0]-hs);
   1.803 +          float *pcm=v->pcm[j]+prevCenter;
   1.804 +          float *p=vb->pcm[j];
   1.805 +          for(i=0;i<n0;i++)
   1.806 +            pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
   1.807 +        }
   1.808 +      }
   1.809 +
   1.810 +      /* the copy section */
   1.811 +      {
   1.812 +        float *pcm=v->pcm[j]+thisCenter;
   1.813 +        float *p=vb->pcm[j]+n;
   1.814 +        for(i=0;i<n;i++)
   1.815 +          pcm[i]=p[i];
   1.816 +      }
   1.817 +    }
   1.818 +
   1.819 +    if(v->centerW)
   1.820 +      v->centerW=0;
   1.821 +    else
   1.822 +      v->centerW=n1;
   1.823 +
   1.824 +    /* deal with initial packet state; we do this using the explicit
   1.825 +       pcm_returned==-1 flag otherwise we're sensitive to first block
   1.826 +       being short or long */
   1.827 +
   1.828 +    if(v->pcm_returned==-1){
   1.829 +      v->pcm_returned=thisCenter;
   1.830 +      v->pcm_current=thisCenter;
   1.831 +    }else{
   1.832 +      v->pcm_returned=prevCenter;
   1.833 +      v->pcm_current=prevCenter+
   1.834 +        ((ci->blocksizes[v->lW]/4+
   1.835 +        ci->blocksizes[v->W]/4)>>hs);
   1.836 +    }
   1.837 +
   1.838 +  }
   1.839 +
   1.840 +  /* track the frame number... This is for convenience, but also
   1.841 +     making sure our last packet doesn't end with added padding.  If
   1.842 +     the last packet is partial, the number of samples we'll have to
   1.843 +     return will be past the vb->granulepos.
   1.844 +
   1.845 +     This is not foolproof!  It will be confused if we begin
   1.846 +     decoding at the last page after a seek or hole.  In that case,
   1.847 +     we don't have a starting point to judge where the last frame
   1.848 +     is.  For this reason, vorbisfile will always try to make sure
   1.849 +     it reads the last two marked pages in proper sequence */
   1.850 +
   1.851 +  if(b->sample_count==-1){
   1.852 +    b->sample_count=0;
   1.853 +  }else{
   1.854 +    b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
   1.855 +  }
   1.856 +
   1.857 +  if(v->granulepos==-1){
   1.858 +    if(vb->granulepos!=-1){ /* only set if we have a position to set to */
   1.859 +
   1.860 +      v->granulepos=vb->granulepos;
   1.861 +
   1.862 +      /* is this a short page? */
   1.863 +      if(b->sample_count>v->granulepos){
   1.864 +        /* corner case; if this is both the first and last audio page,
   1.865 +           then spec says the end is cut, not beginning */
   1.866 +       long extra=b->sample_count-vb->granulepos;
   1.867 +
   1.868 +        /* we use ogg_int64_t for granule positions because a
   1.869 +           uint64 isn't universally available.  Unfortunately,
   1.870 +           that means granposes can be 'negative' and result in
   1.871 +           extra being negative */
   1.872 +        if(extra<0)
   1.873 +          extra=0;
   1.874 +
   1.875 +        if(vb->eofflag){
   1.876 +          /* trim the end */
   1.877 +          /* no preceding granulepos; assume we started at zero (we'd
   1.878 +             have to in a short single-page stream) */
   1.879 +          /* granulepos could be -1 due to a seek, but that would result
   1.880 +             in a long count, not short count */
   1.881 +
   1.882 +          /* Guard against corrupt/malicious frames that set EOP and
   1.883 +             a backdated granpos; don't rewind more samples than we
   1.884 +             actually have */
   1.885 +          if(extra > (v->pcm_current - v->pcm_returned)<<hs)
   1.886 +            extra = (v->pcm_current - v->pcm_returned)<<hs;
   1.887 +
   1.888 +          v->pcm_current-=extra>>hs;
   1.889 +        }else{
   1.890 +          /* trim the beginning */
   1.891 +          v->pcm_returned+=extra>>hs;
   1.892 +          if(v->pcm_returned>v->pcm_current)
   1.893 +            v->pcm_returned=v->pcm_current;
   1.894 +        }
   1.895 +
   1.896 +      }
   1.897 +
   1.898 +    }
   1.899 +  }else{
   1.900 +    v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
   1.901 +    if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
   1.902 +
   1.903 +      if(v->granulepos>vb->granulepos){
   1.904 +        long extra=v->granulepos-vb->granulepos;
   1.905 +
   1.906 +        if(extra)
   1.907 +          if(vb->eofflag){
   1.908 +            /* partial last frame.  Strip the extra samples off */
   1.909 +
   1.910 +            /* Guard against corrupt/malicious frames that set EOP and
   1.911 +               a backdated granpos; don't rewind more samples than we
   1.912 +               actually have */
   1.913 +            if(extra > (v->pcm_current - v->pcm_returned)<<hs)
   1.914 +              extra = (v->pcm_current - v->pcm_returned)<<hs;
   1.915 +
   1.916 +            /* we use ogg_int64_t for granule positions because a
   1.917 +               uint64 isn't universally available.  Unfortunately,
   1.918 +               that means granposes can be 'negative' and result in
   1.919 +               extra being negative */
   1.920 +            if(extra<0)
   1.921 +              extra=0;
   1.922 +
   1.923 +            v->pcm_current-=extra>>hs;
   1.924 +          } /* else {Shouldn't happen *unless* the bitstream is out of
   1.925 +               spec.  Either way, believe the bitstream } */
   1.926 +      } /* else {Shouldn't happen *unless* the bitstream is out of
   1.927 +           spec.  Either way, believe the bitstream } */
   1.928 +      v->granulepos=vb->granulepos;
   1.929 +    }
   1.930 +  }
   1.931 +
   1.932 +  /* Update, cleanup */
   1.933 +
   1.934 +  if(vb->eofflag)v->eofflag=1;
   1.935 +  return(0);
   1.936 +
   1.937 +}
   1.938 +
   1.939 +/* pcm==NULL indicates we just want the pending samples, no more */
   1.940 +int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
   1.941 +  vorbis_info *vi=v->vi;
   1.942 +
   1.943 +  if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
   1.944 +    if(pcm){
   1.945 +      int i;
   1.946 +      for(i=0;i<vi->channels;i++)
   1.947 +        v->pcmret[i]=v->pcm[i]+v->pcm_returned;
   1.948 +      *pcm=v->pcmret;
   1.949 +    }
   1.950 +    return(v->pcm_current-v->pcm_returned);
   1.951 +  }
   1.952 +  return(0);
   1.953 +}
   1.954 +
   1.955 +int vorbis_synthesis_read(vorbis_dsp_state *v,int n){
   1.956 +  if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL);
   1.957 +  v->pcm_returned+=n;
   1.958 +  return(0);
   1.959 +}
   1.960 +
   1.961 +/* intended for use with a specific vorbisfile feature; we want access
   1.962 +   to the [usually synthetic/postextrapolated] buffer and lapping at
   1.963 +   the end of a decode cycle, specifically, a half-short-block worth.
   1.964 +   This funtion works like pcmout above, except it will also expose
   1.965 +   this implicit buffer data not normally decoded. */
   1.966 +int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
   1.967 +  vorbis_info *vi=v->vi;
   1.968 +  codec_setup_info *ci=vi->codec_setup;
   1.969 +  int hs=ci->halfrate_flag;
   1.970 +
   1.971 +  int n=ci->blocksizes[v->W]>>(hs+1);
   1.972 +  int n0=ci->blocksizes[0]>>(hs+1);
   1.973 +  int n1=ci->blocksizes[1]>>(hs+1);
   1.974 +  int i,j;
   1.975 +
   1.976 +  if(v->pcm_returned<0)return 0;
   1.977 +
   1.978 +  /* our returned data ends at pcm_returned; because the synthesis pcm
   1.979 +     buffer is a two-fragment ring, that means our data block may be
   1.980 +     fragmented by buffering, wrapping or a short block not filling
   1.981 +     out a buffer.  To simplify things, we unfragment if it's at all
   1.982 +     possibly needed. Otherwise, we'd need to call lapout more than
   1.983 +     once as well as hold additional dsp state.  Opt for
   1.984 +     simplicity. */
   1.985 +
   1.986 +  /* centerW was advanced by blockin; it would be the center of the
   1.987 +     *next* block */
   1.988 +  if(v->centerW==n1){
   1.989 +    /* the data buffer wraps; swap the halves */
   1.990 +    /* slow, sure, small */
   1.991 +    for(j=0;j<vi->channels;j++){
   1.992 +      float *p=v->pcm[j];
   1.993 +      for(i=0;i<n1;i++){
   1.994 +        float temp=p[i];
   1.995 +        p[i]=p[i+n1];
   1.996 +        p[i+n1]=temp;
   1.997 +      }
   1.998 +    }
   1.999 +
  1.1000 +    v->pcm_current-=n1;
  1.1001 +    v->pcm_returned-=n1;
  1.1002 +    v->centerW=0;
  1.1003 +  }
  1.1004 +
  1.1005 +  /* solidify buffer into contiguous space */
  1.1006 +  if((v->lW^v->W)==1){
  1.1007 +    /* long/short or short/long */
  1.1008 +    for(j=0;j<vi->channels;j++){
  1.1009 +      float *s=v->pcm[j];
  1.1010 +      float *d=v->pcm[j]+(n1-n0)/2;
  1.1011 +      for(i=(n1+n0)/2-1;i>=0;--i)
  1.1012 +        d[i]=s[i];
  1.1013 +    }
  1.1014 +    v->pcm_returned+=(n1-n0)/2;
  1.1015 +    v->pcm_current+=(n1-n0)/2;
  1.1016 +  }else{
  1.1017 +    if(v->lW==0){
  1.1018 +      /* short/short */
  1.1019 +      for(j=0;j<vi->channels;j++){
  1.1020 +        float *s=v->pcm[j];
  1.1021 +        float *d=v->pcm[j]+n1-n0;
  1.1022 +        for(i=n0-1;i>=0;--i)
  1.1023 +          d[i]=s[i];
  1.1024 +      }
  1.1025 +      v->pcm_returned+=n1-n0;
  1.1026 +      v->pcm_current+=n1-n0;
  1.1027 +    }
  1.1028 +  }
  1.1029 +
  1.1030 +  if(pcm){
  1.1031 +    int i;
  1.1032 +    for(i=0;i<vi->channels;i++)
  1.1033 +      v->pcmret[i]=v->pcm[i]+v->pcm_returned;
  1.1034 +    *pcm=v->pcmret;
  1.1035 +  }
  1.1036 +
  1.1037 +  return(n1+n-v->pcm_returned);
  1.1038 +
  1.1039 +}
  1.1040 +
  1.1041 +float *vorbis_window(vorbis_dsp_state *v,int W){
  1.1042 +  vorbis_info *vi=v->vi;
  1.1043 +  codec_setup_info *ci=vi->codec_setup;
  1.1044 +  int hs=ci->halfrate_flag;
  1.1045 +  private_state *b=v->backend_state;
  1.1046 +
  1.1047 +  if(b->window[W]-1<0)return NULL;
  1.1048 +  return _vorbis_window_get(b->window[W]-hs);
  1.1049 +}