1/********************************************************************
2 *                                                                  *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7 *                                                                  *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
9 * by the Xiph.Org Foundation http://www.xiph.org/                  *
10 *                                                                  *
11 ********************************************************************
12
13 function: single-block PCM synthesis
14 last mod: $Id: synthesis.c 17027 2010-03-25 05:21:20Z xiphmont $
15
16 ********************************************************************/
17
18#include <stdio.h>
19#include <ogg/ogg.h>
20#include "vorbis/codec.h"
21#include "codec_internal.h"
22#include "registry.h"
23#include "misc.h"
24#include "os.h"
25
26int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){
27  vorbis_dsp_state     *vd= vb ? vb->vd : 0;
28  private_state        *b= vd ? vd->backend_state : 0;
29  vorbis_info          *vi= vd ? vd->vi : 0;
30  codec_setup_info     *ci= vi ? vi->codec_setup : 0;
31  oggpack_buffer       *opb=vb ? &vb->opb : 0;
32  int                   type,mode,i;
33
34  if (!vd || !b || !vi || !ci || !opb) {
35    return OV_EBADPACKET;
36  }
37
38  /* first things first.  Make sure decode is ready */
39  _vorbis_block_ripcord(vb);
40  oggpack_readinit(opb,op->packet,op->bytes);
41
42  /* Check the packet type */
43  if(oggpack_read(opb,1)!=0){
44    /* Oops.  This is not an audio data packet */
45    return(OV_ENOTAUDIO);
46  }
47
48  /* read our mode and pre/post windowsize */
49  mode=oggpack_read(opb,b->modebits);
50  if(mode==-1){
51    return(OV_EBADPACKET);
52  }
53
54  vb->mode=mode;
55  if(!ci->mode_param[mode]){
56    return(OV_EBADPACKET);
57  }
58
59  vb->W=ci->mode_param[mode]->blockflag;
60  if(vb->W){
61
62    /* this doesn;t get mapped through mode selection as it's used
63       only for window selection */
64    vb->lW=oggpack_read(opb,1);
65    vb->nW=oggpack_read(opb,1);
66    if(vb->nW==-1){
67      return(OV_EBADPACKET);
68    }
69  }else{
70    vb->lW=0;
71    vb->nW=0;
72  }
73
74  /* more setup */
75  vb->granulepos=op->granulepos;
76  vb->sequence=op->packetno;
77  vb->eofflag=op->e_o_s;
78
79  /* alloc pcm passback storage */
80  vb->pcmend=ci->blocksizes[vb->W];
81  vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
82  for(i=0;i<vi->channels;i++)
83    vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
84
85  /* unpack_header enforces range checking */
86  type=ci->map_type[ci->mode_param[mode]->mapping];
87
88  return(_mapping_P[type]->inverse(vb,ci->map_param[ci->mode_param[mode]->
89                                                   mapping]));
90}
91
92/* used to track pcm position without actually performing decode.
93   Useful for sequential 'fast forward' */
94int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){
95  vorbis_dsp_state     *vd=vb->vd;
96  private_state        *b=vd->backend_state;
97  vorbis_info          *vi=vd->vi;
98  codec_setup_info     *ci=vi->codec_setup;
99  oggpack_buffer       *opb=&vb->opb;
100  int                   mode;
101
102  /* first things first.  Make sure decode is ready */
103  _vorbis_block_ripcord(vb);
104  oggpack_readinit(opb,op->packet,op->bytes);
105
106  /* Check the packet type */
107  if(oggpack_read(opb,1)!=0){
108    /* Oops.  This is not an audio data packet */
109    return(OV_ENOTAUDIO);
110  }
111
112  /* read our mode and pre/post windowsize */
113  mode=oggpack_read(opb,b->modebits);
114  if(mode==-1)return(OV_EBADPACKET);
115
116  vb->mode=mode;
117  vb->W=ci->mode_param[mode]->blockflag;
118  if(vb->W){
119    vb->lW=oggpack_read(opb,1);
120    vb->nW=oggpack_read(opb,1);
121    if(vb->nW==-1)   return(OV_EBADPACKET);
122  }else{
123    vb->lW=0;
124    vb->nW=0;
125  }
126
127  /* more setup */
128  vb->granulepos=op->granulepos;
129  vb->sequence=op->packetno;
130  vb->eofflag=op->e_o_s;
131
132  /* no pcm */
133  vb->pcmend=0;
134  vb->pcm=NULL;
135
136  return(0);
137}
138
139long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
140  codec_setup_info     *ci=vi->codec_setup;
141  oggpack_buffer       opb;
142  int                  mode;
143
144  oggpack_readinit(&opb,op->packet,op->bytes);
145
146  /* Check the packet type */
147  if(oggpack_read(&opb,1)!=0){
148    /* Oops.  This is not an audio data packet */
149    return(OV_ENOTAUDIO);
150  }
151
152  {
153    int modebits=0;
154    int v=ci->modes;
155    while(v>1){
156      modebits++;
157      v>>=1;
158    }
159
160    /* read our mode and pre/post windowsize */
161    mode=oggpack_read(&opb,modebits);
162  }
163  if(mode==-1)return(OV_EBADPACKET);
164  return(ci->blocksizes[ci->mode_param[mode]->blockflag]);
165}
166
167int vorbis_synthesis_halfrate(vorbis_info *vi,int flag){
168  /* set / clear half-sample-rate mode */
169  codec_setup_info     *ci=vi->codec_setup;
170
171  /* right now, our MDCT can't handle < 64 sample windows. */
172  if(ci->blocksizes[0]<=64 && flag)return -1;
173  ci->halfrate_flag=(flag?1:0);
174  return 0;
175}
176
177int vorbis_synthesis_halfrate_p(vorbis_info *vi){
178  codec_setup_info     *ci=vi->codec_setup;
179  return ci->halfrate_flag;
180}
181