]>
Commit | Line | Data |
---|---|---|
1 | /* JOrbis | |
2 | * Copyright (C) 2000 ymnk, JCraft,Inc. | |
3 | * | |
4 | * Written by: 2000 ymnk<ymnk@jcraft.com> | |
5 | * | |
6 | * Many thanks to | |
7 | * Monty <monty@xiph.org> and | |
8 | * The XIPHOPHORUS Company http://www.xiph.org/ . | |
9 | * JOrbis has been based on their awesome works, Vorbis codec. | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU Library General Public License | |
13 | * as published by the Free Software Foundation; either version 2 of | |
14 | * the License, or (at your option) any later version. | |
15 | ||
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU Library General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU Library General Public | |
22 | * License along with this program; if not, write to the Free Software | |
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 | */ | |
25 | ||
26 | package com.jcraft.jorbis; | |
27 | ||
28 | import com.jcraft.jogg.*; | |
29 | ||
30 | class Residue0 extends FuncResidue{ | |
31 | void pack(Object vr, Buffer opb){ | |
32 | InfoResidue0 info=(InfoResidue0)vr; | |
33 | int acc=0; | |
34 | opb.write(info.begin,24); | |
35 | opb.write(info.end,24); | |
36 | ||
37 | opb.write(info.grouping-1,24); /* residue vectors to group and | |
38 | code with a partitioned book */ | |
39 | opb.write(info.partitions-1,6); /* possible partition choices */ | |
40 | opb.write(info.groupbook,8); /* group huffman book */ | |
41 | ||
42 | /* secondstages is a bitmask; as encoding progresses pass by pass, a | |
43 | bitmask of one indicates this partition class has bits to write | |
44 | this pass */ | |
45 | for(int j=0;j<info.partitions;j++){ | |
46 | if(ilog(info.secondstages[j])>3){ | |
47 | /* yes, this is a minor hack due to not thinking ahead */ | |
48 | opb.write(info.secondstages[j],3); | |
49 | opb.write(1,1); | |
50 | opb.write(info.secondstages[j]>>>3,5); | |
51 | } | |
52 | else{ | |
53 | opb.write(info.secondstages[j],4); /* trailing zero */ | |
54 | } | |
55 | acc+=icount(info.secondstages[j]); | |
56 | } | |
57 | for(int j=0;j<acc;j++){ | |
58 | opb.write(info.booklist[j],8); | |
59 | } | |
60 | } | |
61 | ||
62 | Object unpack(Info vi, Buffer opb){ | |
63 | int acc=0; | |
64 | InfoResidue0 info=new InfoResidue0(); | |
65 | ||
66 | info.begin=opb.read(24); | |
67 | info.end=opb.read(24); | |
68 | info.grouping=opb.read(24)+1; | |
69 | info.partitions=opb.read(6)+1; | |
70 | info.groupbook=opb.read(8); | |
71 | ||
72 | for(int j=0;j<info.partitions;j++){ | |
73 | int cascade=opb.read(3); | |
74 | if(opb.read(1)!=0){ | |
75 | cascade|=(opb.read(5)<<3); | |
76 | } | |
77 | info.secondstages[j]=cascade; | |
78 | acc+=icount(cascade); | |
79 | } | |
80 | ||
81 | for(int j=0;j<acc;j++){ | |
82 | info.booklist[j]=opb.read(8); | |
83 | // if(info.booklist[j]==255)info.booklist[j]=-1; | |
84 | } | |
85 | ||
86 | if(info.groupbook>=vi.books){ | |
87 | free_info(info); | |
88 | return(null); | |
89 | } | |
90 | ||
91 | for(int j=0;j<acc;j++){ | |
92 | if(info.booklist[j]>=vi.books){ | |
93 | free_info(info); | |
94 | return(null); | |
95 | } | |
96 | } | |
97 | return(info); | |
98 | // errout: | |
99 | // free_info(info); | |
100 | // return(NULL); | |
101 | } | |
102 | ||
103 | Object look(DspState vd, InfoMode vm, Object vr){ | |
104 | InfoResidue0 info=(InfoResidue0)vr; | |
105 | LookResidue0 look=new LookResidue0(); | |
106 | int acc=0; | |
107 | int dim; | |
108 | int maxstage=0; | |
109 | look.info=info; | |
110 | look.map=vm.mapping; | |
111 | ||
112 | look.parts=info.partitions; | |
113 | look.fullbooks=vd.fullbooks; | |
114 | look.phrasebook=vd.fullbooks[info.groupbook]; | |
115 | ||
116 | dim=look.phrasebook.dim; | |
117 | ||
118 | look.partbooks=new int[look.parts][]; | |
119 | ||
120 | for(int j=0;j<look.parts;j++){ | |
121 | int stages=ilog(info.secondstages[j]); | |
122 | if(stages!=0){ | |
123 | if(stages>maxstage)maxstage=stages; | |
124 | look.partbooks[j]=new int[stages]; | |
125 | for(int k=0; k<stages; k++){ | |
126 | if((info.secondstages[j]&(1<<k))!=0){ | |
127 | look.partbooks[j][k]=info.booklist[acc++]; | |
128 | } | |
129 | } | |
130 | } | |
131 | } | |
132 | ||
133 | look.partvals=(int)Math.rint(Math.pow(look.parts,dim)); | |
134 | look.stages=maxstage; | |
135 | look.decodemap=new int[look.partvals][]; | |
136 | for(int j=0;j<look.partvals;j++){ | |
137 | int val=j; | |
138 | int mult=look.partvals/look.parts; | |
139 | look.decodemap[j]=new int[dim]; | |
140 | ||
141 | for(int k=0;k<dim;k++){ | |
142 | int deco=val/mult; | |
143 | val-=deco*mult; | |
144 | mult/=look.parts; | |
145 | look.decodemap[j][k]=deco; | |
146 | } | |
147 | } | |
148 | return(look); | |
149 | } | |
150 | void free_info(Object i){} | |
151 | void free_look(Object i){} | |
152 | int forward(Block vb,Object vl, float[][] in, int ch){ | |
153 | System.err.println("Residue0.forward: not implemented"); | |
154 | return 0; | |
155 | } | |
156 | ||
157 | static int[][][] partword=new int[2][][]; // _01inverse is synchronized for | |
158 | // re-using partword | |
159 | synchronized static int _01inverse(Block vb, Object vl, | |
160 | float[][] in,int ch,int decodepart){ | |
161 | int i,j,k,l,s; | |
162 | LookResidue0 look=(LookResidue0 )vl; | |
163 | InfoResidue0 info=look.info; | |
164 | ||
165 | // move all this setup out later | |
166 | int samples_per_partition=info.grouping; | |
167 | int partitions_per_word=look.phrasebook.dim; | |
168 | int n=info.end-info.begin; | |
169 | ||
170 | int partvals=n/samples_per_partition; | |
171 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; | |
172 | ||
173 | if(partword.length<ch){ | |
174 | partword=new int[ch][][]; | |
175 | for(j=0;j<ch;j++){ | |
176 | partword[j]=new int[partwords][]; | |
177 | } | |
178 | } | |
179 | else{ | |
180 | for(j=0;j<ch;j++){ | |
181 | if(partword[j]==null || partword[j].length<partwords) | |
182 | partword[j]=new int[partwords][]; | |
183 | } | |
184 | } | |
185 | ||
186 | for(s=0;s<look.stages;s++){ | |
187 | // each loop decodes on partition codeword containing | |
188 | // partitions_pre_word partitions | |
189 | for(i=0,l=0;i<partvals;l++){ | |
190 | if(s==0){ | |
191 | // fetch the partition word for each channel | |
192 | for(j=0;j<ch;j++){ | |
193 | int temp=look.phrasebook.decode(vb.opb); | |
194 | if(temp==-1){ | |
195 | //goto eopbreak; | |
196 | return(0); | |
197 | } | |
198 | partword[j][l]=look.decodemap[temp]; | |
199 | if(partword[j][l]==null){ | |
200 | // goto errout; | |
201 | return(0); | |
202 | } | |
203 | } | |
204 | } | |
205 | ||
206 | // now we decode residual values for the partitions | |
207 | for(k=0;k<partitions_per_word && i<partvals;k++,i++) | |
208 | for(j=0;j<ch;j++){ | |
209 | int offset=info.begin+i*samples_per_partition; | |
210 | if((info.secondstages[partword[j][l][k]]&(1<<s))!=0){ | |
211 | CodeBook stagebook=look.fullbooks[look.partbooks[partword[j][l][k]][s]]; | |
212 | // CodeBook stagebook=look.partbooks[partword[j][l][k]][s]; | |
213 | if(stagebook!=null){ | |
214 | if(decodepart==0){ | |
215 | if(stagebook.decodevs_add(in[j],offset,vb.opb,samples_per_partition)==-1){ | |
216 | // goto errout; | |
217 | return(0); | |
218 | } | |
219 | } | |
220 | else if(decodepart==1){ | |
221 | if(stagebook.decodev_add(in[j], offset, vb.opb,samples_per_partition)==-1){ | |
222 | // goto errout; | |
223 | return(0); | |
224 | } | |
225 | } | |
226 | } | |
227 | } | |
228 | } | |
229 | } | |
230 | } | |
231 | // errout: | |
232 | // eopbreak: | |
233 | return(0); | |
234 | } | |
235 | ||
236 | static int _2inverse(Block vb, Object vl, float[][] in, int ch){ | |
237 | int i,j,k,l,s; | |
238 | LookResidue0 look=(LookResidue0 )vl; | |
239 | InfoResidue0 info=look.info; | |
240 | ||
241 | // move all this setup out later | |
242 | int samples_per_partition=info.grouping; | |
243 | int partitions_per_word=look.phrasebook.dim; | |
244 | int n=info.end-info.begin; | |
245 | ||
246 | int partvals=n/samples_per_partition; | |
247 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; | |
248 | ||
249 | int[][] partword=new int[partwords][]; | |
250 | for(s=0;s<look.stages;s++){ | |
251 | for(i=0,l=0;i<partvals;l++){ | |
252 | if(s==0){ | |
253 | // fetch the partition word for each channel | |
254 | int temp=look.phrasebook.decode(vb.opb); | |
255 | if(temp==-1){ | |
256 | // goto eopbreak; | |
257 | return(0); | |
258 | } | |
259 | partword[l]=look.decodemap[temp]; | |
260 | if(partword[l]==null){ | |
261 | // goto errout; | |
262 | return(0); | |
263 | } | |
264 | } | |
265 | ||
266 | // now we decode residual values for the partitions | |
267 | for(k=0;k<partitions_per_word && i<partvals;k++,i++){ | |
268 | int offset=info.begin+i*samples_per_partition; | |
269 | if((info.secondstages[partword[l][k]]&(1<<s))!=0){ | |
270 | CodeBook stagebook=look.fullbooks[look.partbooks[partword[l][k]][s]]; | |
271 | if(stagebook!=null){ | |
272 | if(stagebook.decodevv_add(in, offset, ch, vb.opb,samples_per_partition)==-1){ | |
273 | // goto errout; | |
274 | return(0); | |
275 | } | |
276 | } | |
277 | } | |
278 | } | |
279 | } | |
280 | } | |
281 | // errout: | |
282 | // eopbreak: | |
283 | return(0); | |
284 | } | |
285 | ||
286 | int inverse(Block vb, Object vl, float[][] in, int[] nonzero, int ch){ | |
287 | //System.err.println("Residue0.inverse"); | |
288 | int used=0; | |
289 | for(int i=0;i<ch;i++){ | |
290 | if(nonzero[i]!=0){ | |
291 | in[used++]=in[i]; | |
292 | } | |
293 | } | |
294 | if(used!=0) | |
295 | return(_01inverse(vb,vl,in,used,0)); | |
296 | else | |
297 | return(0); | |
298 | } | |
299 | ||
300 | /* | |
301 | int inverse(Block vb, Object vl, float[][] in, int ch){ | |
302 | //System.err.println("Residue0.inverse"); | |
303 | int i,j,k,l,transend=vb.pcmend/2; | |
304 | LookResidue0 look=(LookResidue0 )vl; | |
305 | InfoResidue0 info=look.info; | |
306 | ||
307 | // move all this setup out later | |
308 | int samples_per_partition=info.grouping; | |
309 | int partitions_per_word=look.phrasebook.dim; | |
310 | int n=info.end-info.begin; | |
311 | ||
312 | int partvals=n/samples_per_partition; | |
313 | int partwords=(partvals+partitions_per_word-1)/partitions_per_word; | |
314 | int[][] partword=new int[ch][]; | |
315 | float[] work=new float[samples_per_partition]; | |
316 | partvals=partwords*partitions_per_word; | |
317 | ||
318 | // make sure we're zeroed up to the start | |
319 | for(j=0;j<ch;j++){ | |
320 | for(k=0; k<info.begin; k++)in[j][k]=0.0f; | |
321 | } | |
322 | ||
323 | for(i=info.begin,l=0;i<info.end;){ | |
324 | // fetch the partition word for each channel | |
325 | for(j=0;j<ch;j++){ | |
326 | int temp=look.phrasebook.decode(vb.opb); | |
327 | if(temp==-1){ | |
328 | //goto eopbreak; | |
329 | if(i<transend){ | |
330 | for(j=0;j<ch;j++){ | |
331 | for(k=0;k<transend-i;k++)in[j][i+k]=0.0f; | |
332 | } | |
333 | } | |
334 | return(0); | |
335 | } | |
336 | partword[j]=look.decodemap[temp]; | |
337 | if(partword[j]==null){ | |
338 | //goto errout; | |
339 | for(j=0;j<ch;j++){ | |
340 | for(k=0;k<transend;k++)in[j][k]=0.0f; | |
341 | } | |
342 | return(0); | |
343 | } | |
344 | } | |
345 | ||
346 | // now we decode interleaved residual values for the partitions | |
347 | for(k=0;k<partitions_per_word;k++,l++,i+=samples_per_partition){ | |
348 | for(j=0;j<ch;j++){ | |
349 | int part=partword[j][k]; | |
350 | if(decodepart(vb.opb,work, in[j], i,samples_per_partition, | |
351 | info.secondstages[part], | |
352 | look.partbooks[part])==-1){ | |
353 | //goto eopbreak; | |
354 | if(i<transend){ | |
355 | for(j=0;j<ch;j++){ | |
356 | for(k=0;k<transend-i;k++)in[j][i+k]=0.0f; | |
357 | } | |
358 | } | |
359 | return(0); | |
360 | } | |
361 | } | |
362 | } | |
363 | } | |
364 | ||
365 | // eopbreak: | |
366 | if(i<transend){ | |
367 | for(j=0;j<ch;j++){ | |
368 | for(k=0;k<transend-i;k++)in[j][i+k]=0.0f; | |
369 | } | |
370 | } | |
371 | return(0); | |
372 | ||
373 | // errout: | |
374 | // for(j=0;j<ch;j++) | |
375 | // for(k=0;k<transend;k++)in[j][k]=0.0f; | |
376 | // return(0); | |
377 | } | |
378 | int decodepart(Buffer opb, float[] work, float[] vec, int veci, | |
379 | int n, int stages, CodeBook[] books){ | |
380 | int i,j; | |
381 | for(i=0;i<n;i++)work[i]=0.0f; | |
382 | ||
383 | for(j=0;j<stages;j++){ | |
384 | int dim=books[j].dim; | |
385 | int step=n/dim; | |
386 | for(i=0;i<step;i++){ | |
387 | if(books[j].decodevs(work, i, opb, step, 0)==-1){ | |
388 | return(-1); | |
389 | } | |
390 | } | |
391 | } | |
392 | for(i=0;i<n;i++){ | |
393 | vec[veci+i]*=work[i]; | |
394 | } | |
395 | return(0); | |
396 | } | |
397 | */ | |
398 | ||
399 | private static int ilog(int v){ | |
400 | int ret=0; | |
401 | while(v!=0){ | |
402 | ret++; | |
403 | v>>>=1; | |
404 | } | |
405 | return(ret); | |
406 | } | |
407 | private static int icount(int v){ | |
408 | int ret=0; | |
409 | while(v!=0){ | |
410 | ret+=(v&1); | |
411 | v>>>=1; | |
412 | } | |
413 | return(ret); | |
414 | } | |
415 | } | |
416 | ||
417 | class LookResidue0 { | |
418 | InfoResidue0 info; | |
419 | int map; | |
420 | ||
421 | int parts; | |
422 | int stages; | |
423 | CodeBook[] fullbooks; | |
424 | CodeBook phrasebook; | |
425 | int[][] partbooks; | |
426 | // CodeBook[][] partbooks; | |
427 | ||
428 | int partvals; | |
429 | int[][] decodemap; | |
430 | ||
431 | int postbits; | |
432 | int phrasebits; | |
433 | // int[][] frames; | |
434 | int frames; | |
435 | } | |
436 | ||
437 | class InfoResidue0{ | |
438 | // block-partitioned VQ coded straight residue | |
439 | int begin; | |
440 | int end; | |
441 | ||
442 | // first stage (lossless partitioning) | |
443 | int grouping; // group n vectors per partition | |
444 | int partitions; // possible codebooks for a partition | |
445 | int groupbook; // huffbook for partitioning | |
446 | int[] secondstages=new int[64]; // expanded out to pointers in lookup | |
447 | int[] booklist=new int[256]; // list of second stage books | |
448 | ||
449 | // encode-only heuristic settings | |
450 | float[] entmax=new float[64]; // book entropy threshholds | |
451 | float[] ampmax=new float[64]; // book amp threshholds | |
452 | int[] subgrp=new int[64]; // book heuristic subgroup size | |
453 | int[] blimit=new int[64]; // subgroup position limits | |
454 | } |