|
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-2002 * |
|
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * |
|
11 * * |
|
12 ******************************************************************** |
|
13 |
|
14 function: residue backend 0, 1 and 2 implementation |
|
15 |
|
16 ********************************************************************/ |
|
17 |
|
18 #include <stdlib.h> |
|
19 #include <string.h> |
|
20 #include <math.h> |
|
21 #include "ogg.h" |
|
22 #include "ivorbiscodec.h" |
|
23 #include "codec_internal.h" |
|
24 #include "registry.h" |
|
25 #include "codebook.h" |
|
26 #include "misc.h" |
|
27 #include "os.h" |
|
28 #include "block.h" |
|
29 |
|
30 typedef struct { |
|
31 vorbis_info_residue0 *info; |
|
32 int map; |
|
33 |
|
34 int parts; |
|
35 int stages; |
|
36 codebook *fullbooks; |
|
37 codebook *phrasebook; |
|
38 codebook ***partbooks; |
|
39 |
|
40 int partvals; |
|
41 int **decodemap; |
|
42 |
|
43 } vorbis_look_residue0; |
|
44 |
|
45 void res0_free_info(vorbis_info_residue *i){ |
|
46 vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; |
|
47 if(info){ |
|
48 memset(info,0,sizeof(*info)); |
|
49 _ogg_free(info); |
|
50 } |
|
51 } |
|
52 |
|
53 void res0_free_look(vorbis_look_residue *i){ |
|
54 int j; |
|
55 if(i){ |
|
56 |
|
57 vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; |
|
58 |
|
59 for(j=0;j<look->parts;j++) |
|
60 if(look->partbooks[j])_ogg_free(look->partbooks[j]); |
|
61 _ogg_free(look->partbooks); |
|
62 for(j=0;j<look->partvals;j++) |
|
63 _ogg_free(look->decodemap[j]); |
|
64 _ogg_free(look->decodemap); |
|
65 |
|
66 memset(look,0,sizeof(*look)); |
|
67 _ogg_free(look); |
|
68 } |
|
69 } |
|
70 |
|
71 static int ilog(unsigned int v){ |
|
72 int ret=0; |
|
73 while(v){ |
|
74 ret++; |
|
75 v>>=1; |
|
76 } |
|
77 return(ret); |
|
78 } |
|
79 |
|
80 static int icount(unsigned int v){ |
|
81 int ret=0; |
|
82 while(v){ |
|
83 ret+=v&1; |
|
84 v>>=1; |
|
85 } |
|
86 return(ret); |
|
87 } |
|
88 |
|
89 /* vorbis_info is for range checking */ |
|
90 vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ |
|
91 int j,acc=0; |
|
92 vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info)); |
|
93 codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; |
|
94 |
|
95 info->begin=oggpack_read(opb,24); |
|
96 info->end=oggpack_read(opb,24); |
|
97 info->grouping=oggpack_read(opb,24)+1; |
|
98 info->partitions=oggpack_read(opb,6)+1; |
|
99 info->groupbook=oggpack_read(opb,8); |
|
100 |
|
101 for(j=0;j<info->partitions;j++){ |
|
102 int cascade=oggpack_read(opb,3); |
|
103 if(oggpack_read(opb,1)) |
|
104 cascade|=(oggpack_read(opb,5)<<3); |
|
105 info->secondstages[j]=cascade; |
|
106 |
|
107 acc+=icount(cascade); |
|
108 } |
|
109 for(j=0;j<acc;j++) |
|
110 info->booklist[j]=oggpack_read(opb,8); |
|
111 |
|
112 if(info->groupbook>=ci->books)goto errout; |
|
113 for(j=0;j<acc;j++) |
|
114 if(info->booklist[j]>=ci->books)goto errout; |
|
115 |
|
116 return(info); |
|
117 errout: |
|
118 res0_free_info(info); |
|
119 return(NULL); |
|
120 } |
|
121 |
|
122 vorbis_look_residue *res0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, |
|
123 vorbis_info_residue *vr){ |
|
124 vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; |
|
125 vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look)); |
|
126 codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; |
|
127 |
|
128 int j,k,acc=0; |
|
129 int dim; |
|
130 int maxstage=0; |
|
131 look->info=info; |
|
132 look->map=vm->mapping; |
|
133 |
|
134 look->parts=info->partitions; |
|
135 look->fullbooks=ci->fullbooks; |
|
136 look->phrasebook=ci->fullbooks+info->groupbook; |
|
137 dim=look->phrasebook->dim; |
|
138 |
|
139 look->partbooks=(codebook ***)_ogg_calloc(look->parts,sizeof(*look->partbooks)); |
|
140 |
|
141 for(j=0;j<look->parts;j++){ |
|
142 int stages=ilog(info->secondstages[j]); |
|
143 if(stages){ |
|
144 if(stages>maxstage)maxstage=stages; |
|
145 look->partbooks[j]=(codebook **)_ogg_calloc(stages,sizeof(*look->partbooks[j])); |
|
146 for(k=0;k<stages;k++) |
|
147 if(info->secondstages[j]&(1<<k)){ |
|
148 look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; |
|
149 #ifdef TRAIN_RES |
|
150 look->training_data[k][j]=calloc(look->partbooks[j][k]->entries, |
|
151 sizeof(***look->training_data)); |
|
152 #endif |
|
153 } |
|
154 } |
|
155 } |
|
156 |
|
157 look->partvals=look->parts; |
|
158 for(j=1;j<dim;j++)look->partvals*=look->parts; |
|
159 look->stages=maxstage; |
|
160 look->decodemap=(int **)_ogg_malloc(look->partvals*sizeof(*look->decodemap)); |
|
161 for(j=0;j<look->partvals;j++){ |
|
162 long val=j; |
|
163 long mult=look->partvals/look->parts; |
|
164 look->decodemap[j]=(int *)_ogg_malloc(dim*sizeof(*look->decodemap[j])); |
|
165 for(k=0;k<dim;k++){ |
|
166 long deco=val/mult; |
|
167 val-=deco*mult; |
|
168 mult/=look->parts; |
|
169 look->decodemap[j][k]=deco; |
|
170 } |
|
171 } |
|
172 |
|
173 return(look); |
|
174 } |
|
175 |
|
176 |
|
177 /* a truncated packet here just means 'stop working'; it's not an error */ |
|
178 static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, |
|
179 ogg_int32_t **in,int ch, |
|
180 long (*decodepart)(codebook *, ogg_int32_t *, |
|
181 oggpack_buffer *,int,int)){ |
|
182 |
|
183 long i,j,k,l,s; |
|
184 vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
|
185 vorbis_info_residue0 *info=look->info; |
|
186 |
|
187 /* move all this setup out later */ |
|
188 int samples_per_partition=info->grouping; |
|
189 int partitions_per_word=look->phrasebook->dim; |
|
190 int max=vb->pcmend>>1; |
|
191 int end=(info->end<max?info->end:max); |
|
192 int n=end-info->begin; |
|
193 |
|
194 if(n>0){ |
|
195 int partvals=n/samples_per_partition; |
|
196 int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
|
197 int ***partword=(int ***)alloca(ch*sizeof(*partword)); |
|
198 |
|
199 for(j=0;j<ch;j++) |
|
200 partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); |
|
201 |
|
202 for(s=0;s<look->stages;s++){ |
|
203 |
|
204 /* each loop decodes on partition codeword containing |
|
205 partitions_pre_word partitions */ |
|
206 for(i=0,l=0;i<partvals;l++){ |
|
207 if(s==0){ |
|
208 /* fetch the partition word for each channel */ |
|
209 for(j=0;j<ch;j++){ |
|
210 int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
|
211 if(temp==-1)goto eopbreak; |
|
212 partword[j][l]=look->decodemap[temp]; |
|
213 if(partword[j][l]==NULL)goto errout; |
|
214 } |
|
215 } |
|
216 |
|
217 /* now we decode residual values for the partitions */ |
|
218 for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
|
219 for(j=0;j<ch;j++){ |
|
220 long offset=info->begin+i*samples_per_partition; |
|
221 if(info->secondstages[partword[j][l][k]]&(1<<s)){ |
|
222 codebook *stagebook=look->partbooks[partword[j][l][k]][s]; |
|
223 if(stagebook){ |
|
224 if(decodepart(stagebook,in[j]+offset,&vb->opb, |
|
225 samples_per_partition,-8)==-1)goto eopbreak; |
|
226 } |
|
227 } |
|
228 } |
|
229 } |
|
230 } |
|
231 } |
|
232 errout: |
|
233 eopbreak: |
|
234 return(0); |
|
235 } |
|
236 |
|
237 int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
|
238 ogg_int32_t **in,int *nonzero,int ch){ |
|
239 int i,used=0; |
|
240 for(i=0;i<ch;i++) |
|
241 if(nonzero[i]) |
|
242 in[used++]=in[i]; |
|
243 if(used) |
|
244 return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add)); |
|
245 else |
|
246 return(0); |
|
247 } |
|
248 |
|
249 int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
|
250 ogg_int32_t **in,int *nonzero,int ch){ |
|
251 int i,used=0; |
|
252 for(i=0;i<ch;i++) |
|
253 if(nonzero[i]) |
|
254 in[used++]=in[i]; |
|
255 if(used) |
|
256 return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add)); |
|
257 else |
|
258 return(0); |
|
259 } |
|
260 |
|
261 /* duplicate code here as speed is somewhat more important */ |
|
262 int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, |
|
263 ogg_int32_t **in,int *nonzero,int ch){ |
|
264 long i,k,l,s; |
|
265 vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; |
|
266 vorbis_info_residue0 *info=look->info; |
|
267 |
|
268 /* move all this setup out later */ |
|
269 int samples_per_partition=info->grouping; |
|
270 int partitions_per_word=look->phrasebook->dim; |
|
271 int max=(vb->pcmend*ch)>>1; |
|
272 int end=(info->end<max?info->end:max); |
|
273 int n=end-info->begin; |
|
274 |
|
275 if(n>0){ |
|
276 |
|
277 int partvals=n/samples_per_partition; |
|
278 int partwords=(partvals+partitions_per_word-1)/partitions_per_word; |
|
279 int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword)); |
|
280 int beginoff=info->begin/ch; |
|
281 |
|
282 for(i=0;i<ch;i++)if(nonzero[i])break; |
|
283 if(i==ch)return(0); /* no nonzero vectors */ |
|
284 |
|
285 samples_per_partition/=ch; |
|
286 |
|
287 for(s=0;s<look->stages;s++){ |
|
288 for(i=0,l=0;i<partvals;l++){ |
|
289 |
|
290 if(s==0){ |
|
291 /* fetch the partition word */ |
|
292 int temp=vorbis_book_decode(look->phrasebook,&vb->opb); |
|
293 if(temp==-1)goto eopbreak; |
|
294 partword[l]=look->decodemap[temp]; |
|
295 if(partword[l]==NULL)goto errout; |
|
296 } |
|
297 |
|
298 /* now we decode residual values for the partitions */ |
|
299 for(k=0;k<partitions_per_word && i<partvals;k++,i++) |
|
300 if(info->secondstages[partword[l][k]]&(1<<s)){ |
|
301 codebook *stagebook=look->partbooks[partword[l][k]][s]; |
|
302 |
|
303 if(stagebook){ |
|
304 if(vorbis_book_decodevv_add(stagebook,in, |
|
305 i*samples_per_partition+beginoff,ch, |
|
306 &vb->opb, |
|
307 samples_per_partition,-8)==-1) |
|
308 goto eopbreak; |
|
309 } |
|
310 } |
|
311 } |
|
312 } |
|
313 } |
|
314 errout: |
|
315 eopbreak: |
|
316 return(0); |
|
317 } |
|
318 |
|
319 |
|
320 vorbis_func_residue residue0_exportbundle={ |
|
321 &res0_unpack, |
|
322 &res0_look, |
|
323 &res0_free_info, |
|
324 &res0_free_look, |
|
325 &res0_inverse |
|
326 }; |
|
327 |
|
328 vorbis_func_residue residue1_exportbundle={ |
|
329 &res0_unpack, |
|
330 &res0_look, |
|
331 &res0_free_info, |
|
332 &res0_free_look, |
|
333 &res1_inverse |
|
334 }; |
|
335 |
|
336 vorbis_func_residue residue2_exportbundle={ |
|
337 &res0_unpack, |
|
338 &res0_look, |
|
339 &res0_free_info, |
|
340 &res0_free_look, |
|
341 &res2_inverse |
|
342 }; |