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