137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang/************************************************************************
22da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Copyright (C) 2002-2009, Xiph.org Foundation
32da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd
437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * All rights reserved.
537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang *
637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Redistribution and use in source and binary forms, with or without
72da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * modification, are permitted provided that the following conditions
82da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * are met:
937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang *
1037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang *     * Redistributions of source code must retain the above copyright
1137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * notice, this list of conditions and the following disclaimer.
1237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang *     * Redistributions in binary form must reproduce the above
1337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * copyright notice, this list of conditions and the following disclaimer
1437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * in the documentation and/or other materials provided with the
1537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * distribution.
162da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang *     * Neither the names of the Xiph.org Foundation nor Pinknoise
172da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Productions Ltd nor the names of its contributors may be used to
182da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * endorse or promote products derived from this software without
192da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * specific prior written permission.
2037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang *
2137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2737fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2837fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang ************************************************************************
337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang function: PCM data vector blocking, windowing and dis/reassembly
357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
3637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang ************************************************************************/
377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include <stdlib.h>
397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "ogg.h"
407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "mdct.h"
417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "ivorbiscodec.h"
427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "codec_internal.h"
437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "misc.h"
447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "window_lookup.h"
457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint vorbis_dsp_restart(vorbis_dsp_state *v){
477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(!v)return -1;
487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  {
497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    vorbis_info *vi=v->vi;
507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    codec_setup_info *ci;
517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(!vi)return -1;
537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    ci=vi->codec_setup;
547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(!ci)return -1;
557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v->out_end=-1;
577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v->out_begin=-1;
587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v->granulepos=-1;
607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v->sequence=-1;
617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v->sample_count=-1;
627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  return 0;
647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint vorbis_dsp_init(vorbis_dsp_state *v,vorbis_info *vi){
677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  int i;
687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  v->vi=vi;
727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  v->work=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->work));
747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  v->mdctright=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->mdctright));
757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  for(i=0;i<vi->channels;i++){
767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v->work[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>1)*
777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang					  sizeof(*v->work[i]));
787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v->mdctright[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>2)*
797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang					       sizeof(*v->mdctright[i]));
807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  v->lW=0; /* previous window size */
837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  v->W=0;  /* current window size */
847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vorbis_dsp_restart(v);
867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  return 0;
877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){
907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vorbis_dsp_state *v=_ogg_calloc(1,sizeof(*v));
917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vorbis_dsp_init(v,vi);
927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  return v;
937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvoid vorbis_dsp_clear(vorbis_dsp_state *v){
967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  int i;
977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(v){
987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    vorbis_info *vi=v->vi;
997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(v->work){
1017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      for(i=0;i<vi->channels;i++)
1027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang        if(v->work[i])_ogg_free(v->work[i]);
1037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      _ogg_free(v->work);
1047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    }
1057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(v->mdctright){
1067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      for(i=0;i<vi->channels;i++)
1077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang        if(v->mdctright[i])_ogg_free(v->mdctright[i]);
1087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      _ogg_free(v->mdctright);
1097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    }
1107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
1117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
1127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvoid vorbis_dsp_destroy(vorbis_dsp_state *v){
1147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vorbis_dsp_clear(v);
1157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  _ogg_free(v);
1167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
1177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic LOOKUP_T *_vorbis_window(int left){
1197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  switch(left){
1207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  case 32:
1217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return vwin64;
1227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  case 64:
1237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return vwin128;
1247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  case 128:
1257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return vwin256;
1267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  case 256:
1277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return vwin512;
1287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  case 512:
1297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return vwin1024;
1307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  case 1024:
1317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return vwin2048;
1327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  case 2048:
1337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return vwin4096;
1347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#ifndef LIMIT_TO_64kHz
1357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  case 4096:
1367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return vwin8192;
1377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif
1387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  default:
1397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return(0);
1407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
1417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
1427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* pcm==0 indicates we just want the pending samples, no more */
1447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint vorbis_dsp_pcmout(vorbis_dsp_state *v,ogg_int16_t *pcm,int samples){
1457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vorbis_info *vi=v->vi;
1467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
1477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(v->out_begin>-1 && v->out_begin<v->out_end){
1487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    int n=v->out_end-v->out_begin;
1497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(pcm){
1507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      int i;
1517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      if(n>samples)n=samples;
1527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      for(i=0;i<vi->channels;i++)
1537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	mdct_unroll_lap(ci->blocksizes[0],ci->blocksizes[1],
1547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang			v->lW,v->W,v->work[i],v->mdctright[i],
1557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang			_vorbis_window(ci->blocksizes[0]>>1),
1567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang			_vorbis_window(ci->blocksizes[1]>>1),
1577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang			pcm+i,vi->channels,
1587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang			v->out_begin,v->out_begin+n);
1597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    }
1607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return(n);
1617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
1627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  return(0);
1637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
1647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint vorbis_dsp_read(vorbis_dsp_state *v,int s){
1667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(s && v->out_begin+s>v->out_end)return(OV_EINVAL);
1677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  v->out_begin+=s;
1687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  return(0);
1697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
1707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanglong vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
1727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
1737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  oggpack_buffer       opb;
1747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  int                  mode;
1757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  int modebits=0;
1767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  int v=ci->modes;
1777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  oggpack_readinit(&opb,op->packet);
1797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  /* Check the packet type */
1817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(oggpack_read(&opb,1)!=0){
1827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    /* Oops.  This is not an audio data packet */
1837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return(OV_ENOTAUDIO);
1847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
1857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  while(v>1){
1877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    modebits++;
1887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v>>=1;
1897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
1907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  /* read our mode and pre/post windowsize */
1927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  mode=oggpack_read(&opb,modebits);
1937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(mode==-1)return(OV_EBADPACKET);
1947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  return(ci->blocksizes[ci->mode_param[mode].blockflag]);
1957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
1967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
1987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int ilog(ogg_uint32_t v){
1997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  int ret=0;
2007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(v)--v;
2017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  while(v){
2027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    ret++;
2037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    v>>=1;
2047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
2057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  return(ret);
2067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
2077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint vorbis_dsp_synthesis(vorbis_dsp_state *vd,ogg_packet *op,int decodep){
2097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vorbis_info          *vi=vd->vi;
2107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  codec_setup_info     *ci=(codec_setup_info *)vi->codec_setup;
2117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  int                   mode,i;
2127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  oggpack_readinit(&vd->opb,op->packet);
2147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  /* Check the packet type */
2167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(oggpack_read(&vd->opb,1)!=0){
2177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    /* Oops.  This is not an audio data packet */
2187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    return OV_ENOTAUDIO ;
2197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
2207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  /* read our mode and pre/post windowsize */
2227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  mode=oggpack_read(&vd->opb,ilog(ci->modes));
2237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(mode==-1 || mode>=ci->modes) return OV_EBADPACKET;
2247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  /* shift information we still need from last window */
2267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vd->lW=vd->W;
2277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vd->W=ci->mode_param[mode].blockflag;
2287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  for(i=0;i<vi->channels;i++)
2297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    mdct_shift_right(ci->blocksizes[vd->lW],vd->work[i],vd->mdctright[i]);
2307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(vd->W){
2327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    int temp;
2337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    oggpack_read(&vd->opb,1);
2347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    temp=oggpack_read(&vd->opb,1);
2357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(temp==-1) return OV_EBADPACKET;
2367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
2377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  /* packet decode and portions of synthesis that rely on only this block */
2397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(decodep){
2407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    mapping_inverse(vd,ci->map_param+ci->mode_param[mode].mapping);
2417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(vd->out_begin==-1){
2437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      vd->out_begin=0;
2447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      vd->out_end=0;
2457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    }else{
2467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      vd->out_begin=0;
2477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      vd->out_end=ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
2487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    }
2497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
2507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  /* track the frame number... This is for convenience, but also
2527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang     making sure our last packet doesn't end with added padding.
2537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang     This is not foolproof!  It will be confused if we begin
2557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang     decoding at the last page after a seek or hole.  In that case,
2567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang     we don't have a starting point to judge where the last frame
2577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang     is.  For this reason, vorbisfile will always try to make sure
2587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang     it reads the last two marked pages in proper sequence */
2597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  /* if we're out of sequence, dump granpos tracking until we sync back up */
2617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(vd->sequence==-1 || vd->sequence+1 != op->packetno-3){
2627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    /* out of sequence; lose count */
2637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    vd->granulepos=-1;
2647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    vd->sample_count=-1;
2657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
2667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vd->sequence=op->packetno;
2687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  vd->sequence=vd->sequence-3;
2697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(vd->sample_count==-1){
2717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    vd->sample_count=0;
2727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }else{
2737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    vd->sample_count+=
2747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
2757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
2767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  if(vd->granulepos==-1){
2787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(op->granulepos!=-1){ /* only set if we have a
2797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang			       position to set to */
2807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      vd->granulepos=op->granulepos;
2827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      /* is this a short page? */
2847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      if(vd->sample_count>vd->granulepos){
2857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	/* corner case; if this is both the first and last audio page,
2867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	   then spec says the end is cut, not beginning */
2877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	if(op->e_o_s){
2887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  /* trim the end */
2897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  /* no preceeding granulepos; assume we started at zero (we'd
2907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	     have to in a short single-page stream) */
2917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  /* granulepos could be -1 due to a seek, but that would result
2927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	     in a long coun t, not short count */
2937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
2947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  vd->out_end-=(int)(vd->sample_count-vd->granulepos);
2957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	}else{
2967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  /* trim the beginning */
2977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  vd->out_begin+=(int)(vd->sample_count-vd->granulepos);
2987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  if(vd->out_begin>vd->out_end)
2997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	    vd->out_begin=vd->out_end;
3007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	}
3017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
3027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      }
3037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
3047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    }
3057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }else{
3067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    vd->granulepos+=
3077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
3087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    if(op->granulepos!=-1 && vd->granulepos!=op->granulepos){
3097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
3107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      if(vd->granulepos>op->granulepos){
3117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	long extra=(long)(vd->granulepos-op->granulepos);
3127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
3137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	if(extra)
3147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  if(op->e_o_s){
3157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	    /* partial last frame.  Strip the extra samples off */
3167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	    vd->out_end-=extra;
3177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	  } /* else {Shouldn't happen *unless* the bitstream is out of
3187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	       spec.  Either way, believe the bitstream } */
3197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      } /* else {Shouldn't happen *unless* the bitstream is out of
3207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang	   spec.  Either way, believe the bitstream } */
3217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang      vd->granulepos=op->granulepos;
3227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang    }
3237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  }
3247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang
3257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang  return(0);
3267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang}
327