1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
4 * *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
11 * *
12 ********************************************************************
13
14 function: PCM data vector blocking, windowing and dis/reassembly
15
16 ********************************************************************/
17
18 #include <stdlib.h>
19 #include "ogg.h"
20 #include "mdct.h"
21 #include "ivorbiscodec.h"
22 #include "codec_internal.h"
23 #include "misc.h"
24 #include "window_lookup.h"
25
vorbis_dsp_restart(vorbis_dsp_state * v)26 int vorbis_dsp_restart(vorbis_dsp_state *v){
27 if(!v)return -1;
28 {
29 vorbis_info *vi=v->vi;
30 codec_setup_info *ci;
31
32 if(!vi)return -1;
33 ci=vi->codec_setup;
34 if(!ci)return -1;
35
36 v->out_end=-1;
37 v->out_begin=-1;
38
39 v->granulepos=-1;
40 v->sequence=-1;
41 v->sample_count=-1;
42 }
43 return 0;
44 }
45
vorbis_dsp_create(vorbis_info * vi)46 vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){
47 int i;
48
49 vorbis_dsp_state *v=_ogg_calloc(1,sizeof(*v));
50 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
51
52 v->vi=vi;
53
54 v->work=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->work));
55 v->mdctright=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->mdctright));
56 for(i=0;i<vi->channels;i++){
57 v->work[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>1)*
58 sizeof(*v->work[i]));
59 v->mdctright[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>2)*
60 sizeof(*v->mdctright[i]));
61 }
62
63 v->lW=0; /* previous window size */
64 v->W=0; /* current window size */
65
66 vorbis_dsp_restart(v);
67 return v;
68 }
69
vorbis_dsp_destroy(vorbis_dsp_state * v)70 void vorbis_dsp_destroy(vorbis_dsp_state *v){
71 int i;
72 if(v){
73 vorbis_info *vi=v->vi;
74
75 if(v->work){
76 for(i=0;i<vi->channels;i++)
77 if(v->work[i])_ogg_free(v->work[i]);
78 _ogg_free(v->work);
79 }
80 if(v->mdctright){
81 for(i=0;i<vi->channels;i++)
82 if(v->mdctright[i])_ogg_free(v->mdctright[i]);
83 _ogg_free(v->mdctright);
84 }
85
86 _ogg_free(v);
87 }
88 }
89
_vorbis_window(int left)90 static LOOKUP_T *_vorbis_window(int left){
91 switch(left){
92 case 32:
93 return vwin64;
94 case 64:
95 return vwin128;
96 case 128:
97 return vwin256;
98 case 256:
99 return vwin512;
100 case 512:
101 return vwin1024;
102 case 1024:
103 return vwin2048;
104 case 2048:
105 return vwin4096;
106 #ifndef LIMIT_TO_64kHz
107 case 4096:
108 return vwin8192;
109 #endif
110 default:
111 return(0);
112 }
113 }
114
115 /* pcm==0 indicates we just want the pending samples, no more */
vorbis_dsp_pcmout(vorbis_dsp_state * v,ogg_int16_t * pcm,int samples)116 int vorbis_dsp_pcmout(vorbis_dsp_state *v,ogg_int16_t *pcm,int samples){
117 vorbis_info *vi=v->vi;
118 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
119 if(v->out_begin>-1 && v->out_begin<v->out_end){
120 int n=v->out_end-v->out_begin;
121 if(pcm){
122 int i;
123 if(n>samples)n=samples;
124 for(i=0;i<vi->channels;i++)
125 mdct_unroll_lap(ci->blocksizes[0],ci->blocksizes[1],
126 v->lW,v->W,v->work[i],v->mdctright[i],
127 _vorbis_window(ci->blocksizes[0]>>1),
128 _vorbis_window(ci->blocksizes[1]>>1),
129 pcm+i,vi->channels,
130 v->out_begin,v->out_begin+n);
131 }
132 return(n);
133 }
134 return(0);
135 }
136
vorbis_dsp_read(vorbis_dsp_state * v,int s)137 int vorbis_dsp_read(vorbis_dsp_state *v,int s){
138 if(s && v->out_begin+s>v->out_end)return(OV_EINVAL);
139 v->out_begin+=s;
140 return(0);
141 }
142
vorbis_packet_blocksize(vorbis_info * vi,ogg_packet * op)143 long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
144 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
145 oggpack_buffer opb;
146 int mode;
147 int modebits=0;
148 int v=ci->modes;
149
150 oggpack_readinit(&opb,op->packet);
151
152 /* Check the packet type */
153 if(oggpack_read(&opb,1)!=0){
154 /* Oops. This is not an audio data packet */
155 return(OV_ENOTAUDIO);
156 }
157
158 while(v>1){
159 modebits++;
160 v>>=1;
161 }
162
163 /* read our mode and pre/post windowsize */
164 mode=oggpack_read(&opb,modebits);
165 if(mode==-1)return(OV_EBADPACKET);
166 return(ci->blocksizes[ci->mode_param[mode].blockflag]);
167 }
168
169
ilog(ogg_uint32_t v)170 static int ilog(ogg_uint32_t v){
171 int ret=0;
172 if(v)--v;
173 while(v){
174 ret++;
175 v>>=1;
176 }
177 return(ret);
178 }
179
vorbis_dsp_synthesis(vorbis_dsp_state * vd,ogg_packet * op,int decodep)180 int vorbis_dsp_synthesis(vorbis_dsp_state *vd,ogg_packet *op,int decodep){
181 vorbis_info *vi=vd->vi;
182 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
183 int mode,i;
184
185 oggpack_readinit(&vd->opb,op->packet);
186
187 /* Check the packet type */
188 if(oggpack_read(&vd->opb,1)!=0){
189 /* Oops. This is not an audio data packet */
190 return OV_ENOTAUDIO ;
191 }
192
193 /* read our mode and pre/post windowsize */
194 mode=oggpack_read(&vd->opb,ilog(ci->modes));
195 if(mode==-1 || mode>=ci->modes) return OV_EBADPACKET;
196
197 /* shift information we still need from last window */
198 vd->lW=vd->W;
199 vd->W=ci->mode_param[mode].blockflag;
200 for(i=0;i<vi->channels;i++)
201 mdct_shift_right(ci->blocksizes[vd->lW],vd->work[i],vd->mdctright[i]);
202
203 if(vd->W){
204 int temp;
205 oggpack_read(&vd->opb,1);
206 temp=oggpack_read(&vd->opb,1);
207 if(temp==-1) return OV_EBADPACKET;
208 }
209
210 /* packet decode and portions of synthesis that rely on only this block */
211 if(decodep){
212 mapping_inverse(vd,ci->map_param+ci->mode_param[mode].mapping);
213
214 if(vd->out_begin==-1){
215 vd->out_begin=0;
216 vd->out_end=0;
217 }else{
218 vd->out_begin=0;
219 vd->out_end=ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
220 }
221 }
222
223 /* track the frame number... This is for convenience, but also
224 making sure our last packet doesn't end with added padding.
225
226 This is not foolproof! It will be confused if we begin
227 decoding at the last page after a seek or hole. In that case,
228 we don't have a starting point to judge where the last frame
229 is. For this reason, vorbisfile will always try to make sure
230 it reads the last two marked pages in proper sequence */
231
232 /* if we're out of sequence, dump granpos tracking until we sync back up */
233 if(vd->sequence==-1 || vd->sequence+1 != op->packetno-3){
234 /* out of sequence; lose count */
235 vd->granulepos=-1;
236 vd->sample_count=-1;
237 }
238
239 vd->sequence=op->packetno;
240 vd->sequence=vd->sequence-3;
241
242 if(vd->sample_count==-1){
243 vd->sample_count=0;
244 }else{
245 vd->sample_count+=
246 ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
247 }
248
249 if(vd->granulepos==-1){
250 if(op->granulepos!=-1){ /* only set if we have a
251 position to set to */
252
253 vd->granulepos=op->granulepos;
254
255 /* is this a short page? */
256 if(vd->sample_count>vd->granulepos){
257 /* corner case; if this is both the first and last audio page,
258 then spec says the end is cut, not beginning */
259 if(op->e_o_s){
260 /* trim the end */
261 /* no preceeding granulepos; assume we started at zero (we'd
262 have to in a short single-page stream) */
263 /* granulepos could be -1 due to a seek, but that would result
264 in a long coun t, not short count */
265
266 vd->out_end-=vd->sample_count-vd->granulepos;
267 }else{
268 /* trim the beginning */
269 vd->out_begin+=vd->sample_count-vd->granulepos;
270 if(vd->out_begin>vd->out_end)
271 vd->out_begin=vd->out_end;
272 }
273
274 }
275
276 }
277 }else{
278 vd->granulepos+=
279 ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
280 if(op->granulepos!=-1 && vd->granulepos!=op->granulepos){
281
282 if(vd->granulepos>op->granulepos){
283 long extra=vd->granulepos-op->granulepos;
284
285 if(extra)
286 if(op->e_o_s){
287 /* partial last frame. Strip the extra samples off */
288 vd->out_end-=extra;
289 } /* else {Shouldn't happen *unless* the bitstream is out of
290 spec. Either way, believe the bitstream } */
291 } /* else {Shouldn't happen *unless* the bitstream is out of
292 spec. Either way, believe the bitstream } */
293 vd->granulepos=op->granulepos;
294 }
295 }
296
297 return(0);
298 }
299