blob: b6b321601de02969ed27e8189ec3295f23f21967 [file] [log] [blame]
Gloria Wang37fe1582010-03-12 14:53:20 -08001/************************************************************************
2 * Copyright (C) 2010, The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of the Android Open Source Project nor the
16 * names of its contributors may be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 ************************************************************************
Gloria Wang79130732010-02-08 14:41:04 -080031
32 function: PCM data vector blocking, windowing and dis/reassembly
33
Gloria Wang37fe1582010-03-12 14:53:20 -080034 ************************************************************************/
Gloria Wang79130732010-02-08 14:41:04 -080035
36#include <stdlib.h>
37#include "ogg.h"
38#include "mdct.h"
39#include "ivorbiscodec.h"
40#include "codec_internal.h"
41#include "misc.h"
42#include "window_lookup.h"
43
44int vorbis_dsp_restart(vorbis_dsp_state *v){
45 if(!v)return -1;
46 {
47 vorbis_info *vi=v->vi;
48 codec_setup_info *ci;
49
50 if(!vi)return -1;
51 ci=vi->codec_setup;
52 if(!ci)return -1;
53
54 v->out_end=-1;
55 v->out_begin=-1;
56
57 v->granulepos=-1;
58 v->sequence=-1;
59 v->sample_count=-1;
60 }
61 return 0;
62}
63
64int vorbis_dsp_init(vorbis_dsp_state *v,vorbis_info *vi){
65 int i;
66
67 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
68
69 v->vi=vi;
70
71 v->work=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->work));
72 v->mdctright=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->mdctright));
73 for(i=0;i<vi->channels;i++){
74 v->work[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>1)*
75 sizeof(*v->work[i]));
76 v->mdctright[i]=(ogg_int32_t *)_ogg_calloc(1,(ci->blocksizes[1]>>2)*
77 sizeof(*v->mdctright[i]));
78 }
79
80 v->lW=0; /* previous window size */
81 v->W=0; /* current window size */
82
83 vorbis_dsp_restart(v);
84 return 0;
85}
86
87vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){
88 vorbis_dsp_state *v=_ogg_calloc(1,sizeof(*v));
89 vorbis_dsp_init(v,vi);
90 return v;
91}
92
93void vorbis_dsp_clear(vorbis_dsp_state *v){
94 int i;
95 if(v){
96 vorbis_info *vi=v->vi;
97
98 if(v->work){
99 for(i=0;i<vi->channels;i++)
100 if(v->work[i])_ogg_free(v->work[i]);
101 _ogg_free(v->work);
102 }
103 if(v->mdctright){
104 for(i=0;i<vi->channels;i++)
105 if(v->mdctright[i])_ogg_free(v->mdctright[i]);
106 _ogg_free(v->mdctright);
107 }
108 }
109}
110
111void vorbis_dsp_destroy(vorbis_dsp_state *v){
112 vorbis_dsp_clear(v);
113 _ogg_free(v);
114}
115
116static LOOKUP_T *_vorbis_window(int left){
117 switch(left){
118 case 32:
119 return vwin64;
120 case 64:
121 return vwin128;
122 case 128:
123 return vwin256;
124 case 256:
125 return vwin512;
126 case 512:
127 return vwin1024;
128 case 1024:
129 return vwin2048;
130 case 2048:
131 return vwin4096;
132#ifndef LIMIT_TO_64kHz
133 case 4096:
134 return vwin8192;
135#endif
136 default:
137 return(0);
138 }
139}
140
141/* pcm==0 indicates we just want the pending samples, no more */
142int vorbis_dsp_pcmout(vorbis_dsp_state *v,ogg_int16_t *pcm,int samples){
143 vorbis_info *vi=v->vi;
144 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
145 if(v->out_begin>-1 && v->out_begin<v->out_end){
146 int n=v->out_end-v->out_begin;
147 if(pcm){
148 int i;
149 if(n>samples)n=samples;
150 for(i=0;i<vi->channels;i++)
151 mdct_unroll_lap(ci->blocksizes[0],ci->blocksizes[1],
152 v->lW,v->W,v->work[i],v->mdctright[i],
153 _vorbis_window(ci->blocksizes[0]>>1),
154 _vorbis_window(ci->blocksizes[1]>>1),
155 pcm+i,vi->channels,
156 v->out_begin,v->out_begin+n);
157 }
158 return(n);
159 }
160 return(0);
161}
162
163int vorbis_dsp_read(vorbis_dsp_state *v,int s){
164 if(s && v->out_begin+s>v->out_end)return(OV_EINVAL);
165 v->out_begin+=s;
166 return(0);
167}
168
169long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
170 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
171 oggpack_buffer opb;
172 int mode;
173 int modebits=0;
174 int v=ci->modes;
175
176 oggpack_readinit(&opb,op->packet);
177
178 /* Check the packet type */
179 if(oggpack_read(&opb,1)!=0){
180 /* Oops. This is not an audio data packet */
181 return(OV_ENOTAUDIO);
182 }
183
184 while(v>1){
185 modebits++;
186 v>>=1;
187 }
188
189 /* read our mode and pre/post windowsize */
190 mode=oggpack_read(&opb,modebits);
191 if(mode==-1)return(OV_EBADPACKET);
192 return(ci->blocksizes[ci->mode_param[mode].blockflag]);
193}
194
195
196static int ilog(ogg_uint32_t v){
197 int ret=0;
198 if(v)--v;
199 while(v){
200 ret++;
201 v>>=1;
202 }
203 return(ret);
204}
205
206int vorbis_dsp_synthesis(vorbis_dsp_state *vd,ogg_packet *op,int decodep){
207 vorbis_info *vi=vd->vi;
208 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
209 int mode,i;
210
211 oggpack_readinit(&vd->opb,op->packet);
212
213 /* Check the packet type */
214 if(oggpack_read(&vd->opb,1)!=0){
215 /* Oops. This is not an audio data packet */
216 return OV_ENOTAUDIO ;
217 }
218
219 /* read our mode and pre/post windowsize */
220 mode=oggpack_read(&vd->opb,ilog(ci->modes));
221 if(mode==-1 || mode>=ci->modes) return OV_EBADPACKET;
222
223 /* shift information we still need from last window */
224 vd->lW=vd->W;
225 vd->W=ci->mode_param[mode].blockflag;
226 for(i=0;i<vi->channels;i++)
227 mdct_shift_right(ci->blocksizes[vd->lW],vd->work[i],vd->mdctright[i]);
228
229 if(vd->W){
230 int temp;
231 oggpack_read(&vd->opb,1);
232 temp=oggpack_read(&vd->opb,1);
233 if(temp==-1) return OV_EBADPACKET;
234 }
235
236 /* packet decode and portions of synthesis that rely on only this block */
237 if(decodep){
238 mapping_inverse(vd,ci->map_param+ci->mode_param[mode].mapping);
239
240 if(vd->out_begin==-1){
241 vd->out_begin=0;
242 vd->out_end=0;
243 }else{
244 vd->out_begin=0;
245 vd->out_end=ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
246 }
247 }
248
249 /* track the frame number... This is for convenience, but also
250 making sure our last packet doesn't end with added padding.
251
252 This is not foolproof! It will be confused if we begin
253 decoding at the last page after a seek or hole. In that case,
254 we don't have a starting point to judge where the last frame
255 is. For this reason, vorbisfile will always try to make sure
256 it reads the last two marked pages in proper sequence */
257
258 /* if we're out of sequence, dump granpos tracking until we sync back up */
259 if(vd->sequence==-1 || vd->sequence+1 != op->packetno-3){
260 /* out of sequence; lose count */
261 vd->granulepos=-1;
262 vd->sample_count=-1;
263 }
264
265 vd->sequence=op->packetno;
266 vd->sequence=vd->sequence-3;
267
268 if(vd->sample_count==-1){
269 vd->sample_count=0;
270 }else{
271 vd->sample_count+=
272 ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
273 }
274
275 if(vd->granulepos==-1){
276 if(op->granulepos!=-1){ /* only set if we have a
277 position to set to */
278
279 vd->granulepos=op->granulepos;
280
281 /* is this a short page? */
282 if(vd->sample_count>vd->granulepos){
283 /* corner case; if this is both the first and last audio page,
284 then spec says the end is cut, not beginning */
285 if(op->e_o_s){
286 /* trim the end */
287 /* no preceeding granulepos; assume we started at zero (we'd
288 have to in a short single-page stream) */
289 /* granulepos could be -1 due to a seek, but that would result
290 in a long coun t, not short count */
291
292 vd->out_end-=(int)(vd->sample_count-vd->granulepos);
293 }else{
294 /* trim the beginning */
295 vd->out_begin+=(int)(vd->sample_count-vd->granulepos);
296 if(vd->out_begin>vd->out_end)
297 vd->out_begin=vd->out_end;
298 }
299
300 }
301
302 }
303 }else{
304 vd->granulepos+=
305 ci->blocksizes[vd->lW]/4+ci->blocksizes[vd->W]/4;
306 if(op->granulepos!=-1 && vd->granulepos!=op->granulepos){
307
308 if(vd->granulepos>op->granulepos){
309 long extra=(long)(vd->granulepos-op->granulepos);
310
311 if(extra)
312 if(op->e_o_s){
313 /* partial last frame. Strip the extra samples off */
314 vd->out_end-=extra;
315 } /* else {Shouldn't happen *unless* the bitstream is out of
316 spec. Either way, believe the bitstream } */
317 } /* else {Shouldn't happen *unless* the bitstream is out of
318 spec. Either way, believe the bitstream } */
319 vd->granulepos=op->granulepos;
320 }
321 }
322
323 return(0);
324}