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