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 |
|
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 |
|
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 |
|
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 |
|
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 */ |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 } |
|