diff options
Diffstat (limited to 'songdbj/com')
38 files changed, 13089 insertions, 0 deletions
diff --git a/songdbj/com/jcraft/jogg/Buffer.java b/songdbj/com/jcraft/jogg/Buffer.java new file mode 100644 index 0000000000..a40a9def9c --- /dev/null +++ b/songdbj/com/jcraft/jogg/Buffer.java | |||
@@ -0,0 +1,541 @@ | |||
1 | /* -*-mode:java; c-basic-offset:2; -*- */ | ||
2 | /* JOrbis | ||
3 | * Copyright (C) 2000 ymnk, JCraft,Inc. | ||
4 | * | ||
5 | * Written by: 2000 ymnk<ymnk@jcraft.com> | ||
6 | * | ||
7 | * Many thanks to | ||
8 | * Monty <monty@xiph.org> and | ||
9 | * The XIPHOPHORUS Company http://www.xiph.org/ . | ||
10 | * JOrbis has been based on their awesome works, Vorbis codec. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU Library General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 of | ||
15 | * the License, or (at your option) any later version. | ||
16 | |||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | package com.jcraft.jogg; | ||
28 | |||
29 | public class Buffer{ | ||
30 | private static final int BUFFER_INCREMENT=256; | ||
31 | |||
32 | private static final int[] mask={ | ||
33 | 0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f, | ||
34 | 0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff, | ||
35 | 0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff, | ||
36 | 0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, | ||
37 | 0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff, | ||
38 | 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff, | ||
39 | 0x3fffffff,0x7fffffff,0xffffffff | ||
40 | }; | ||
41 | |||
42 | int ptr=0; | ||
43 | byte[] buffer=null; | ||
44 | int endbit=0; | ||
45 | int endbyte=0; | ||
46 | int storage=0; | ||
47 | |||
48 | public void writeinit(){ | ||
49 | buffer=new byte[BUFFER_INCREMENT]; | ||
50 | ptr=0; | ||
51 | buffer[0]=(byte)'\0'; | ||
52 | storage=BUFFER_INCREMENT; | ||
53 | } | ||
54 | |||
55 | public void write(byte[] s){ | ||
56 | for(int i=0; i<s.length; i++){ | ||
57 | if(s[i]==0)break; | ||
58 | write(s[i],8); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | public void read(byte[] s, int bytes){ | ||
63 | int i=0; | ||
64 | while(bytes--!=0){ | ||
65 | s[i++]=(byte)(read(8)); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | void reset(){ | ||
70 | ptr=0; | ||
71 | buffer[0]=(byte)'\0'; | ||
72 | endbit=endbyte=0; | ||
73 | } | ||
74 | |||
75 | public void writeclear(){ | ||
76 | buffer=null; | ||
77 | } | ||
78 | |||
79 | public void readinit(byte[] buf, int bytes){ | ||
80 | readinit(buf, 0, bytes); | ||
81 | } | ||
82 | |||
83 | public void readinit(byte[] buf, int start, int bytes){ | ||
84 | //System.err.println("readinit: start="+start+", bytes="+bytes); | ||
85 | //for(int i=0;i<bytes; i++){ | ||
86 | //System.err.println(i+": "+Integer.toHexString(buf[i+start])); | ||
87 | //} | ||
88 | ptr=start; | ||
89 | buffer=buf; | ||
90 | endbit=endbyte=0; | ||
91 | storage=bytes; | ||
92 | } | ||
93 | |||
94 | public void write(int value, int bits){ | ||
95 | //System.err.println("write: "+Integer.toHexString(value)+", bits="+bits+" ptr="+ptr+", storage="+storage+", endbyte="+endbyte); | ||
96 | if(endbyte+4>=storage){ | ||
97 | byte[] foo=new byte[storage+BUFFER_INCREMENT]; | ||
98 | System.arraycopy(buffer, 0, foo, 0, storage); | ||
99 | buffer=foo; | ||
100 | storage+=BUFFER_INCREMENT; | ||
101 | } | ||
102 | |||
103 | value&=mask[bits]; | ||
104 | bits+=endbit; | ||
105 | buffer[ptr]|=(byte)(value<<endbit); | ||
106 | |||
107 | if(bits>=8){ | ||
108 | buffer[ptr+1]=(byte)(value>>>(8-endbit)); | ||
109 | if(bits>=16){ | ||
110 | buffer[ptr+2]=(byte)(value>>>(16-endbit)); | ||
111 | if(bits>=24){ | ||
112 | buffer[ptr+3]=(byte)(value>>>(24-endbit)); | ||
113 | if(bits>=32){ | ||
114 | if(endbit>0) | ||
115 | buffer[ptr+4]=(byte)(value>>>(32-endbit)); | ||
116 | else | ||
117 | buffer[ptr+4]=0; | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | |||
123 | endbyte+=bits/8; | ||
124 | ptr+=bits/8; | ||
125 | endbit=bits&7; | ||
126 | } | ||
127 | |||
128 | public int look(int bits){ | ||
129 | int ret; | ||
130 | int m=mask[bits]; | ||
131 | |||
132 | bits+=endbit; | ||
133 | |||
134 | //System.err.println("look ptr:"+ptr+", bits="+bits+", endbit="+endbit+", storage="+storage); | ||
135 | |||
136 | if(endbyte+4>=storage){ | ||
137 | if(endbyte+(bits-1)/8>=storage)return(-1); | ||
138 | } | ||
139 | |||
140 | ret=((buffer[ptr])&0xff)>>>endbit; | ||
141 | // ret=((byte)(buffer[ptr]))>>>endbit; | ||
142 | if(bits>8){ | ||
143 | ret|=((buffer[ptr+1])&0xff)<<(8-endbit); | ||
144 | // ret|=((byte)(buffer[ptr+1]))<<(8-endbit); | ||
145 | if(bits>16){ | ||
146 | ret|=((buffer[ptr+2])&0xff)<<(16-endbit); | ||
147 | // ret|=((byte)(buffer[ptr+2]))<<(16-endbit); | ||
148 | if(bits>24){ | ||
149 | ret|=((buffer[ptr+3])&0xff)<<(24-endbit); | ||
150 | //System.err.print("ret="+Integer.toHexString(ret)+", ((byte)(buffer[ptr+3]))="+Integer.toHexString(((buffer[ptr+3])&0xff))); | ||
151 | // ret|=((byte)(buffer[ptr+3]))<<(24-endbit); | ||
152 | //System.err.println(" ->ret="+Integer.toHexString(ret)); | ||
153 | if(bits>32 && endbit!=0){ | ||
154 | ret|=((buffer[ptr+4])&0xff)<<(32-endbit); | ||
155 | // ret|=((byte)(buffer[ptr+4]))<<(32-endbit); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | return(m&ret); | ||
161 | } | ||
162 | |||
163 | public int look1(){ | ||
164 | if(endbyte>=storage)return(-1); | ||
165 | return((buffer[ptr]>>endbit)&1); | ||
166 | } | ||
167 | |||
168 | public void adv(int bits){ | ||
169 | bits+=endbit; | ||
170 | ptr+=bits/8; | ||
171 | endbyte+=bits/8; | ||
172 | endbit=bits&7; | ||
173 | } | ||
174 | |||
175 | public void adv1(){ | ||
176 | ++endbit; | ||
177 | if(endbit>7){ | ||
178 | endbit=0; | ||
179 | ptr++; | ||
180 | endbyte++; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | public int read(int bits){ | ||
185 | //System.err.println(this+" read: bits="+bits+", storage="+storage+", endbyte="+endbyte); | ||
186 | //System.err.println(this+" read: bits="+bits+", storage="+storage+", endbyte="+endbyte+ | ||
187 | // ", ptr="+ptr+", endbit="+endbit+", buf[ptr]="+buffer[ptr]); | ||
188 | |||
189 | int ret; | ||
190 | int m=mask[bits]; | ||
191 | |||
192 | bits+=endbit; | ||
193 | |||
194 | if(endbyte+4>=storage){ | ||
195 | ret=-1; | ||
196 | if(endbyte+(bits-1)/8>=storage){ | ||
197 | ptr+=bits/8; | ||
198 | endbyte+=bits/8; | ||
199 | endbit=bits&7; | ||
200 | return(ret); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | ret=(byte)(buffer[ptr]>>>endbit); | ||
206 | if(bits>8){ | ||
207 | ret|=(buffer[ptr+1]<<(8-endbit)); | ||
208 | if(bits>16){ | ||
209 | ret|=(buffer[ptr+2]<<(16-endbit)); | ||
210 | if(bits>24){ | ||
211 | ret|=(buffer[ptr+3]<<(24-endbit)); | ||
212 | if(bits>32 && endbit>0){ | ||
213 | ret|=(buffer[ptr+4]<<(32-endbit)); | ||
214 | } | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | */ | ||
219 | ret=((buffer[ptr])&0xff)>>>endbit; | ||
220 | if(bits>8){ | ||
221 | ret|=((buffer[ptr+1])&0xff)<<(8-endbit); | ||
222 | // ret|=((byte)(buffer[ptr+1]))<<(8-endbit); | ||
223 | if(bits>16){ | ||
224 | ret|=((buffer[ptr+2])&0xff)<<(16-endbit); | ||
225 | // ret|=((byte)(buffer[ptr+2]))<<(16-endbit); | ||
226 | if(bits>24){ | ||
227 | ret|=((buffer[ptr+3])&0xff)<<(24-endbit); | ||
228 | // ret|=((byte)(buffer[ptr+3]))<<(24-endbit); | ||
229 | if(bits>32 && endbit!=0){ | ||
230 | ret|=((buffer[ptr+4])&0xff)<<(32-endbit); | ||
231 | // ret|=((byte)(buffer[ptr+4]))<<(32-endbit); | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | ret&=m; | ||
238 | |||
239 | ptr+=bits/8; | ||
240 | // ptr=bits/8; | ||
241 | endbyte+=bits/8; | ||
242 | // endbyte=bits/8; | ||
243 | endbit=bits&7; | ||
244 | return(ret); | ||
245 | } | ||
246 | |||
247 | public int readB(int bits){ | ||
248 | //System.err.println(this+" read: bits="+bits+", storage="+storage+", endbyte="+endbyte+ | ||
249 | // ", ptr="+ptr+", endbit="+endbit+", buf[ptr]="+buffer[ptr]); | ||
250 | int ret; | ||
251 | int m=32-bits; | ||
252 | |||
253 | bits+=endbit; | ||
254 | |||
255 | if(endbyte+4>=storage){ | ||
256 | /* not the main path */ | ||
257 | ret=-1; | ||
258 | if(endbyte*8+bits>storage*8) { | ||
259 | ptr+=bits/8; | ||
260 | endbyte+=bits/8; | ||
261 | endbit=bits&7; | ||
262 | return(ret); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | ret=(buffer[ptr]&0xff)<<(24+endbit); | ||
267 | if(bits>8){ | ||
268 | ret|=(buffer[ptr+1]&0xff)<<(16+endbit); | ||
269 | if(bits>16){ | ||
270 | ret|=(buffer[ptr+2]&0xff)<<(8+endbit); | ||
271 | if(bits>24){ | ||
272 | ret|=(buffer[ptr+3]&0xff)<<(endbit); | ||
273 | if(bits>32 && (endbit != 0)) | ||
274 | ret|=(buffer[ptr+4]&0xff)>>(8-endbit); | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | ret=(ret>>>(m>>1))>>>((m+1)>>1); | ||
279 | |||
280 | ptr+=bits/8; | ||
281 | endbyte+=bits/8; | ||
282 | endbit=bits&7; | ||
283 | return(ret); | ||
284 | } | ||
285 | |||
286 | public int read1(){ | ||
287 | int ret; | ||
288 | if(endbyte>=storage){ | ||
289 | ret=-1; | ||
290 | endbit++; | ||
291 | if(endbit>7){ | ||
292 | endbit=0; | ||
293 | ptr++; | ||
294 | endbyte++; | ||
295 | } | ||
296 | return(ret); | ||
297 | } | ||
298 | |||
299 | ret=(buffer[ptr]>>endbit)&1; | ||
300 | |||
301 | endbit++; | ||
302 | if(endbit>7){ | ||
303 | endbit=0; | ||
304 | ptr++; | ||
305 | endbyte++; | ||
306 | } | ||
307 | return(ret); | ||
308 | } | ||
309 | |||
310 | public int bytes(){ | ||
311 | return(endbyte+(endbit+7)/8); | ||
312 | } | ||
313 | |||
314 | public int bits(){ | ||
315 | return(endbyte*8+endbit); | ||
316 | } | ||
317 | |||
318 | public byte[] buffer(){ | ||
319 | return(buffer); | ||
320 | } | ||
321 | |||
322 | public static int ilog(int v){ | ||
323 | int ret=0; | ||
324 | while(v>0){ | ||
325 | ret++; | ||
326 | v>>>=1; | ||
327 | } | ||
328 | return(ret); | ||
329 | } | ||
330 | |||
331 | public static void report(String in){ | ||
332 | System.err.println(in); | ||
333 | System.exit(1); | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | static void cliptest(int[] b, int vals, int bits, int[] comp, int compsize){ | ||
338 | int bytes; | ||
339 | byte[] buffer; | ||
340 | |||
341 | o.reset(); | ||
342 | for(int i=0;i<vals;i++){ | ||
343 | o.write(b[i],((bits!=0)?bits:ilog(b[i]))); | ||
344 | } | ||
345 | buffer=o.buffer(); | ||
346 | bytes=o.bytes(); | ||
347 | System.err.println("cliptest: bytes="+bytes); | ||
348 | if(bytes!=compsize)report("wrong number of bytes!\n"); | ||
349 | for(int i=0;i<bytes;i++){ | ||
350 | if(buffer[i]!=(byte)comp[i]){ | ||
351 | for(int j=0;j<bytes;j++){ | ||
352 | System.err.println(j+": "+Integer.toHexString(buffer[j])+" "+ | ||
353 | Integer.toHexString(comp[j])); | ||
354 | } | ||
355 | report("wrote incorrect value!\n"); | ||
356 | } | ||
357 | } | ||
358 | System.err.println("bits: "+bits); | ||
359 | r.readinit(buffer,bytes); | ||
360 | for(int i=0;i<vals;i++){ | ||
361 | int tbit=(bits!=0)?bits:ilog(b[i]); | ||
362 | System.err.println(Integer.toHexString(b[i])+" tbit: "+tbit); | ||
363 | if(r.look(tbit)==-1){ | ||
364 | report("out of data!\n"); | ||
365 | } | ||
366 | if(r.look(tbit)!=(b[i]&mask[tbit])){ | ||
367 | report(i+" looked at incorrect value! "+Integer.toHexString(r.look(tbit))+", "+Integer.toHexString(b[i]&mask[tbit])+":"+b[i]+" bit="+tbit); | ||
368 | } | ||
369 | if(tbit==1){ | ||
370 | if(r.look1()!=(b[i]&mask[tbit])){ | ||
371 | report("looked at single bit incorrect value!\n"); | ||
372 | } | ||
373 | } | ||
374 | if(tbit==1){ | ||
375 | if(r.read1()!=(b[i]&mask[tbit])){ | ||
376 | report("read incorrect single bit value!\n"); | ||
377 | } | ||
378 | } | ||
379 | else{ | ||
380 | if(r.read(tbit)!=(b[i]&mask[tbit])){ | ||
381 | report("read incorrect value!\n"); | ||
382 | } | ||
383 | } | ||
384 | } | ||
385 | if(r.bytes()!=bytes){ | ||
386 | report("leftover bytes after read!\n"); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | static int[] testbuffer1= | ||
391 | {18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7, | ||
392 | 567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4}; | ||
393 | static int test1size=43; | ||
394 | |||
395 | static int[] testbuffer2= | ||
396 | {216531625,1237861823,56732452,131,3212421,12325343,34547562,12313212, | ||
397 | 1233432,534,5,346435231,14436467,7869299,76326614,167548585, | ||
398 | 85525151,0,12321,1,349528352}; | ||
399 | static int test2size=21; | ||
400 | |||
401 | static int[] large= | ||
402 | {2136531625,2137861823,56732452,131,3212421,12325343,34547562,12313212, | ||
403 | 1233432,534,5,2146435231,14436467,7869299,76326614,167548585, | ||
404 | 85525151,0,12321,1,2146528352}; | ||
405 | |||
406 | static int[] testbuffer3= | ||
407 | {1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1, | ||
408 | 0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1}; | ||
409 | static int test3size=56; | ||
410 | |||
411 | static int onesize=33; | ||
412 | static int[] one={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40, | ||
413 | 34,242,223,136,35,222,211,86,171,50,225,135,214,75,172, | ||
414 | 223,4}; | ||
415 | |||
416 | static int twosize=6; | ||
417 | static int[] two={61,255,255,251,231,29}; | ||
418 | |||
419 | static int threesize=54; | ||
420 | static int[] three={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254, | ||
421 | 142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83, | ||
422 | 58,135,196,61,55,129,183,54,101,100,170,37,127,126,10, | ||
423 | 100,52,4,14,18,86,77,1}; | ||
424 | |||
425 | static int foursize=38; | ||
426 | static int[] four={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72, | ||
427 | 132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169, | ||
428 | 28,2,133,0,1}; | ||
429 | |||
430 | static int fivesize=45; | ||
431 | static int[] five={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62, | ||
432 | 241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169, | ||
433 | 84,75,159,2,1,0,132,192,8,0,0,18,22}; | ||
434 | |||
435 | static int sixsize=7; | ||
436 | static int[] six={17,177,170,242,169,19,148}; | ||
437 | |||
438 | static Buffer o=new Buffer(); | ||
439 | static Buffer r=new Buffer(); | ||
440 | |||
441 | public static void main(String[] arg){ | ||
442 | byte[] buffer; | ||
443 | int bytes; | ||
444 | // o=new Buffer(); | ||
445 | // r=new Buffer(); | ||
446 | |||
447 | o.writeinit(); | ||
448 | |||
449 | System.err.print("\nSmall preclipped packing: "); | ||
450 | cliptest(testbuffer1,test1size,0,one,onesize); | ||
451 | System.err.print("ok."); | ||
452 | |||
453 | System.err.print("\nNull bit call: "); | ||
454 | cliptest(testbuffer3,test3size,0,two,twosize); | ||
455 | System.err.print("ok."); | ||
456 | |||
457 | System.err.print("\nLarge preclipped packing: "); | ||
458 | cliptest(testbuffer2,test2size,0,three,threesize); | ||
459 | System.err.print("ok."); | ||
460 | |||
461 | System.err.print("\n32 bit preclipped packing: "); | ||
462 | o.reset(); | ||
463 | for(int i=0;i<test2size;i++) | ||
464 | o.write(large[i],32); | ||
465 | buffer=o.buffer(); | ||
466 | bytes=o.bytes(); | ||
467 | |||
468 | |||
469 | r.readinit(buffer,bytes); | ||
470 | for(int i=0;i<test2size;i++){ | ||
471 | if(r.look(32)==-1){ | ||
472 | report("out of data. failed!"); | ||
473 | } | ||
474 | if(r.look(32)!=large[i]){ | ||
475 | System.err.print(r.look(32)+" != "+large[i]+" ("+ | ||
476 | Integer.toHexString(r.look(32))+"!="+ | ||
477 | Integer.toHexString(large[i])+")"); | ||
478 | report("read incorrect value!\n"); | ||
479 | } | ||
480 | r.adv(32); | ||
481 | } | ||
482 | if(r.bytes()!=bytes)report("leftover bytes after read!\n"); | ||
483 | System.err.print("ok."); | ||
484 | |||
485 | System.err.print("\nSmall unclipped packing: "); | ||
486 | cliptest(testbuffer1,test1size,7,four,foursize); | ||
487 | System.err.print("ok."); | ||
488 | |||
489 | System.err.print("\nLarge unclipped packing: "); | ||
490 | cliptest(testbuffer2,test2size,17,five,fivesize); | ||
491 | System.err.print("ok."); | ||
492 | |||
493 | System.err.print("\nSingle bit unclicpped packing: "); | ||
494 | cliptest(testbuffer3,test3size,1,six,sixsize); | ||
495 | System.err.print("ok."); | ||
496 | |||
497 | System.err.print("\nTesting read past end: "); | ||
498 | r.readinit("\0\0\0\0\0\0\0\0".getBytes(),8); | ||
499 | for(int i=0;i<64;i++){ | ||
500 | if(r.read(1)!=0){ | ||
501 | System.err.print("failed; got -1 prematurely.\n"); | ||
502 | System.exit(1); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | if(r.look(1)!=-1 || | ||
507 | r.read(1)!=-1){ | ||
508 | System.err.print("failed; read past end without -1.\n"); | ||
509 | System.exit(1); | ||
510 | } | ||
511 | |||
512 | r.readinit("\0\0\0\0\0\0\0\0".getBytes(),8); | ||
513 | if(r.read(30)!=0 || r.read(16)!=0){ | ||
514 | System.err.print("failed 2; got -1 prematurely.\n"); | ||
515 | System.exit(1); | ||
516 | } | ||
517 | |||
518 | if(r.look(18)!=0 || | ||
519 | r.look(18)!=0){ | ||
520 | System.err.print("failed 3; got -1 prematurely.\n"); | ||
521 | System.exit(1); | ||
522 | } | ||
523 | if(r.look(19)!=-1 || | ||
524 | r.look(19)!=-1){ | ||
525 | System.err.print("failed; read past end without -1.\n"); | ||
526 | System.exit(1); | ||
527 | } | ||
528 | if(r.look(32)!=-1 || | ||
529 | r.look(32)!=-1){ | ||
530 | System.err.print("failed; read past end without -1.\n"); | ||
531 | System.exit(1); | ||
532 | } | ||
533 | System.err.print("ok.\n\n"); | ||
534 | } | ||
535 | */ | ||
536 | } | ||
537 | |||
538 | |||
539 | |||
540 | |||
541 | |||
diff --git a/songdbj/com/jcraft/jogg/Packet.java b/songdbj/com/jcraft/jogg/Packet.java new file mode 100644 index 0000000000..22a8a5439b --- /dev/null +++ b/songdbj/com/jcraft/jogg/Packet.java | |||
@@ -0,0 +1,82 @@ | |||
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.jogg; | ||
27 | |||
28 | public class Packet{ | ||
29 | public byte[] packet_base; | ||
30 | public int packet; | ||
31 | public int bytes; | ||
32 | public int b_o_s; | ||
33 | public int e_o_s; | ||
34 | |||
35 | public long granulepos; | ||
36 | |||
37 | public long packetno; // sequence number for decode; the framing | ||
38 | // knows where there's a hole in the data, | ||
39 | // but we need coupling so that the codec | ||
40 | // (which is in a seperate abstraction | ||
41 | // layer) also knows about the gap | ||
42 | |||
43 | /* | ||
44 | // TEST | ||
45 | static int sequence=0; | ||
46 | static int lastno=0; | ||
47 | void checkpacket(int len, int no, int pos){ | ||
48 | if(bytes!=len){ | ||
49 | System.err.println("incorrect packet length!"); | ||
50 | System.exit(1); | ||
51 | } | ||
52 | if(granulepos!=pos){ | ||
53 | System.err.println("incorrect packet position!"); | ||
54 | System.exit(1); | ||
55 | } | ||
56 | |||
57 | // packet number just follows sequence/gap; adjust the input number | ||
58 | // for that | ||
59 | if(no==0){ | ||
60 | sequence=0; | ||
61 | } | ||
62 | else{ | ||
63 | sequence++; | ||
64 | if(no>lastno+1) | ||
65 | sequence++; | ||
66 | } | ||
67 | lastno=no; | ||
68 | if(packetno!=sequence){ | ||
69 | System.err.println("incorrect packet sequence "+packetno+" != "+sequence); | ||
70 | System.exit(1); | ||
71 | } | ||
72 | |||
73 | // Test data | ||
74 | for(int j=0;j<bytes;j++){ | ||
75 | if((packet_base[packet+j]&0xff)!=((j+no)&0xff)){ | ||
76 | System.err.println("body data mismatch at pos "+ j+": "+(packet_base[packet+j]&0xff)+"!="+((j+no)&0xff)+"!\n"); | ||
77 | System.exit(1); | ||
78 | } | ||
79 | } | ||
80 | } | ||
81 | */ | ||
82 | } | ||
diff --git a/songdbj/com/jcraft/jogg/Page.java b/songdbj/com/jcraft/jogg/Page.java new file mode 100644 index 0000000000..fc1add010e --- /dev/null +++ b/songdbj/com/jcraft/jogg/Page.java | |||
@@ -0,0 +1,973 @@ | |||
1 | /* -*-mode:java; c-basic-offset:2; -*- */ | ||
2 | /* JOrbis | ||
3 | * Copyright (C) 2000 ymnk, JCraft,Inc. | ||
4 | * | ||
5 | * Written by: 2000 ymnk<ymnk@jcraft.com> | ||
6 | * | ||
7 | * Many thanks to | ||
8 | * Monty <monty@xiph.org> and | ||
9 | * The XIPHOPHORUS Company http://www.xiph.org/ . | ||
10 | * JOrbis has been based on their awesome works, Vorbis codec. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU Library General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 of | ||
15 | * the License, or (at your option) any later version. | ||
16 | |||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | package com.jcraft.jogg; | ||
28 | |||
29 | public class Page{ | ||
30 | private static int[] crc_lookup=new int[256]; | ||
31 | static { | ||
32 | for(int i=0; i<crc_lookup.length; i++){ | ||
33 | crc_lookup[i]=crc_entry(i); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | private static int crc_entry(int index){ | ||
38 | int r=index<<24; | ||
39 | for(int i=0; i<8; i++){ | ||
40 | if((r& 0x80000000)!=0){ | ||
41 | r=(r << 1)^0x04c11db7; /* The same as the ethernet generator | ||
42 | polynomial, although we use an | ||
43 | unreflected alg and an init/final | ||
44 | of 0, not 0xffffffff */ | ||
45 | } | ||
46 | else{ | ||
47 | r<<=1; | ||
48 | } | ||
49 | } | ||
50 | return(r&0xffffffff); | ||
51 | } | ||
52 | |||
53 | public byte[] header_base; | ||
54 | public int header; | ||
55 | public int header_len; | ||
56 | public byte[] body_base; | ||
57 | public int body; | ||
58 | public int body_len; | ||
59 | |||
60 | int version(){ | ||
61 | return header_base[header+4]&0xff; | ||
62 | } | ||
63 | int continued(){ | ||
64 | return (header_base[header+5]&0x01); | ||
65 | } | ||
66 | public int bos(){ | ||
67 | return (header_base[header+5]&0x02); | ||
68 | } | ||
69 | public int eos(){ | ||
70 | return (header_base[header+5]&0x04); | ||
71 | } | ||
72 | public long granulepos(){ | ||
73 | long foo=header_base[header+13]&0xff; | ||
74 | foo=(foo<<8)|(header_base[header+12]&0xff); | ||
75 | foo=(foo<<8)|(header_base[header+11]&0xff); | ||
76 | foo=(foo<<8)|(header_base[header+10]&0xff); | ||
77 | foo=(foo<<8)|(header_base[header+9]&0xff); | ||
78 | foo=(foo<<8)|(header_base[header+8]&0xff); | ||
79 | foo=(foo<<8)|(header_base[header+7]&0xff); | ||
80 | foo=(foo<<8)|(header_base[header+6]&0xff); | ||
81 | return(foo); | ||
82 | } | ||
83 | public int serialno(){ | ||
84 | return (header_base[header+14]&0xff)| | ||
85 | ((header_base[header+15]&0xff)<<8)| | ||
86 | ((header_base[header+16]&0xff)<<16)| | ||
87 | ((header_base[header+17]&0xff)<<24); | ||
88 | } | ||
89 | int pageno(){ | ||
90 | return (header_base[header+18]&0xff)| | ||
91 | ((header_base[header+19]&0xff)<<8)| | ||
92 | ((header_base[header+20]&0xff)<<16)| | ||
93 | ((header_base[header+21]&0xff)<<24); | ||
94 | } | ||
95 | |||
96 | void checksum(){ | ||
97 | int crc_reg=0; | ||
98 | |||
99 | // for(int i=0;i<header_len;i++){ | ||
100 | // System.err.println("chksum: "+Integer.toHexString(header_base[header+i]&0xff)); | ||
101 | // } | ||
102 | |||
103 | for(int i=0;i<header_len;i++){ | ||
104 | crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg>>>24)&0xff)^(header_base[header+i]&0xff)]; | ||
105 | } | ||
106 | for(int i=0;i<body_len;i++){ | ||
107 | crc_reg=(crc_reg<<8)^crc_lookup[((crc_reg>>>24)&0xff)^(body_base[body+i]&0xff)]; | ||
108 | } | ||
109 | header_base[header+22]=(byte)crc_reg/*&0xff*/; | ||
110 | header_base[header+23]=(byte)(crc_reg>>>8)/*&0xff*/; | ||
111 | header_base[header+24]=(byte)(crc_reg>>>16)/*&0xff*/; | ||
112 | header_base[header+25]=(byte)(crc_reg>>>24)/*&0xff*/; | ||
113 | } | ||
114 | public Page copy(){ | ||
115 | return copy(new Page()); | ||
116 | } | ||
117 | public Page copy(Page p){ | ||
118 | byte[] tmp=new byte[header_len]; | ||
119 | System.arraycopy(header_base, header, tmp, 0, header_len); | ||
120 | p.header_len=header_len; | ||
121 | p.header_base=tmp; | ||
122 | p.header=0; | ||
123 | tmp=new byte[body_len]; | ||
124 | System.arraycopy(body_base, body, tmp, 0, body_len); | ||
125 | p.body_len=body_len; | ||
126 | p.body_base=tmp; | ||
127 | p.body=0; | ||
128 | return p; | ||
129 | } | ||
130 | /* | ||
131 | // TEST | ||
132 | static StreamState os_en, os_de; | ||
133 | static SyncState oy; | ||
134 | void check_page(byte[] data_base, int data, int[] _header){ | ||
135 | // Test data | ||
136 | for(int j=0;j<body_len;j++) | ||
137 | if(body_base[body+j]!=data_base[data+j]){ | ||
138 | System.err.println("body data mismatch at pos "+j+": "+data_base[data+j]+"!="+body_base[body+j]+"!\n"); | ||
139 | System.exit(1); | ||
140 | } | ||
141 | |||
142 | // Test header | ||
143 | for(int j=0;j<header_len;j++){ | ||
144 | if((header_base[header+j]&0xff)!=_header[j]){ | ||
145 | System.err.println("header content mismatch at pos "+j); | ||
146 | for(int jj=0;jj<_header[26]+27;jj++) | ||
147 | System.err.print(" ("+jj+")"+Integer.toHexString(_header[jj])+":"+Integer.toHexString(header_base[header+jj])); | ||
148 | System.err.println(""); | ||
149 | System.exit(1); | ||
150 | } | ||
151 | } | ||
152 | if(header_len!=_header[26]+27){ | ||
153 | System.err.print("header length incorrect! ("+header_len+"!="+(_header[26]+27)+")"); | ||
154 | System.exit(1); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | void print_header(){ | ||
159 | System.err.println("\nHEADER:"); | ||
160 | System.err.println(" capture: "+ | ||
161 | (header_base[header+0]&0xff)+" "+ | ||
162 | (header_base[header+1]&0xff)+" "+ | ||
163 | (header_base[header+2]&0xff)+" "+ | ||
164 | (header_base[header+3]&0xff)+" "+ | ||
165 | " version: "+(header_base[header+4]&0xff)+" flags: "+ | ||
166 | (header_base[header+5]&0xff)); | ||
167 | System.err.println(" pcmpos: "+ | ||
168 | (((header_base[header+9]&0xff)<<24)| | ||
169 | ((header_base[header+8]&0xff)<<16)| | ||
170 | ((header_base[header+7]&0xff)<<8)| | ||
171 | ((header_base[header+6]&0xff)))+ | ||
172 | " serialno: "+ | ||
173 | (((header_base[header+17]&0xff)<<24)| | ||
174 | ((header_base[header+16]&0xff)<<16)| | ||
175 | ((header_base[header+15]&0xff)<<8)| | ||
176 | ((header_base[header+14]&0xff)))+ | ||
177 | " pageno: "+ | ||
178 | (((header_base[header+21]&0xff)<<24)| | ||
179 | ((header_base[header+20]&0xff)<<16)| | ||
180 | ((header_base[header+19]&0xff)<<8)| | ||
181 | ((header_base[header+18]&0xff)))); | ||
182 | |||
183 | System.err.println(" checksum: "+ | ||
184 | (header_base[header+22]&0xff)+":"+ | ||
185 | (header_base[header+23]&0xff)+":"+ | ||
186 | (header_base[header+24]&0xff)+":"+ | ||
187 | (header_base[header+25]&0xff)+"\n segments: "+ | ||
188 | (header_base[header+26]&0xff)+" ("); | ||
189 | for(int j=27;j<header_len;j++){ | ||
190 | System.err.println((header_base[header+j]&0xff)+" "); | ||
191 | } | ||
192 | System.err.println(")\n"); | ||
193 | } | ||
194 | |||
195 | void copy_page(){ | ||
196 | byte[] tmp=new byte[header_len]; | ||
197 | System.arraycopy(header_base, header, tmp, 0, header_len); | ||
198 | header_base=tmp; | ||
199 | header=0; | ||
200 | tmp=new byte[body_len]; | ||
201 | System.arraycopy(body_base, body, tmp, 0, body_len); | ||
202 | body_base=tmp; | ||
203 | body=0; | ||
204 | } | ||
205 | |||
206 | static void test_pack(int[] pl, int[][] headers){ | ||
207 | byte[] data=new byte[1024*1024]; // for scripted test cases only | ||
208 | int inptr=0; | ||
209 | int outptr=0; | ||
210 | int deptr=0; | ||
211 | int depacket=0; | ||
212 | int pcm_pos=7; | ||
213 | int packets,pageno=0,pageout=0; | ||
214 | int eosflag=0; | ||
215 | int bosflag=0; | ||
216 | |||
217 | os_en.reset(); | ||
218 | os_de.reset(); | ||
219 | oy.reset(); | ||
220 | |||
221 | for(packets=0;;packets++){ | ||
222 | if(pl[packets]==-1)break; | ||
223 | } | ||
224 | |||
225 | for(int i=0;i<packets;i++){ | ||
226 | // construct a test packet | ||
227 | Packet op=new Packet(); | ||
228 | int len=pl[i]; | ||
229 | op.packet_base=data; | ||
230 | op.packet=inptr; | ||
231 | op.bytes=len; | ||
232 | op.e_o_s=(pl[i+1]<0?1:0); | ||
233 | op.granulepos=pcm_pos; | ||
234 | |||
235 | pcm_pos+=1024; | ||
236 | |||
237 | for(int j=0;j<len;j++){ | ||
238 | data[inptr++]=(byte)(i+j); | ||
239 | } | ||
240 | |||
241 | // submit the test packet | ||
242 | os_en.packetin(op); | ||
243 | |||
244 | // retrieve any finished pages | ||
245 | { | ||
246 | Page og=new Page(); | ||
247 | |||
248 | while(os_en.pageout(og)!=0){ | ||
249 | // We have a page. Check it carefully | ||
250 | //System.err.print(pageno+", "); | ||
251 | if(headers[pageno]==null){ | ||
252 | System.err.println("coded too many pages!"); | ||
253 | System.exit(1); | ||
254 | } | ||
255 | og.check_page(data, outptr, headers[pageno]); | ||
256 | |||
257 | outptr+=og.body_len; | ||
258 | pageno++; | ||
259 | |||
260 | //System.err.println("1# pageno="+pageno+", pageout="+pageout); | ||
261 | |||
262 | // have a complete page; submit it to sync/decode | ||
263 | |||
264 | { | ||
265 | Page og_de=new Page(); | ||
266 | Packet op_de=new Packet(); | ||
267 | int index=oy.buffer(og.header_len+og.body_len); | ||
268 | byte[] buf=oy.data; | ||
269 | System.arraycopy(og.header_base, og.header, buf, index, og.header_len); | ||
270 | System.arraycopy(og.body_base, og.body, buf, index+og.header_len, og.body_len); | ||
271 | oy.wrote(og.header_len+og.body_len); | ||
272 | |||
273 | //System.err.println("2# pageno="+pageno+", pageout="+pageout); | ||
274 | |||
275 | while(oy.pageout(og_de)>0){ | ||
276 | // got a page. Happy happy. Verify that it's good. | ||
277 | |||
278 | og_de.check_page(data, deptr, headers[pageout]); | ||
279 | deptr+=og_de.body_len; | ||
280 | pageout++; | ||
281 | |||
282 | // submit it to deconstitution | ||
283 | os_de.pagein(og_de); | ||
284 | |||
285 | // packets out? | ||
286 | while(os_de.packetout(op_de)>0){ | ||
287 | |||
288 | // verify the packet! | ||
289 | // check data | ||
290 | boolean check=false; | ||
291 | for(int ii=0; ii<op_de.bytes; ii++){ | ||
292 | if(data[depacket+ii]!=op_de.packet_base[op_de.packet+ii]){ | ||
293 | check=true; | ||
294 | break; | ||
295 | } | ||
296 | } | ||
297 | if(check){ | ||
298 | System.err.println("packet data mismatch in decode! pos="+ | ||
299 | depacket); | ||
300 | System.exit(1); | ||
301 | } | ||
302 | |||
303 | // check bos flag | ||
304 | if(bosflag==0 && op_de.b_o_s==0){ | ||
305 | System.err.println("b_o_s flag not set on packet!"); | ||
306 | System.exit(1); | ||
307 | } | ||
308 | if(bosflag!=0 && op_de.b_o_s!=0){ | ||
309 | System.err.println("b_o_s flag incorrectly set on packet!"); | ||
310 | System.exit(1); | ||
311 | } | ||
312 | |||
313 | bosflag=1; | ||
314 | depacket+=op_de.bytes; | ||
315 | |||
316 | // check eos flag | ||
317 | if(eosflag!=0){ | ||
318 | System.err.println("Multiple decoded packets with eos flag!"); | ||
319 | System.exit(1); | ||
320 | } | ||
321 | |||
322 | if(op_de.e_o_s!=0)eosflag=1; | ||
323 | |||
324 | // check pcmpos flag | ||
325 | if(op_de.granulepos!=-1){ | ||
326 | System.err.print(" pcm:"+op_de.granulepos+" "); | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | } | ||
334 | //free(data); | ||
335 | if(headers[pageno]!=null){ | ||
336 | System.err.println("did not write last page!"); | ||
337 | System.exit(1); | ||
338 | } | ||
339 | if(headers[pageout]!=null){ | ||
340 | System.err.println("did not decode last page!"); | ||
341 | System.exit(1); | ||
342 | } | ||
343 | if(inptr!=outptr){ | ||
344 | System.err.println("encoded page data incomplete!"); | ||
345 | System.exit(1); | ||
346 | } | ||
347 | if(inptr!=deptr){ | ||
348 | System.err.println("decoded page data incomplete!"); | ||
349 | System.exit(1); | ||
350 | } | ||
351 | if(inptr!=depacket){ | ||
352 | System.err.println("decoded packet data incomplete!"); | ||
353 | System.exit(1); | ||
354 | } | ||
355 | if(eosflag==0){ | ||
356 | System.err.println("Never got a packet with EOS set!"); | ||
357 | } | ||
358 | System.err.println("ok."); | ||
359 | } | ||
360 | |||
361 | static void error(){ | ||
362 | System.err.println("error!"); | ||
363 | System.exit(1); | ||
364 | } | ||
365 | public static void main(String[] arg){ | ||
366 | |||
367 | os_en=new StreamState(0x04030201); | ||
368 | os_de=new StreamState(0x04030201); | ||
369 | |||
370 | oy=new SyncState(); | ||
371 | |||
372 | // Exercise each code path in the framing code. Also verify that | ||
373 | // the checksums are working. | ||
374 | |||
375 | { | ||
376 | // 17 only | ||
377 | int[] packets={17, -1}; | ||
378 | int[] head1={0x4f,0x67,0x67,0x53,0,0x06, | ||
379 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
380 | 0x01,0x02,0x03,0x04,0,0,0,0, | ||
381 | 0x15,0xed,0xec,0x91, | ||
382 | 1, | ||
383 | 17}; | ||
384 | int[][] headret={head1, null}; | ||
385 | |||
386 | System.err.print("testing single page encoding... "); | ||
387 | test_pack(packets,headret); | ||
388 | } | ||
389 | |||
390 | { | ||
391 | // 17, 254, 255, 256, 500, 510, 600 byte, pad | ||
392 | int[] packets={17, 254, 255, 256, 500, 510, 600, -1}; | ||
393 | int[] head1={0x4f,0x67,0x67,0x53,0,0x02, | ||
394 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
395 | 0x01,0x02,0x03,0x04,0,0,0,0, | ||
396 | 0x59,0x10,0x6c,0x2c, | ||
397 | 1, | ||
398 | 17}; | ||
399 | int[] head2={0x4f,0x67,0x67,0x53,0,0x04, | ||
400 | 0x07,0x18,0x00,0x00,0x00,0x00,0x00,0x00, | ||
401 | 0x01,0x02,0x03,0x04,1,0,0,0, | ||
402 | 0x89,0x33,0x85,0xce, | ||
403 | 13, | ||
404 | 254,255,0,255,1,255,245,255,255,0, | ||
405 | 255,255,90}; | ||
406 | int[][] headret={head1,head2,null}; | ||
407 | |||
408 | System.err.print("testing basic page encoding... "); | ||
409 | test_pack(packets,headret); | ||
410 | } | ||
411 | |||
412 | { | ||
413 | // nil packets; beginning,middle,end | ||
414 | int[] packets={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1}; | ||
415 | |||
416 | int[] head1={0x4f,0x67,0x67,0x53,0,0x02, | ||
417 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
418 | 0x01,0x02,0x03,0x04,0,0,0,0, | ||
419 | 0xff,0x7b,0x23,0x17, | ||
420 | 1, | ||
421 | 0}; | ||
422 | int[] head2={0x4f,0x67,0x67,0x53,0,0x04, | ||
423 | 0x07,0x28,0x00,0x00,0x00,0x00,0x00,0x00, | ||
424 | 0x01,0x02,0x03,0x04,1,0,0,0, | ||
425 | 0x5c,0x3f,0x66,0xcb, | ||
426 | 17, | ||
427 | 17,254,255,0,0,255,1,0,255,245,255,255,0, | ||
428 | 255,255,90,0}; | ||
429 | int[][] headret={head1,head2,null}; | ||
430 | |||
431 | System.err.print("testing basic nil packets... "); | ||
432 | test_pack(packets,headret); | ||
433 | } | ||
434 | |||
435 | { | ||
436 | // large initial packet | ||
437 | int[] packets={4345,259,255,-1}; | ||
438 | |||
439 | int[] head1={0x4f,0x67,0x67,0x53,0,0x02, | ||
440 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
441 | 0x01,0x02,0x03,0x04,0,0,0,0, | ||
442 | 0x01,0x27,0x31,0xaa, | ||
443 | 18, | ||
444 | 255,255,255,255,255,255,255,255, | ||
445 | 255,255,255,255,255,255,255,255,255,10}; | ||
446 | |||
447 | int[] head2={0x4f,0x67,0x67,0x53,0,0x04, | ||
448 | 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, | ||
449 | 0x01,0x02,0x03,0x04,1,0,0,0, | ||
450 | 0x7f,0x4e,0x8a,0xd2, | ||
451 | 4, | ||
452 | 255,4,255,0}; | ||
453 | int[][] headret={head1,head2,null}; | ||
454 | |||
455 | System.err.print("testing initial-packet lacing > 4k... "); | ||
456 | test_pack(packets,headret); | ||
457 | } | ||
458 | |||
459 | { | ||
460 | // continuing packet test | ||
461 | int[] packets={0,4345,259,255,-1}; | ||
462 | |||
463 | int[] head1={0x4f,0x67,0x67,0x53,0,0x02, | ||
464 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
465 | 0x01,0x02,0x03,0x04,0,0,0,0, | ||
466 | 0xff,0x7b,0x23,0x17, | ||
467 | 1, | ||
468 | 0}; | ||
469 | |||
470 | int[] head2={0x4f,0x67,0x67,0x53,0,0x00, | ||
471 | 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
472 | 0x01,0x02,0x03,0x04,1,0,0,0, | ||
473 | 0x34,0x24,0xd5,0x29, | ||
474 | 17, | ||
475 | 255,255,255,255,255,255,255,255, | ||
476 | 255,255,255,255,255,255,255,255,255}; | ||
477 | |||
478 | int[] head3={0x4f,0x67,0x67,0x53,0,0x05, | ||
479 | 0x07,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, | ||
480 | 0x01,0x02,0x03,0x04,2,0,0,0, | ||
481 | 0xc8,0xc3,0xcb,0xed, | ||
482 | 5, | ||
483 | 10,255,4,255,0}; | ||
484 | int[][] headret={head1,head2,head3,null}; | ||
485 | |||
486 | System.err.print("testing single packet page span... "); | ||
487 | test_pack(packets,headret); | ||
488 | } | ||
489 | |||
490 | // page with the 255 segment limit | ||
491 | { | ||
492 | |||
493 | int[] packets={0,10,10,10,10,10,10,10,10, | ||
494 | 10,10,10,10,10,10,10,10, | ||
495 | 10,10,10,10,10,10,10,10, | ||
496 | 10,10,10,10,10,10,10,10, | ||
497 | 10,10,10,10,10,10,10,10, | ||
498 | 10,10,10,10,10,10,10,10, | ||
499 | 10,10,10,10,10,10,10,10, | ||
500 | 10,10,10,10,10,10,10,10, | ||
501 | 10,10,10,10,10,10,10,10, | ||
502 | 10,10,10,10,10,10,10,10, | ||
503 | 10,10,10,10,10,10,10,10, | ||
504 | 10,10,10,10,10,10,10,10, | ||
505 | 10,10,10,10,10,10,10,10, | ||
506 | 10,10,10,10,10,10,10,10, | ||
507 | 10,10,10,10,10,10,10,10, | ||
508 | 10,10,10,10,10,10,10,10, | ||
509 | 10,10,10,10,10,10,10,10, | ||
510 | 10,10,10,10,10,10,10,10, | ||
511 | 10,10,10,10,10,10,10,10, | ||
512 | 10,10,10,10,10,10,10,10, | ||
513 | 10,10,10,10,10,10,10,10, | ||
514 | 10,10,10,10,10,10,10,10, | ||
515 | 10,10,10,10,10,10,10,10, | ||
516 | 10,10,10,10,10,10,10,10, | ||
517 | 10,10,10,10,10,10,10,10, | ||
518 | 10,10,10,10,10,10,10,10, | ||
519 | 10,10,10,10,10,10,10,10, | ||
520 | 10,10,10,10,10,10,10,10, | ||
521 | 10,10,10,10,10,10,10,10, | ||
522 | 10,10,10,10,10,10,10,10, | ||
523 | 10,10,10,10,10,10,10,10, | ||
524 | 10,10,10,10,10,10,10,50,-1}; | ||
525 | |||
526 | int[] head1={0x4f,0x67,0x67,0x53,0,0x02, | ||
527 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
528 | 0x01,0x02,0x03,0x04,0,0,0,0, | ||
529 | 0xff,0x7b,0x23,0x17, | ||
530 | 1, | ||
531 | 0}; | ||
532 | |||
533 | int[] head2={0x4f,0x67,0x67,0x53,0,0x00, | ||
534 | 0x07,0xfc,0x03,0x00,0x00,0x00,0x00,0x00, | ||
535 | 0x01,0x02,0x03,0x04,1,0,0,0, | ||
536 | 0xed,0x2a,0x2e,0xa7, | ||
537 | 255, | ||
538 | 10,10,10,10,10,10,10,10, | ||
539 | 10,10,10,10,10,10,10,10, | ||
540 | 10,10,10,10,10,10,10,10, | ||
541 | 10,10,10,10,10,10,10,10, | ||
542 | 10,10,10,10,10,10,10,10, | ||
543 | 10,10,10,10,10,10,10,10, | ||
544 | 10,10,10,10,10,10,10,10, | ||
545 | 10,10,10,10,10,10,10,10, | ||
546 | 10,10,10,10,10,10,10,10, | ||
547 | 10,10,10,10,10,10,10,10, | ||
548 | 10,10,10,10,10,10,10,10, | ||
549 | 10,10,10,10,10,10,10,10, | ||
550 | 10,10,10,10,10,10,10,10, | ||
551 | 10,10,10,10,10,10,10,10, | ||
552 | 10,10,10,10,10,10,10,10, | ||
553 | 10,10,10,10,10,10,10,10, | ||
554 | 10,10,10,10,10,10,10,10, | ||
555 | 10,10,10,10,10,10,10,10, | ||
556 | 10,10,10,10,10,10,10,10, | ||
557 | 10,10,10,10,10,10,10,10, | ||
558 | 10,10,10,10,10,10,10,10, | ||
559 | 10,10,10,10,10,10,10,10, | ||
560 | 10,10,10,10,10,10,10,10, | ||
561 | 10,10,10,10,10,10,10,10, | ||
562 | 10,10,10,10,10,10,10,10, | ||
563 | 10,10,10,10,10,10,10,10, | ||
564 | 10,10,10,10,10,10,10,10, | ||
565 | 10,10,10,10,10,10,10,10, | ||
566 | 10,10,10,10,10,10,10,10, | ||
567 | 10,10,10,10,10,10,10,10, | ||
568 | 10,10,10,10,10,10,10,10, | ||
569 | 10,10,10,10,10,10,10}; | ||
570 | |||
571 | int[] head3={0x4f,0x67,0x67,0x53,0,0x04, | ||
572 | 0x07,0x00,0x04,0x00,0x00,0x00,0x00,0x00, | ||
573 | 0x01,0x02,0x03,0x04,2,0,0,0, | ||
574 | 0x6c,0x3b,0x82,0x3d, | ||
575 | 1, | ||
576 | 50}; | ||
577 | int[][] headret={head1,head2,head3,null}; | ||
578 | |||
579 | System.err.print("testing max packet segments... "); | ||
580 | test_pack(packets,headret); | ||
581 | } | ||
582 | |||
583 | { | ||
584 | // packet that overspans over an entire page | ||
585 | |||
586 | int[] packets={0,100,9000,259,255,-1}; | ||
587 | |||
588 | int[] head1={0x4f,0x67,0x67,0x53,0,0x02, | ||
589 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
590 | 0x01,0x02,0x03,0x04,0,0,0,0, | ||
591 | 0xff,0x7b,0x23,0x17, | ||
592 | 1, | ||
593 | 0}; | ||
594 | |||
595 | int[] head2={0x4f,0x67,0x67,0x53,0,0x00, | ||
596 | 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, | ||
597 | 0x01,0x02,0x03,0x04,1,0,0,0, | ||
598 | 0x3c,0xd9,0x4d,0x3f, | ||
599 | 17, | ||
600 | 100,255,255,255,255,255,255,255,255, | ||
601 | 255,255,255,255,255,255,255,255}; | ||
602 | |||
603 | int[] head3={0x4f,0x67,0x67,0x53,0,0x01, | ||
604 | 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, | ||
605 | 0x01,0x02,0x03,0x04,2,0,0,0, | ||
606 | 0xbd,0xd5,0xb5,0x8b, | ||
607 | 17, | ||
608 | 255,255,255,255,255,255,255,255, | ||
609 | 255,255,255,255,255,255,255,255,255}; | ||
610 | |||
611 | int[] head4={0x4f,0x67,0x67,0x53,0,0x05, | ||
612 | 0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x00, | ||
613 | 0x01,0x02,0x03,0x04,3,0,0,0, | ||
614 | 0xef,0xdd,0x88,0xde, | ||
615 | 7, | ||
616 | 255,255,75,255,4,255,0}; | ||
617 | int[][] headret={head1,head2,head3,head4,null}; | ||
618 | |||
619 | System.err.print("testing very large packets... "); | ||
620 | test_pack(packets,headret); | ||
621 | } | ||
622 | |||
623 | { | ||
624 | // term only page. why not? | ||
625 | |||
626 | int[] packets={0,100,4080,-1}; | ||
627 | |||
628 | int[] head1={0x4f,0x67,0x67,0x53,0,0x02, | ||
629 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | ||
630 | 0x01,0x02,0x03,0x04,0,0,0,0, | ||
631 | 0xff,0x7b,0x23,0x17, | ||
632 | 1, | ||
633 | 0}; | ||
634 | |||
635 | int[] head2={0x4f,0x67,0x67,0x53,0,0x00, | ||
636 | 0x07,0x04,0x00,0x00,0x00,0x00,0x00,0x00, | ||
637 | 0x01,0x02,0x03,0x04,1,0,0,0, | ||
638 | 0x3c,0xd9,0x4d,0x3f, | ||
639 | 17, | ||
640 | 100,255,255,255,255,255,255,255,255, | ||
641 | 255,255,255,255,255,255,255,255}; | ||
642 | |||
643 | int[] head3={0x4f,0x67,0x67,0x53,0,0x05, | ||
644 | 0x07,0x08,0x00,0x00,0x00,0x00,0x00,0x00, | ||
645 | 0x01,0x02,0x03,0x04,2,0,0,0, | ||
646 | 0xd4,0xe0,0x60,0xe5, | ||
647 | 1,0}; | ||
648 | |||
649 | int[][] headret={head1,head2,head3,null}; | ||
650 | |||
651 | System.err.print("testing zero data page (1 nil packet)... "); | ||
652 | test_pack(packets,headret); | ||
653 | } | ||
654 | |||
655 | { | ||
656 | // build a bunch of pages for testing | ||
657 | byte[] data=new byte[1024*1024]; | ||
658 | int[] pl={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1}; | ||
659 | int inptr=0; | ||
660 | Page[] og=new Page[5]; | ||
661 | for(int i=0; i<5; i++){ | ||
662 | og[i]=new Page(); | ||
663 | } | ||
664 | |||
665 | os_en.reset(); | ||
666 | |||
667 | for(int i=0;pl[i]!=-1;i++){ | ||
668 | Packet op=new Packet(); | ||
669 | int len=pl[i]; | ||
670 | |||
671 | op.packet_base=data; | ||
672 | op.packet=inptr; | ||
673 | op.bytes=len; | ||
674 | op.e_o_s=(pl[i+1]<0?1:0); | ||
675 | op.granulepos=(i+1)*1000; | ||
676 | |||
677 | for(int j=0;j<len;j++)data[inptr++]=(byte)(i+j); | ||
678 | os_en.packetin(op); | ||
679 | } | ||
680 | |||
681 | // free(data); | ||
682 | |||
683 | // retrieve finished pages | ||
684 | for(int i=0;i<5;i++){ | ||
685 | if(os_en.pageout(og[i])==0){ | ||
686 | System.err.print("Too few pages output building sync tests!\n"); | ||
687 | System.exit(1); | ||
688 | } | ||
689 | og[i].copy_page(); | ||
690 | } | ||
691 | |||
692 | // Test lost pages on pagein/packetout: no rollback | ||
693 | { | ||
694 | Page temp=new Page(); | ||
695 | Packet test=new Packet(); | ||
696 | |||
697 | System.err.print("Testing loss of pages... "); | ||
698 | |||
699 | oy.reset(); | ||
700 | os_de.reset(); | ||
701 | for(int i=0;i<5;i++){ | ||
702 | int index=oy.buffer(og[i].header_len); | ||
703 | System.arraycopy(og[i].header_base, og[i].header, | ||
704 | oy.data, index, og[i].header_len); | ||
705 | oy.wrote(og[i].header_len); | ||
706 | index=oy.buffer(og[i].body_len); | ||
707 | System.arraycopy(og[i].body_base, og[i].body, | ||
708 | oy.data, index, og[i].body_len); | ||
709 | oy.wrote(og[i].body_len); | ||
710 | } | ||
711 | |||
712 | oy.pageout(temp); | ||
713 | os_de.pagein(temp); | ||
714 | oy.pageout(temp); | ||
715 | os_de.pagein(temp); | ||
716 | oy.pageout(temp); | ||
717 | |||
718 | // skip | ||
719 | oy.pageout(temp); | ||
720 | os_de.pagein(temp); | ||
721 | |||
722 | // do we get the expected results/packets? | ||
723 | |||
724 | if(os_de.packetout(test)!=1)error(); | ||
725 | test.checkpacket(0,0,0); | ||
726 | if(os_de.packetout(test)!=1)error(); | ||
727 | test.checkpacket(100,1,-1); | ||
728 | if(os_de.packetout(test)!=1)error(); | ||
729 | test.checkpacket(4079,2,3000); | ||
730 | if(os_de.packetout(test)!=-1){ | ||
731 | System.err.println("Error: loss of page did not return error"); | ||
732 | System.exit(1); | ||
733 | } | ||
734 | if(os_de.packetout(test)!=1)error(); | ||
735 | test.checkpacket(76,5,-1); | ||
736 | if(os_de.packetout(test)!=1)error(); | ||
737 | test.checkpacket(34,6,-1); | ||
738 | System.err.println("ok."); | ||
739 | } | ||
740 | |||
741 | // Test lost pages on pagein/packetout: rollback with continuation | ||
742 | { | ||
743 | Page temp=new Page(); | ||
744 | Packet test=new Packet(); | ||
745 | |||
746 | System.err.print("Testing loss of pages (rollback required)... "); | ||
747 | |||
748 | oy.reset(); | ||
749 | os_de.reset(); | ||
750 | for(int i=0;i<5;i++){ | ||
751 | int index=oy.buffer(og[i].header_len); | ||
752 | System.arraycopy(og[i].header_base, og[i].header, | ||
753 | oy.data, index, og[i].header_len); | ||
754 | oy.wrote(og[i].header_len); | ||
755 | index=oy.buffer(og[i].body_len); | ||
756 | System.arraycopy(og[i].body_base, og[i].body, | ||
757 | oy.data, index, og[i].body_len); | ||
758 | oy.wrote(og[i].body_len); | ||
759 | } | ||
760 | |||
761 | oy.pageout(temp); | ||
762 | os_de.pagein(temp); | ||
763 | oy.pageout(temp); | ||
764 | os_de.pagein(temp); | ||
765 | oy.pageout(temp); | ||
766 | os_de.pagein(temp); | ||
767 | oy.pageout(temp); | ||
768 | // skip | ||
769 | oy.pageout(temp); | ||
770 | os_de.pagein(temp); | ||
771 | |||
772 | // do we get the expected results/packets? | ||
773 | |||
774 | if(os_de.packetout(test)!=1)error(); | ||
775 | test.checkpacket(0,0,0); | ||
776 | if(os_de.packetout(test)!=1)error(); | ||
777 | test.checkpacket(100,1,-1); | ||
778 | if(os_de.packetout(test)!=1)error(); | ||
779 | test.checkpacket(4079,2,3000); | ||
780 | if(os_de.packetout(test)!=1)error(); | ||
781 | test.checkpacket(2956,3,4000); | ||
782 | if(os_de.packetout(test)!=-1){ | ||
783 | System.err.println("Error: loss of page did not return error"); | ||
784 | System.exit(1); | ||
785 | } | ||
786 | if(os_de.packetout(test)!=1)error(); | ||
787 | test.checkpacket(300,13,14000); | ||
788 | System.err.println("ok."); | ||
789 | } | ||
790 | |||
791 | // the rest only test sync | ||
792 | { | ||
793 | Page og_de=new Page(); | ||
794 | // Test fractional page inputs: incomplete capture | ||
795 | System.err.print("Testing sync on partial inputs... "); | ||
796 | oy.reset(); | ||
797 | int index=oy.buffer(og[1].header_len); | ||
798 | System.arraycopy(og[1].header_base, og[1].header, | ||
799 | oy.data, index, 3); | ||
800 | oy.wrote(3); | ||
801 | if(oy.pageout(og_de)>0)error(); | ||
802 | |||
803 | // Test fractional page inputs: incomplete fixed header | ||
804 | index=oy.buffer(og[1].header_len); | ||
805 | System.arraycopy(og[1].header_base, og[1].header+3, | ||
806 | oy.data, index, 20); | ||
807 | |||
808 | oy.wrote(20); | ||
809 | if(oy.pageout(og_de)>0)error(); | ||
810 | |||
811 | // Test fractional page inputs: incomplete header | ||
812 | index=oy.buffer(og[1].header_len); | ||
813 | System.arraycopy(og[1].header_base, og[1].header+23, | ||
814 | oy.data, index, 5); | ||
815 | oy.wrote(5); | ||
816 | if(oy.pageout(og_de)>0)error(); | ||
817 | |||
818 | // Test fractional page inputs: incomplete body | ||
819 | index=oy.buffer(og[1].header_len); | ||
820 | System.arraycopy(og[1].header_base, og[1].header+28, | ||
821 | oy.data, index, og[1].header_len-28); | ||
822 | oy.wrote(og[1].header_len-28); | ||
823 | if(oy.pageout(og_de)>0)error(); | ||
824 | |||
825 | index=oy.buffer(og[1].body_len); | ||
826 | System.arraycopy(og[1].body_base, og[1].body, | ||
827 | oy.data, index, 1000); | ||
828 | oy.wrote(1000); | ||
829 | if(oy.pageout(og_de)>0)error(); | ||
830 | |||
831 | index=oy.buffer(og[1].body_len); | ||
832 | System.arraycopy(og[1].body_base, og[1].body+1000, | ||
833 | oy.data, index, og[1].body_len-1000); | ||
834 | oy.wrote(og[1].body_len-1000); | ||
835 | if(oy.pageout(og_de)<=0)error(); | ||
836 | System.err.println("ok."); | ||
837 | } | ||
838 | |||
839 | // Test fractional page inputs: page + incomplete capture | ||
840 | { | ||
841 | Page og_de=new Page(); | ||
842 | System.err.print("Testing sync on 1+partial inputs... "); | ||
843 | oy.reset(); | ||
844 | |||
845 | int index=oy.buffer(og[1].header_len); | ||
846 | System.arraycopy(og[1].header_base, og[1].header, | ||
847 | oy.data, index, og[1].header_len); | ||
848 | oy.wrote(og[1].header_len); | ||
849 | |||
850 | index=oy.buffer(og[1].body_len); | ||
851 | System.arraycopy(og[1].body_base, og[1].body, | ||
852 | oy.data, index, og[1].body_len); | ||
853 | oy.wrote(og[1].body_len); | ||
854 | |||
855 | index=oy.buffer(og[1].header_len); | ||
856 | System.arraycopy(og[1].header_base, og[1].header, | ||
857 | oy.data, index, 20); | ||
858 | oy.wrote(20); | ||
859 | if(oy.pageout(og_de)<=0)error(); | ||
860 | if(oy.pageout(og_de)>0)error(); | ||
861 | |||
862 | index=oy.buffer(og[1].header_len); | ||
863 | System.arraycopy(og[1].header_base, og[1].header+20, | ||
864 | oy.data, index, og[1].header_len-20); | ||
865 | oy.wrote(og[1].header_len-20); | ||
866 | index=oy.buffer(og[1].body_len); | ||
867 | System.arraycopy(og[1].body_base, og[1].body, | ||
868 | oy.data, index, og[1].body_len); | ||
869 | |||
870 | oy.wrote(og[1].body_len); | ||
871 | if(oy.pageout(og_de)<=0)error(); | ||
872 | |||
873 | System.err.println("ok."); | ||
874 | } | ||
875 | |||
876 | // // // // // // // // // | ||
877 | // Test recapture: garbage + page | ||
878 | { | ||
879 | Page og_de=new Page(); | ||
880 | System.err.print("Testing search for capture... "); | ||
881 | oy.reset(); | ||
882 | |||
883 | // 'garbage' | ||
884 | int index=oy.buffer(og[1].body_len); | ||
885 | System.arraycopy(og[1].body_base, og[1].body, | ||
886 | oy.data, index, og[1].body_len); | ||
887 | oy.wrote(og[1].body_len); | ||
888 | |||
889 | index=oy.buffer(og[1].header_len); | ||
890 | System.arraycopy(og[1].header_base, og[1].header, | ||
891 | oy.data, index, og[1].header_len); | ||
892 | oy.wrote(og[1].header_len); | ||
893 | |||
894 | index=oy.buffer(og[1].body_len); | ||
895 | System.arraycopy(og[1].body_base, og[1].body, | ||
896 | oy.data, index, og[1].body_len); | ||
897 | oy.wrote(og[1].body_len); | ||
898 | |||
899 | index=oy.buffer(og[2].header_len); | ||
900 | System.arraycopy(og[2].header_base, og[2].header, | ||
901 | oy.data, index, 20); | ||
902 | |||
903 | oy.wrote(20); | ||
904 | if(oy.pageout(og_de)>0)error(); | ||
905 | if(oy.pageout(og_de)<=0)error(); | ||
906 | if(oy.pageout(og_de)>0)error(); | ||
907 | |||
908 | index=oy.buffer(og[2].header_len); | ||
909 | System.arraycopy(og[2].header_base, og[2].header+20, | ||
910 | oy.data, index, og[2].header_len-20); | ||
911 | oy.wrote(og[2].header_len-20); | ||
912 | index=oy.buffer(og[2].body_len); | ||
913 | System.arraycopy(og[2].body_base, og[2].body, | ||
914 | oy.data, index, og[2].body_len); | ||
915 | oy.wrote(og[2].body_len); | ||
916 | if(oy.pageout(og_de)<=0)error(); | ||
917 | |||
918 | System.err.println("ok."); | ||
919 | } | ||
920 | |||
921 | // Test recapture: page + garbage + page | ||
922 | { | ||
923 | Page og_de=new Page(); | ||
924 | System.err.print("Testing recapture... "); | ||
925 | oy.reset(); | ||
926 | |||
927 | int index=oy.buffer(og[1].header_len); | ||
928 | System.arraycopy(og[1].header_base, og[1].header, | ||
929 | oy.data, index, og[1].header_len); | ||
930 | oy.wrote(og[1].header_len); | ||
931 | |||
932 | index=oy.buffer(og[1].body_len); | ||
933 | System.arraycopy(og[1].body_base, og[1].body, | ||
934 | oy.data, index, og[1].body_len); | ||
935 | oy.wrote(og[1].body_len); | ||
936 | |||
937 | index=oy.buffer(og[2].header_len); | ||
938 | System.arraycopy(og[2].header_base, og[2].header, | ||
939 | oy.data, index, og[2].header_len); | ||
940 | oy.wrote(og[2].header_len); | ||
941 | |||
942 | index=oy.buffer(og[2].header_len); | ||
943 | System.arraycopy(og[2].header_base, og[2].header, | ||
944 | oy.data, index, og[2].header_len); | ||
945 | oy.wrote(og[2].header_len); | ||
946 | |||
947 | if(oy.pageout(og_de)<=0)error(); | ||
948 | |||
949 | index=oy.buffer(og[2].body_len); | ||
950 | System.arraycopy(og[2].body_base, og[2].body, | ||
951 | oy.data, index, og[2].body_len-5); | ||
952 | oy.wrote(og[2].body_len-5); | ||
953 | |||
954 | index=oy.buffer(og[3].header_len); | ||
955 | System.arraycopy(og[3].header_base, og[3].header, | ||
956 | oy.data, index, og[3].header_len); | ||
957 | oy.wrote(og[3].header_len); | ||
958 | |||
959 | index=oy.buffer(og[3].body_len); | ||
960 | System.arraycopy(og[3].body_base, og[3].body, | ||
961 | oy.data, index, og[3].body_len); | ||
962 | oy.wrote(og[3].body_len); | ||
963 | |||
964 | if(oy.pageout(og_de)>0)error(); | ||
965 | if(oy.pageout(og_de)<=0)error(); | ||
966 | |||
967 | System.err.println("ok."); | ||
968 | } | ||
969 | } | ||
970 | //return(0); | ||
971 | } | ||
972 | */ | ||
973 | } | ||
diff --git a/songdbj/com/jcraft/jogg/StreamState.java b/songdbj/com/jcraft/jogg/StreamState.java new file mode 100644 index 0000000000..2f34b374f8 --- /dev/null +++ b/songdbj/com/jcraft/jogg/StreamState.java | |||
@@ -0,0 +1,657 @@ | |||
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.jogg; | ||
27 | |||
28 | public class StreamState{ | ||
29 | byte[] body_data; /* bytes from packet bodies */ | ||
30 | int body_storage; /* storage elements allocated */ | ||
31 | int body_fill; /* elements stored; fill mark */ | ||
32 | private int body_returned; /* elements of fill returned */ | ||
33 | |||
34 | |||
35 | int[] lacing_vals; /* The values that will go to the segment table */ | ||
36 | long[] granule_vals; /* pcm_pos values for headers. Not compact | ||
37 | this way, but it is simple coupled to the | ||
38 | lacing fifo */ | ||
39 | int lacing_storage; | ||
40 | int lacing_fill; | ||
41 | int lacing_packet; | ||
42 | int lacing_returned; | ||
43 | |||
44 | byte[] header=new byte[282]; /* working space for header encode */ | ||
45 | int header_fill; | ||
46 | |||
47 | public int e_o_s; /* set when we have buffered the last packet in the | ||
48 | logical bitstream */ | ||
49 | int b_o_s; /* set after we've written the initial page | ||
50 | of a logical bitstream */ | ||
51 | int serialno; | ||
52 | int pageno; | ||
53 | long packetno; /* sequence number for decode; the framing | ||
54 | knows where there's a hole in the data, | ||
55 | but we need coupling so that the codec | ||
56 | (which is in a seperate abstraction | ||
57 | layer) also knows about the gap */ | ||
58 | long granulepos; | ||
59 | |||
60 | public StreamState(){ | ||
61 | init(); | ||
62 | } | ||
63 | |||
64 | StreamState(int serialno){ | ||
65 | this(); | ||
66 | init(serialno); | ||
67 | } | ||
68 | void init(){ | ||
69 | body_storage=16*1024; | ||
70 | body_data=new byte[body_storage]; | ||
71 | lacing_storage=1024; | ||
72 | lacing_vals=new int[lacing_storage]; | ||
73 | granule_vals=new long[lacing_storage]; | ||
74 | } | ||
75 | public void init(int serialno){ | ||
76 | if(body_data==null){ init(); } | ||
77 | else{ | ||
78 | for(int i=0; i<body_data.length; i++) body_data[i]=0; | ||
79 | for(int i=0; i<lacing_vals.length; i++) lacing_vals[i]=0; | ||
80 | for(int i=0; i<granule_vals.length; i++) granule_vals[i]=0; | ||
81 | } | ||
82 | this.serialno=serialno; | ||
83 | } | ||
84 | public void clear(){ | ||
85 | body_data=null; | ||
86 | lacing_vals=null; | ||
87 | granule_vals=null; | ||
88 | //memset(os,0,sizeof(ogg_stream_state)); | ||
89 | } | ||
90 | void destroy(){ | ||
91 | clear(); | ||
92 | } | ||
93 | void body_expand(int needed){ | ||
94 | if(body_storage<=body_fill+needed){ | ||
95 | body_storage+=(needed+1024); | ||
96 | byte[] foo=new byte[body_storage]; | ||
97 | System.arraycopy(body_data, 0, foo, 0, body_data.length); | ||
98 | body_data=foo; | ||
99 | //System.out.println("expand: body_fill="+body_fill+", body_storage="+body_data.length); | ||
100 | } | ||
101 | } | ||
102 | void lacing_expand(int needed){ | ||
103 | if(lacing_storage<=lacing_fill+needed){ | ||
104 | lacing_storage+=(needed+32); | ||
105 | int[] foo=new int[lacing_storage]; | ||
106 | System.arraycopy(lacing_vals, 0, foo, 0, lacing_vals.length); | ||
107 | lacing_vals=foo; | ||
108 | |||
109 | long[] bar=new long[lacing_storage]; | ||
110 | System.arraycopy(granule_vals, 0, bar, 0, granule_vals.length); | ||
111 | granule_vals=bar; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* submit data to the internal buffer of the framing engine */ | ||
116 | public int packetin(Packet op){ | ||
117 | int lacing_val=op.bytes/255+1; | ||
118 | |||
119 | if(body_returned!=0){ | ||
120 | /* advance packet data according to the body_returned pointer. We | ||
121 | had to keep it around to return a pointer into the buffer last | ||
122 | call */ | ||
123 | |||
124 | body_fill-=body_returned; | ||
125 | if(body_fill!=0){ | ||
126 | // memmove(os->body_data,os->body_data+os->body_returned, | ||
127 | // os->body_fill*sizeof(char)); | ||
128 | System.arraycopy(body_data, body_returned, body_data, 0, body_fill); | ||
129 | } | ||
130 | body_returned=0; | ||
131 | } | ||
132 | |||
133 | /* make sure we have the buffer storage */ | ||
134 | body_expand(op.bytes); | ||
135 | lacing_expand(lacing_val); | ||
136 | |||
137 | /* Copy in the submitted packet. Yes, the copy is a waste; this is | ||
138 | the liability of overly clean abstraction for the time being. It | ||
139 | will actually be fairly easy to eliminate the extra copy in the | ||
140 | future */ | ||
141 | |||
142 | System.arraycopy(op.packet_base, op.packet, body_data, body_fill, op.bytes); | ||
143 | body_fill+=op.bytes; | ||
144 | //System.out.println("add: "+body_fill); | ||
145 | |||
146 | /* Store lacing vals for this packet */ | ||
147 | int j; | ||
148 | for(j=0;j<lacing_val-1;j++){ | ||
149 | lacing_vals[lacing_fill+j]=255; | ||
150 | granule_vals[lacing_fill+j]=granulepos; | ||
151 | } | ||
152 | lacing_vals[lacing_fill+j]=(op.bytes)%255; | ||
153 | granulepos=granule_vals[lacing_fill+j]=op.granulepos; | ||
154 | |||
155 | /* flag the first segment as the beginning of the packet */ | ||
156 | lacing_vals[lacing_fill]|= 0x100; | ||
157 | |||
158 | lacing_fill+=lacing_val; | ||
159 | |||
160 | /* for the sake of completeness */ | ||
161 | packetno++; | ||
162 | |||
163 | if(op.e_o_s!=0)e_o_s=1; | ||
164 | return(0); | ||
165 | } | ||
166 | |||
167 | public int packetout(Packet op){ | ||
168 | |||
169 | /* The last part of decode. We have the stream broken into packet | ||
170 | segments. Now we need to group them into packets (or return the | ||
171 | out of sync markers) */ | ||
172 | |||
173 | int ptr=lacing_returned; | ||
174 | |||
175 | if(lacing_packet<=ptr){ | ||
176 | return(0); | ||
177 | } | ||
178 | |||
179 | if((lacing_vals[ptr]&0x400)!=0){ | ||
180 | /* We lost sync here; let the app know */ | ||
181 | lacing_returned++; | ||
182 | |||
183 | /* we need to tell the codec there's a gap; it might need to | ||
184 | handle previous packet dependencies. */ | ||
185 | packetno++; | ||
186 | return(-1); | ||
187 | } | ||
188 | |||
189 | /* Gather the whole packet. We'll have no holes or a partial packet */ | ||
190 | { | ||
191 | int size=lacing_vals[ptr]&0xff; | ||
192 | int bytes=0; | ||
193 | |||
194 | op.packet_base=body_data; | ||
195 | op.packet=body_returned; | ||
196 | op.e_o_s=lacing_vals[ptr]&0x200; /* last packet of the stream? */ | ||
197 | op.b_o_s=lacing_vals[ptr]&0x100; /* first packet of the stream? */ | ||
198 | bytes+=size; | ||
199 | |||
200 | while(size==255){ | ||
201 | int val=lacing_vals[++ptr]; | ||
202 | size=val&0xff; | ||
203 | if((val&0x200)!=0)op.e_o_s=0x200; | ||
204 | bytes+=size; | ||
205 | } | ||
206 | |||
207 | op.packetno=packetno; | ||
208 | op.granulepos=granule_vals[ptr]; | ||
209 | op.bytes=bytes; | ||
210 | |||
211 | //System.out.println(this+" # body_returned="+body_returned); | ||
212 | body_returned+=bytes; | ||
213 | //System.out.println(this+"## body_returned="+body_returned); | ||
214 | |||
215 | lacing_returned=ptr+1; | ||
216 | } | ||
217 | packetno++; | ||
218 | return(1); | ||
219 | } | ||
220 | |||
221 | |||
222 | // add the incoming page to the stream state; we decompose the page | ||
223 | // into packet segments here as well. | ||
224 | |||
225 | public int pagein(Page og){ | ||
226 | byte[] header_base=og.header_base; | ||
227 | int header=og.header; | ||
228 | byte[] body_base=og.body_base; | ||
229 | int body=og.body; | ||
230 | int bodysize=og.body_len; | ||
231 | int segptr=0; | ||
232 | |||
233 | int version=og.version(); | ||
234 | int continued=og.continued(); | ||
235 | int bos=og.bos(); | ||
236 | int eos=og.eos(); | ||
237 | long granulepos=og.granulepos(); | ||
238 | int _serialno=og.serialno(); | ||
239 | int _pageno=og.pageno(); | ||
240 | int segments=header_base[header+26]&0xff; | ||
241 | |||
242 | // clean up 'returned data' | ||
243 | { | ||
244 | int lr=lacing_returned; | ||
245 | int br=body_returned; | ||
246 | |||
247 | // body data | ||
248 | |||
249 | //System.out.println("br="+br+", body_fill="+body_fill); | ||
250 | |||
251 | if(br!=0){ | ||
252 | body_fill-=br; | ||
253 | if(body_fill!=0){ | ||
254 | System.arraycopy(body_data, br, body_data, 0, body_fill); | ||
255 | } | ||
256 | body_returned=0; | ||
257 | } | ||
258 | |||
259 | //System.out.println("?? br="+br+", body_fill="+body_fill+" body_returned="+body_returned); | ||
260 | |||
261 | if(lr!=0){ | ||
262 | // segment table | ||
263 | if((lacing_fill-lr)!=0){ | ||
264 | System.arraycopy(lacing_vals, lr, lacing_vals, 0, lacing_fill-lr); | ||
265 | System.arraycopy(granule_vals, lr, granule_vals, 0, lacing_fill-lr); | ||
266 | } | ||
267 | lacing_fill-=lr; | ||
268 | lacing_packet-=lr; | ||
269 | lacing_returned=0; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | // check the serial number | ||
274 | if(_serialno!=serialno)return(-1); | ||
275 | if(version>0)return(-1); | ||
276 | |||
277 | lacing_expand(segments+1); | ||
278 | |||
279 | // are we in sequence? | ||
280 | if(_pageno!=pageno){ | ||
281 | int i; | ||
282 | |||
283 | // unroll previous partial packet (if any) | ||
284 | for(i=lacing_packet;i<lacing_fill;i++){ | ||
285 | body_fill-=lacing_vals[i]&0xff; | ||
286 | //System.out.println("??"); | ||
287 | } | ||
288 | lacing_fill=lacing_packet; | ||
289 | |||
290 | // make a note of dropped data in segment table | ||
291 | if(pageno!=-1){ | ||
292 | lacing_vals[lacing_fill++]=0x400; | ||
293 | lacing_packet++; | ||
294 | } | ||
295 | |||
296 | // are we a 'continued packet' page? If so, we'll need to skip | ||
297 | // some segments | ||
298 | if(continued!=0){ | ||
299 | bos=0; | ||
300 | for(;segptr<segments;segptr++){ | ||
301 | int val=(header_base[header+27+segptr]&0xff); | ||
302 | body+=val; | ||
303 | bodysize-=val; | ||
304 | if(val<255){ | ||
305 | segptr++; | ||
306 | break; | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | |||
312 | //System.out.println("bodysize="+bodysize); | ||
313 | |||
314 | if(bodysize!=0){ | ||
315 | body_expand(bodysize); | ||
316 | System.arraycopy(body_base, body, body_data, body_fill, bodysize); | ||
317 | body_fill+=bodysize; | ||
318 | } | ||
319 | |||
320 | //System.out.println("bodyfill="+body_fill); | ||
321 | |||
322 | { | ||
323 | int saved=-1; | ||
324 | while(segptr<segments){ | ||
325 | int val=(header_base[header+27+segptr]&0xff); | ||
326 | lacing_vals[lacing_fill]=val; | ||
327 | granule_vals[lacing_fill]=-1; | ||
328 | |||
329 | if(bos!=0){ | ||
330 | lacing_vals[lacing_fill]|=0x100; | ||
331 | bos=0; | ||
332 | } | ||
333 | |||
334 | if(val<255)saved=lacing_fill; | ||
335 | |||
336 | lacing_fill++; | ||
337 | segptr++; | ||
338 | |||
339 | if(val<255)lacing_packet=lacing_fill; | ||
340 | } | ||
341 | |||
342 | /* set the granulepos on the last pcmval of the last full packet */ | ||
343 | if(saved!=-1){ | ||
344 | granule_vals[saved]=granulepos; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | if(eos!=0){ | ||
349 | e_o_s=1; | ||
350 | if(lacing_fill>0) | ||
351 | lacing_vals[lacing_fill-1]|=0x200; | ||
352 | } | ||
353 | |||
354 | pageno=_pageno+1; | ||
355 | return(0); | ||
356 | } | ||
357 | |||
358 | |||
359 | /* This will flush remaining packets into a page (returning nonzero), | ||
360 | even if there is not enough data to trigger a flush normally | ||
361 | (undersized page). If there are no packets or partial packets to | ||
362 | flush, ogg_stream_flush returns 0. Note that ogg_stream_flush will | ||
363 | try to flush a normal sized page like ogg_stream_pageout; a call to | ||
364 | ogg_stream_flush does not gurantee that all packets have flushed. | ||
365 | Only a return value of 0 from ogg_stream_flush indicates all packet | ||
366 | data is flushed into pages. | ||
367 | |||
368 | ogg_stream_page will flush the last page in a stream even if it's | ||
369 | undersized; you almost certainly want to use ogg_stream_pageout | ||
370 | (and *not* ogg_stream_flush) unless you need to flush an undersized | ||
371 | page in the middle of a stream for some reason. */ | ||
372 | |||
373 | public int flush(Page og){ | ||
374 | |||
375 | //System.out.println(this+" ---body_returned: "+body_returned); | ||
376 | |||
377 | int i; | ||
378 | int vals=0; | ||
379 | int maxvals=(lacing_fill>255?255:lacing_fill); | ||
380 | int bytes=0; | ||
381 | int acc=0; | ||
382 | long granule_pos=granule_vals[0]; | ||
383 | |||
384 | if(maxvals==0)return(0); | ||
385 | |||
386 | /* construct a page */ | ||
387 | /* decide how many segments to include */ | ||
388 | |||
389 | /* If this is the initial header case, the first page must only include | ||
390 | the initial header packet */ | ||
391 | if(b_o_s==0){ /* 'initial header page' case */ | ||
392 | granule_pos=0; | ||
393 | for(vals=0;vals<maxvals;vals++){ | ||
394 | if((lacing_vals[vals]&0x0ff)<255){ | ||
395 | vals++; | ||
396 | break; | ||
397 | } | ||
398 | } | ||
399 | } | ||
400 | else{ | ||
401 | for(vals=0;vals<maxvals;vals++){ | ||
402 | if(acc>4096)break; | ||
403 | acc+=(lacing_vals[vals]&0x0ff); | ||
404 | granule_pos=granule_vals[vals]; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | /* construct the header in temp storage */ | ||
409 | System.arraycopy("OggS".getBytes(), 0, header, 0, 4); | ||
410 | |||
411 | /* stream structure version */ | ||
412 | header[4]=0x00; | ||
413 | |||
414 | /* continued packet flag? */ | ||
415 | header[5]=0x00; | ||
416 | if((lacing_vals[0]&0x100)==0)header[5]|=0x01; | ||
417 | /* first page flag? */ | ||
418 | if(b_o_s==0) header[5]|=0x02; | ||
419 | /* last page flag? */ | ||
420 | if(e_o_s!=0 && lacing_fill==vals) header[5]|=0x04; | ||
421 | b_o_s=1; | ||
422 | |||
423 | /* 64 bits of PCM position */ | ||
424 | for(i=6;i<14;i++){ | ||
425 | header[i]=(byte)granule_pos; | ||
426 | granule_pos>>>=8; | ||
427 | } | ||
428 | |||
429 | /* 32 bits of stream serial number */ | ||
430 | { | ||
431 | int _serialno=serialno; | ||
432 | for(i=14;i<18;i++){ | ||
433 | header[i]=(byte)_serialno; | ||
434 | _serialno>>>=8; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | /* 32 bits of page counter (we have both counter and page header | ||
439 | because this val can roll over) */ | ||
440 | if(pageno==-1)pageno=0; /* because someone called | ||
441 | stream_reset; this would be a | ||
442 | strange thing to do in an | ||
443 | encode stream, but it has | ||
444 | plausible uses */ | ||
445 | { | ||
446 | int _pageno=pageno++; | ||
447 | for(i=18;i<22;i++){ | ||
448 | header[i]=(byte)_pageno; | ||
449 | _pageno>>>=8; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | /* zero for computation; filled in later */ | ||
454 | header[22]=0; | ||
455 | header[23]=0; | ||
456 | header[24]=0; | ||
457 | header[25]=0; | ||
458 | |||
459 | /* segment table */ | ||
460 | header[26]=(byte)vals; | ||
461 | for(i=0;i<vals;i++){ | ||
462 | header[i+27]=(byte)lacing_vals[i]; | ||
463 | bytes+=(header[i+27]&0xff); | ||
464 | } | ||
465 | |||
466 | /* set pointers in the ogg_page struct */ | ||
467 | og.header_base=header; | ||
468 | og.header=0; | ||
469 | og.header_len=header_fill=vals+27; | ||
470 | og.body_base=body_data; | ||
471 | og.body=body_returned; | ||
472 | og.body_len=bytes; | ||
473 | |||
474 | /* advance the lacing data and set the body_returned pointer */ | ||
475 | |||
476 | //System.out.println("###body_returned: "+body_returned); | ||
477 | |||
478 | lacing_fill-=vals; | ||
479 | System.arraycopy(lacing_vals, vals, lacing_vals, 0, lacing_fill*4); | ||
480 | System.arraycopy(granule_vals, vals, granule_vals, 0, lacing_fill*8); | ||
481 | body_returned+=bytes; | ||
482 | |||
483 | //System.out.println("####body_returned: "+body_returned); | ||
484 | |||
485 | /* calculate the checksum */ | ||
486 | |||
487 | og.checksum(); | ||
488 | |||
489 | /* done */ | ||
490 | return(1); | ||
491 | } | ||
492 | |||
493 | |||
494 | /* This constructs pages from buffered packet segments. The pointers | ||
495 | returned are to static buffers; do not free. The returned buffers are | ||
496 | good only until the next call (using the same ogg_stream_state) */ | ||
497 | public int pageout(Page og){ | ||
498 | // if(body_returned!=0){ | ||
499 | // /* advance packet data according to the body_returned pointer. We | ||
500 | // had to keep it around to return a pointer into the buffer last | ||
501 | // call */ | ||
502 | // | ||
503 | // body_fill-=body_returned; | ||
504 | // if(body_fill!=0){ // overlap? | ||
505 | // System.arraycopy(body_data, body_returned, body_data, 0, body_fill); | ||
506 | // } | ||
507 | // body_returned=0; | ||
508 | // } | ||
509 | // | ||
510 | //System.out.println("pageout: e_o_s="+e_o_s+" lacing_fill="+lacing_fill+" body_fill="+body_fill+", lacing_fill="+lacing_fill+" b_o_s="+b_o_s); | ||
511 | // | ||
512 | // if((e_o_s!=0&&lacing_fill!=0) || /* 'were done, now flush' case */ | ||
513 | // body_fill > 4096 || /* 'page nominal size' case */ | ||
514 | // lacing_fill>=255 || /* 'segment table full' case */ | ||
515 | // (lacing_fill!=0&&b_o_s==0)){ /* 'initial header page' case */ | ||
516 | // int vals=0,bytes=0; | ||
517 | // int maxvals=(lacing_fill>255?255:lacing_fill); | ||
518 | // long acc=0; | ||
519 | // long pcm_pos=granule_vals[0]; | ||
520 | // | ||
521 | // /* construct a page */ | ||
522 | // /* decide how many segments to include */ | ||
523 | // | ||
524 | // /* If this is the initial header case, the first page must only include | ||
525 | // the initial header packet */ | ||
526 | // if(b_o_s==0){ /* 'initial header page' case */ | ||
527 | // pcm_pos=0; | ||
528 | // for(vals=0;vals<maxvals;vals++){ | ||
529 | // if((lacing_vals[vals]&0x0ff)<255){ | ||
530 | // vals++; | ||
531 | // break; | ||
532 | // } | ||
533 | // } | ||
534 | // } | ||
535 | // else{ | ||
536 | // for(vals=0;vals<maxvals;vals++){ | ||
537 | // if(acc>4096)break; | ||
538 | // acc+=lacing_vals[vals]&0x0ff; | ||
539 | // pcm_pos=granule_vals[vals]; | ||
540 | // } | ||
541 | // } | ||
542 | // | ||
543 | // /* construct the header in temp storage */ | ||
544 | // System.arraycopy("OggS".getBytes(), 0, header, 0, 4); | ||
545 | // | ||
546 | // /* stream structure version */ | ||
547 | // header[4]=0x00; | ||
548 | // | ||
549 | // /* continued packet flag? */ | ||
550 | // header[5]=0x00; | ||
551 | // if((lacing_vals[0]&0x100)==0)header[5]|=0x01; | ||
552 | // /* first page flag? */ | ||
553 | // if(b_o_s==0)header[5]|=0x02; | ||
554 | // /* last page flag? */ | ||
555 | // if(e_o_s!=0 && lacing_fill==vals)header[5]|=0x04; | ||
556 | // b_o_s=1; | ||
557 | // | ||
558 | // /* 64 bits of PCM position */ | ||
559 | // for(int i=6;i<14;i++){ | ||
560 | // header[i]=(byte)pcm_pos; | ||
561 | // pcm_pos>>>=8; | ||
562 | // } | ||
563 | // | ||
564 | // /* 32 bits of stream serial number */ | ||
565 | // { | ||
566 | // int serialn=serialno; | ||
567 | // for(int i=14;i<18;i++){ | ||
568 | // header[i]=(byte)serialn; | ||
569 | // serialn>>>=8; | ||
570 | // } | ||
571 | // } | ||
572 | // | ||
573 | // | ||
574 | ///* 32 bits of page counter (we have both counter and page header | ||
575 | // because this val can roll over) */ | ||
576 | // if(pageno==-1)pageno=0; /* because someone called | ||
577 | // stream_reset; this would be a | ||
578 | // strange thing to do in an | ||
579 | // encode stream, but it has | ||
580 | // plausible uses */ | ||
581 | // { | ||
582 | // int pagen=pageno++; | ||
583 | // for(int i=18;i<22;i++){ | ||
584 | // header[i]=(byte)pagen; | ||
585 | // pagen>>>=8; | ||
586 | // } | ||
587 | // } | ||
588 | // | ||
589 | // /* zero for computation; filled in later */ | ||
590 | // header[22]=0; | ||
591 | // header[23]=0; | ||
592 | // header[24]=0; | ||
593 | // header[25]=0; | ||
594 | // | ||
595 | // /* segment table */ | ||
596 | // header[26]=(byte)vals; | ||
597 | // for(int i=0;i<vals;i++){ | ||
598 | // header[i+27]=(byte)lacing_vals[i]; | ||
599 | // bytes+=header[i+27]&0xff; | ||
600 | //// bytes+=header[i+27]=(lacing_vals[i]&0xff); | ||
601 | // } | ||
602 | // | ||
603 | // /* advance the lacing data and set the body_returned pointer */ | ||
604 | // | ||
605 | // lacing_fill-=vals; | ||
606 | // System.arraycopy(lacing_vals, vals, lacing_vals, 0, lacing_fill); | ||
607 | // System.arraycopy(granule_vals, vals, granule_vals, 0, lacing_fill); | ||
608 | // body_returned=bytes; | ||
609 | // | ||
610 | // /* set pointers in the ogg_page struct */ | ||
611 | // og.header_base=header; | ||
612 | // og.header=0; | ||
613 | // og.header_len=header_fill=vals+27; | ||
614 | // | ||
615 | // og.body_base=body_data; | ||
616 | // og.body=0; | ||
617 | // og.body_len=bytes; | ||
618 | // | ||
619 | // /* calculate the checksum */ | ||
620 | // | ||
621 | // og.checksum(); | ||
622 | // return(1); | ||
623 | // } | ||
624 | // /* not enough data to construct a page and not end of stream */ | ||
625 | // return(0); | ||
626 | //System.out.println("pageout: "+body_returned); | ||
627 | if((e_o_s!=0&&lacing_fill!=0) || /* 'were done, now flush' case */ | ||
628 | body_fill-body_returned> 4096 || /* 'page nominal size' case */ | ||
629 | lacing_fill>=255 || /* 'segment table full' case */ | ||
630 | (lacing_fill!=0&&b_o_s==0)){ /* 'initial header page' case */ | ||
631 | return flush(og); | ||
632 | } | ||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | public int eof(){ | ||
637 | return e_o_s; | ||
638 | } | ||
639 | |||
640 | public int reset(){ | ||
641 | body_fill=0; | ||
642 | body_returned=0; | ||
643 | |||
644 | lacing_fill=0; | ||
645 | lacing_packet=0; | ||
646 | lacing_returned=0; | ||
647 | |||
648 | header_fill=0; | ||
649 | |||
650 | e_o_s=0; | ||
651 | b_o_s=0; | ||
652 | pageno=-1; | ||
653 | packetno=0; | ||
654 | granulepos=0; | ||
655 | return(0); | ||
656 | } | ||
657 | } | ||
diff --git a/songdbj/com/jcraft/jogg/SyncState.java b/songdbj/com/jcraft/jogg/SyncState.java new file mode 100644 index 0000000000..b3705e54dd --- /dev/null +++ b/songdbj/com/jcraft/jogg/SyncState.java | |||
@@ -0,0 +1,275 @@ | |||
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.jogg; | ||
27 | |||
28 | // DECODING PRIMITIVES: packet streaming layer | ||
29 | |||
30 | // This has two layers to place more of the multi-serialno and paging | ||
31 | // control in the application's hands. First, we expose a data buffer | ||
32 | // using ogg_decode_buffer(). The app either copies into the | ||
33 | // buffer, or passes it directly to read(), etc. We then call | ||
34 | // ogg_decode_wrote() to tell how many bytes we just added. | ||
35 | // | ||
36 | // Pages are returned (pointers into the buffer in ogg_sync_state) | ||
37 | // by ogg_decode_stream(). The page is then submitted to | ||
38 | // ogg_decode_page() along with the appropriate | ||
39 | // ogg_stream_state* (ie, matching serialno). We then get raw | ||
40 | // packets out calling ogg_stream_packet() with a | ||
41 | // ogg_stream_state. See the 'frame-prog.txt' docs for details and | ||
42 | // example code. | ||
43 | |||
44 | public class SyncState{ | ||
45 | |||
46 | public byte[] data; | ||
47 | int storage; | ||
48 | int fill; | ||
49 | int returned; | ||
50 | |||
51 | int unsynced; | ||
52 | int headerbytes; | ||
53 | int bodybytes; | ||
54 | |||
55 | public int clear(){ | ||
56 | data=null; | ||
57 | return(0); | ||
58 | } | ||
59 | |||
60 | // !!!!!!!!!!!! | ||
61 | // byte[] buffer(int size){ | ||
62 | public int buffer(int size){ | ||
63 | // first, clear out any space that has been previously returned | ||
64 | if(returned!=0){ | ||
65 | fill-=returned; | ||
66 | if(fill>0){ | ||
67 | System.arraycopy(data, returned, data, 0, fill); | ||
68 | } | ||
69 | returned=0; | ||
70 | } | ||
71 | |||
72 | if(size>storage-fill){ | ||
73 | // We need to extend the internal buffer | ||
74 | int newsize=size+fill+4096; // an extra page to be nice | ||
75 | if(data!=null){ | ||
76 | byte[] foo=new byte[newsize]; | ||
77 | System.arraycopy(data, 0, foo, 0, data.length); | ||
78 | data=foo; | ||
79 | } | ||
80 | else{ | ||
81 | data=new byte[newsize]; | ||
82 | } | ||
83 | storage=newsize; | ||
84 | } | ||
85 | |||
86 | // expose a segment at least as large as requested at the fill mark | ||
87 | // return((char *)oy->data+oy->fill); | ||
88 | // return(data); | ||
89 | return(fill); | ||
90 | } | ||
91 | |||
92 | public int wrote(int bytes){ | ||
93 | if(fill+bytes>storage)return(-1); | ||
94 | fill+=bytes; | ||
95 | return(0); | ||
96 | } | ||
97 | |||
98 | // sync the stream. This is meant to be useful for finding page | ||
99 | // boundaries. | ||
100 | // | ||
101 | // return values for this: | ||
102 | // -n) skipped n bytes | ||
103 | // 0) page not ready; more data (no bytes skipped) | ||
104 | // n) page synced at current location; page length n bytes | ||
105 | private Page pageseek=new Page(); | ||
106 | private byte[] chksum=new byte[4]; | ||
107 | public int pageseek(Page og){ | ||
108 | int page=returned; | ||
109 | int next; | ||
110 | int bytes=fill-returned; | ||
111 | |||
112 | if(headerbytes==0){ | ||
113 | int _headerbytes,i; | ||
114 | if(bytes<27)return(0); // not enough for a header | ||
115 | |||
116 | /* verify capture pattern */ | ||
117 | //!!!!!!!!!!! | ||
118 | if(data[page]!='O' || | ||
119 | data[page+1]!='g' || | ||
120 | data[page+2]!='g' || | ||
121 | data[page+3]!='S'){ | ||
122 | headerbytes=0; | ||
123 | bodybytes=0; | ||
124 | |||
125 | // search for possible capture | ||
126 | next=0; | ||
127 | for(int ii=0; ii<bytes-1; ii++){ | ||
128 | if(data[page+1+ii]=='O'){next=page+1+ii; break;} | ||
129 | } | ||
130 | //next=memchr(page+1,'O',bytes-1); | ||
131 | if(next==0) next=fill; | ||
132 | |||
133 | returned=next; | ||
134 | return(-(next-page)); | ||
135 | } | ||
136 | _headerbytes=(data[page+26]&0xff)+27; | ||
137 | if(bytes<_headerbytes)return(0); // not enough for header + seg table | ||
138 | |||
139 | // count up body length in the segment table | ||
140 | |||
141 | for(i=0;i<(data[page+26]&0xff);i++){ | ||
142 | bodybytes+=(data[page+27+i]&0xff); | ||
143 | } | ||
144 | headerbytes=_headerbytes; | ||
145 | } | ||
146 | |||
147 | if(bodybytes+headerbytes>bytes)return(0); | ||
148 | |||
149 | // The whole test page is buffered. Verify the checksum | ||
150 | synchronized(chksum){ | ||
151 | // Grab the checksum bytes, set the header field to zero | ||
152 | |||
153 | System.arraycopy(data, page+22, chksum, 0, 4); | ||
154 | data[page+22]=0; | ||
155 | data[page+23]=0; | ||
156 | data[page+24]=0; | ||
157 | data[page+25]=0; | ||
158 | |||
159 | // set up a temp page struct and recompute the checksum | ||
160 | Page log=pageseek; | ||
161 | log.header_base=data; | ||
162 | log.header=page; | ||
163 | log.header_len=headerbytes; | ||
164 | |||
165 | log.body_base=data; | ||
166 | log.body=page+headerbytes; | ||
167 | log.body_len=bodybytes; | ||
168 | log.checksum(); | ||
169 | |||
170 | // Compare | ||
171 | if(chksum[0]!=data[page+22] || | ||
172 | chksum[1]!=data[page+23] || | ||
173 | chksum[2]!=data[page+24] || | ||
174 | chksum[3]!=data[page+25]){ | ||
175 | // D'oh. Mismatch! Corrupt page (or miscapture and not a page at all) | ||
176 | // replace the computed checksum with the one actually read in | ||
177 | System.arraycopy(chksum, 0, data, page+22, 4); | ||
178 | // Bad checksum. Lose sync */ | ||
179 | |||
180 | headerbytes=0; | ||
181 | bodybytes=0; | ||
182 | // search for possible capture | ||
183 | next=0; | ||
184 | for(int ii=0; ii<bytes-1; ii++){ | ||
185 | if(data[page+1+ii]=='O'){next=page+1+ii; break;} | ||
186 | } | ||
187 | //next=memchr(page+1,'O',bytes-1); | ||
188 | if(next==0) next=fill; | ||
189 | returned=next; | ||
190 | return(-(next-page)); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | // yes, have a whole page all ready to go | ||
195 | { | ||
196 | page=returned; | ||
197 | |||
198 | if(og!=null){ | ||
199 | og.header_base=data; | ||
200 | og.header=page; | ||
201 | og.header_len=headerbytes; | ||
202 | og.body_base=data; | ||
203 | og.body=page+headerbytes; | ||
204 | og.body_len=bodybytes; | ||
205 | } | ||
206 | |||
207 | unsynced=0; | ||
208 | returned+=(bytes=headerbytes+bodybytes); | ||
209 | headerbytes=0; | ||
210 | bodybytes=0; | ||
211 | return(bytes); | ||
212 | } | ||
213 | // headerbytes=0; | ||
214 | // bodybytes=0; | ||
215 | // next=0; | ||
216 | // for(int ii=0; ii<bytes-1; ii++){ | ||
217 | // if(data[page+1+ii]=='O'){next=page+1+ii;} | ||
218 | // } | ||
219 | // //next=memchr(page+1,'O',bytes-1); | ||
220 | // if(next==0) next=fill; | ||
221 | // returned=next; | ||
222 | // return(-(next-page)); | ||
223 | } | ||
224 | |||
225 | |||
226 | // sync the stream and get a page. Keep trying until we find a page. | ||
227 | // Supress 'sync errors' after reporting the first. | ||
228 | // | ||
229 | // return values: | ||
230 | // -1) recapture (hole in data) | ||
231 | // 0) need more data | ||
232 | // 1) page returned | ||
233 | // | ||
234 | // Returns pointers into buffered data; invalidated by next call to | ||
235 | // _stream, _clear, _init, or _buffer | ||
236 | |||
237 | public int pageout(Page og){ | ||
238 | // all we need to do is verify a page at the head of the stream | ||
239 | // buffer. If it doesn't verify, we look for the next potential | ||
240 | // frame | ||
241 | |||
242 | while(true){ | ||
243 | int ret=pageseek(og); | ||
244 | if(ret>0){ | ||
245 | // have a page | ||
246 | return(1); | ||
247 | } | ||
248 | if(ret==0){ | ||
249 | // need more data | ||
250 | return(0); | ||
251 | } | ||
252 | |||
253 | // head did not start a synced page... skipped some bytes | ||
254 | if(unsynced==0){ | ||
255 | unsynced=1; | ||
256 | return(-1); | ||
257 | } | ||
258 | // loop. keep looking | ||
259 | } | ||
260 | } | ||
261 | |||
262 | // clear things to an initial state. Good to call, eg, before seeking | ||
263 | public int reset(){ | ||
264 | fill=0; | ||
265 | returned=0; | ||
266 | unsynced=0; | ||
267 | headerbytes=0; | ||
268 | bodybytes=0; | ||
269 | return(0); | ||
270 | } | ||
271 | public void init(){} | ||
272 | |||
273 | public int getDataOffset(){ return returned; } | ||
274 | public int getBufferOffset(){ return fill; } | ||
275 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/AllocChain.java b/songdbj/com/jcraft/jorbis/AllocChain.java new file mode 100644 index 0000000000..b3492d5c94 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/AllocChain.java | |||
@@ -0,0 +1,31 @@ | |||
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 | class AllocChain{ | ||
29 | Object ptr; | ||
30 | AllocChain next; | ||
31 | }; | ||
diff --git a/songdbj/com/jcraft/jorbis/Block.java b/songdbj/com/jcraft/jorbis/Block.java new file mode 100644 index 0000000000..8fd15f76bf --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Block.java | |||
@@ -0,0 +1,188 @@ | |||
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 | public class Block{ | ||
31 | ///necessary stream state for linking to the framing abstraction | ||
32 | float[][] pcm=new float[0][]; // this is a pointer into local storage | ||
33 | Buffer opb=new Buffer(); | ||
34 | |||
35 | int lW; | ||
36 | int W; | ||
37 | int nW; | ||
38 | int pcmend; | ||
39 | int mode; | ||
40 | |||
41 | int eofflag; | ||
42 | long granulepos; | ||
43 | long sequence; | ||
44 | DspState vd; // For read-only access of configuration | ||
45 | |||
46 | // local storage to avoid remallocing; it's up to the mapping to | ||
47 | // structure it | ||
48 | //byte[] localstore; | ||
49 | //int localtop; | ||
50 | //int localalloc; | ||
51 | //int totaluse; | ||
52 | //AllocChain reap; | ||
53 | |||
54 | // bitmetrics for the frame | ||
55 | int glue_bits; | ||
56 | int time_bits; | ||
57 | int floor_bits; | ||
58 | int res_bits; | ||
59 | |||
60 | public Block(DspState vd){ | ||
61 | this.vd=vd; | ||
62 | // localalloc=0; | ||
63 | // localstore=null; | ||
64 | if(vd.analysisp!=0){ | ||
65 | opb.writeinit(); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | public void init(DspState vd){ | ||
70 | this.vd=vd; | ||
71 | } | ||
72 | |||
73 | // int alloc(int bytes){ | ||
74 | // bytes=(bytes+(8-1))&(~(8-1)); | ||
75 | // if(bytes+localtop>localalloc){ | ||
76 | // if(localstore!=null){ | ||
77 | // AllocChain link=new AllocChain(); | ||
78 | // totaluse+=localtop; | ||
79 | // link.next=reap; | ||
80 | // link.ptr=localstore; | ||
81 | // reap=link; | ||
82 | // } | ||
83 | // // highly conservative | ||
84 | // localalloc=bytes; | ||
85 | // localstore=new byte[localalloc]; | ||
86 | // localtop=0; | ||
87 | // } | ||
88 | // { | ||
89 | // int foo=localtop; | ||
90 | // //void *ret=(void *)(((char *)vb->localstore)+vb->localtop); | ||
91 | // localtop+=bytes; | ||
92 | // return foo; | ||
93 | // } | ||
94 | // } | ||
95 | |||
96 | // reap the chain, pull the ripcord | ||
97 | // void ripcord(){ | ||
98 | // // reap the chain | ||
99 | // while(reap!=null){ | ||
100 | // AllocChain next=reap.next; | ||
101 | // //free(reap->ptr); | ||
102 | // reap.ptr=null; | ||
103 | // //memset(reap,0,sizeof(struct alloc_chain)); | ||
104 | // //free(reap); | ||
105 | // reap=next; | ||
106 | // } | ||
107 | // // consolidate storage | ||
108 | // if(totaluse!=0){ | ||
109 | // //vb->localstore=realloc(vb->localstore,vb->totaluse+vb->localalloc); | ||
110 | // byte[] foo=new byte[totaluse+localalloc]; | ||
111 | // System.arraycopy(localstore, 0, foo, 0, localstore.length); | ||
112 | // localstore=foo; | ||
113 | // localalloc+=totaluse; | ||
114 | // totaluse=0; | ||
115 | // } | ||
116 | // // pull the ripcord | ||
117 | // localtop=0; | ||
118 | // reap=null; | ||
119 | // } | ||
120 | |||
121 | public int clear(){ | ||
122 | if(vd!=null){ | ||
123 | if(vd.analysisp!=0){ | ||
124 | opb.writeclear(); | ||
125 | } | ||
126 | } | ||
127 | //ripcord(); | ||
128 | //if(localstore!=null) | ||
129 | // localstore=null; | ||
130 | //memset(vb,0,sizeof(vorbis_block)); | ||
131 | return(0); | ||
132 | } | ||
133 | |||
134 | public int synthesis(Packet op){ | ||
135 | Info vi=vd.vi; | ||
136 | |||
137 | // first things first. Make sure decode is ready | ||
138 | // ripcord(); | ||
139 | opb.readinit(op.packet_base, op.packet, op.bytes); | ||
140 | |||
141 | // Check the packet type | ||
142 | if(opb.read(1)!=0){ | ||
143 | // Oops. This is not an audio data packet | ||
144 | return(-1); | ||
145 | } | ||
146 | |||
147 | // read our mode and pre/post windowsize | ||
148 | int _mode=opb.read(vd.modebits); | ||
149 | if(_mode==-1)return(-1); | ||
150 | |||
151 | mode=_mode; | ||
152 | W=vi.mode_param[mode].blockflag; | ||
153 | if(W!=0){ | ||
154 | lW=opb.read(1); | ||
155 | nW=opb.read(1); | ||
156 | if(nW==-1) return(-1); | ||
157 | } | ||
158 | else{ | ||
159 | lW=0; | ||
160 | nW=0; | ||
161 | } | ||
162 | |||
163 | // more setup | ||
164 | granulepos=op.granulepos; | ||
165 | sequence=op.packetno-3; // first block is third packet | ||
166 | eofflag=op.e_o_s; | ||
167 | |||
168 | // alloc pcm passback storage | ||
169 | pcmend=vi.blocksizes[W]; | ||
170 | //pcm=alloc(vi.channels); | ||
171 | if(pcm.length<vi.channels){ | ||
172 | pcm=new float[vi.channels][]; | ||
173 | } | ||
174 | for(int i=0;i<vi.channels;i++){ | ||
175 | if(pcm[i]==null || pcm[i].length<pcmend){ | ||
176 | pcm[i]=new float[pcmend]; | ||
177 | //pcm[i]=alloc(pcmend); | ||
178 | } | ||
179 | else{ | ||
180 | for(int j=0;j<pcmend;j++){ pcm[i][j]=0; } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | // unpack_header enforces range checking | ||
185 | int type=vi.map_type[vi.mode_param[mode].mapping]; | ||
186 | return(FuncMapping.mapping_P[type].inverse(this, vd.mode[mode])); | ||
187 | } | ||
188 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/ChainingExample.java b/songdbj/com/jcraft/jorbis/ChainingExample.java new file mode 100644 index 0000000000..82592f29c4 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/ChainingExample.java | |||
@@ -0,0 +1,61 @@ | |||
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 | class ChainingExample{ | ||
29 | public static void main(String[] arg){ | ||
30 | VorbisFile ov=null; | ||
31 | |||
32 | try{ | ||
33 | ov=new VorbisFile(System.in, null, -1); | ||
34 | } | ||
35 | catch(Exception e){ | ||
36 | System.err.println(e); | ||
37 | return; | ||
38 | } | ||
39 | |||
40 | if(ov.seekable()){ | ||
41 | System.out.println("Input bitstream contained "+ov.streams()+" logical bitstream section(s)."); | ||
42 | System.out.println("Total bitstream playing time: "+ov.time_total(-1)+" seconds\n"); | ||
43 | } | ||
44 | else{ | ||
45 | System.out.println("Standard input was not seekable."); | ||
46 | System.out.println("First logical bitstream information:\n"); | ||
47 | } | ||
48 | |||
49 | for(int i=0;i<ov.streams();i++){ | ||
50 | Info vi=ov.getInfo(i); | ||
51 | System.out.println("\tlogical bitstream section "+(i+1)+" information:"); | ||
52 | System.out.println("\t\t"+vi.rate+"Hz "+vi.channels+" channels bitrate "+ | ||
53 | (ov.bitrate(i)/1000)+"kbps serial number="+ov.serialnumber(i)); | ||
54 | System.out.print("\t\tcompressed length: "+ov.raw_total(i)+" bytes "); | ||
55 | System.out.println(" play time: "+ov.time_total(i)+"s"); | ||
56 | Comment vc=ov.getComment(i); | ||
57 | System.out.println(vc); | ||
58 | } | ||
59 | //clear(&ov); | ||
60 | } | ||
61 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/CodeBook.java b/songdbj/com/jcraft/jorbis/CodeBook.java new file mode 100644 index 0000000000..9708e066a4 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/CodeBook.java | |||
@@ -0,0 +1,742 @@ | |||
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 CodeBook{ | ||
31 | int dim; // codebook dimensions (elements per vector) | ||
32 | int entries; // codebook entries | ||
33 | StaticCodeBook c=new StaticCodeBook(); | ||
34 | |||
35 | float[] valuelist; // list of dim*entries actual entry values | ||
36 | int[] codelist; // list of bitstream codewords for each entry | ||
37 | DecodeAux decode_tree; | ||
38 | |||
39 | // returns the number of bits | ||
40 | int encode(int a, Buffer b){ | ||
41 | b.write(codelist[a], c.lengthlist[a]); | ||
42 | return(c.lengthlist[a]); | ||
43 | } | ||
44 | |||
45 | // One the encode side, our vector writers are each designed for a | ||
46 | // specific purpose, and the encoder is not flexible without modification: | ||
47 | // | ||
48 | // The LSP vector coder uses a single stage nearest-match with no | ||
49 | // interleave, so no step and no error return. This is specced by floor0 | ||
50 | // and doesn't change. | ||
51 | // | ||
52 | // Residue0 encoding interleaves, uses multiple stages, and each stage | ||
53 | // peels of a specific amount of resolution from a lattice (thus we want | ||
54 | // to match by threshhold, not nearest match). Residue doesn't *have* to | ||
55 | // be encoded that way, but to change it, one will need to add more | ||
56 | // infrastructure on the encode side (decode side is specced and simpler) | ||
57 | |||
58 | // floor0 LSP (single stage, non interleaved, nearest match) | ||
59 | // returns entry number and *modifies a* to the quantization value | ||
60 | int errorv(float[] a){ | ||
61 | int best=best(a,1); | ||
62 | for(int k=0;k<dim;k++){ | ||
63 | a[k]=valuelist[best*dim+k]; | ||
64 | } | ||
65 | return(best); | ||
66 | } | ||
67 | |||
68 | // returns the number of bits and *modifies a* to the quantization value | ||
69 | int encodev(int best, float[] a, Buffer b){ | ||
70 | for(int k=0;k<dim;k++){ | ||
71 | a[k]=valuelist[best*dim+k]; | ||
72 | } | ||
73 | return(encode(best,b)); | ||
74 | } | ||
75 | |||
76 | // res0 (multistage, interleave, lattice) | ||
77 | // returns the number of bits and *modifies a* to the remainder value | ||
78 | int encodevs(float[] a, Buffer b, int step,int addmul){ | ||
79 | int best=besterror(a,step,addmul); | ||
80 | return(encode(best,b)); | ||
81 | } | ||
82 | |||
83 | private int[] t=new int[15]; // decodevs_add is synchronized for re-using t. | ||
84 | synchronized int decodevs_add(float[]a, int offset, Buffer b, int n){ | ||
85 | int step=n/dim; | ||
86 | int entry; | ||
87 | int i,j,o; | ||
88 | |||
89 | if(t.length<step){ | ||
90 | t=new int[step]; | ||
91 | } | ||
92 | |||
93 | for(i = 0; i < step; i++){ | ||
94 | entry=decode(b); | ||
95 | if(entry==-1)return(-1); | ||
96 | t[i]=entry*dim; | ||
97 | } | ||
98 | for(i=0,o=0;i<dim;i++,o+=step){ | ||
99 | for(j=0;j<step;j++){ | ||
100 | a[offset+o+j]+=valuelist[t[j]+i]; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | return(0); | ||
105 | } | ||
106 | |||
107 | int decodev_add(float[]a, int offset, Buffer b,int n){ | ||
108 | int i,j,entry; | ||
109 | int t; | ||
110 | |||
111 | if(dim>8){ | ||
112 | for(i=0;i<n;){ | ||
113 | entry = decode(b); | ||
114 | if(entry==-1)return(-1); | ||
115 | t=entry*dim; | ||
116 | for(j=0;j<dim;){ | ||
117 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | else{ | ||
122 | for(i=0;i<n;){ | ||
123 | entry=decode(b); | ||
124 | if(entry==-1)return(-1); | ||
125 | t=entry*dim; | ||
126 | j=0; | ||
127 | switch(dim){ | ||
128 | case 8: | ||
129 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
130 | case 7: | ||
131 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
132 | case 6: | ||
133 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
134 | case 5: | ||
135 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
136 | case 4: | ||
137 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
138 | case 3: | ||
139 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
140 | case 2: | ||
141 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
142 | case 1: | ||
143 | a[offset+(i++)]+=valuelist[t+(j++)]; | ||
144 | case 0: | ||
145 | break; | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | return(0); | ||
150 | } | ||
151 | |||
152 | int decodev_set(float[] a,int offset, Buffer b, int n){ | ||
153 | int i,j,entry; | ||
154 | int t; | ||
155 | |||
156 | for(i=0;i<n;){ | ||
157 | entry = decode(b); | ||
158 | if(entry==-1)return(-1); | ||
159 | t=entry*dim; | ||
160 | for(j=0;j<dim;){ | ||
161 | a[offset+i++]=valuelist[t+(j++)]; | ||
162 | } | ||
163 | } | ||
164 | return(0); | ||
165 | } | ||
166 | |||
167 | int decodevv_add(float[][] a, int offset,int ch, Buffer b,int n){ | ||
168 | int i,j,k,entry; | ||
169 | int chptr=0; | ||
170 | //System.out.println("decodevv_add: a="+a+",b="+b+",valuelist="+valuelist); | ||
171 | |||
172 | for(i=offset/ch;i<(offset+n)/ch;){ | ||
173 | entry = decode(b); | ||
174 | if(entry==-1)return(-1); | ||
175 | |||
176 | int t = entry*dim; | ||
177 | for(j=0;j<dim;j++){ | ||
178 | a[chptr++][i]+=valuelist[t+j]; | ||
179 | if(chptr==ch){ | ||
180 | chptr=0; | ||
181 | i++; | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | return(0); | ||
186 | } | ||
187 | |||
188 | |||
189 | // Decode side is specced and easier, because we don't need to find | ||
190 | // matches using different criteria; we simply read and map. There are | ||
191 | // two things we need to do 'depending': | ||
192 | // | ||
193 | // We may need to support interleave. We don't really, but it's | ||
194 | // convenient to do it here rather than rebuild the vector later. | ||
195 | // | ||
196 | // Cascades may be additive or multiplicitive; this is not inherent in | ||
197 | // the codebook, but set in the code using the codebook. Like | ||
198 | // interleaving, it's easiest to do it here. | ||
199 | // stage==0 -> declarative (set the value) | ||
200 | // stage==1 -> additive | ||
201 | // stage==2 -> multiplicitive | ||
202 | |||
203 | // returns the entry number or -1 on eof | ||
204 | int decode(Buffer b){ | ||
205 | int ptr=0; | ||
206 | DecodeAux t=decode_tree; | ||
207 | int lok=b.look(t.tabn); | ||
208 | //System.err.println(this+" "+t+" lok="+lok+", tabn="+t.tabn); | ||
209 | |||
210 | if(lok>=0){ | ||
211 | ptr=t.tab[lok]; | ||
212 | b.adv(t.tabl[lok]); | ||
213 | if(ptr<=0){ | ||
214 | return -ptr; | ||
215 | } | ||
216 | } | ||
217 | do{ | ||
218 | switch(b.read1()){ | ||
219 | case 0: | ||
220 | ptr=t.ptr0[ptr]; | ||
221 | break; | ||
222 | case 1: | ||
223 | ptr=t.ptr1[ptr]; | ||
224 | break; | ||
225 | case -1: | ||
226 | default: | ||
227 | return(-1); | ||
228 | } | ||
229 | } | ||
230 | while(ptr>0); | ||
231 | return(-ptr); | ||
232 | } | ||
233 | |||
234 | // returns the entry number or -1 on eof | ||
235 | int decodevs(float[] a, int index, Buffer b, int step,int addmul){ | ||
236 | int entry=decode(b); | ||
237 | if(entry==-1)return(-1); | ||
238 | switch(addmul){ | ||
239 | case -1: | ||
240 | for(int i=0,o=0;i<dim;i++,o+=step) | ||
241 | a[index+o]=valuelist[entry*dim+i]; | ||
242 | break; | ||
243 | case 0: | ||
244 | for(int i=0,o=0;i<dim;i++,o+=step) | ||
245 | a[index+o]+=valuelist[entry*dim+i]; | ||
246 | break; | ||
247 | case 1: | ||
248 | for(int i=0,o=0;i<dim;i++,o+=step) | ||
249 | a[index+o]*=valuelist[entry*dim+i]; | ||
250 | break; | ||
251 | default: | ||
252 | //System.err.println("CodeBook.decodeves: addmul="+addmul); | ||
253 | } | ||
254 | return(entry); | ||
255 | } | ||
256 | |||
257 | int best(float[] a, int step){ | ||
258 | EncodeAuxNearestMatch nt=c.nearest_tree; | ||
259 | EncodeAuxThreshMatch tt=c.thresh_tree; | ||
260 | int ptr=0; | ||
261 | |||
262 | // we assume for now that a thresh tree is the only other possibility | ||
263 | if(tt!=null){ | ||
264 | int index=0; | ||
265 | // find the quant val of each scalar | ||
266 | for(int k=0,o=step*(dim-1);k<dim;k++,o-=step){ | ||
267 | int i; | ||
268 | // linear search the quant list for now; it's small and although | ||
269 | // with > 8 entries, it would be faster to bisect, this would be | ||
270 | // a misplaced optimization for now | ||
271 | for(i=0;i<tt.threshvals-1;i++){ | ||
272 | if(a[o]<tt.quantthresh[i]){ | ||
273 | break; | ||
274 | } | ||
275 | } | ||
276 | index=(index*tt.quantvals)+tt.quantmap[i]; | ||
277 | } | ||
278 | // regular lattices are easy :-) | ||
279 | if(c.lengthlist[index]>0){ | ||
280 | // is this unused? If so, we'll | ||
281 | // use a decision tree after all | ||
282 | // and fall through | ||
283 | return(index); | ||
284 | } | ||
285 | } | ||
286 | if(nt!=null){ | ||
287 | // optimized using the decision tree | ||
288 | while(true){ | ||
289 | float c=0.f; | ||
290 | int p=nt.p[ptr]; | ||
291 | int q=nt.q[ptr]; | ||
292 | for(int k=0,o=0;k<dim;k++,o+=step){ | ||
293 | c+=(valuelist[p+k]-valuelist[q+k])* | ||
294 | (a[o]-(valuelist[p+k]+valuelist[q+k])*.5); | ||
295 | } | ||
296 | if(c>0.){ // in A | ||
297 | ptr= -nt.ptr0[ptr]; | ||
298 | } | ||
299 | else{ // in B | ||
300 | ptr= -nt.ptr1[ptr]; | ||
301 | } | ||
302 | if(ptr<=0)break; | ||
303 | } | ||
304 | return(-ptr); | ||
305 | } | ||
306 | |||
307 | // brute force it! | ||
308 | { | ||
309 | int besti=-1; | ||
310 | float best=0.f; | ||
311 | int e=0; | ||
312 | for(int i=0;i<entries;i++){ | ||
313 | if(c.lengthlist[i]>0){ | ||
314 | float _this=dist(dim, valuelist, e, a, step); | ||
315 | if(besti==-1 || _this<best){ | ||
316 | best=_this; | ||
317 | besti=i; | ||
318 | } | ||
319 | } | ||
320 | e+=dim; | ||
321 | } | ||
322 | return(besti); | ||
323 | } | ||
324 | } | ||
325 | |||
326 | // returns the entry number and *modifies a* to the remainder value | ||
327 | int besterror(float[] a, int step, int addmul){ | ||
328 | int best=best(a,step); | ||
329 | switch(addmul){ | ||
330 | case 0: | ||
331 | for(int i=0,o=0;i<dim;i++,o+=step) | ||
332 | a[o]-=valuelist[best*dim+i]; | ||
333 | break; | ||
334 | case 1: | ||
335 | for(int i=0,o=0;i<dim;i++,o+=step){ | ||
336 | float val=valuelist[best*dim+i]; | ||
337 | if(val==0){ | ||
338 | a[o]=0; | ||
339 | }else{ | ||
340 | a[o]/=val; | ||
341 | } | ||
342 | } | ||
343 | break; | ||
344 | } | ||
345 | return(best); | ||
346 | } | ||
347 | |||
348 | void clear(){ | ||
349 | // static book is not cleared; we're likely called on the lookup and | ||
350 | // the static codebook belongs to the info struct | ||
351 | //if(decode_tree!=null){ | ||
352 | // free(b->decode_tree->ptr0); | ||
353 | // free(b->decode_tree->ptr1); | ||
354 | // memset(b->decode_tree,0,sizeof(decode_aux)); | ||
355 | // free(b->decode_tree); | ||
356 | //} | ||
357 | //if(valuelist!=null)free(b->valuelist); | ||
358 | //if(codelist!=null)free(b->codelist); | ||
359 | //memset(b,0,sizeof(codebook)); | ||
360 | } | ||
361 | |||
362 | private static float dist(int el, float[] ref, int index, float[] b, int step){ | ||
363 | float acc=(float)0.; | ||
364 | for(int i=0; i<el; i++){ | ||
365 | float val=(ref[index+i]-b[i*step]); | ||
366 | acc+=val*val; | ||
367 | } | ||
368 | return(acc); | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | int init_encode(StaticCodeBook s){ | ||
373 | //memset(c,0,sizeof(codebook)); | ||
374 | c=s; | ||
375 | entries=s.entries; | ||
376 | dim=s.dim; | ||
377 | codelist=make_words(s.lengthlist, s.entries); | ||
378 | valuelist=s.unquantize(); | ||
379 | return(0); | ||
380 | } | ||
381 | */ | ||
382 | |||
383 | int init_decode(StaticCodeBook s){ | ||
384 | //memset(c,0,sizeof(codebook)); | ||
385 | c=s; | ||
386 | entries=s.entries; | ||
387 | dim=s.dim; | ||
388 | valuelist=s.unquantize(); | ||
389 | |||
390 | decode_tree=make_decode_tree(); | ||
391 | if(decode_tree==null){ | ||
392 | //goto err_out; | ||
393 | clear(); | ||
394 | return(-1); | ||
395 | } | ||
396 | return(0); | ||
397 | // err_out: | ||
398 | // vorbis_book_clear(c); | ||
399 | // return(-1); | ||
400 | } | ||
401 | |||
402 | // given a list of word lengths, generate a list of codewords. Works | ||
403 | // for length ordered or unordered, always assigns the lowest valued | ||
404 | // codewords first. Extended to handle unused entries (length 0) | ||
405 | static int[] make_words(int[] l, int n){ | ||
406 | int[] marker=new int[33]; | ||
407 | int[] r=new int[n]; | ||
408 | //memset(marker,0,sizeof(marker)); | ||
409 | |||
410 | for(int i=0;i<n;i++){ | ||
411 | int length=l[i]; | ||
412 | if(length>0){ | ||
413 | int entry=marker[length]; | ||
414 | |||
415 | // when we claim a node for an entry, we also claim the nodes | ||
416 | // below it (pruning off the imagined tree that may have dangled | ||
417 | // from it) as well as blocking the use of any nodes directly | ||
418 | // above for leaves | ||
419 | |||
420 | // update ourself | ||
421 | if(length<32 && (entry>>>length)!=0){ | ||
422 | // error condition; the lengths must specify an overpopulated tree | ||
423 | //free(r); | ||
424 | return(null); | ||
425 | } | ||
426 | r[i]=entry; | ||
427 | |||
428 | // Look to see if the next shorter marker points to the node | ||
429 | // above. if so, update it and repeat. | ||
430 | { | ||
431 | for(int j=length;j>0;j--){ | ||
432 | if((marker[j]&1)!=0){ | ||
433 | // have to jump branches | ||
434 | if(j==1)marker[1]++; | ||
435 | else marker[j]=marker[j-1]<<1; | ||
436 | break; // invariant says next upper marker would already | ||
437 | // have been moved if it was on the same path | ||
438 | } | ||
439 | marker[j]++; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | // prune the tree; the implicit invariant says all the longer | ||
444 | // markers were dangling from our just-taken node. Dangle them | ||
445 | // from our *new* node. | ||
446 | for(int j=length+1;j<33;j++){ | ||
447 | if((marker[j]>>>1) == entry){ | ||
448 | entry=marker[j]; | ||
449 | marker[j]=marker[j-1]<<1; | ||
450 | } | ||
451 | else{ | ||
452 | break; | ||
453 | } | ||
454 | } | ||
455 | } | ||
456 | } | ||
457 | |||
458 | // bitreverse the words because our bitwise packer/unpacker is LSb | ||
459 | // endian | ||
460 | for(int i=0;i<n;i++){ | ||
461 | int temp=0; | ||
462 | for(int j=0;j<l[i];j++){ | ||
463 | temp<<=1; | ||
464 | temp|=(r[i]>>>j)&1; | ||
465 | } | ||
466 | r[i]=temp; | ||
467 | } | ||
468 | |||
469 | return(r); | ||
470 | } | ||
471 | |||
472 | // build the decode helper tree from the codewords | ||
473 | DecodeAux make_decode_tree(){ | ||
474 | int top=0; | ||
475 | DecodeAux t=new DecodeAux(); | ||
476 | int[] ptr0=t.ptr0=new int[entries*2]; | ||
477 | int[] ptr1=t.ptr1=new int[entries*2]; | ||
478 | int[] codelist=make_words(c.lengthlist, c.entries); | ||
479 | |||
480 | if(codelist==null)return(null); | ||
481 | t.aux=entries*2; | ||
482 | |||
483 | for(int i=0;i<entries;i++){ | ||
484 | if(c.lengthlist[i]>0){ | ||
485 | int ptr=0; | ||
486 | int j; | ||
487 | for(j=0;j<c.lengthlist[i]-1;j++){ | ||
488 | int bit=(codelist[i]>>>j)&1; | ||
489 | if(bit==0){ | ||
490 | if(ptr0[ptr]==0){ | ||
491 | ptr0[ptr]=++top; | ||
492 | } | ||
493 | ptr=ptr0[ptr]; | ||
494 | } | ||
495 | else{ | ||
496 | if(ptr1[ptr]==0){ | ||
497 | ptr1[ptr]= ++top; | ||
498 | } | ||
499 | ptr=ptr1[ptr]; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | if(((codelist[i]>>>j)&1)==0){ ptr0[ptr]=-i; } | ||
504 | else{ ptr1[ptr]=-i; } | ||
505 | |||
506 | } | ||
507 | } | ||
508 | //free(codelist); | ||
509 | |||
510 | t.tabn = ilog(entries)-4; | ||
511 | |||
512 | if(t.tabn<5)t.tabn=5; | ||
513 | int n = 1<<t.tabn; | ||
514 | t.tab = new int[n]; | ||
515 | t.tabl = new int[n]; | ||
516 | for(int i = 0; i < n; i++){ | ||
517 | int p = 0; | ||
518 | int j=0; | ||
519 | for(j = 0; j < t.tabn && (p > 0 || j == 0); j++){ | ||
520 | if ((i&(1<<j))!=0){ | ||
521 | p = ptr1[p]; | ||
522 | } | ||
523 | else{ | ||
524 | p = ptr0[p]; | ||
525 | } | ||
526 | } | ||
527 | t.tab[i]=p; // -code | ||
528 | t.tabl[i]=j; // length | ||
529 | } | ||
530 | |||
531 | return(t); | ||
532 | } | ||
533 | |||
534 | private static int ilog(int v){ | ||
535 | int ret=0; | ||
536 | while(v!=0){ | ||
537 | ret++; | ||
538 | v>>>=1; | ||
539 | } | ||
540 | return(ret); | ||
541 | } | ||
542 | |||
543 | /* | ||
544 | // TEST | ||
545 | // Simple enough; pack a few candidate codebooks, unpack them. Code a | ||
546 | // number of vectors through (keeping track of the quantized values), | ||
547 | // and decode using the unpacked book. quantized version of in should | ||
548 | // exactly equal out | ||
549 | |||
550 | //#include "vorbis/book/lsp20_0.vqh" | ||
551 | //#include "vorbis/book/lsp32_0.vqh" | ||
552 | //#include "vorbis/book/res0_1a.vqh" | ||
553 | static final int TESTSIZE=40; | ||
554 | |||
555 | static float[] test1={ | ||
556 | 0.105939, | ||
557 | 0.215373, | ||
558 | 0.429117, | ||
559 | 0.587974, | ||
560 | |||
561 | 0.181173, | ||
562 | 0.296583, | ||
563 | 0.515707, | ||
564 | 0.715261, | ||
565 | |||
566 | 0.162327, | ||
567 | 0.263834, | ||
568 | 0.342876, | ||
569 | 0.406025, | ||
570 | |||
571 | 0.103571, | ||
572 | 0.223561, | ||
573 | 0.368513, | ||
574 | 0.540313, | ||
575 | |||
576 | 0.136672, | ||
577 | 0.395882, | ||
578 | 0.587183, | ||
579 | 0.652476, | ||
580 | |||
581 | 0.114338, | ||
582 | 0.417300, | ||
583 | 0.525486, | ||
584 | 0.698679, | ||
585 | |||
586 | 0.147492, | ||
587 | 0.324481, | ||
588 | 0.643089, | ||
589 | 0.757582, | ||
590 | |||
591 | 0.139556, | ||
592 | 0.215795, | ||
593 | 0.324559, | ||
594 | 0.399387, | ||
595 | |||
596 | 0.120236, | ||
597 | 0.267420, | ||
598 | 0.446940, | ||
599 | 0.608760, | ||
600 | |||
601 | 0.115587, | ||
602 | 0.287234, | ||
603 | 0.571081, | ||
604 | 0.708603, | ||
605 | }; | ||
606 | |||
607 | static float[] test2={ | ||
608 | 0.088654, | ||
609 | 0.165742, | ||
610 | 0.279013, | ||
611 | 0.395894, | ||
612 | |||
613 | 0.110812, | ||
614 | 0.218422, | ||
615 | 0.283423, | ||
616 | 0.371719, | ||
617 | |||
618 | 0.136985, | ||
619 | 0.186066, | ||
620 | 0.309814, | ||
621 | 0.381521, | ||
622 | |||
623 | 0.123925, | ||
624 | 0.211707, | ||
625 | 0.314771, | ||
626 | 0.433026, | ||
627 | |||
628 | 0.088619, | ||
629 | 0.192276, | ||
630 | 0.277568, | ||
631 | 0.343509, | ||
632 | |||
633 | 0.068400, | ||
634 | 0.132901, | ||
635 | 0.223999, | ||
636 | 0.302538, | ||
637 | |||
638 | 0.202159, | ||
639 | 0.306131, | ||
640 | 0.360362, | ||
641 | 0.416066, | ||
642 | |||
643 | 0.072591, | ||
644 | 0.178019, | ||
645 | 0.304315, | ||
646 | 0.376516, | ||
647 | |||
648 | 0.094336, | ||
649 | 0.188401, | ||
650 | 0.325119, | ||
651 | 0.390264, | ||
652 | |||
653 | 0.091636, | ||
654 | 0.223099, | ||
655 | 0.282899, | ||
656 | 0.375124, | ||
657 | }; | ||
658 | |||
659 | static float[] test3={ | ||
660 | 0,1,-2,3,4,-5,6,7,8,9, | ||
661 | 8,-2,7,-1,4,6,8,3,1,-9, | ||
662 | 10,11,12,13,14,15,26,17,18,19, | ||
663 | 30,-25,-30,-1,-5,-32,4,3,-2,0}; | ||
664 | |||
665 | // static_codebook *testlist[]={&_vq_book_lsp20_0, | ||
666 | // &_vq_book_lsp32_0, | ||
667 | // &_vq_book_res0_1a,NULL}; | ||
668 | static[][] float testvec={test1,test2,test3}; | ||
669 | |||
670 | static void main(String[] arg){ | ||
671 | Buffer write=new Buffer(); | ||
672 | Buffer read=new Buffer(); | ||
673 | int ptr=0; | ||
674 | write.writeinit(); | ||
675 | |||
676 | System.err.println("Testing codebook abstraction...:"); | ||
677 | |||
678 | while(testlist[ptr]!=null){ | ||
679 | CodeBook c=new CodeBook(); | ||
680 | StaticCodeBook s=new StaticCodeBook();; | ||
681 | float *qv=alloca(sizeof(float)*TESTSIZE); | ||
682 | float *iv=alloca(sizeof(float)*TESTSIZE); | ||
683 | memcpy(qv,testvec[ptr],sizeof(float)*TESTSIZE); | ||
684 | memset(iv,0,sizeof(float)*TESTSIZE); | ||
685 | |||
686 | System.err.print("\tpacking/coding "+ptr+"... "); | ||
687 | |||
688 | // pack the codebook, write the testvector | ||
689 | write.reset(); | ||
690 | vorbis_book_init_encode(&c,testlist[ptr]); // get it into memory | ||
691 | // we can write | ||
692 | vorbis_staticbook_pack(testlist[ptr],&write); | ||
693 | System.err.print("Codebook size "+write.bytes()+" bytes... "); | ||
694 | for(int i=0;i<TESTSIZE;i+=c.dim){ | ||
695 | vorbis_book_encodev(&c,qv+i,&write); | ||
696 | } | ||
697 | c.clear(); | ||
698 | |||
699 | System.err.print("OK.\n"); | ||
700 | System.err.print("\tunpacking/decoding "+ptr+"... "); | ||
701 | |||
702 | // transfer the write data to a read buffer and unpack/read | ||
703 | _oggpack_readinit(&read,_oggpack_buffer(&write),_oggpack_bytes(&write)); | ||
704 | if(s.unpack(read)){ | ||
705 | System.err.print("Error unpacking codebook.\n"); | ||
706 | System.exit(1); | ||
707 | } | ||
708 | if(vorbis_book_init_decode(&c,&s)){ | ||
709 | System.err.print("Error initializing codebook.\n"); | ||
710 | System.exit(1); | ||
711 | } | ||
712 | for(int i=0;i<TESTSIZE;i+=c.dim){ | ||
713 | if(vorbis_book_decodevs(&c,iv+i,&read,1,-1)==-1){ | ||
714 | System.err.print("Error reading codebook test data (EOP).\n"); | ||
715 | System.exit(1); | ||
716 | } | ||
717 | } | ||
718 | for(int i=0;i<TESTSIZE;i++){ | ||
719 | if(fabs(qv[i]-iv[i])>.000001){ | ||
720 | System.err.print("read ("+iv[i]+") != written ("+qv[i]+") at position ("+i+")\n"); | ||
721 | System.exit(1); | ||
722 | } | ||
723 | } | ||
724 | |||
725 | System.err.print("OK\n"); | ||
726 | ptr++; | ||
727 | } | ||
728 | // The above is the trivial stuff; | ||
729 | // now try unquantizing a log scale codebook | ||
730 | } | ||
731 | */ | ||
732 | } | ||
733 | |||
734 | class DecodeAux{ | ||
735 | int[] tab; | ||
736 | int[] tabl; | ||
737 | int tabn; | ||
738 | |||
739 | int[] ptr0; | ||
740 | int[] ptr1; | ||
741 | int aux; // number of tree entries | ||
742 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Comment.java b/songdbj/com/jcraft/jorbis/Comment.java new file mode 100644 index 0000000000..f83b7cb985 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Comment.java | |||
@@ -0,0 +1,252 @@ | |||
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 | // the comments are not part of vorbis_info so that vorbis_info can be | ||
31 | // static storage | ||
32 | public class Comment{ | ||
33 | private static byte[] _vorbis="vorbis".getBytes(); | ||
34 | |||
35 | private static final int OV_EFAULT=-129; | ||
36 | private static final int OV_EIMPL=-130; | ||
37 | |||
38 | // unlimited user comment fields. libvorbis writes 'libvorbis' | ||
39 | // whatever vendor is set to in encode | ||
40 | public byte[][] user_comments; | ||
41 | public int[] comment_lengths; | ||
42 | public int comments; | ||
43 | public byte[] vendor; | ||
44 | |||
45 | public void init(){ | ||
46 | user_comments=null; | ||
47 | comments=0; | ||
48 | vendor=null; | ||
49 | } | ||
50 | |||
51 | public void add(String comment){ | ||
52 | add(comment.getBytes()); | ||
53 | } | ||
54 | |||
55 | private void add(byte[] comment){ | ||
56 | byte[][] foo=new byte[comments+2][]; | ||
57 | if(user_comments!=null){ | ||
58 | System.arraycopy(user_comments, 0, foo, 0, comments); | ||
59 | } | ||
60 | user_comments=foo; | ||
61 | |||
62 | int[] goo=new int[comments+2]; | ||
63 | if(comment_lengths!=null){ | ||
64 | System.arraycopy(comment_lengths, 0, goo, 0, comments); | ||
65 | } | ||
66 | comment_lengths=goo; | ||
67 | |||
68 | byte[] bar=new byte[comment.length+1]; | ||
69 | System.arraycopy(comment, 0, bar, 0, comment.length); | ||
70 | user_comments[comments]=bar; | ||
71 | comment_lengths[comments]=comment.length; | ||
72 | comments++; | ||
73 | user_comments[comments]=null; | ||
74 | } | ||
75 | |||
76 | public void add_tag(String tag, String contents){ | ||
77 | if(contents==null) contents=""; | ||
78 | add(tag+"="+contents); | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | private void add_tag(byte[] tag, byte[] contents){ | ||
83 | byte[] foo=new byte[tag.length+contents.length+1]; | ||
84 | int j=0; | ||
85 | for(int i=0; i<tag.length; i++){foo[j++]=tag[i];} | ||
86 | foo[j++]=(byte)'='; j++; | ||
87 | for(int i=0; i<contents.length; i++){foo[j++]=tag[i];} | ||
88 | add(foo); | ||
89 | } | ||
90 | */ | ||
91 | |||
92 | // This is more or less the same as strncasecmp - but that doesn't exist | ||
93 | // * everywhere, and this is a fairly trivial function, so we include it | ||
94 | static boolean tagcompare(byte[] s1, byte[] s2, int n){ | ||
95 | int c=0; | ||
96 | byte u1, u2; | ||
97 | while(c < n){ | ||
98 | u1=s1[c]; u2=s2[c]; | ||
99 | if('Z'>=u1 && u1>='A')u1=(byte)(u1-'A'+'a'); | ||
100 | if('Z'>=u2 && u2>='A')u2=(byte)(u2-'A'+'a'); | ||
101 | if(u1!=u2){ return false; } | ||
102 | c++; | ||
103 | } | ||
104 | return true; | ||
105 | } | ||
106 | |||
107 | public String query(String tag){ | ||
108 | return query(tag, 0); | ||
109 | } | ||
110 | |||
111 | public String query(String tag, int count){ | ||
112 | int foo=query(tag.getBytes(), count); | ||
113 | if(foo==-1)return null; | ||
114 | byte[] comment=user_comments[foo]; | ||
115 | for(int i=0; i<comment_lengths[foo]; i++){ | ||
116 | if(comment[i]=='='){ | ||
117 | return new String(comment, i+1, comment_lengths[foo]-(i+1)); | ||
118 | } | ||
119 | } | ||
120 | return null; | ||
121 | } | ||
122 | |||
123 | private int query(byte[] tag, int count){ | ||
124 | int i=0; | ||
125 | int found = 0; | ||
126 | int fulltaglen = tag.length + 1; | ||
127 | byte[] fulltag = new byte[fulltaglen]; | ||
128 | System.arraycopy(tag, 0, fulltag, 0, tag.length); | ||
129 | fulltag[tag.length]=(byte)'='; | ||
130 | |||
131 | for(i=0;i<comments;i++){ | ||
132 | if(tagcompare(user_comments[i], fulltag, fulltaglen)){ | ||
133 | if(count==found){ | ||
134 | // We return a pointer to the data, not a copy | ||
135 | //return user_comments[i] + taglen + 1; | ||
136 | return i; | ||
137 | } | ||
138 | else{ found++; } | ||
139 | } | ||
140 | } | ||
141 | return -1; | ||
142 | } | ||
143 | |||
144 | int unpack(Buffer opb){ | ||
145 | int vendorlen=opb.read(32); | ||
146 | if(vendorlen<0){ | ||
147 | //goto err_out; | ||
148 | clear(); | ||
149 | return(-1); | ||
150 | } | ||
151 | vendor=new byte[vendorlen+1]; | ||
152 | opb.read(vendor,vendorlen); | ||
153 | comments=opb.read(32); | ||
154 | if(comments<0){ | ||
155 | //goto err_out; | ||
156 | clear(); | ||
157 | return(-1); | ||
158 | } | ||
159 | user_comments=new byte[comments+1][]; | ||
160 | comment_lengths=new int[comments+1]; | ||
161 | |||
162 | for(int i=0;i<comments;i++){ | ||
163 | int len=opb.read(32); | ||
164 | if(len<0){ | ||
165 | //goto err_out; | ||
166 | clear(); | ||
167 | return(-1); | ||
168 | } | ||
169 | comment_lengths[i]=len; | ||
170 | user_comments[i]=new byte[len+1]; | ||
171 | opb.read(user_comments[i], len); | ||
172 | } | ||
173 | if(opb.read(1)!=1){ | ||
174 | //goto err_out; // EOP check | ||
175 | clear(); | ||
176 | return(-1); | ||
177 | |||
178 | } | ||
179 | return(0); | ||
180 | // err_out: | ||
181 | // comment_clear(vc); | ||
182 | // return(-1); | ||
183 | } | ||
184 | |||
185 | int pack(Buffer opb){ | ||
186 | byte[] temp="Xiphophorus libVorbis I 20000508".getBytes(); | ||
187 | |||
188 | // preamble | ||
189 | opb.write(0x03,8); | ||
190 | opb.write(_vorbis); | ||
191 | |||
192 | // vendor | ||
193 | opb.write(temp.length,32); | ||
194 | opb.write(temp); | ||
195 | |||
196 | // comments | ||
197 | |||
198 | opb.write(comments,32); | ||
199 | if(comments!=0){ | ||
200 | for(int i=0;i<comments;i++){ | ||
201 | if(user_comments[i]!=null){ | ||
202 | opb.write(comment_lengths[i],32); | ||
203 | opb.write(user_comments[i]); | ||
204 | } | ||
205 | else{ | ||
206 | opb.write(0,32); | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | opb.write(1,1); | ||
211 | return(0); | ||
212 | } | ||
213 | |||
214 | public int header_out(Packet op){ | ||
215 | Buffer opb=new Buffer(); | ||
216 | opb.writeinit(); | ||
217 | |||
218 | if(pack(opb)!=0) return OV_EIMPL; | ||
219 | |||
220 | op.packet_base = new byte[opb.bytes()]; | ||
221 | op.packet=0; | ||
222 | op.bytes=opb.bytes(); | ||
223 | System.arraycopy(opb.buffer(), 0, op.packet_base, 0, op.bytes); | ||
224 | op.b_o_s=0; | ||
225 | op.e_o_s=0; | ||
226 | op.granulepos=0; | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | void clear(){ | ||
231 | for(int i=0;i<comments;i++) | ||
232 | user_comments[i]=null; | ||
233 | user_comments=null; | ||
234 | vendor=null; | ||
235 | } | ||
236 | |||
237 | public String getVendor(){ | ||
238 | return new String(vendor, 0, vendor.length-1); | ||
239 | } | ||
240 | public String getComment(int i){ | ||
241 | if(comments<=i)return null; | ||
242 | return new String(user_comments[i], 0, user_comments[i].length-1); | ||
243 | } | ||
244 | public String toString(){ | ||
245 | String foo="Vendor: "+new String(vendor, 0, vendor.length-1); | ||
246 | for(int i=0; i<comments; i++){ | ||
247 | foo=foo+"\nComment: "+new String(user_comments[i], 0, user_comments[i].length-1); | ||
248 | } | ||
249 | foo=foo+"\n"; | ||
250 | return foo; | ||
251 | } | ||
252 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/DecodeExample.java b/songdbj/com/jcraft/jorbis/DecodeExample.java new file mode 100644 index 0000000000..f8768969a2 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/DecodeExample.java | |||
@@ -0,0 +1,316 @@ | |||
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 | // Takes a vorbis bitstream from stdin and writes raw stereo PCM to | ||
31 | // stdout. Decodes simple and chained OggVorbis files from beginning | ||
32 | // to end. Vorbisfile.a is somewhat more complex than the code below. | ||
33 | |||
34 | class DecodeExample{ | ||
35 | static int convsize=4096*2; | ||
36 | static byte[] convbuffer=new byte[convsize]; // take 8k out of the data segment, not the stack | ||
37 | |||
38 | public static void main(String[] arg){ | ||
39 | java.io.InputStream input=System.in; | ||
40 | if(arg.length>0){ | ||
41 | try{ | ||
42 | input=new java.io.FileInputStream(arg[0]); | ||
43 | } | ||
44 | catch(Exception e){ | ||
45 | System.err.println(e); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | SyncState oy=new SyncState(); // sync and verify incoming physical bitstream | ||
50 | StreamState os=new StreamState(); // take physical pages, weld into a logical stream of packets | ||
51 | Page og=new Page(); // one Ogg bitstream page. Vorbis packets are inside | ||
52 | Packet op=new Packet(); // one raw packet of data for decode | ||
53 | |||
54 | Info vi=new Info(); // struct that stores all the static vorbis bitstream settings | ||
55 | Comment vc=new Comment(); // struct that stores all the bitstream user comments | ||
56 | DspState vd=new DspState(); // central working state for the packet->PCM decoder | ||
57 | Block vb=new Block(vd); // local working space for packet->PCM decode | ||
58 | |||
59 | byte[] buffer; | ||
60 | int bytes=0; | ||
61 | |||
62 | // Decode setup | ||
63 | |||
64 | oy.init(); // Now we can read pages | ||
65 | |||
66 | while(true){ // we repeat if the bitstream is chained | ||
67 | int eos=0; | ||
68 | |||
69 | // grab some data at the head of the stream. We want the first page | ||
70 | // (which is guaranteed to be small and only contain the Vorbis | ||
71 | // stream initial header) We need the first page to get the stream | ||
72 | // serialno. | ||
73 | |||
74 | // submit a 4k block to libvorbis' Ogg layer | ||
75 | int index=oy.buffer(4096); | ||
76 | buffer=oy.data; | ||
77 | try{ | ||
78 | bytes=input.read(buffer, index, 4096); | ||
79 | } | ||
80 | catch(Exception e){ | ||
81 | System.err.println(e); | ||
82 | System.exit(-1); | ||
83 | } | ||
84 | oy.wrote(bytes); | ||
85 | |||
86 | // Get the first page. | ||
87 | if(oy.pageout(og)!=1){ | ||
88 | // have we simply run out of data? If so, we're done. | ||
89 | if(bytes<4096)break; | ||
90 | |||
91 | // error case. Must not be Vorbis data | ||
92 | System.err.println("Input does not appear to be an Ogg bitstream."); | ||
93 | System.exit(1); | ||
94 | } | ||
95 | |||
96 | // Get the serial number and set up the rest of decode. | ||
97 | // serialno first; use it to set up a logical stream | ||
98 | os.init(og.serialno()); | ||
99 | |||
100 | // extract the initial header from the first page and verify that the | ||
101 | // Ogg bitstream is in fact Vorbis data | ||
102 | |||
103 | // I handle the initial header first instead of just having the code | ||
104 | // read all three Vorbis headers at once because reading the initial | ||
105 | // header is an easy way to identify a Vorbis bitstream and it's | ||
106 | // useful to see that functionality seperated out. | ||
107 | |||
108 | vi.init(); | ||
109 | vc.init(); | ||
110 | if(os.pagein(og)<0){ | ||
111 | // error; stream version mismatch perhaps | ||
112 | System.err.println("Error reading first page of Ogg bitstream data."); | ||
113 | System.exit(1); | ||
114 | } | ||
115 | |||
116 | if(os.packetout(op)!=1){ | ||
117 | // no page? must not be vorbis | ||
118 | System.err.println("Error reading initial header packet."); | ||
119 | System.exit(1); | ||
120 | } | ||
121 | |||
122 | if(vi.synthesis_headerin(vc,op)<0){ | ||
123 | // error case; not a vorbis header | ||
124 | System.err.println("This Ogg bitstream does not contain Vorbis audio data."); | ||
125 | System.exit(1); | ||
126 | } | ||
127 | |||
128 | // At this point, we're sure we're Vorbis. We've set up the logical | ||
129 | // (Ogg) bitstream decoder. Get the comment and codebook headers and | ||
130 | // set up the Vorbis decoder | ||
131 | |||
132 | // The next two packets in order are the comment and codebook headers. | ||
133 | // They're likely large and may span multiple pages. Thus we reead | ||
134 | // and submit data until we get our two pacakets, watching that no | ||
135 | // pages are missing. If a page is missing, error out; losing a | ||
136 | // header page is the only place where missing data is fatal. */ | ||
137 | |||
138 | int i=0; | ||
139 | while(i<2){ | ||
140 | while(i<2){ | ||
141 | |||
142 | int result=oy.pageout(og); | ||
143 | if(result==0) break; // Need more data | ||
144 | // Don't complain about missing or corrupt data yet. We'll | ||
145 | // catch it at the packet output phase | ||
146 | |||
147 | if(result==1){ | ||
148 | os.pagein(og); // we can ignore any errors here | ||
149 | // as they'll also become apparent | ||
150 | // at packetout | ||
151 | while(i<2){ | ||
152 | result=os.packetout(op); | ||
153 | if(result==0)break; | ||
154 | if(result==-1){ | ||
155 | // Uh oh; data at some point was corrupted or missing! | ||
156 | // We can't tolerate that in a header. Die. | ||
157 | System.err.println("Corrupt secondary header. Exiting."); | ||
158 | System.exit(1); | ||
159 | } | ||
160 | vi.synthesis_headerin(vc,op); | ||
161 | i++; | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | // no harm in not checking before adding more | ||
166 | index=oy.buffer(4096); | ||
167 | buffer=oy.data; | ||
168 | try{ | ||
169 | bytes=input.read(buffer, index, 4096); | ||
170 | } | ||
171 | catch(Exception e){ | ||
172 | System.err.println(e); | ||
173 | System.exit(1); | ||
174 | } | ||
175 | if(bytes==0 && i<2){ | ||
176 | System.err.println("End of file before finding all Vorbis headers!"); | ||
177 | System.exit(1); | ||
178 | } | ||
179 | oy.wrote(bytes); | ||
180 | } | ||
181 | |||
182 | // Throw the comments plus a few lines about the bitstream we're | ||
183 | // decoding | ||
184 | { | ||
185 | byte[][] ptr=vc.user_comments; | ||
186 | for(int j=0; j<ptr.length;j++){ | ||
187 | if(ptr[j]==null) break; | ||
188 | System.err.println(new String(ptr[j], 0, ptr[j].length-1)); | ||
189 | } | ||
190 | System.err.println("\nBitstream is "+vi.channels+" channel, "+vi.rate+"Hz"); | ||
191 | System.err.println("Encoded by: "+new String(vc.vendor, 0, vc.vendor.length-1)+"\n"); | ||
192 | } | ||
193 | |||
194 | convsize=4096/vi.channels; | ||
195 | |||
196 | // OK, got and parsed all three headers. Initialize the Vorbis | ||
197 | // packet->PCM decoder. | ||
198 | vd.synthesis_init(vi); // central decode state | ||
199 | vb.init(vd); // local state for most of the decode | ||
200 | // so multiple block decodes can | ||
201 | // proceed in parallel. We could init | ||
202 | // multiple vorbis_block structures | ||
203 | // for vd here | ||
204 | |||
205 | float[][][] _pcm=new float[1][][]; | ||
206 | int[] _index=new int[vi.channels]; | ||
207 | // The rest is just a straight decode loop until end of stream | ||
208 | while(eos==0){ | ||
209 | while(eos==0){ | ||
210 | |||
211 | int result=oy.pageout(og); | ||
212 | if(result==0)break; // need more data | ||
213 | if(result==-1){ // missing or corrupt data at this page position | ||
214 | System.err.println("Corrupt or missing data in bitstream; continuing..."); | ||
215 | } | ||
216 | else{ | ||
217 | os.pagein(og); // can safely ignore errors at | ||
218 | // this point | ||
219 | while(true){ | ||
220 | result=os.packetout(op); | ||
221 | |||
222 | if(result==0)break; // need more data | ||
223 | if(result==-1){ // missing or corrupt data at this page position | ||
224 | // no reason to complain; already complained above | ||
225 | } | ||
226 | else{ | ||
227 | // we have a packet. Decode it | ||
228 | int samples; | ||
229 | if(vb.synthesis(op)==0){ // test for success! | ||
230 | vd.synthesis_blockin(vb); | ||
231 | } | ||
232 | |||
233 | // **pcm is a multichannel float vector. In stereo, for | ||
234 | // example, pcm[0] is left, and pcm[1] is right. samples is | ||
235 | // the size of each channel. Convert the float values | ||
236 | // (-1.<=range<=1.) to whatever PCM format and write it out | ||
237 | |||
238 | while((samples=vd.synthesis_pcmout(_pcm, _index))>0){ | ||
239 | float[][] pcm=_pcm[0]; | ||
240 | boolean clipflag=false; | ||
241 | int bout=(samples<convsize?samples:convsize); | ||
242 | |||
243 | // convert floats to 16 bit signed ints (host order) and | ||
244 | // interleave | ||
245 | for(i=0;i<vi.channels;i++){ | ||
246 | int ptr=i*2; | ||
247 | //int ptr=i; | ||
248 | int mono=_index[i]; | ||
249 | for(int j=0;j<bout;j++){ | ||
250 | int val=(int)(pcm[i][mono+j]*32767.); | ||
251 | // short val=(short)(pcm[i][mono+j]*32767.); | ||
252 | // int val=(int)Math.round(pcm[i][mono+j]*32767.); | ||
253 | // might as well guard against clipping | ||
254 | if(val>32767){ | ||
255 | val=32767; | ||
256 | clipflag=true; | ||
257 | } | ||
258 | if(val<-32768){ | ||
259 | val=-32768; | ||
260 | clipflag=true; | ||
261 | } | ||
262 | if(val<0) val=val|0x8000; | ||
263 | convbuffer[ptr]=(byte)(val); | ||
264 | convbuffer[ptr+1]=(byte)(val>>>8); | ||
265 | ptr+=2*(vi.channels); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | //if(clipflag) | ||
270 | // System.err.println("Clipping in frame "+vd.sequence); | ||
271 | |||
272 | System.out.write(convbuffer, 0, 2*vi.channels*bout); | ||
273 | |||
274 | vd.synthesis_read(bout); // tell libvorbis how | ||
275 | // many samples we | ||
276 | // actually consumed | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | if(og.eos()!=0)eos=1; | ||
281 | } | ||
282 | } | ||
283 | if(eos==0){ | ||
284 | index=oy.buffer(4096); | ||
285 | buffer=oy.data; | ||
286 | try{ | ||
287 | bytes=input.read(buffer,index,4096); | ||
288 | } | ||
289 | catch(Exception e){ | ||
290 | System.err.println(e); | ||
291 | System.exit(1); | ||
292 | } | ||
293 | oy.wrote(bytes); | ||
294 | if(bytes==0)eos=1; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | // clean up this logical bitstream; before exit we see if we're | ||
299 | // followed by another [chained] | ||
300 | |||
301 | os.clear(); | ||
302 | |||
303 | // ogg_page and ogg_packet structs always point to storage in | ||
304 | // libvorbis. They're never freed or manipulated directly | ||
305 | |||
306 | vb.clear(); | ||
307 | vd.clear(); | ||
308 | vi.clear(); // must be called last | ||
309 | } | ||
310 | |||
311 | // OK, clean up the framer | ||
312 | oy.clear(); | ||
313 | System.err.println("Done."); | ||
314 | } | ||
315 | } | ||
316 | |||
diff --git a/songdbj/com/jcraft/jorbis/Drft.java b/songdbj/com/jcraft/jorbis/Drft.java new file mode 100644 index 0000000000..c7ff2032e7 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Drft.java | |||
@@ -0,0 +1,1317 @@ | |||
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 | class Drft{ | ||
29 | int n; | ||
30 | float[] trigcache; | ||
31 | int[] splitcache; | ||
32 | |||
33 | void backward(float[] data){ | ||
34 | //System.err.println("Drft.backward"); | ||
35 | if(n==1)return; | ||
36 | drftb1(n,data,trigcache,trigcache,n,splitcache); | ||
37 | } | ||
38 | |||
39 | void init(int n){ | ||
40 | //System.err.println("Drft.init"); | ||
41 | this.n=n; | ||
42 | trigcache=new float[3*n]; | ||
43 | splitcache=new int[32]; | ||
44 | fdrffti(n, trigcache, splitcache); | ||
45 | } | ||
46 | |||
47 | void clear(){ | ||
48 | //System.err.println("Drft.clear"); | ||
49 | if(trigcache!=null)trigcache=null; | ||
50 | if(splitcache!=null)splitcache=null; | ||
51 | // memset(l,0,sizeof(drft_lookup)); | ||
52 | } | ||
53 | |||
54 | static int[] ntryh = { 4,2,3,5 }; | ||
55 | static float tpi = 6.28318530717958647692528676655900577f; | ||
56 | static float hsqt2 = .70710678118654752440084436210485f; | ||
57 | static float taui = .86602540378443864676372317075293618f; | ||
58 | static float taur = -.5f; | ||
59 | static float sqrt2 = 1.4142135623730950488016887242097f; | ||
60 | |||
61 | static void drfti1(int n, float[] wa, int index, int[] ifac){ | ||
62 | float arg,argh,argld,fi; | ||
63 | int ntry=0,i,j=-1; | ||
64 | int k1, l1, l2, ib; | ||
65 | int ld, ii, ip, is, nq, nr; | ||
66 | int ido, ipm, nfm1; | ||
67 | int nl=n; | ||
68 | int nf=0; | ||
69 | |||
70 | int state=101; | ||
71 | |||
72 | loop: while(true){ | ||
73 | switch(state){ | ||
74 | case 101: | ||
75 | j++; | ||
76 | if (j < 4) | ||
77 | ntry=ntryh[j]; | ||
78 | else | ||
79 | ntry+=2; | ||
80 | case 104: | ||
81 | nq=nl/ntry; | ||
82 | nr=nl-ntry*nq; | ||
83 | if(nr!=0){ | ||
84 | state=101; | ||
85 | break; | ||
86 | } | ||
87 | nf++; | ||
88 | ifac[nf+1]=ntry; | ||
89 | nl=nq; | ||
90 | if(ntry!=2){ | ||
91 | state=107; | ||
92 | break; | ||
93 | } | ||
94 | if(nf==1){ | ||
95 | state=107; | ||
96 | break; | ||
97 | } | ||
98 | |||
99 | for(i=1;i<nf;i++){ | ||
100 | ib=nf-i+1; | ||
101 | ifac[ib+1]=ifac[ib]; | ||
102 | } | ||
103 | ifac[2] = 2; | ||
104 | case 107: | ||
105 | if(nl!=1){ | ||
106 | state=104; | ||
107 | break; | ||
108 | } | ||
109 | ifac[0]=n; | ||
110 | ifac[1]=nf; | ||
111 | argh=tpi/n; | ||
112 | is=0; | ||
113 | nfm1=nf-1; | ||
114 | l1=1; | ||
115 | |||
116 | if(nfm1==0)return; | ||
117 | |||
118 | for (k1=0;k1<nfm1;k1++){ | ||
119 | ip=ifac[k1+2]; | ||
120 | ld=0; | ||
121 | l2=l1*ip; | ||
122 | ido=n/l2; | ||
123 | ipm=ip-1; | ||
124 | |||
125 | for (j=0;j<ipm;j++){ | ||
126 | ld+=l1; | ||
127 | i=is; | ||
128 | argld=(float)ld*argh; | ||
129 | fi=0.f; | ||
130 | for (ii=2;ii<ido;ii+=2){ | ||
131 | fi+=1.f; | ||
132 | arg=fi*argld; | ||
133 | wa[index+i++]=(float)Math.cos(arg); | ||
134 | wa[index+i++]=(float)Math.sin(arg); | ||
135 | } | ||
136 | is+=ido; | ||
137 | } | ||
138 | l1=l2; | ||
139 | } | ||
140 | break loop; | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
145 | static void fdrffti(int n, float[] wsave, int[] ifac){ | ||
146 | //System.err.println("fdrffti: n="+n); | ||
147 | if(n == 1) return; | ||
148 | drfti1(n, wsave, n, ifac); | ||
149 | } | ||
150 | |||
151 | static void dradf2(int ido,int l1,float[] cc, float[] ch, float[] wa1, int index){ | ||
152 | int i,k; | ||
153 | float ti2,tr2; | ||
154 | int t0,t1,t2,t3,t4,t5,t6; | ||
155 | |||
156 | t1=0; | ||
157 | t0=(t2=l1*ido); | ||
158 | t3=ido<<1; | ||
159 | for(k=0;k<l1;k++){ | ||
160 | ch[t1<<1]=cc[t1]+cc[t2]; | ||
161 | ch[(t1<<1)+t3-1]=cc[t1]-cc[t2]; | ||
162 | t1+=ido; | ||
163 | t2+=ido; | ||
164 | } | ||
165 | |||
166 | if(ido<2)return; | ||
167 | |||
168 | if(ido!=2){ | ||
169 | t1=0; | ||
170 | t2=t0; | ||
171 | for(k=0;k<l1;k++){ | ||
172 | t3=t2; | ||
173 | t4=(t1<<1)+(ido<<1); | ||
174 | t5=t1; | ||
175 | t6=t1+t1; | ||
176 | for(i=2;i<ido;i+=2){ | ||
177 | t3+=2; | ||
178 | t4-=2; | ||
179 | t5+=2; | ||
180 | t6+=2; | ||
181 | tr2=wa1[index+i-2]*cc[t3-1]+wa1[index+i-1]*cc[t3]; | ||
182 | ti2=wa1[index+i-2]*cc[t3]-wa1[index+i-1]*cc[t3-1]; | ||
183 | ch[t6]=cc[t5]+ti2; | ||
184 | ch[t4]=ti2-cc[t5]; | ||
185 | ch[t6-1]=cc[t5-1]+tr2; | ||
186 | ch[t4-1]=cc[t5-1]-tr2; | ||
187 | } | ||
188 | t1+=ido; | ||
189 | t2+=ido; | ||
190 | } | ||
191 | if(ido%2==1)return; | ||
192 | } | ||
193 | |||
194 | t3=(t2=(t1=ido)-1); | ||
195 | t2+=t0; | ||
196 | for(k=0;k<l1;k++){ | ||
197 | ch[t1]=-cc[t2]; | ||
198 | ch[t1-1]=cc[t3]; | ||
199 | t1+=ido<<1; | ||
200 | t2+=ido; | ||
201 | t3+=ido; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static void dradf4(int ido,int l1,float[] cc, float[] ch, | ||
206 | float[] wa1, int index1, | ||
207 | float[] wa2, int index2, | ||
208 | float[] wa3, int index3){ | ||
209 | int i,k,t0,t1,t2,t3,t4,t5,t6; | ||
210 | float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4; | ||
211 | t0=l1*ido; | ||
212 | |||
213 | t1=t0; | ||
214 | t4=t1<<1; | ||
215 | t2=t1+(t1<<1); | ||
216 | t3=0; | ||
217 | |||
218 | for(k=0;k<l1;k++){ | ||
219 | tr1=cc[t1]+cc[t2]; | ||
220 | tr2=cc[t3]+cc[t4]; | ||
221 | |||
222 | ch[t5=t3<<2]=tr1+tr2; | ||
223 | ch[(ido<<2)+t5-1]=tr2-tr1; | ||
224 | ch[(t5+=(ido<<1))-1]=cc[t3]-cc[t4]; | ||
225 | ch[t5]=cc[t2]-cc[t1]; | ||
226 | |||
227 | t1+=ido; | ||
228 | t2+=ido; | ||
229 | t3+=ido; | ||
230 | t4+=ido; | ||
231 | } | ||
232 | if(ido<2)return; | ||
233 | |||
234 | if(ido!=2){ | ||
235 | t1=0; | ||
236 | for(k=0;k<l1;k++){ | ||
237 | t2=t1; | ||
238 | t4=t1<<2; | ||
239 | t5=(t6=ido<<1)+t4; | ||
240 | for(i=2;i<ido;i+=2){ | ||
241 | t3=(t2+=2); | ||
242 | t4+=2; | ||
243 | t5-=2; | ||
244 | |||
245 | t3+=t0; | ||
246 | cr2=wa1[index1+i-2]*cc[t3-1]+wa1[index1+i-1]*cc[t3]; | ||
247 | ci2=wa1[index1+i-2]*cc[t3]-wa1[index1+i-1]*cc[t3-1]; | ||
248 | t3+=t0; | ||
249 | cr3=wa2[index2+i-2]*cc[t3-1]+wa2[index2+i-1]*cc[t3]; | ||
250 | ci3=wa2[index2+i-2]*cc[t3]-wa2[index2+i-1]*cc[t3-1]; | ||
251 | t3+=t0; | ||
252 | cr4=wa3[index3+i-2]*cc[t3-1]+wa3[index3+i-1]*cc[t3]; | ||
253 | ci4=wa3[index3+i-2]*cc[t3]-wa3[index3+i-1]*cc[t3-1]; | ||
254 | |||
255 | tr1=cr2+cr4; | ||
256 | tr4=cr4-cr2; | ||
257 | ti1=ci2+ci4; | ||
258 | ti4=ci2-ci4; | ||
259 | |||
260 | ti2=cc[t2]+ci3; | ||
261 | ti3=cc[t2]-ci3; | ||
262 | tr2=cc[t2-1]+cr3; | ||
263 | tr3=cc[t2-1]-cr3; | ||
264 | |||
265 | ch[t4-1]=tr1+tr2; | ||
266 | ch[t4]=ti1+ti2; | ||
267 | |||
268 | ch[t5-1]=tr3-ti4; | ||
269 | ch[t5]=tr4-ti3; | ||
270 | |||
271 | ch[t4+t6-1]=ti4+tr3; | ||
272 | ch[t4+t6]=tr4+ti3; | ||
273 | |||
274 | ch[t5+t6-1]=tr2-tr1; | ||
275 | ch[t5+t6]=ti1-ti2; | ||
276 | } | ||
277 | t1+=ido; | ||
278 | } | ||
279 | if((ido&1)!=0)return; | ||
280 | } | ||
281 | |||
282 | t2=(t1=t0+ido-1)+(t0<<1); | ||
283 | t3=ido<<2; | ||
284 | t4=ido; | ||
285 | t5=ido<<1; | ||
286 | t6=ido; | ||
287 | |||
288 | for(k=0;k<l1;k++){ | ||
289 | ti1=-hsqt2*(cc[t1]+cc[t2]); | ||
290 | tr1=hsqt2*(cc[t1]-cc[t2]); | ||
291 | |||
292 | ch[t4-1]=tr1+cc[t6-1]; | ||
293 | ch[t4+t5-1]=cc[t6-1]-tr1; | ||
294 | |||
295 | ch[t4]=ti1-cc[t1+t0]; | ||
296 | ch[t4+t5]=ti1+cc[t1+t0]; | ||
297 | |||
298 | t1+=ido; | ||
299 | t2+=ido; | ||
300 | t4+=t3; | ||
301 | t6+=ido; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | static void dradfg(int ido,int ip,int l1,int idl1,float[] cc,float[] c1, | ||
306 | float[] c2, float[] ch, float[] ch2, float[] wa, int index){ | ||
307 | int idij,ipph,i,j,k,l,ic,ik,is; | ||
308 | int t0,t1,t2=0,t3,t4,t5,t6,t7,t8,t9,t10; | ||
309 | float dc2,ai1,ai2,ar1,ar2,ds2; | ||
310 | int nbd; | ||
311 | float dcp=0,arg,dsp=0,ar1h,ar2h; | ||
312 | int idp2,ipp2; | ||
313 | |||
314 | arg=tpi/(float)ip; | ||
315 | dcp=(float)Math.cos(arg); | ||
316 | dsp=(float)Math.sin(arg); | ||
317 | ipph=(ip+1)>>1; | ||
318 | ipp2=ip; | ||
319 | idp2=ido; | ||
320 | nbd=(ido-1)>>1; | ||
321 | t0=l1*ido; | ||
322 | t10=ip*ido; | ||
323 | |||
324 | int state=100; | ||
325 | loop: while(true){ | ||
326 | switch(state){ | ||
327 | case 101: | ||
328 | if(ido==1){ | ||
329 | state=119; | ||
330 | break; | ||
331 | } | ||
332 | for(ik=0;ik<idl1;ik++)ch2[ik]=c2[ik]; | ||
333 | |||
334 | t1=0; | ||
335 | for(j=1;j<ip;j++){ | ||
336 | t1+=t0; | ||
337 | t2=t1; | ||
338 | for(k=0;k<l1;k++){ | ||
339 | ch[t2]=c1[t2]; | ||
340 | t2+=ido; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | is=-ido; | ||
345 | t1=0; | ||
346 | if(nbd>l1){ | ||
347 | for(j=1;j<ip;j++){ | ||
348 | t1+=t0; | ||
349 | is+=ido; | ||
350 | t2= -ido+t1; | ||
351 | for(k=0;k<l1;k++){ | ||
352 | idij=is-1; | ||
353 | t2+=ido; | ||
354 | t3=t2; | ||
355 | for(i=2;i<ido;i+=2){ | ||
356 | idij+=2; | ||
357 | t3+=2; | ||
358 | ch[t3-1]=wa[index+idij-1]*c1[t3-1]+wa[index+idij]*c1[t3]; | ||
359 | ch[t3]=wa[index+idij-1]*c1[t3]-wa[index+idij]*c1[t3-1]; | ||
360 | } | ||
361 | } | ||
362 | } | ||
363 | } | ||
364 | else{ | ||
365 | |||
366 | for(j=1;j<ip;j++){ | ||
367 | is+=ido; | ||
368 | idij=is-1; | ||
369 | t1+=t0; | ||
370 | t2=t1; | ||
371 | for(i=2;i<ido;i+=2){ | ||
372 | idij+=2; | ||
373 | t2+=2; | ||
374 | t3=t2; | ||
375 | for(k=0;k<l1;k++){ | ||
376 | ch[t3-1]=wa[index+idij-1]*c1[t3-1]+wa[index+idij]*c1[t3]; | ||
377 | ch[t3]=wa[index+idij-1]*c1[t3]-wa[index+idij]*c1[t3-1]; | ||
378 | t3+=ido; | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | |||
384 | t1=0; | ||
385 | t2=ipp2*t0; | ||
386 | if(nbd<l1){ | ||
387 | for(j=1;j<ipph;j++){ | ||
388 | t1+=t0; | ||
389 | t2-=t0; | ||
390 | t3=t1; | ||
391 | t4=t2; | ||
392 | for(i=2;i<ido;i+=2){ | ||
393 | t3+=2; | ||
394 | t4+=2; | ||
395 | t5=t3-ido; | ||
396 | t6=t4-ido; | ||
397 | for(k=0;k<l1;k++){ | ||
398 | t5+=ido; | ||
399 | t6+=ido; | ||
400 | c1[t5-1]=ch[t5-1]+ch[t6-1]; | ||
401 | c1[t6-1]=ch[t5]-ch[t6]; | ||
402 | c1[t5]=ch[t5]+ch[t6]; | ||
403 | c1[t6]=ch[t6-1]-ch[t5-1]; | ||
404 | } | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | else{ | ||
409 | for(j=1;j<ipph;j++){ | ||
410 | t1+=t0; | ||
411 | t2-=t0; | ||
412 | t3=t1; | ||
413 | t4=t2; | ||
414 | for(k=0;k<l1;k++){ | ||
415 | t5=t3; | ||
416 | t6=t4; | ||
417 | for(i=2;i<ido;i+=2){ | ||
418 | t5+=2; | ||
419 | t6+=2; | ||
420 | c1[t5-1]=ch[t5-1]+ch[t6-1]; | ||
421 | c1[t6-1]=ch[t5]-ch[t6]; | ||
422 | c1[t5]=ch[t5]+ch[t6]; | ||
423 | c1[t6]=ch[t6-1]-ch[t5-1]; | ||
424 | } | ||
425 | t3+=ido; | ||
426 | t4+=ido; | ||
427 | } | ||
428 | } | ||
429 | } | ||
430 | case 119: | ||
431 | for(ik=0;ik<idl1;ik++)c2[ik]=ch2[ik]; | ||
432 | |||
433 | t1=0; | ||
434 | t2=ipp2*idl1; | ||
435 | for(j=1;j<ipph;j++){ | ||
436 | t1+=t0; | ||
437 | t2-=t0; | ||
438 | t3=t1-ido; | ||
439 | t4=t2-ido; | ||
440 | for(k=0;k<l1;k++){ | ||
441 | t3+=ido; | ||
442 | t4+=ido; | ||
443 | c1[t3]=ch[t3]+ch[t4]; | ||
444 | c1[t4]=ch[t4]-ch[t3]; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | ar1=1.f; | ||
449 | ai1=0.f; | ||
450 | t1=0; | ||
451 | t2=ipp2*idl1; | ||
452 | t3=(ip-1)*idl1; | ||
453 | for(l=1;l<ipph;l++){ | ||
454 | t1+=idl1; | ||
455 | t2-=idl1; | ||
456 | ar1h=dcp*ar1-dsp*ai1; | ||
457 | ai1=dcp*ai1+dsp*ar1; | ||
458 | ar1=ar1h; | ||
459 | t4=t1; | ||
460 | t5=t2; | ||
461 | t6=t3; | ||
462 | t7=idl1; | ||
463 | |||
464 | for(ik=0;ik<idl1;ik++){ | ||
465 | ch2[t4++]=c2[ik]+ar1*c2[t7++]; | ||
466 | ch2[t5++]=ai1*c2[t6++]; | ||
467 | } | ||
468 | |||
469 | dc2=ar1; | ||
470 | ds2=ai1; | ||
471 | ar2=ar1; | ||
472 | ai2=ai1; | ||
473 | |||
474 | t4=idl1; | ||
475 | t5=(ipp2-1)*idl1; | ||
476 | for(j=2;j<ipph;j++){ | ||
477 | t4+=idl1; | ||
478 | t5-=idl1; | ||
479 | |||
480 | ar2h=dc2*ar2-ds2*ai2; | ||
481 | ai2=dc2*ai2+ds2*ar2; | ||
482 | ar2=ar2h; | ||
483 | |||
484 | t6=t1; | ||
485 | t7=t2; | ||
486 | t8=t4; | ||
487 | t9=t5; | ||
488 | for(ik=0;ik<idl1;ik++){ | ||
489 | ch2[t6++]+=ar2*c2[t8++]; | ||
490 | ch2[t7++]+=ai2*c2[t9++]; | ||
491 | } | ||
492 | } | ||
493 | } | ||
494 | t1=0; | ||
495 | for(j=1;j<ipph;j++){ | ||
496 | t1+=idl1; | ||
497 | t2=t1; | ||
498 | for(ik=0;ik<idl1;ik++)ch2[ik]+=c2[t2++]; | ||
499 | } | ||
500 | |||
501 | if(ido<l1){ | ||
502 | state=132; | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | t1=0; | ||
507 | t2=0; | ||
508 | for(k=0;k<l1;k++){ | ||
509 | t3=t1; | ||
510 | t4=t2; | ||
511 | for(i=0;i<ido;i++)cc[t4++]=ch[t3++]; | ||
512 | t1+=ido; | ||
513 | t2+=t10; | ||
514 | } | ||
515 | state=135; | ||
516 | break; | ||
517 | |||
518 | case 132: | ||
519 | for(i=0;i<ido;i++){ | ||
520 | t1=i; | ||
521 | t2=i; | ||
522 | for(k=0;k<l1;k++){ | ||
523 | cc[t2]=ch[t1]; | ||
524 | t1+=ido; | ||
525 | t2+=t10; | ||
526 | } | ||
527 | } | ||
528 | case 135: | ||
529 | t1=0; | ||
530 | t2=ido<<1; | ||
531 | t3=0; | ||
532 | t4=ipp2*t0; | ||
533 | for(j=1;j<ipph;j++){ | ||
534 | t1+=t2; | ||
535 | t3+=t0; | ||
536 | t4-=t0; | ||
537 | |||
538 | t5=t1; | ||
539 | t6=t3; | ||
540 | t7=t4; | ||
541 | |||
542 | for(k=0;k<l1;k++){ | ||
543 | cc[t5-1]=ch[t6]; | ||
544 | cc[t5]=ch[t7]; | ||
545 | t5+=t10; | ||
546 | t6+=ido; | ||
547 | t7+=ido; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | if(ido==1)return; | ||
552 | if(nbd<l1){ | ||
553 | state=141; | ||
554 | break; | ||
555 | } | ||
556 | |||
557 | t1=-ido; | ||
558 | t3=0; | ||
559 | t4=0; | ||
560 | t5=ipp2*t0; | ||
561 | for(j=1;j<ipph;j++){ | ||
562 | t1+=t2; | ||
563 | t3+=t2; | ||
564 | t4+=t0; | ||
565 | t5-=t0; | ||
566 | t6=t1; | ||
567 | t7=t3; | ||
568 | t8=t4; | ||
569 | t9=t5; | ||
570 | for(k=0;k<l1;k++){ | ||
571 | for(i=2;i<ido;i+=2){ | ||
572 | ic=idp2-i; | ||
573 | cc[i+t7-1]=ch[i+t8-1]+ch[i+t9-1]; | ||
574 | cc[ic+t6-1]=ch[i+t8-1]-ch[i+t9-1]; | ||
575 | cc[i+t7]=ch[i+t8]+ch[i+t9]; | ||
576 | cc[ic+t6]=ch[i+t9]-ch[i+t8]; | ||
577 | } | ||
578 | t6+=t10; | ||
579 | t7+=t10; | ||
580 | t8+=ido; | ||
581 | t9+=ido; | ||
582 | } | ||
583 | } | ||
584 | return; | ||
585 | case 141: | ||
586 | t1=-ido; | ||
587 | t3=0; | ||
588 | t4=0; | ||
589 | t5=ipp2*t0; | ||
590 | for(j=1;j<ipph;j++){ | ||
591 | t1+=t2; | ||
592 | t3+=t2; | ||
593 | t4+=t0; | ||
594 | t5-=t0; | ||
595 | for(i=2;i<ido;i+=2){ | ||
596 | t6=idp2+t1-i; | ||
597 | t7=i+t3; | ||
598 | t8=i+t4; | ||
599 | t9=i+t5; | ||
600 | for(k=0;k<l1;k++){ | ||
601 | cc[t7-1]=ch[t8-1]+ch[t9-1]; | ||
602 | cc[t6-1]=ch[t8-1]-ch[t9-1]; | ||
603 | cc[t7]=ch[t8]+ch[t9]; | ||
604 | cc[t6]=ch[t9]-ch[t8]; | ||
605 | t6+=t10; | ||
606 | t7+=t10; | ||
607 | t8+=ido; | ||
608 | t9+=ido; | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | break loop; | ||
613 | } | ||
614 | } | ||
615 | } | ||
616 | |||
617 | static void drftf1(int n,float[] c, float[] ch, float[] wa, int[] ifac){ | ||
618 | int i,k1,l1,l2; | ||
619 | int na,kh,nf; | ||
620 | int ip,iw,ido,idl1,ix2,ix3; | ||
621 | |||
622 | nf=ifac[1]; | ||
623 | na=1; | ||
624 | l2=n; | ||
625 | iw=n; | ||
626 | |||
627 | for(k1=0;k1<nf;k1++){ | ||
628 | kh=nf-k1; | ||
629 | ip=ifac[kh+1]; | ||
630 | l1=l2/ip; | ||
631 | ido=n/l2; | ||
632 | idl1=ido*l1; | ||
633 | iw-=(ip-1)*ido; | ||
634 | na=1-na; | ||
635 | |||
636 | int state=100; | ||
637 | loop: while(true){ | ||
638 | switch(state){ | ||
639 | case 100: | ||
640 | if(ip!=4){ | ||
641 | state=102; | ||
642 | break; | ||
643 | } | ||
644 | |||
645 | ix2=iw+ido; | ||
646 | ix3=ix2+ido; | ||
647 | if(na!=0) | ||
648 | dradf4(ido,l1,ch,c,wa,iw-1,wa,ix2-1,wa,ix3-1); | ||
649 | else | ||
650 | dradf4(ido,l1,c,ch,wa,iw-1,wa,ix2-1,wa,ix3-1); | ||
651 | state=110; | ||
652 | break; | ||
653 | case 102: | ||
654 | if(ip!=2){ | ||
655 | state=104; | ||
656 | break; | ||
657 | } | ||
658 | if(na!=0){ | ||
659 | state=103; | ||
660 | break; | ||
661 | } | ||
662 | dradf2(ido,l1,c,ch,wa, iw-1); | ||
663 | state=110; | ||
664 | break; | ||
665 | case 103: | ||
666 | dradf2(ido,l1,ch,c,wa, iw-1); | ||
667 | case 104: | ||
668 | if(ido==1)na=1-na; | ||
669 | if(na!=0){ | ||
670 | state=109; | ||
671 | break; | ||
672 | } | ||
673 | dradfg(ido,ip,l1,idl1,c,c,c,ch,ch,wa,iw-1); | ||
674 | na=1; | ||
675 | state=110; | ||
676 | break; | ||
677 | case 109: | ||
678 | dradfg(ido,ip,l1,idl1,ch,ch,ch,c,c,wa,iw-1); | ||
679 | na=0; | ||
680 | case 110: | ||
681 | l2=l1; | ||
682 | break loop; | ||
683 | } | ||
684 | } | ||
685 | } | ||
686 | if(na==1)return; | ||
687 | for(i=0;i<n;i++)c[i]=ch[i]; | ||
688 | } | ||
689 | |||
690 | static void dradb2(int ido,int l1,float[] cc,float[] ch,float[] wa1, int index){ | ||
691 | int i,k,t0,t1,t2,t3,t4,t5,t6; | ||
692 | float ti2,tr2; | ||
693 | |||
694 | t0=l1*ido; | ||
695 | |||
696 | t1=0; | ||
697 | t2=0; | ||
698 | t3=(ido<<1)-1; | ||
699 | for(k=0;k<l1;k++){ | ||
700 | ch[t1]=cc[t2]+cc[t3+t2]; | ||
701 | ch[t1+t0]=cc[t2]-cc[t3+t2]; | ||
702 | t2=(t1+=ido)<<1; | ||
703 | } | ||
704 | |||
705 | if(ido<2)return; | ||
706 | if(ido!=2){ | ||
707 | t1=0; | ||
708 | t2=0; | ||
709 | for(k=0;k<l1;k++){ | ||
710 | t3=t1; | ||
711 | t5=(t4=t2)+(ido<<1); | ||
712 | t6=t0+t1; | ||
713 | for(i=2;i<ido;i+=2){ | ||
714 | t3+=2; | ||
715 | t4+=2; | ||
716 | t5-=2; | ||
717 | t6+=2; | ||
718 | ch[t3-1]=cc[t4-1]+cc[t5-1]; | ||
719 | tr2=cc[t4-1]-cc[t5-1]; | ||
720 | ch[t3]=cc[t4]-cc[t5]; | ||
721 | ti2=cc[t4]+cc[t5]; | ||
722 | ch[t6-1]=wa1[index+i-2]*tr2-wa1[index+i-1]*ti2; | ||
723 | ch[t6]=wa1[index+i-2]*ti2+wa1[index+i-1]*tr2; | ||
724 | } | ||
725 | t2=(t1+=ido)<<1; | ||
726 | } | ||
727 | if((ido%2)==1)return; | ||
728 | } | ||
729 | |||
730 | t1=ido-1; | ||
731 | t2=ido-1; | ||
732 | for(k=0;k<l1;k++){ | ||
733 | ch[t1]=cc[t2]+cc[t2]; | ||
734 | ch[t1+t0]=-(cc[t2+1]+cc[t2+1]); | ||
735 | t1+=ido; | ||
736 | t2+=ido<<1; | ||
737 | } | ||
738 | } | ||
739 | |||
740 | static void dradb3(int ido,int l1,float[] cc,float[] ch, | ||
741 | float[] wa1, int index1, | ||
742 | float[] wa2, int index2){ | ||
743 | int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; | ||
744 | float ci2,ci3,di2,di3,cr2,cr3,dr2,dr3,ti2,tr2; | ||
745 | t0=l1*ido; | ||
746 | |||
747 | t1=0; | ||
748 | t2=t0<<1; | ||
749 | t3=ido<<1; | ||
750 | t4=ido+(ido<<1); | ||
751 | t5=0; | ||
752 | for(k=0;k<l1;k++){ | ||
753 | tr2=cc[t3-1]+cc[t3-1]; | ||
754 | cr2=cc[t5]+(taur*tr2); | ||
755 | ch[t1]=cc[t5]+tr2; | ||
756 | ci3=taui*(cc[t3]+cc[t3]); | ||
757 | ch[t1+t0]=cr2-ci3; | ||
758 | ch[t1+t2]=cr2+ci3; | ||
759 | t1+=ido; | ||
760 | t3+=t4; | ||
761 | t5+=t4; | ||
762 | } | ||
763 | |||
764 | if(ido==1)return; | ||
765 | |||
766 | t1=0; | ||
767 | t3=ido<<1; | ||
768 | for(k=0;k<l1;k++){ | ||
769 | t7=t1+(t1<<1); | ||
770 | t6=(t5=t7+t3); | ||
771 | t8=t1; | ||
772 | t10=(t9=t1+t0)+t0; | ||
773 | |||
774 | for(i=2;i<ido;i+=2){ | ||
775 | t5+=2; | ||
776 | t6-=2; | ||
777 | t7+=2; | ||
778 | t8+=2; | ||
779 | t9+=2; | ||
780 | t10+=2; | ||
781 | tr2=cc[t5-1]+cc[t6-1]; | ||
782 | cr2=cc[t7-1]+(taur*tr2); | ||
783 | ch[t8-1]=cc[t7-1]+tr2; | ||
784 | ti2=cc[t5]-cc[t6]; | ||
785 | ci2=cc[t7]+(taur*ti2); | ||
786 | ch[t8]=cc[t7]+ti2; | ||
787 | cr3=taui*(cc[t5-1]-cc[t6-1]); | ||
788 | ci3=taui*(cc[t5]+cc[t6]); | ||
789 | dr2=cr2-ci3; | ||
790 | dr3=cr2+ci3; | ||
791 | di2=ci2+cr3; | ||
792 | di3=ci2-cr3; | ||
793 | ch[t9-1]=wa1[index1+i-2]*dr2-wa1[index1+i-1]*di2; | ||
794 | ch[t9]=wa1[index1+i-2]*di2+wa1[index1+i-1]*dr2; | ||
795 | ch[t10-1]=wa2[index2+i-2]*dr3-wa2[index2+i-1]*di3; | ||
796 | ch[t10]=wa2[index2+i-2]*di3+wa2[index2+i-1]*dr3; | ||
797 | } | ||
798 | t1+=ido; | ||
799 | } | ||
800 | } | ||
801 | |||
802 | static void dradb4(int ido,int l1,float[] cc,float[] ch, | ||
803 | float[] wa1, int index1, | ||
804 | float[] wa2, int index2, | ||
805 | float[] wa3, int index3){ | ||
806 | int i,k,t0,t1,t2,t3,t4,t5,t6,t7,t8; | ||
807 | float ci2,ci3,ci4,cr2,cr3,cr4,ti1,ti2,ti3,ti4,tr1,tr2,tr3,tr4; | ||
808 | t0=l1*ido; | ||
809 | |||
810 | t1=0; | ||
811 | t2=ido<<2; | ||
812 | t3=0; | ||
813 | t6=ido<<1; | ||
814 | for(k=0;k<l1;k++){ | ||
815 | t4=t3+t6; | ||
816 | t5=t1; | ||
817 | tr3=cc[t4-1]+cc[t4-1]; | ||
818 | tr4=cc[t4]+cc[t4]; | ||
819 | tr1=cc[t3]-cc[(t4+=t6)-1]; | ||
820 | tr2=cc[t3]+cc[t4-1]; | ||
821 | ch[t5]=tr2+tr3; | ||
822 | ch[t5+=t0]=tr1-tr4; | ||
823 | ch[t5+=t0]=tr2-tr3; | ||
824 | ch[t5+=t0]=tr1+tr4; | ||
825 | t1+=ido; | ||
826 | t3+=t2; | ||
827 | } | ||
828 | |||
829 | if(ido<2)return; | ||
830 | if(ido!=2){ | ||
831 | t1=0; | ||
832 | for(k=0;k<l1;k++){ | ||
833 | t5=(t4=(t3=(t2=t1<<2)+t6))+t6; | ||
834 | t7=t1; | ||
835 | for(i=2;i<ido;i+=2){ | ||
836 | t2+=2; | ||
837 | t3+=2; | ||
838 | t4-=2; | ||
839 | t5-=2; | ||
840 | t7+=2; | ||
841 | ti1=cc[t2]+cc[t5]; | ||
842 | ti2=cc[t2]-cc[t5]; | ||
843 | ti3=cc[t3]-cc[t4]; | ||
844 | tr4=cc[t3]+cc[t4]; | ||
845 | tr1=cc[t2-1]-cc[t5-1]; | ||
846 | tr2=cc[t2-1]+cc[t5-1]; | ||
847 | ti4=cc[t3-1]-cc[t4-1]; | ||
848 | tr3=cc[t3-1]+cc[t4-1]; | ||
849 | ch[t7-1]=tr2+tr3; | ||
850 | cr3=tr2-tr3; | ||
851 | ch[t7]=ti2+ti3; | ||
852 | ci3=ti2-ti3; | ||
853 | cr2=tr1-tr4; | ||
854 | cr4=tr1+tr4; | ||
855 | ci2=ti1+ti4; | ||
856 | ci4=ti1-ti4; | ||
857 | |||
858 | ch[(t8=t7+t0)-1]=wa1[index1+i-2]*cr2-wa1[index1+i-1]*ci2; | ||
859 | ch[t8]=wa1[index1+i-2]*ci2+wa1[index1+i-1]*cr2; | ||
860 | ch[(t8+=t0)-1]=wa2[index2+i-2]*cr3-wa2[index2+i-1]*ci3; | ||
861 | ch[t8]=wa2[index2+i-2]*ci3+wa2[index2+i-1]*cr3; | ||
862 | ch[(t8+=t0)-1]=wa3[index3+i-2]*cr4-wa3[index3+i-1]*ci4; | ||
863 | ch[t8]=wa3[index3+i-2]*ci4+wa3[index3+i-1]*cr4; | ||
864 | } | ||
865 | t1+=ido; | ||
866 | } | ||
867 | if(ido%2 == 1)return; | ||
868 | } | ||
869 | |||
870 | t1=ido; | ||
871 | t2=ido<<2; | ||
872 | t3=ido-1; | ||
873 | t4=ido+(ido<<1); | ||
874 | for(k=0;k<l1;k++){ | ||
875 | t5=t3; | ||
876 | ti1=cc[t1]+cc[t4]; | ||
877 | ti2=cc[t4]-cc[t1]; | ||
878 | tr1=cc[t1-1]-cc[t4-1]; | ||
879 | tr2=cc[t1-1]+cc[t4-1]; | ||
880 | ch[t5]=tr2+tr2; | ||
881 | ch[t5+=t0]=sqrt2*(tr1-ti1); | ||
882 | ch[t5+=t0]=ti2+ti2; | ||
883 | ch[t5+=t0]=-sqrt2*(tr1+ti1); | ||
884 | |||
885 | t3+=ido; | ||
886 | t1+=t2; | ||
887 | t4+=t2; | ||
888 | } | ||
889 | } | ||
890 | |||
891 | static void dradbg(int ido,int ip,int l1,int idl1,float[] cc,float[] c1, | ||
892 | float[] c2,float[] ch,float[] ch2,float[] wa, int index ){ | ||
893 | |||
894 | int idij,ipph=0,i,j,k,l,ik,is,t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10=0, | ||
895 | t11,t12; | ||
896 | float dc2,ai1,ai2,ar1,ar2,ds2; | ||
897 | int nbd=0; | ||
898 | float dcp=0,arg,dsp=0,ar1h,ar2h; | ||
899 | int ipp2=0; | ||
900 | |||
901 | int state=100; | ||
902 | |||
903 | loop: while(true){ | ||
904 | switch(state){ | ||
905 | case 100: | ||
906 | t10=ip*ido; | ||
907 | t0=l1*ido; | ||
908 | arg=tpi/(float)ip; | ||
909 | dcp=(float)Math.cos(arg); | ||
910 | dsp=(float)Math.sin(arg); | ||
911 | nbd=(ido-1)>>>1; | ||
912 | ipp2=ip; | ||
913 | ipph=(ip+1)>>>1; | ||
914 | if(ido<l1){ | ||
915 | state=103; | ||
916 | break; | ||
917 | } | ||
918 | t1=0; | ||
919 | t2=0; | ||
920 | for(k=0;k<l1;k++){ | ||
921 | t3=t1; | ||
922 | t4=t2; | ||
923 | for(i=0;i<ido;i++){ | ||
924 | ch[t3]=cc[t4]; | ||
925 | t3++; | ||
926 | t4++; | ||
927 | } | ||
928 | t1+=ido; | ||
929 | t2+=t10; | ||
930 | } | ||
931 | state=106; | ||
932 | break; | ||
933 | case 103: | ||
934 | t1=0; | ||
935 | for(i=0;i<ido;i++){ | ||
936 | t2=t1; | ||
937 | t3=t1; | ||
938 | for(k=0;k<l1;k++){ | ||
939 | ch[t2]=cc[t3]; | ||
940 | t2+=ido; | ||
941 | t3+=t10; | ||
942 | } | ||
943 | t1++; | ||
944 | } | ||
945 | case 106: | ||
946 | t1=0; | ||
947 | t2=ipp2*t0; | ||
948 | t7=(t5=ido<<1); | ||
949 | for(j=1;j<ipph;j++){ | ||
950 | t1+=t0; | ||
951 | t2-=t0; | ||
952 | t3=t1; | ||
953 | t4=t2; | ||
954 | t6=t5; | ||
955 | for(k=0;k<l1;k++){ | ||
956 | ch[t3]=cc[t6-1]+cc[t6-1]; | ||
957 | ch[t4]=cc[t6]+cc[t6]; | ||
958 | t3+=ido; | ||
959 | t4+=ido; | ||
960 | t6+=t10; | ||
961 | } | ||
962 | t5+=t7; | ||
963 | } | ||
964 | if (ido == 1){ | ||
965 | state=116; | ||
966 | break; | ||
967 | } | ||
968 | if(nbd<l1){ | ||
969 | state=112; | ||
970 | break; | ||
971 | } | ||
972 | |||
973 | t1=0; | ||
974 | t2=ipp2*t0; | ||
975 | t7=0; | ||
976 | for(j=1;j<ipph;j++){ | ||
977 | t1+=t0; | ||
978 | t2-=t0; | ||
979 | t3=t1; | ||
980 | t4=t2; | ||
981 | |||
982 | t7+=(ido<<1); | ||
983 | t8=t7; | ||
984 | for(k=0;k<l1;k++){ | ||
985 | t5=t3; | ||
986 | t6=t4; | ||
987 | t9=t8; | ||
988 | t11=t8; | ||
989 | for(i=2;i<ido;i+=2){ | ||
990 | t5+=2; | ||
991 | t6+=2; | ||
992 | t9+=2; | ||
993 | t11-=2; | ||
994 | ch[t5-1]=cc[t9-1]+cc[t11-1]; | ||
995 | ch[t6-1]=cc[t9-1]-cc[t11-1]; | ||
996 | ch[t5]=cc[t9]-cc[t11]; | ||
997 | ch[t6]=cc[t9]+cc[t11]; | ||
998 | } | ||
999 | t3+=ido; | ||
1000 | t4+=ido; | ||
1001 | t8+=t10; | ||
1002 | } | ||
1003 | } | ||
1004 | state=116; | ||
1005 | break; | ||
1006 | case 112: | ||
1007 | t1=0; | ||
1008 | t2=ipp2*t0; | ||
1009 | t7=0; | ||
1010 | for(j=1;j<ipph;j++){ | ||
1011 | t1+=t0; | ||
1012 | t2-=t0; | ||
1013 | t3=t1; | ||
1014 | t4=t2; | ||
1015 | t7+=(ido<<1); | ||
1016 | t8=t7; | ||
1017 | t9=t7; | ||
1018 | for(i=2;i<ido;i+=2){ | ||
1019 | t3+=2; | ||
1020 | t4+=2; | ||
1021 | t8+=2; | ||
1022 | t9-=2; | ||
1023 | t5=t3; | ||
1024 | t6=t4; | ||
1025 | t11=t8; | ||
1026 | t12=t9; | ||
1027 | for(k=0;k<l1;k++){ | ||
1028 | ch[t5-1]=cc[t11-1]+cc[t12-1]; | ||
1029 | ch[t6-1]=cc[t11-1]-cc[t12-1]; | ||
1030 | ch[t5]=cc[t11]-cc[t12]; | ||
1031 | ch[t6]=cc[t11]+cc[t12]; | ||
1032 | t5+=ido; | ||
1033 | t6+=ido; | ||
1034 | t11+=t10; | ||
1035 | t12+=t10; | ||
1036 | } | ||
1037 | } | ||
1038 | } | ||
1039 | case 116: | ||
1040 | ar1=1.f; | ||
1041 | ai1=0.f; | ||
1042 | t1=0; | ||
1043 | t9=(t2=ipp2*idl1); | ||
1044 | t3=(ip-1)*idl1; | ||
1045 | for(l=1;l<ipph;l++){ | ||
1046 | t1+=idl1; | ||
1047 | t2-=idl1; | ||
1048 | |||
1049 | ar1h=dcp*ar1-dsp*ai1; | ||
1050 | ai1=dcp*ai1+dsp*ar1; | ||
1051 | ar1=ar1h; | ||
1052 | t4=t1; | ||
1053 | t5=t2; | ||
1054 | t6=0; | ||
1055 | t7=idl1; | ||
1056 | t8=t3; | ||
1057 | for(ik=0;ik<idl1;ik++){ | ||
1058 | c2[t4++]=ch2[t6++]+ar1*ch2[t7++]; | ||
1059 | c2[t5++]=ai1*ch2[t8++]; | ||
1060 | } | ||
1061 | dc2=ar1; | ||
1062 | ds2=ai1; | ||
1063 | ar2=ar1; | ||
1064 | ai2=ai1; | ||
1065 | |||
1066 | t6=idl1; | ||
1067 | t7=t9-idl1; | ||
1068 | for(j=2;j<ipph;j++){ | ||
1069 | t6+=idl1; | ||
1070 | t7-=idl1; | ||
1071 | ar2h=dc2*ar2-ds2*ai2; | ||
1072 | ai2=dc2*ai2+ds2*ar2; | ||
1073 | ar2=ar2h; | ||
1074 | t4=t1; | ||
1075 | t5=t2; | ||
1076 | t11=t6; | ||
1077 | t12=t7; | ||
1078 | for(ik=0;ik<idl1;ik++){ | ||
1079 | c2[t4++]+=ar2*ch2[t11++]; | ||
1080 | c2[t5++]+=ai2*ch2[t12++]; | ||
1081 | } | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | t1=0; | ||
1086 | for(j=1;j<ipph;j++){ | ||
1087 | t1+=idl1; | ||
1088 | t2=t1; | ||
1089 | for(ik=0;ik<idl1;ik++)ch2[ik]+=ch2[t2++]; | ||
1090 | } | ||
1091 | |||
1092 | t1=0; | ||
1093 | t2=ipp2*t0; | ||
1094 | for(j=1;j<ipph;j++){ | ||
1095 | t1+=t0; | ||
1096 | t2-=t0; | ||
1097 | t3=t1; | ||
1098 | t4=t2; | ||
1099 | for(k=0;k<l1;k++){ | ||
1100 | ch[t3]=c1[t3]-c1[t4]; | ||
1101 | ch[t4]=c1[t3]+c1[t4]; | ||
1102 | t3+=ido; | ||
1103 | t4+=ido; | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | if(ido==1){ | ||
1108 | state=132; | ||
1109 | break; | ||
1110 | } | ||
1111 | if(nbd<l1){ | ||
1112 | state=128; | ||
1113 | break; | ||
1114 | } | ||
1115 | |||
1116 | t1=0; | ||
1117 | t2=ipp2*t0; | ||
1118 | for(j=1;j<ipph;j++){ | ||
1119 | t1+=t0; | ||
1120 | t2-=t0; | ||
1121 | t3=t1; | ||
1122 | t4=t2; | ||
1123 | for(k=0;k<l1;k++){ | ||
1124 | t5=t3; | ||
1125 | t6=t4; | ||
1126 | for(i=2;i<ido;i+=2){ | ||
1127 | t5+=2; | ||
1128 | t6+=2; | ||
1129 | ch[t5-1]=c1[t5-1]-c1[t6]; | ||
1130 | ch[t6-1]=c1[t5-1]+c1[t6]; | ||
1131 | ch[t5]=c1[t5]+c1[t6-1]; | ||
1132 | ch[t6]=c1[t5]-c1[t6-1]; | ||
1133 | } | ||
1134 | t3+=ido; | ||
1135 | t4+=ido; | ||
1136 | } | ||
1137 | } | ||
1138 | state=132; | ||
1139 | break; | ||
1140 | case 128: | ||
1141 | t1=0; | ||
1142 | t2=ipp2*t0; | ||
1143 | for(j=1;j<ipph;j++){ | ||
1144 | t1+=t0; | ||
1145 | t2-=t0; | ||
1146 | t3=t1; | ||
1147 | t4=t2; | ||
1148 | for(i=2;i<ido;i+=2){ | ||
1149 | t3+=2; | ||
1150 | t4+=2; | ||
1151 | t5=t3; | ||
1152 | t6=t4; | ||
1153 | for(k=0;k<l1;k++){ | ||
1154 | ch[t5-1]=c1[t5-1]-c1[t6]; | ||
1155 | ch[t6-1]=c1[t5-1]+c1[t6]; | ||
1156 | ch[t5]=c1[t5]+c1[t6-1]; | ||
1157 | ch[t6]=c1[t5]-c1[t6-1]; | ||
1158 | t5+=ido; | ||
1159 | t6+=ido; | ||
1160 | } | ||
1161 | } | ||
1162 | } | ||
1163 | case 132: | ||
1164 | if(ido==1)return; | ||
1165 | |||
1166 | for(ik=0;ik<idl1;ik++)c2[ik]=ch2[ik]; | ||
1167 | |||
1168 | t1=0; | ||
1169 | for(j=1;j<ip;j++){ | ||
1170 | t2=(t1+=t0); | ||
1171 | for(k=0;k<l1;k++){ | ||
1172 | c1[t2]=ch[t2]; | ||
1173 | t2+=ido; | ||
1174 | } | ||
1175 | } | ||
1176 | |||
1177 | if(nbd>l1){ | ||
1178 | state=139; | ||
1179 | break; | ||
1180 | } | ||
1181 | |||
1182 | is= -ido-1; | ||
1183 | t1=0; | ||
1184 | for(j=1;j<ip;j++){ | ||
1185 | is+=ido; | ||
1186 | t1+=t0; | ||
1187 | idij=is; | ||
1188 | t2=t1; | ||
1189 | for(i=2;i<ido;i+=2){ | ||
1190 | t2+=2; | ||
1191 | idij+=2; | ||
1192 | t3=t2; | ||
1193 | for(k=0;k<l1;k++){ | ||
1194 | c1[t3-1]=wa[index+idij-1]*ch[t3-1]-wa[index+idij]*ch[t3]; | ||
1195 | c1[t3]=wa[index+idij-1]*ch[t3]+wa[index+idij]*ch[t3-1]; | ||
1196 | t3+=ido; | ||
1197 | } | ||
1198 | } | ||
1199 | } | ||
1200 | return; | ||
1201 | |||
1202 | case 139: | ||
1203 | is= -ido-1; | ||
1204 | t1=0; | ||
1205 | for(j=1;j<ip;j++){ | ||
1206 | is+=ido; | ||
1207 | t1+=t0; | ||
1208 | t2=t1; | ||
1209 | for(k=0;k<l1;k++){ | ||
1210 | idij=is; | ||
1211 | t3=t2; | ||
1212 | for(i=2;i<ido;i+=2){ | ||
1213 | idij+=2; | ||
1214 | t3+=2; | ||
1215 | c1[t3-1]=wa[index+idij-1]*ch[t3-1]-wa[index+idij]*ch[t3]; | ||
1216 | c1[t3]=wa[index+idij-1]*ch[t3]+wa[index+idij]*ch[t3-1]; | ||
1217 | } | ||
1218 | t2+=ido; | ||
1219 | } | ||
1220 | } | ||
1221 | break loop; | ||
1222 | } | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | static void drftb1(int n, float[] c, float[] ch, float[] wa, int index, int[] ifac){ | ||
1227 | int i,k1,l1,l2=0; | ||
1228 | int na; | ||
1229 | int nf,ip=0,iw,ix2,ix3,ido=0,idl1=0; | ||
1230 | |||
1231 | nf=ifac[1]; | ||
1232 | na=0; | ||
1233 | l1=1; | ||
1234 | iw=1; | ||
1235 | |||
1236 | for(k1=0;k1<nf;k1++){ | ||
1237 | int state=100; | ||
1238 | loop: while(true){ | ||
1239 | switch(state){ | ||
1240 | case 100: | ||
1241 | ip=ifac[k1 + 2]; | ||
1242 | l2=ip*l1; | ||
1243 | ido=n/l2; | ||
1244 | idl1=ido*l1; | ||
1245 | if(ip!=4){ | ||
1246 | state=103; | ||
1247 | break; | ||
1248 | } | ||
1249 | ix2=iw+ido; | ||
1250 | ix3=ix2+ido; | ||
1251 | |||
1252 | if(na!=0) | ||
1253 | dradb4(ido,l1,ch,c,wa,index+iw-1,wa,index+ix2-1,wa,index+ix3-1); | ||
1254 | else | ||
1255 | dradb4(ido,l1,c,ch,wa,index+iw-1,wa,index+ix2-1,wa,index+ix3-1); | ||
1256 | na=1-na; | ||
1257 | state=115; | ||
1258 | break; | ||
1259 | case 103: | ||
1260 | if(ip!=2){ | ||
1261 | state=106; | ||
1262 | break; | ||
1263 | } | ||
1264 | |||
1265 | if(na!=0) | ||
1266 | dradb2(ido,l1,ch,c,wa,index+iw-1); | ||
1267 | else | ||
1268 | dradb2(ido,l1,c,ch,wa,index+iw-1); | ||
1269 | na=1-na; | ||
1270 | state=115; | ||
1271 | break; | ||
1272 | |||
1273 | case 106: | ||
1274 | if(ip!=3){ | ||
1275 | state=109; | ||
1276 | break; | ||
1277 | } | ||
1278 | |||
1279 | ix2=iw+ido; | ||
1280 | if(na!=0) | ||
1281 | dradb3(ido,l1,ch,c,wa,index+iw-1,wa,index+ix2-1); | ||
1282 | else | ||
1283 | dradb3(ido,l1,c,ch,wa,index+iw-1,wa,index+ix2-1); | ||
1284 | na=1-na; | ||
1285 | state=115; | ||
1286 | break; | ||
1287 | case 109: | ||
1288 | // The radix five case can be translated later..... | ||
1289 | // if(ip!=5)goto L112; | ||
1290 | // | ||
1291 | //ix2=iw+ido; | ||
1292 | //ix3=ix2+ido; | ||
1293 | //ix4=ix3+ido; | ||
1294 | //if(na!=0) | ||
1295 | // dradb5(ido,l1,ch,c,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1); | ||
1296 | //else | ||
1297 | // dradb5(ido,l1,c,ch,wa+iw-1,wa+ix2-1,wa+ix3-1,wa+ix4-1); | ||
1298 | //na=1-na; | ||
1299 | //state=115; | ||
1300 | //break; | ||
1301 | if(na!=0) | ||
1302 | dradbg(ido,ip,l1,idl1,ch,ch,ch,c,c,wa,index+iw-1); | ||
1303 | else | ||
1304 | dradbg(ido,ip,l1,idl1,c,c,c,ch,ch,wa,index+iw-1); | ||
1305 | if(ido==1)na=1-na; | ||
1306 | |||
1307 | case 115: | ||
1308 | l1=l2; | ||
1309 | iw+=(ip-1)*ido; | ||
1310 | break loop; | ||
1311 | } | ||
1312 | } | ||
1313 | } | ||
1314 | if(na==0)return; | ||
1315 | for(i=0;i<n;i++)c[i]=ch[i]; | ||
1316 | } | ||
1317 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/DspState.java b/songdbj/com/jcraft/jorbis/DspState.java new file mode 100644 index 0000000000..5676f640c1 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/DspState.java | |||
@@ -0,0 +1,459 @@ | |||
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 | public class DspState{ | ||
29 | static final float M_PI=3.1415926539f; | ||
30 | static final int VI_TRANSFORMB=1; | ||
31 | static final int VI_WINDOWB=1; | ||
32 | |||
33 | int analysisp; | ||
34 | Info vi; | ||
35 | int modebits; | ||
36 | |||
37 | float[][] pcm; | ||
38 | //float[][] pcmret; | ||
39 | int pcm_storage; | ||
40 | int pcm_current; | ||
41 | int pcm_returned; | ||
42 | |||
43 | float[] multipliers; | ||
44 | int envelope_storage; | ||
45 | int envelope_current; | ||
46 | |||
47 | int eofflag; | ||
48 | |||
49 | int lW; | ||
50 | int W; | ||
51 | int nW; | ||
52 | int centerW; | ||
53 | |||
54 | long granulepos; | ||
55 | long sequence; | ||
56 | |||
57 | long glue_bits; | ||
58 | long time_bits; | ||
59 | long floor_bits; | ||
60 | long res_bits; | ||
61 | |||
62 | // local lookup storage | ||
63 | //!! Envelope ve=new Envelope(); // envelope | ||
64 | //float **window[2][2][2]; // block, leadin, leadout, type | ||
65 | float[][][][][] window; // block, leadin, leadout, type | ||
66 | //vorbis_look_transform **transform[2]; // block, type | ||
67 | Object[][] transform; | ||
68 | CodeBook[] fullbooks; | ||
69 | // backend lookups are tied to the mode, not the backend or naked mapping | ||
70 | Object[] mode; | ||
71 | |||
72 | // local storage, only used on the encoding side. This way the | ||
73 | // application does not need to worry about freeing some packets' | ||
74 | // memory and not others'; packet storage is always tracked. | ||
75 | // Cleared next call to a _dsp_ function | ||
76 | byte[] header; | ||
77 | byte[] header1; | ||
78 | byte[] header2; | ||
79 | |||
80 | public DspState(){ | ||
81 | transform=new Object[2][]; | ||
82 | window=new float[2][][][][]; | ||
83 | window[0]=new float[2][][][]; | ||
84 | window[0][0]=new float[2][][]; | ||
85 | window[0][1]=new float[2][][]; | ||
86 | window[0][0][0]=new float[2][]; | ||
87 | window[0][0][1]=new float[2][]; | ||
88 | window[0][1][0]=new float[2][]; | ||
89 | window[0][1][1]=new float[2][]; | ||
90 | window[1]=new float[2][][][]; | ||
91 | window[1][0]=new float[2][][]; | ||
92 | window[1][1]=new float[2][][]; | ||
93 | window[1][0][0]=new float[2][]; | ||
94 | window[1][0][1]=new float[2][]; | ||
95 | window[1][1][0]=new float[2][]; | ||
96 | window[1][1][1]=new float[2][]; | ||
97 | } | ||
98 | |||
99 | private static int ilog2(int v){ | ||
100 | int ret=0; | ||
101 | while(v>1){ | ||
102 | ret++; | ||
103 | v>>>=1; | ||
104 | } | ||
105 | return(ret); | ||
106 | } | ||
107 | |||
108 | static float[] window(int type, int window, int left, int right){ | ||
109 | float[] ret=new float[window]; | ||
110 | switch(type){ | ||
111 | case 0: | ||
112 | // The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi) | ||
113 | { | ||
114 | int leftbegin=window/4-left/2; | ||
115 | int rightbegin=window-window/4-right/2; | ||
116 | |||
117 | for(int i=0;i<left;i++){ | ||
118 | float x=(float)((i+.5)/left*M_PI/2.); | ||
119 | x=(float)Math.sin(x); | ||
120 | x*=x; | ||
121 | x*=M_PI/2.; | ||
122 | x=(float)Math.sin(x); | ||
123 | ret[i+leftbegin]=x; | ||
124 | } | ||
125 | |||
126 | for(int i=leftbegin+left;i<rightbegin;i++){ | ||
127 | ret[i]=1.f; | ||
128 | } | ||
129 | |||
130 | for(int i=0;i<right;i++){ | ||
131 | float x=(float)((right-i-.5)/right*M_PI/2.); | ||
132 | x=(float)Math.sin(x); | ||
133 | x*=x; | ||
134 | x*=M_PI/2.; | ||
135 | x=(float)Math.sin(x); | ||
136 | ret[i+rightbegin]=x; | ||
137 | } | ||
138 | } | ||
139 | break; | ||
140 | default: | ||
141 | //free(ret); | ||
142 | return(null); | ||
143 | } | ||
144 | return(ret); | ||
145 | } | ||
146 | |||
147 | // Analysis side code, but directly related to blocking. Thus it's | ||
148 | // here and not in analysis.c (which is for analysis transforms only). | ||
149 | // The init is here because some of it is shared | ||
150 | |||
151 | int init(Info vi, boolean encp){ | ||
152 | //System.err.println("DspState.init: vi="+vi+", encp="+encp); | ||
153 | //memset(v,0,sizeof(vorbis_dsp_state)); | ||
154 | this.vi=vi; | ||
155 | modebits=ilog2(vi.modes); | ||
156 | |||
157 | transform[0]=new Object[VI_TRANSFORMB]; | ||
158 | transform[1]=new Object[VI_TRANSFORMB]; | ||
159 | |||
160 | // MDCT is tranform 0 | ||
161 | |||
162 | transform[0][0]=new Mdct(); | ||
163 | transform[1][0]=new Mdct(); | ||
164 | ((Mdct)transform[0][0]).init(vi.blocksizes[0]); | ||
165 | ((Mdct)transform[1][0]).init(vi.blocksizes[1]); | ||
166 | |||
167 | window[0][0][0]=new float[VI_WINDOWB][]; | ||
168 | window[0][0][1]=window[0][0][0]; | ||
169 | window[0][1][0]=window[0][0][0]; | ||
170 | window[0][1][1]=window[0][0][0]; | ||
171 | window[1][0][0]=new float[VI_WINDOWB][]; | ||
172 | window[1][0][1]=new float[VI_WINDOWB][]; | ||
173 | window[1][1][0]=new float[VI_WINDOWB][]; | ||
174 | window[1][1][1]=new float[VI_WINDOWB][]; | ||
175 | |||
176 | for(int i=0;i<VI_WINDOWB;i++){ | ||
177 | window[0][0][0][i]= | ||
178 | window(i,vi.blocksizes[0],vi.blocksizes[0]/2,vi.blocksizes[0]/2); | ||
179 | window[1][0][0][i]= | ||
180 | window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[0]/2); | ||
181 | window[1][0][1][i]= | ||
182 | window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[1]/2); | ||
183 | window[1][1][0][i]= | ||
184 | window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[0]/2); | ||
185 | window[1][1][1][i]= | ||
186 | window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[1]/2); | ||
187 | } | ||
188 | |||
189 | // if(encp){ // encode/decode differ here | ||
190 | // // finish the codebooks | ||
191 | // fullbooks=new CodeBook[vi.books]; | ||
192 | // for(int i=0;i<vi.books;i++){ | ||
193 | // fullbooks[i]=new CodeBook(); | ||
194 | // fullbooks[i].init_encode(vi.book_param[i]); | ||
195 | // } | ||
196 | // analysisp=1; | ||
197 | // } | ||
198 | // else{ | ||
199 | // finish the codebooks | ||
200 | fullbooks=new CodeBook[vi.books]; | ||
201 | for(int i=0;i<vi.books;i++){ | ||
202 | fullbooks[i]=new CodeBook(); | ||
203 | fullbooks[i].init_decode(vi.book_param[i]); | ||
204 | } | ||
205 | // } | ||
206 | |||
207 | // initialize the storage vectors to a decent size greater than the | ||
208 | // minimum | ||
209 | |||
210 | pcm_storage=8192; // we'll assume later that we have | ||
211 | // a minimum of twice the blocksize of | ||
212 | // accumulated samples in analysis | ||
213 | pcm=new float[vi.channels][]; | ||
214 | //pcmret=new float[vi.channels][]; | ||
215 | { | ||
216 | for(int i=0;i<vi.channels;i++){ | ||
217 | pcm[i]=new float[pcm_storage]; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | // all 1 (large block) or 0 (small block) | ||
222 | // explicitly set for the sake of clarity | ||
223 | lW=0; // previous window size | ||
224 | W=0; // current window size | ||
225 | |||
226 | // all vector indexes; multiples of samples_per_envelope_step | ||
227 | centerW=vi.blocksizes[1]/2; | ||
228 | |||
229 | pcm_current=centerW; | ||
230 | |||
231 | // initialize all the mapping/backend lookups | ||
232 | mode=new Object[vi.modes]; | ||
233 | for(int i=0;i<vi.modes;i++){ | ||
234 | int mapnum=vi.mode_param[i].mapping; | ||
235 | int maptype=vi.map_type[mapnum]; | ||
236 | mode[i]=FuncMapping.mapping_P[maptype].look(this,vi.mode_param[i], | ||
237 | vi.map_param[mapnum]); | ||
238 | } | ||
239 | return(0); | ||
240 | } | ||
241 | |||
242 | public int synthesis_init(Info vi){ | ||
243 | init(vi, false); | ||
244 | // Adjust centerW to allow an easier mechanism for determining output | ||
245 | pcm_returned=centerW; | ||
246 | centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4; | ||
247 | granulepos=-1; | ||
248 | sequence=-1; | ||
249 | return(0); | ||
250 | } | ||
251 | |||
252 | DspState(Info vi){ | ||
253 | this(); | ||
254 | init(vi, false); | ||
255 | // Adjust centerW to allow an easier mechanism for determining output | ||
256 | pcm_returned=centerW; | ||
257 | centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4; | ||
258 | granulepos=-1; | ||
259 | sequence=-1; | ||
260 | } | ||
261 | |||
262 | // Unike in analysis, the window is only partially applied for each | ||
263 | // block. The time domain envelope is not yet handled at the point of | ||
264 | // calling (as it relies on the previous block). | ||
265 | |||
266 | public int synthesis_blockin(Block vb){ | ||
267 | // Shift out any PCM/multipliers that we returned previously | ||
268 | // centerW is currently the center of the last block added | ||
269 | if(centerW>vi.blocksizes[1]/2 && pcm_returned>8192){ | ||
270 | // don't shift too much; we need to have a minimum PCM buffer of | ||
271 | // 1/2 long block | ||
272 | |||
273 | int shiftPCM=centerW-vi.blocksizes[1]/2; | ||
274 | shiftPCM=(pcm_returned<shiftPCM?pcm_returned:shiftPCM); | ||
275 | |||
276 | pcm_current-=shiftPCM; | ||
277 | centerW-=shiftPCM; | ||
278 | pcm_returned-=shiftPCM; | ||
279 | if(shiftPCM!=0){ | ||
280 | for(int i=0;i<vi.channels;i++){ | ||
281 | System.arraycopy(pcm[i], shiftPCM, pcm[i], 0, pcm_current); | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | lW=W; | ||
287 | W=vb.W; | ||
288 | nW=-1; | ||
289 | |||
290 | glue_bits+=vb.glue_bits; | ||
291 | time_bits+=vb.time_bits; | ||
292 | floor_bits+=vb.floor_bits; | ||
293 | res_bits+=vb.res_bits; | ||
294 | |||
295 | if(sequence+1 != vb.sequence)granulepos=-1; // out of sequence; lose count | ||
296 | |||
297 | sequence=vb.sequence; | ||
298 | |||
299 | { | ||
300 | int sizeW=vi.blocksizes[W]; | ||
301 | int _centerW=centerW+vi.blocksizes[lW]/4+sizeW/4; | ||
302 | int beginW=_centerW-sizeW/2; | ||
303 | int endW=beginW+sizeW; | ||
304 | int beginSl=0; | ||
305 | int endSl=0; | ||
306 | |||
307 | // Do we have enough PCM/mult storage for the block? | ||
308 | if(endW>pcm_storage){ | ||
309 | // expand the storage | ||
310 | pcm_storage=endW+vi.blocksizes[1]; | ||
311 | for(int i=0;i<vi.channels;i++){ | ||
312 | float[] foo=new float[pcm_storage]; | ||
313 | System.arraycopy(pcm[i], 0, foo, 0, pcm[i].length); | ||
314 | pcm[i]=foo; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | // overlap/add PCM | ||
319 | switch(W){ | ||
320 | case 0: | ||
321 | beginSl=0; | ||
322 | endSl=vi.blocksizes[0]/2; | ||
323 | break; | ||
324 | case 1: | ||
325 | beginSl=vi.blocksizes[1]/4-vi.blocksizes[lW]/4; | ||
326 | endSl=beginSl+vi.blocksizes[lW]/2; | ||
327 | break; | ||
328 | } | ||
329 | |||
330 | for(int j=0;j<vi.channels;j++){ | ||
331 | int _pcm=beginW; | ||
332 | // the overlap/add section | ||
333 | int i=0; | ||
334 | for(i=beginSl;i<endSl;i++){ | ||
335 | pcm[j][_pcm+i]+=vb.pcm[j][i]; | ||
336 | } | ||
337 | // the remaining section | ||
338 | for(;i<sizeW;i++){ | ||
339 | pcm[j][_pcm+i]=vb.pcm[j][i]; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | // track the frame number... This is for convenience, but also | ||
344 | // making sure our last packet doesn't end with added padding. If | ||
345 | // the last packet is partial, the number of samples we'll have to | ||
346 | // return will be past the vb->granulepos. | ||
347 | // | ||
348 | // This is not foolproof! It will be confused if we begin | ||
349 | // decoding at the last page after a seek or hole. In that case, | ||
350 | // we don't have a starting point to judge where the last frame | ||
351 | // is. For this reason, vorbisfile will always try to make sure | ||
352 | // it reads the last two marked pages in proper sequence | ||
353 | |||
354 | if(granulepos==-1){ | ||
355 | granulepos=vb.granulepos; | ||
356 | } | ||
357 | else{ | ||
358 | granulepos+=(_centerW-centerW); | ||
359 | if(vb.granulepos!=-1 && granulepos!=vb.granulepos){ | ||
360 | if(granulepos>vb.granulepos && vb.eofflag!=0){ | ||
361 | // partial last frame. Strip the padding off | ||
362 | _centerW-=(granulepos-vb.granulepos); | ||
363 | }// else{ Shouldn't happen *unless* the bitstream is out of | ||
364 | // spec. Either way, believe the bitstream } | ||
365 | granulepos=vb.granulepos; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | // Update, cleanup | ||
370 | |||
371 | centerW=_centerW; | ||
372 | pcm_current=endW; | ||
373 | if(vb.eofflag!=0)eofflag=1; | ||
374 | } | ||
375 | return(0); | ||
376 | } | ||
377 | |||
378 | // pcm==NULL indicates we just want the pending samples, no more | ||
379 | public int synthesis_pcmout(float[][][] _pcm, int[] index){ | ||
380 | if(pcm_returned<centerW){ | ||
381 | if(_pcm!=null){ | ||
382 | for(int i=0;i<vi.channels;i++){ | ||
383 | // pcmret[i]=pcm[i]+v.pcm_returned; | ||
384 | //!!!!!!!! | ||
385 | index[i]=pcm_returned; | ||
386 | } | ||
387 | _pcm[0]=pcm; | ||
388 | } | ||
389 | return(centerW-pcm_returned); | ||
390 | } | ||
391 | return(0); | ||
392 | } | ||
393 | |||
394 | public int synthesis_read(int bytes){ | ||
395 | if(bytes!=0 && pcm_returned+bytes>centerW)return(-1); | ||
396 | pcm_returned+=bytes; | ||
397 | return(0); | ||
398 | } | ||
399 | |||
400 | public void clear(){ | ||
401 | /* | ||
402 | if(window[0][0][0]!=0){ | ||
403 | for(i=0;i<VI_WINDOWB;i++) | ||
404 | if(v->window[0][0][0][i])free(v->window[0][0][0][i]); | ||
405 | free(v->window[0][0][0]); | ||
406 | |||
407 | for(j=0;j<2;j++) | ||
408 | for(k=0;k<2;k++){ | ||
409 | for(i=0;i<VI_WINDOWB;i++) | ||
410 | if(v->window[1][j][k][i])free(v->window[1][j][k][i]); | ||
411 | free(v->window[1][j][k]); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | if(v->pcm){ | ||
416 | for(i=0;i<vi->channels;i++) | ||
417 | if(v->pcm[i])free(v->pcm[i]); | ||
418 | free(v->pcm); | ||
419 | if(v->pcmret)free(v->pcmret); | ||
420 | } | ||
421 | if(v->multipliers)free(v->multipliers); | ||
422 | |||
423 | _ve_envelope_clear(&v->ve); | ||
424 | if(v->transform[0]){ | ||
425 | mdct_clear(v->transform[0][0]); | ||
426 | free(v->transform[0][0]); | ||
427 | free(v->transform[0]); | ||
428 | } | ||
429 | if(v->transform[1]){ | ||
430 | mdct_clear(v->transform[1][0]); | ||
431 | free(v->transform[1][0]); | ||
432 | free(v->transform[1]); | ||
433 | } | ||
434 | |||
435 | // free mode lookups; these are actually vorbis_look_mapping structs | ||
436 | if(vi){ | ||
437 | for(i=0;i<vi->modes;i++){ | ||
438 | int mapnum=vi->mode_param[i]->mapping; | ||
439 | int maptype=vi->map_type[mapnum]; | ||
440 | _mapping_P[maptype]->free_look(v->mode[i]); | ||
441 | } | ||
442 | // free codebooks | ||
443 | for(i=0;i<vi->books;i++) | ||
444 | vorbis_book_clear(v->fullbooks+i); | ||
445 | } | ||
446 | |||
447 | if(v->mode)free(v->mode); | ||
448 | if(v->fullbooks)free(v->fullbooks); | ||
449 | |||
450 | // free header, header1, header2 | ||
451 | if(v->header)free(v->header); | ||
452 | if(v->header1)free(v->header1); | ||
453 | if(v->header2)free(v->header2); | ||
454 | |||
455 | memset(v,0,sizeof(vorbis_dsp_state)); | ||
456 | } | ||
457 | */ | ||
458 | } | ||
459 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/EncodeAuxNearestMatch.java b/songdbj/com/jcraft/jorbis/EncodeAuxNearestMatch.java new file mode 100644 index 0000000000..c4b3b06c6e --- /dev/null +++ b/songdbj/com/jcraft/jorbis/EncodeAuxNearestMatch.java | |||
@@ -0,0 +1,36 @@ | |||
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 | class EncodeAuxNearestMatch{ | ||
29 | int[] ptr0; | ||
30 | int[] ptr1; | ||
31 | |||
32 | int[] p; // decision points (each is an entry) | ||
33 | int[] q; // decision points (each is an entry) | ||
34 | int aux; // number of tree entries | ||
35 | int alloc; | ||
36 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/EncodeAuxThreshMatch.java b/songdbj/com/jcraft/jorbis/EncodeAuxThreshMatch.java new file mode 100644 index 0000000000..33cb58733c --- /dev/null +++ b/songdbj/com/jcraft/jorbis/EncodeAuxThreshMatch.java | |||
@@ -0,0 +1,33 @@ | |||
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 | class EncodeAuxThreshMatch{ | ||
29 | float[] quantthresh; | ||
30 | int[] quantmap; | ||
31 | int quantvals; | ||
32 | int threshvals; | ||
33 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Floor0.java b/songdbj/com/jcraft/jorbis/Floor0.java new file mode 100644 index 0000000000..3f1d1c32d5 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Floor0.java | |||
@@ -0,0 +1,352 @@ | |||
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 Floor0 extends FuncFloor{ | ||
31 | |||
32 | void pack(Object i, Buffer opb){ | ||
33 | InfoFloor0 info=(InfoFloor0)i; | ||
34 | opb.write(info.order,8); | ||
35 | opb.write(info.rate,16); | ||
36 | opb.write(info.barkmap,16); | ||
37 | opb.write(info.ampbits,6); | ||
38 | opb.write(info.ampdB,8); | ||
39 | opb.write(info.numbooks-1,4); | ||
40 | for(int j=0;j<info.numbooks;j++) | ||
41 | opb.write(info.books[j],8); | ||
42 | } | ||
43 | |||
44 | Object unpack(Info vi , Buffer opb){ | ||
45 | InfoFloor0 info=new InfoFloor0(); | ||
46 | info.order=opb.read(8); | ||
47 | info.rate=opb.read(16); | ||
48 | info.barkmap=opb.read(16); | ||
49 | info.ampbits=opb.read(6); | ||
50 | info.ampdB=opb.read(8); | ||
51 | info.numbooks=opb.read(4)+1; | ||
52 | |||
53 | if((info.order<1)|| | ||
54 | (info.rate<1)|| | ||
55 | (info.barkmap<1)|| | ||
56 | (info.numbooks<1)){ | ||
57 | //free_info(info); | ||
58 | return(null); | ||
59 | } | ||
60 | |||
61 | for(int j=0;j<info.numbooks;j++){ | ||
62 | info.books[j]=opb.read(8); | ||
63 | if(info.books[j]<0 || info.books[j]>=vi.books){ | ||
64 | //free_info(info); | ||
65 | return(null); | ||
66 | } | ||
67 | } | ||
68 | return(info); | ||
69 | // err_out: | ||
70 | // free_info(info); | ||
71 | // return(NULL); | ||
72 | } | ||
73 | Object look(DspState vd, InfoMode mi, Object i){ | ||
74 | float scale; | ||
75 | Info vi=vd.vi; | ||
76 | InfoFloor0 info=(InfoFloor0)i; | ||
77 | LookFloor0 look=new LookFloor0(); | ||
78 | look.m=info.order; | ||
79 | look.n=vi.blocksizes[mi.blockflag]/2; | ||
80 | look.ln=info.barkmap; | ||
81 | look.vi=info; | ||
82 | look.lpclook.init(look.ln,look.m); | ||
83 | |||
84 | // we choose a scaling constant so that: | ||
85 | // floor(bark(rate/2-1)*C)=mapped-1 | ||
86 | // floor(bark(rate/2)*C)=mapped | ||
87 | scale=look.ln/toBARK((float)(info.rate/2.)); | ||
88 | |||
89 | // the mapping from a linear scale to a smaller bark scale is | ||
90 | // straightforward. We do *not* make sure that the linear mapping | ||
91 | // does not skip bark-scale bins; the decoder simply skips them and | ||
92 | // the encoder may do what it wishes in filling them. They're | ||
93 | // necessary in some mapping combinations to keep the scale spacing | ||
94 | // accurate | ||
95 | look.linearmap=new int[look.n]; | ||
96 | for(int j=0;j<look.n;j++){ | ||
97 | int val=(int)Math.floor(toBARK((float)((info.rate/2.)/look.n*j)) | ||
98 | *scale); // bark numbers represent band edges | ||
99 | if(val>=look.ln)val=look.ln; // guard against the approximation | ||
100 | look.linearmap[j]=val; | ||
101 | } | ||
102 | return look; | ||
103 | } | ||
104 | |||
105 | static float toBARK(float f){ | ||
106 | return (float)(13.1*Math.atan(.00074*(f))+2.24*Math.atan((f)*(f)*1.85e-8)+1e-4*(f)); | ||
107 | } | ||
108 | |||
109 | Object state(Object i){ | ||
110 | EchstateFloor0 state=new EchstateFloor0(); | ||
111 | InfoFloor0 info=(InfoFloor0)i; | ||
112 | |||
113 | // a safe size if usually too big (dim==1) | ||
114 | state.codewords=new int[info.order]; | ||
115 | state.curve=new float[info.barkmap]; | ||
116 | state.frameno=-1; | ||
117 | return(state); | ||
118 | } | ||
119 | void free_info(Object i){} | ||
120 | void free_look(Object i){} | ||
121 | void free_state(Object vs){} | ||
122 | int forward(Block vb, Object i, float[] in, float[] out, Object vs){return 0;} | ||
123 | |||
124 | float[] lsp=null; | ||
125 | int inverse(Block vb, Object i, float[] out){ | ||
126 | //System.err.println("Floor0.inverse "+i.getClass()+"]"); | ||
127 | LookFloor0 look=(LookFloor0)i; | ||
128 | InfoFloor0 info=look.vi; | ||
129 | int ampraw=vb.opb.read(info.ampbits); | ||
130 | if(ampraw>0){ // also handles the -1 out of data case | ||
131 | int maxval=(1<<info.ampbits)-1; | ||
132 | float amp=(float)ampraw/maxval*info.ampdB; | ||
133 | int booknum=vb.opb.read(ilog(info.numbooks)); | ||
134 | |||
135 | if(booknum!=-1 && booknum<info.numbooks){ | ||
136 | |||
137 | synchronized(this){ | ||
138 | if(lsp==null||lsp.length<look.m){ | ||
139 | lsp=new float[look.m]; | ||
140 | } | ||
141 | else{ | ||
142 | for(int j=0; j<look.m; j++)lsp[j]=0.f; | ||
143 | } | ||
144 | |||
145 | CodeBook b=vb.vd.fullbooks[info.books[booknum]]; | ||
146 | float last=0.f; | ||
147 | |||
148 | //memset(out,0,sizeof(float)*look->m); | ||
149 | for(int j=0; j<look.m; j++)out[j]=0.0f; | ||
150 | |||
151 | for(int j=0;j<look.m;j+=b.dim){ | ||
152 | if(b.decodevs(lsp, j, vb.opb, 1, -1)==-1){ | ||
153 | //goto eop; | ||
154 | // memset(out,0,sizeof(float)*look->n); | ||
155 | for(int k=0; k<look.n; k++)out[k]=0.0f; | ||
156 | return(0); | ||
157 | } | ||
158 | } | ||
159 | for(int j=0;j<look.m;){ | ||
160 | for(int k=0;k<b.dim;k++,j++)lsp[j]+=last; | ||
161 | last=lsp[j-1]; | ||
162 | } | ||
163 | // take the coefficients back to a spectral envelope curve | ||
164 | /* | ||
165 | lsp_to_lpc(out,out,look.m); | ||
166 | lpc_to_curve(out,out,amp,look,"",0); | ||
167 | for(int j=0;j<look.n;j++){ | ||
168 | out[j]=fromdB(out[j]-info.ampdB); | ||
169 | } | ||
170 | */ | ||
171 | Lsp.lsp_to_curve(out,look.linearmap,look.n,look.ln, | ||
172 | lsp,look.m,amp,info.ampdB); | ||
173 | |||
174 | return(1); | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | // eop: | ||
179 | // memset(out,0,sizeof(float)*look->n); | ||
180 | return(0); | ||
181 | } | ||
182 | |||
183 | Object inverse1(Block vb, Object i, Object memo){ | ||
184 | //System.err.println("Floor0.inverse "+i.getClass()+"]"); | ||
185 | LookFloor0 look=(LookFloor0)i; | ||
186 | InfoFloor0 info=look.vi; | ||
187 | float[] lsp=null; | ||
188 | if(memo instanceof float[]){ | ||
189 | lsp=(float[])memo; | ||
190 | } | ||
191 | |||
192 | int ampraw=vb.opb.read(info.ampbits); | ||
193 | if(ampraw>0){ // also handles the -1 out of data case | ||
194 | int maxval=(1<<info.ampbits)-1; | ||
195 | float amp=(float)ampraw/maxval*info.ampdB; | ||
196 | int booknum=vb.opb.read(ilog(info.numbooks)); | ||
197 | |||
198 | if(booknum!=-1 && booknum<info.numbooks){ | ||
199 | CodeBook b=vb.vd.fullbooks[info.books[booknum]]; | ||
200 | float last=0.f; | ||
201 | |||
202 | if(lsp==null||lsp.length<look.m+1){ | ||
203 | lsp=new float[look.m+1]; | ||
204 | } | ||
205 | else{ | ||
206 | for(int j=0; j<lsp.length; j++)lsp[j]=0.f; | ||
207 | } | ||
208 | |||
209 | for(int j=0;j<look.m;j+=b.dim){ | ||
210 | if(b.decodev_set(lsp, j, vb.opb, b.dim)==-1){ | ||
211 | //goto eop; | ||
212 | return(null); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | for(int j=0;j<look.m;){ | ||
217 | for(int k=0;k<b.dim;k++,j++)lsp[j]+=last; | ||
218 | last=lsp[j-1]; | ||
219 | } | ||
220 | lsp[look.m]=amp; | ||
221 | return(lsp); | ||
222 | } | ||
223 | } | ||
224 | // eop: | ||
225 | return(null); | ||
226 | } | ||
227 | |||
228 | int inverse2(Block vb, Object i, Object memo, float[] out){ | ||
229 | //System.err.println("Floor0.inverse "+i.getClass()+"]"); | ||
230 | LookFloor0 look=(LookFloor0)i; | ||
231 | InfoFloor0 info=look.vi; | ||
232 | |||
233 | if(memo!=null){ | ||
234 | float[] lsp=(float[])memo; | ||
235 | float amp=lsp[look.m]; | ||
236 | |||
237 | Lsp.lsp_to_curve(out,look.linearmap,look.n,look.ln, | ||
238 | lsp,look.m,amp,info.ampdB); | ||
239 | return(1); | ||
240 | } | ||
241 | // eop: | ||
242 | // memset(out,0,sizeof(float)*look->n); | ||
243 | for(int j=0; j<look.n; j++){ | ||
244 | out[j]=0.f; | ||
245 | } | ||
246 | return(0); | ||
247 | } | ||
248 | |||
249 | static float fromdB(float x){ | ||
250 | return (float)(Math.exp((x)*.11512925)); | ||
251 | } | ||
252 | private static int ilog(int v){ | ||
253 | int ret=0; | ||
254 | while(v!=0){ | ||
255 | ret++; | ||
256 | v>>>=1; | ||
257 | } | ||
258 | return(ret); | ||
259 | } | ||
260 | |||
261 | static void lsp_to_lpc(float[] lsp, float[] lpc, int m){ | ||
262 | int i,j,m2=m/2; | ||
263 | float[] O=new float[m2]; | ||
264 | float[] E=new float[m2]; | ||
265 | float A; | ||
266 | float[] Ae=new float[m2+1]; | ||
267 | float[] Ao=new float[m2+1]; | ||
268 | float B; | ||
269 | float[] Be=new float[m2]; | ||
270 | float[] Bo=new float[m2]; | ||
271 | float temp; | ||
272 | |||
273 | // even/odd roots setup | ||
274 | for(i=0;i<m2;i++){ | ||
275 | O[i]=(float)(-2.*Math.cos(lsp[i*2])); | ||
276 | E[i]=(float)(-2.*Math.cos(lsp[i*2+1])); | ||
277 | } | ||
278 | |||
279 | // set up impulse response | ||
280 | for(j=0;j<m2;j++){ | ||
281 | Ae[j]=0.f; | ||
282 | Ao[j]=1.f; | ||
283 | Be[j]=0.f; | ||
284 | Bo[j]=1.f; | ||
285 | } | ||
286 | Ao[j]=1.f; | ||
287 | Ae[j]=1.f; | ||
288 | |||
289 | // run impulse response | ||
290 | for(i=1;i<m+1;i++){ | ||
291 | A=B=0.f; | ||
292 | for(j=0;j<m2;j++){ | ||
293 | temp=O[j]*Ao[j]+Ae[j]; | ||
294 | Ae[j]=Ao[j]; | ||
295 | Ao[j]=A; | ||
296 | A+=temp; | ||
297 | |||
298 | temp=E[j]*Bo[j]+Be[j]; | ||
299 | Be[j]=Bo[j]; | ||
300 | Bo[j]=B; | ||
301 | B+=temp; | ||
302 | } | ||
303 | lpc[i-1]=(A+Ao[j]+B-Ae[j])/2; | ||
304 | Ao[j]=A; | ||
305 | Ae[j]=B; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | static void lpc_to_curve(float[] curve, float[] lpc,float amp, | ||
310 | LookFloor0 l, String name, int frameno){ | ||
311 | // l->m+1 must be less than l->ln, but guard in case we get a bad stream | ||
312 | float[] lcurve=new float[Math.max(l.ln*2,l.m*2+2)]; | ||
313 | |||
314 | if(amp==0){ | ||
315 | //memset(curve,0,sizeof(float)*l->n); | ||
316 | for(int j=0; j<l.n; j++)curve[j]=0.0f; | ||
317 | return; | ||
318 | } | ||
319 | l.lpclook.lpc_to_curve(lcurve,lpc,amp); | ||
320 | |||
321 | for(int i=0;i<l.n;i++)curve[i]=lcurve[l.linearmap[i]]; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | class InfoFloor0{ | ||
326 | int order; | ||
327 | int rate; | ||
328 | int barkmap; | ||
329 | |||
330 | int ampbits; | ||
331 | int ampdB; | ||
332 | |||
333 | int numbooks; // <= 16 | ||
334 | int[] books=new int[16]; | ||
335 | } | ||
336 | |||
337 | class LookFloor0{ | ||
338 | int n; | ||
339 | int ln; | ||
340 | int m; | ||
341 | int[] linearmap; | ||
342 | |||
343 | InfoFloor0 vi; | ||
344 | Lpc lpclook=new Lpc(); | ||
345 | } | ||
346 | |||
347 | class EchstateFloor0{ | ||
348 | int[] codewords; | ||
349 | float[] curve; | ||
350 | long frameno; | ||
351 | long codes; | ||
352 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Floor1.java b/songdbj/com/jcraft/jorbis/Floor1.java new file mode 100644 index 0000000000..1e52c3e537 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Floor1.java | |||
@@ -0,0 +1,653 @@ | |||
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 Floor1 extends FuncFloor{ | ||
31 | static final int floor1_rangedb=140; | ||
32 | static final int VIF_POSIT=63; | ||
33 | |||
34 | void pack(Object i, Buffer opb){ | ||
35 | InfoFloor1 info=(InfoFloor1)i; | ||
36 | |||
37 | int count=0; | ||
38 | int rangebits; | ||
39 | int maxposit=info.postlist[1]; | ||
40 | int maxclass=-1; | ||
41 | |||
42 | /* save out partitions */ | ||
43 | opb.write(info.partitions,5); /* only 0 to 31 legal */ | ||
44 | for(int j=0;j<info.partitions;j++){ | ||
45 | opb.write(info.partitionclass[j],4); /* only 0 to 15 legal */ | ||
46 | if(maxclass<info.partitionclass[j]) | ||
47 | maxclass=info.partitionclass[j]; | ||
48 | } | ||
49 | |||
50 | /* save out partition classes */ | ||
51 | for(int j=0;j<maxclass+1;j++){ | ||
52 | opb.write(info.class_dim[j]-1,3); /* 1 to 8 */ | ||
53 | opb.write(info.class_subs[j],2); /* 0 to 3 */ | ||
54 | if(info.class_subs[j]!=0){ | ||
55 | opb.write(info.class_book[j],8); | ||
56 | } | ||
57 | for(int k=0;k<(1<<info.class_subs[j]);k++){ | ||
58 | opb.write(info.class_subbook[j][k]+1,8); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | /* save out the post list */ | ||
63 | opb.write(info.mult-1,2); /* only 1,2,3,4 legal now */ | ||
64 | opb.write(ilog2(maxposit),4); | ||
65 | rangebits=ilog2(maxposit); | ||
66 | |||
67 | for(int j=0,k=0;j<info.partitions;j++){ | ||
68 | count+=info.class_dim[info.partitionclass[j]]; | ||
69 | for(;k<count;k++){ | ||
70 | opb.write(info.postlist[k+2],rangebits); | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | |||
75 | Object unpack(Info vi , Buffer opb){ | ||
76 | int count=0,maxclass=-1,rangebits; | ||
77 | InfoFloor1 info=new InfoFloor1(); | ||
78 | |||
79 | /* read partitions */ | ||
80 | info.partitions=opb.read(5); /* only 0 to 31 legal */ | ||
81 | for(int j=0;j<info.partitions;j++){ | ||
82 | info.partitionclass[j]=opb.read(4); /* only 0 to 15 legal */ | ||
83 | if(maxclass<info.partitionclass[j]) | ||
84 | maxclass=info.partitionclass[j]; | ||
85 | } | ||
86 | |||
87 | /* read partition classes */ | ||
88 | for(int j=0;j<maxclass+1;j++){ | ||
89 | info.class_dim[j]=opb.read(3)+1; /* 1 to 8 */ | ||
90 | info.class_subs[j]=opb.read(2); /* 0,1,2,3 bits */ | ||
91 | if(info.class_subs[j]<0){ | ||
92 | //goto err_out; | ||
93 | info.free(); | ||
94 | return(null); | ||
95 | } | ||
96 | if(info.class_subs[j]!=0){ | ||
97 | info.class_book[j]=opb.read(8); | ||
98 | } | ||
99 | if(info.class_book[j]<0 || info.class_book[j]>=vi.books){ | ||
100 | //goto err_out; | ||
101 | info.free(); | ||
102 | return(null); | ||
103 | } | ||
104 | for(int k=0;k<(1<<info.class_subs[j]);k++){ | ||
105 | info.class_subbook[j][k]=opb.read(8)-1; | ||
106 | if(info.class_subbook[j][k]<-1 || info.class_subbook[j][k]>=vi.books){ | ||
107 | //goto err_out; | ||
108 | info.free(); | ||
109 | return(null); | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | /* read the post list */ | ||
115 | info.mult=opb.read(2)+1; /* only 1,2,3,4 legal now */ | ||
116 | rangebits=opb.read(4); | ||
117 | |||
118 | for(int j=0,k=0;j<info.partitions;j++){ | ||
119 | count+=info.class_dim[info.partitionclass[j]]; | ||
120 | for(;k<count;k++){ | ||
121 | int t=info.postlist[k+2]=opb.read(rangebits); | ||
122 | if(t<0 || t>=(1<<rangebits)){ | ||
123 | //goto err_out; | ||
124 | info.free(); | ||
125 | return(null); | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | info.postlist[0]=0; | ||
130 | info.postlist[1]=1<<rangebits; | ||
131 | |||
132 | return(info); | ||
133 | // err_out: | ||
134 | // info.free(); | ||
135 | // return(null); | ||
136 | } | ||
137 | |||
138 | Object look(DspState vd, InfoMode mi, Object i){ | ||
139 | int _n=0; | ||
140 | |||
141 | int[] sortpointer=new int[VIF_POSIT+2]; | ||
142 | |||
143 | // Info vi=vd.vi; | ||
144 | |||
145 | InfoFloor1 info=(InfoFloor1)i; | ||
146 | LookFloor1 look=new LookFloor1(); | ||
147 | look.vi=info; | ||
148 | look.n=info.postlist[1]; | ||
149 | |||
150 | /* we drop each position value in-between already decoded values, | ||
151 | and use linear interpolation to predict each new value past the | ||
152 | edges. The positions are read in the order of the position | ||
153 | list... we precompute the bounding positions in the lookup. Of | ||
154 | course, the neighbors can change (if a position is declined), but | ||
155 | this is an initial mapping */ | ||
156 | |||
157 | for(int j=0;j<info.partitions;j++){ | ||
158 | _n+=info.class_dim[info.partitionclass[j]]; | ||
159 | } | ||
160 | _n+=2; | ||
161 | look.posts=_n; | ||
162 | |||
163 | /* also store a sorted position index */ | ||
164 | for(int j=0;j<_n;j++){ | ||
165 | sortpointer[j]=j; | ||
166 | } | ||
167 | // qsort(sortpointer,n,sizeof(int),icomp); // !! | ||
168 | |||
169 | int foo; | ||
170 | for(int j=0; j<_n-1; j++){ | ||
171 | for(int k=j; k<_n; k++){ | ||
172 | if(info.postlist[sortpointer[j]]>info.postlist[sortpointer[k]]){ | ||
173 | foo=sortpointer[k]; | ||
174 | sortpointer[k]=sortpointer[j]; | ||
175 | sortpointer[j]=foo; | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /* points from sort order back to range number */ | ||
181 | for(int j=0;j<_n;j++){ | ||
182 | look.forward_index[j]=sortpointer[j]; | ||
183 | } | ||
184 | /* points from range order to sorted position */ | ||
185 | for(int j=0;j<_n;j++){ | ||
186 | look.reverse_index[look.forward_index[j]]=j; | ||
187 | } | ||
188 | /* we actually need the post values too */ | ||
189 | for(int j=0;j<_n;j++){ | ||
190 | look.sorted_index[j]=info.postlist[look.forward_index[j]]; | ||
191 | } | ||
192 | |||
193 | |||
194 | /* quantize values to multiplier spec */ | ||
195 | switch(info.mult){ | ||
196 | case 1: /* 1024 -> 256 */ | ||
197 | look.quant_q=256; | ||
198 | break; | ||
199 | case 2: /* 1024 -> 128 */ | ||
200 | look.quant_q=128; | ||
201 | break; | ||
202 | case 3: /* 1024 -> 86 */ | ||
203 | look.quant_q=86; | ||
204 | break; | ||
205 | case 4: /* 1024 -> 64 */ | ||
206 | look.quant_q=64; | ||
207 | break; | ||
208 | default: | ||
209 | look.quant_q=-1; | ||
210 | } | ||
211 | |||
212 | /* discover our neighbors for decode where we don't use fit flags | ||
213 | (that would push the neighbors outward) */ | ||
214 | for(int j=0;j<_n-2;j++){ | ||
215 | int lo=0; | ||
216 | int hi=1; | ||
217 | int lx=0; | ||
218 | int hx=look.n; | ||
219 | int currentx=info.postlist[j+2]; | ||
220 | for(int k=0;k<j+2;k++){ | ||
221 | int x=info.postlist[k]; | ||
222 | if(x>lx && x<currentx){ | ||
223 | lo=k; | ||
224 | lx=x; | ||
225 | } | ||
226 | if(x<hx && x>currentx){ | ||
227 | hi=k; | ||
228 | hx=x; | ||
229 | } | ||
230 | } | ||
231 | look.loneighbor[j]=lo; | ||
232 | look.hineighbor[j]=hi; | ||
233 | } | ||
234 | |||
235 | return look; | ||
236 | } | ||
237 | |||
238 | void free_info(Object i){} | ||
239 | void free_look(Object i){} | ||
240 | void free_state(Object vs){} | ||
241 | |||
242 | int forward(Block vb, Object i, float[] in, float[] out, Object vs){return 0;} | ||
243 | |||
244 | Object inverse1(Block vb, Object ii, Object memo){ | ||
245 | //System.err.println("Floor1.inverse "+i.getClass()+"]"); | ||
246 | LookFloor1 look=(LookFloor1)ii; | ||
247 | InfoFloor1 info=look.vi; | ||
248 | CodeBook[] books=vb.vd.fullbooks; | ||
249 | |||
250 | /* unpack wrapped/predicted values from stream */ | ||
251 | if(vb.opb.read(1)==1){ | ||
252 | int[] fit_value=null; | ||
253 | if(memo instanceof int[]){ | ||
254 | fit_value=(int[])memo; | ||
255 | } | ||
256 | if(fit_value==null || fit_value.length<look.posts){ | ||
257 | fit_value=new int[look.posts]; | ||
258 | } | ||
259 | else{ | ||
260 | for(int i=0; i<fit_value.length; i++) fit_value[i]=0; | ||
261 | } | ||
262 | |||
263 | fit_value[0]=vb.opb.read(ilog(look.quant_q-1)); | ||
264 | fit_value[1]=vb.opb.read(ilog(look.quant_q-1)); | ||
265 | |||
266 | /* partition by partition */ | ||
267 | for(int i=0,j=2;i<info.partitions;i++){ | ||
268 | int clss=info.partitionclass[i]; | ||
269 | int cdim=info.class_dim[clss]; | ||
270 | int csubbits=info.class_subs[clss]; | ||
271 | int csub=1<<csubbits; | ||
272 | int cval=0; | ||
273 | |||
274 | /* decode the partition's first stage cascade value */ | ||
275 | if(csubbits!=0){ | ||
276 | cval=books[info.class_book[clss]].decode(vb.opb); | ||
277 | |||
278 | if(cval==-1){ | ||
279 | //goto eop; | ||
280 | return(null); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | for(int k=0;k<cdim;k++){ | ||
285 | int book=info.class_subbook[clss][cval&(csub-1)]; | ||
286 | cval>>>=csubbits; | ||
287 | if(book>=0){ | ||
288 | if((fit_value[j+k]=books[book].decode(vb.opb))==-1){ | ||
289 | //goto eop; | ||
290 | return(null); | ||
291 | } | ||
292 | } | ||
293 | else{ | ||
294 | fit_value[j+k]=0; | ||
295 | } | ||
296 | } | ||
297 | j+=cdim; | ||
298 | } | ||
299 | |||
300 | /* unwrap positive values and reconsitute via linear interpolation */ | ||
301 | for(int i=2;i<look.posts;i++){ | ||
302 | int predicted=render_point(info.postlist[look.loneighbor[i-2]], | ||
303 | info.postlist[look.hineighbor[i-2]], | ||
304 | fit_value[look.loneighbor[i-2]], | ||
305 | fit_value[look.hineighbor[i-2]], | ||
306 | info.postlist[i]); | ||
307 | int hiroom=look.quant_q-predicted; | ||
308 | int loroom=predicted; | ||
309 | int room=(hiroom<loroom?hiroom:loroom)<<1; | ||
310 | int val=fit_value[i]; | ||
311 | |||
312 | if(val!=0){ | ||
313 | if(val>=room){ | ||
314 | if(hiroom>loroom){ | ||
315 | val = val-loroom; | ||
316 | } | ||
317 | else{ | ||
318 | val = -1-(val-hiroom); | ||
319 | } | ||
320 | } | ||
321 | else{ | ||
322 | if((val&1)!=0){ | ||
323 | val= -((val+1)>>>1); | ||
324 | } | ||
325 | else{ | ||
326 | val>>=1; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | fit_value[i]=val+predicted; | ||
331 | fit_value[look.loneighbor[i-2]]&=0x7fff; | ||
332 | fit_value[look.hineighbor[i-2]]&=0x7fff; | ||
333 | } | ||
334 | else{ | ||
335 | fit_value[i]=predicted|0x8000; | ||
336 | } | ||
337 | } | ||
338 | return(fit_value); | ||
339 | } | ||
340 | |||
341 | // eop: | ||
342 | // return(NULL); | ||
343 | return(null); | ||
344 | } | ||
345 | |||
346 | private static int render_point(int x0,int x1,int y0,int y1,int x){ | ||
347 | y0&=0x7fff; /* mask off flag */ | ||
348 | y1&=0x7fff; | ||
349 | |||
350 | { | ||
351 | int dy=y1-y0; | ||
352 | int adx=x1-x0; | ||
353 | int ady=Math.abs(dy); | ||
354 | int err=ady*(x-x0); | ||
355 | |||
356 | int off=(int)(err/adx); | ||
357 | if(dy<0)return(y0-off); | ||
358 | return(y0+off); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | int inverse2(Block vb, Object i, Object memo, float[] out){ | ||
363 | LookFloor1 look=(LookFloor1)i; | ||
364 | InfoFloor1 info=look.vi; | ||
365 | int n=vb.vd.vi.blocksizes[vb.mode]/2; | ||
366 | |||
367 | if(memo!=null){ | ||
368 | /* render the lines */ | ||
369 | int[] fit_value=(int[] )memo; | ||
370 | int hx=0; | ||
371 | int lx=0; | ||
372 | int ly=fit_value[0]*info.mult; | ||
373 | for(int j=1;j<look.posts;j++){ | ||
374 | int current=look.forward_index[j]; | ||
375 | int hy=fit_value[current]&0x7fff; | ||
376 | if(hy==fit_value[current]){ | ||
377 | hy*=info.mult; | ||
378 | hx=info.postlist[current]; | ||
379 | |||
380 | render_line(lx,hx,ly,hy,out); | ||
381 | |||
382 | lx=hx; | ||
383 | ly=hy; | ||
384 | } | ||
385 | } | ||
386 | for(int j=hx;j<n;j++){ | ||
387 | out[j]*=out[j-1]; /* be certain */ | ||
388 | } | ||
389 | return(1); | ||
390 | } | ||
391 | for(int j=0; j<n; j++){ | ||
392 | out[j]=0.f; | ||
393 | } | ||
394 | return(0); | ||
395 | } | ||
396 | |||
397 | |||
398 | private static float[] FLOOR_fromdB_LOOKUP={ | ||
399 | 1.0649863e-07F, 1.1341951e-07F, 1.2079015e-07F, 1.2863978e-07F, | ||
400 | 1.3699951e-07F, 1.4590251e-07F, 1.5538408e-07F, 1.6548181e-07F, | ||
401 | 1.7623575e-07F, 1.8768855e-07F, 1.9988561e-07F, 2.128753e-07F, | ||
402 | 2.2670913e-07F, 2.4144197e-07F, 2.5713223e-07F, 2.7384213e-07F, | ||
403 | 2.9163793e-07F, 3.1059021e-07F, 3.3077411e-07F, 3.5226968e-07F, | ||
404 | 3.7516214e-07F, 3.9954229e-07F, 4.2550680e-07F, 4.5315863e-07F, | ||
405 | 4.8260743e-07F, 5.1396998e-07F, 5.4737065e-07F, 5.8294187e-07F, | ||
406 | 6.2082472e-07F, 6.6116941e-07F, 7.0413592e-07F, 7.4989464e-07F, | ||
407 | 7.9862701e-07F, 8.5052630e-07F, 9.0579828e-07F, 9.6466216e-07F, | ||
408 | 1.0273513e-06F, 1.0941144e-06F, 1.1652161e-06F, 1.2409384e-06F, | ||
409 | 1.3215816e-06F, 1.4074654e-06F, 1.4989305e-06F, 1.5963394e-06F, | ||
410 | 1.7000785e-06F, 1.8105592e-06F, 1.9282195e-06F, 2.0535261e-06F, | ||
411 | 2.1869758e-06F, 2.3290978e-06F, 2.4804557e-06F, 2.6416497e-06F, | ||
412 | 2.8133190e-06F, 2.9961443e-06F, 3.1908506e-06F, 3.3982101e-06F, | ||
413 | 3.6190449e-06F, 3.8542308e-06F, 4.1047004e-06F, 4.3714470e-06F, | ||
414 | 4.6555282e-06F, 4.9580707e-06F, 5.2802740e-06F, 5.6234160e-06F, | ||
415 | 5.9888572e-06F, 6.3780469e-06F, 6.7925283e-06F, 7.2339451e-06F, | ||
416 | 7.7040476e-06F, 8.2047000e-06F, 8.7378876e-06F, 9.3057248e-06F, | ||
417 | 9.9104632e-06F, 1.0554501e-05F, 1.1240392e-05F, 1.1970856e-05F, | ||
418 | 1.2748789e-05F, 1.3577278e-05F, 1.4459606e-05F, 1.5399272e-05F, | ||
419 | 1.6400004e-05F, 1.7465768e-05F, 1.8600792e-05F, 1.9809576e-05F, | ||
420 | 2.1096914e-05F, 2.2467911e-05F, 2.3928002e-05F, 2.5482978e-05F, | ||
421 | 2.7139006e-05F, 2.8902651e-05F, 3.0780908e-05F, 3.2781225e-05F, | ||
422 | 3.4911534e-05F, 3.7180282e-05F, 3.9596466e-05F, 4.2169667e-05F, | ||
423 | 4.4910090e-05F, 4.7828601e-05F, 5.0936773e-05F, 5.4246931e-05F, | ||
424 | 5.7772202e-05F, 6.1526565e-05F, 6.5524908e-05F, 6.9783085e-05F, | ||
425 | 7.4317983e-05F, 7.9147585e-05F, 8.4291040e-05F, 8.9768747e-05F, | ||
426 | 9.5602426e-05F, 0.00010181521F, 0.00010843174F, 0.00011547824F, | ||
427 | 0.00012298267F, 0.00013097477F, 0.00013948625F, 0.00014855085F, | ||
428 | 0.00015820453F, 0.00016848555F, 0.00017943469F, 0.00019109536F, | ||
429 | 0.00020351382F, 0.00021673929F, 0.00023082423F, 0.00024582449F, | ||
430 | 0.00026179955F, 0.00027881276F, 0.00029693158F, 0.00031622787F, | ||
431 | 0.00033677814F, 0.00035866388F, 0.00038197188F, 0.00040679456F, | ||
432 | 0.00043323036F, 0.00046138411F, 0.00049136745F, 0.00052329927F, | ||
433 | 0.00055730621F, 0.00059352311F, 0.00063209358F, 0.00067317058F, | ||
434 | 0.00071691700F, 0.00076350630F, 0.00081312324F, 0.00086596457F, | ||
435 | 0.00092223983F, 0.00098217216F, 0.0010459992F, 0.0011139742F, | ||
436 | 0.0011863665F, 0.0012634633F, 0.0013455702F, 0.0014330129F, | ||
437 | 0.0015261382F, 0.0016253153F, 0.0017309374F, 0.0018434235F, | ||
438 | 0.0019632195F, 0.0020908006F, 0.0022266726F, 0.0023713743F, | ||
439 | 0.0025254795F, 0.0026895994F, 0.0028643847F, 0.0030505286F, | ||
440 | 0.0032487691F, 0.0034598925F, 0.0036847358F, 0.0039241906F, | ||
441 | 0.0041792066F, 0.0044507950F, 0.0047400328F, 0.0050480668F, | ||
442 | 0.0053761186F, 0.0057254891F, 0.0060975636F, 0.0064938176F, | ||
443 | 0.0069158225F, 0.0073652516F, 0.0078438871F, 0.0083536271F, | ||
444 | 0.0088964928F, 0.009474637F, 0.010090352F, 0.010746080F, | ||
445 | 0.011444421F, 0.012188144F, 0.012980198F, 0.013823725F, | ||
446 | 0.014722068F, 0.015678791F, 0.016697687F, 0.017782797F, | ||
447 | 0.018938423F, 0.020169149F, 0.021479854F, 0.022875735F, | ||
448 | 0.024362330F, 0.025945531F, 0.027631618F, 0.029427276F, | ||
449 | 0.031339626F, 0.033376252F, 0.035545228F, 0.037855157F, | ||
450 | 0.040315199F, 0.042935108F, 0.045725273F, 0.048696758F, | ||
451 | 0.051861348F, 0.055231591F, 0.058820850F, 0.062643361F, | ||
452 | 0.066714279F, 0.071049749F, 0.075666962F, 0.080584227F, | ||
453 | 0.085821044F, 0.091398179F, 0.097337747F, 0.10366330F, | ||
454 | 0.11039993F, 0.11757434F, 0.12521498F, 0.13335215F, | ||
455 | 0.14201813F, 0.15124727F, 0.16107617F, 0.17154380F, | ||
456 | 0.18269168F, 0.19456402F, 0.20720788F, 0.22067342F, | ||
457 | 0.23501402F, 0.25028656F, 0.26655159F, 0.28387361F, | ||
458 | 0.30232132F, 0.32196786F, 0.34289114F, 0.36517414F, | ||
459 | 0.38890521F, 0.41417847F, 0.44109412F, 0.46975890F, | ||
460 | 0.50028648F, 0.53279791F, 0.56742212F, 0.60429640F, | ||
461 | 0.64356699F, 0.68538959F, 0.72993007F, 0.77736504F, | ||
462 | 0.82788260F, 0.88168307F, 0.9389798F, 1.F | ||
463 | }; | ||
464 | |||
465 | private static void render_line(int x0, int x1,int y0,int y1,float[] d){ | ||
466 | int dy=y1-y0; | ||
467 | int adx=x1-x0; | ||
468 | int ady=Math.abs(dy); | ||
469 | int base=dy/adx; | ||
470 | int sy=(dy<0?base-1:base+1); | ||
471 | int x=x0; | ||
472 | int y=y0; | ||
473 | int err=0; | ||
474 | |||
475 | ady-=Math.abs(base*adx); | ||
476 | |||
477 | d[x]*=FLOOR_fromdB_LOOKUP[y]; | ||
478 | while(++x<x1){ | ||
479 | err=err+ady; | ||
480 | if(err>=adx){ | ||
481 | err-=adx; | ||
482 | y+=sy; | ||
483 | } | ||
484 | else{ | ||
485 | y+=base; | ||
486 | } | ||
487 | d[x]*=FLOOR_fromdB_LOOKUP[y]; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | static int ilog(int v){ | ||
492 | int ret=0; | ||
493 | while(v!=0){ | ||
494 | ret++; | ||
495 | v>>>=1; | ||
496 | } | ||
497 | return(ret); | ||
498 | } | ||
499 | |||
500 | private static int ilog2(int v){ | ||
501 | int ret=0; | ||
502 | while(v>1){ | ||
503 | ret++; | ||
504 | v>>>=1; | ||
505 | } | ||
506 | return(ret); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | class InfoFloor1{ | ||
511 | static final int VIF_POSIT=63; | ||
512 | static final int VIF_CLASS=16; | ||
513 | static final int VIF_PARTS=31; | ||
514 | |||
515 | int partitions; /* 0 to 31 */ | ||
516 | int[] partitionclass=new int[VIF_PARTS]; /* 0 to 15 */ | ||
517 | |||
518 | int[] class_dim=new int[VIF_CLASS]; /* 1 to 8 */ | ||
519 | int[] class_subs=new int[VIF_CLASS]; /* 0,1,2,3 (bits: 1<<n poss) */ | ||
520 | int[] class_book=new int[VIF_CLASS]; /* subs ^ dim entries */ | ||
521 | int[][] class_subbook=new int[VIF_CLASS][]; /* [VIF_CLASS][subs] */ | ||
522 | |||
523 | |||
524 | int mult; /* 1 2 3 or 4 */ | ||
525 | int[] postlist=new int[VIF_POSIT+2]; /* first two implicit */ | ||
526 | |||
527 | |||
528 | /* encode side analysis parameters */ | ||
529 | float maxover; | ||
530 | float maxunder; | ||
531 | float maxerr; | ||
532 | |||
533 | int twofitminsize; | ||
534 | int twofitminused; | ||
535 | int twofitweight; | ||
536 | float twofitatten; | ||
537 | int unusedminsize; | ||
538 | int unusedmin_n; | ||
539 | |||
540 | int n; | ||
541 | |||
542 | InfoFloor1(){ | ||
543 | for(int i=0; i<class_subbook.length; i++){ | ||
544 | class_subbook[i]=new int[8]; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | void free(){ | ||
549 | partitionclass=null; | ||
550 | class_dim=null; | ||
551 | class_subs=null; | ||
552 | class_book=null; | ||
553 | class_subbook=null; | ||
554 | postlist=null; | ||
555 | } | ||
556 | |||
557 | Object copy_info(){ | ||
558 | InfoFloor1 info=this; | ||
559 | InfoFloor1 ret=new InfoFloor1(); | ||
560 | |||
561 | ret.partitions=info.partitions; | ||
562 | System.arraycopy(info.partitionclass, 0, ret.partitionclass, 0, VIF_PARTS); | ||
563 | System.arraycopy(info.class_dim, 0, ret.class_dim, 0, VIF_CLASS); | ||
564 | System.arraycopy(info.class_subs, 0, ret.class_subs, 0, VIF_CLASS); | ||
565 | System.arraycopy(info.class_book, 0, ret.class_book, 0, VIF_CLASS); | ||
566 | |||
567 | for(int j=0; j<VIF_CLASS; j++){ | ||
568 | System.arraycopy(info.class_subbook[j], 0, | ||
569 | ret.class_subbook[j], 0, 8); | ||
570 | } | ||
571 | |||
572 | ret.mult=info.mult; | ||
573 | System.arraycopy(info.postlist, 0, ret.postlist, 0, VIF_POSIT+2); | ||
574 | |||
575 | ret.maxover=info.maxover; | ||
576 | ret.maxunder=info.maxunder; | ||
577 | ret.maxerr=info.maxerr; | ||
578 | |||
579 | ret.twofitminsize=info.twofitminsize; | ||
580 | ret.twofitminused=info.twofitminused; | ||
581 | ret.twofitweight=info.twofitweight; | ||
582 | ret.twofitatten=info.twofitatten; | ||
583 | ret.unusedminsize=info.unusedminsize; | ||
584 | ret.unusedmin_n=info.unusedmin_n; | ||
585 | |||
586 | ret.n=info.n; | ||
587 | |||
588 | return(ret); | ||
589 | } | ||
590 | |||
591 | } | ||
592 | |||
593 | class LookFloor1{ | ||
594 | static final int VIF_POSIT=63; | ||
595 | |||
596 | int[] sorted_index=new int[VIF_POSIT+2]; | ||
597 | int[] forward_index=new int[VIF_POSIT+2]; | ||
598 | int[] reverse_index=new int[VIF_POSIT+2]; | ||
599 | int[] hineighbor=new int[VIF_POSIT]; | ||
600 | int[] loneighbor=new int[VIF_POSIT]; | ||
601 | int posts; | ||
602 | |||
603 | int n; | ||
604 | int quant_q; | ||
605 | InfoFloor1 vi; | ||
606 | |||
607 | int phrasebits; | ||
608 | int postbits; | ||
609 | int frames; | ||
610 | |||
611 | void free(){ | ||
612 | |||
613 | /* | ||
614 | System.out.println("floor 1 bit usage "+ | ||
615 | (float)(phrasebits/frames) | ||
616 | +":"+ | ||
617 | (float)(postbits/frames) | ||
618 | +"("+ | ||
619 | (float)((postbits+phrasebits)/frames) | ||
620 | +" total)" | ||
621 | |||
622 | */ | ||
623 | |||
624 | sorted_index=null; | ||
625 | forward_index=null; | ||
626 | reverse_index=null; | ||
627 | hineighbor=null; | ||
628 | loneighbor=null; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | class Lsfit_acc{ | ||
633 | long x0; | ||
634 | long x1; | ||
635 | |||
636 | long xa; | ||
637 | long ya; | ||
638 | long x2a; | ||
639 | long y2a; | ||
640 | long xya; | ||
641 | long n; | ||
642 | long an; | ||
643 | long un; | ||
644 | long edgey0; | ||
645 | long edgey1; | ||
646 | } | ||
647 | |||
648 | class EchstateFloor1{ | ||
649 | int[] codewords; | ||
650 | float[] curve; | ||
651 | long frameno; | ||
652 | long codes; | ||
653 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/FuncFloor.java b/songdbj/com/jcraft/jorbis/FuncFloor.java new file mode 100644 index 0000000000..f438d0f260 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/FuncFloor.java | |||
@@ -0,0 +1,45 @@ | |||
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 | abstract class FuncFloor{ | ||
31 | // public static FuncFloor[] floor_P={new Floor0()}; | ||
32 | public static FuncFloor[] floor_P={new Floor0(),new Floor1()}; | ||
33 | |||
34 | abstract void pack(Object i, Buffer opb); | ||
35 | abstract Object unpack(Info vi, Buffer opb); | ||
36 | abstract Object look(DspState vd, InfoMode mi, Object i); | ||
37 | // abstract Object state(Object i); | ||
38 | abstract void free_info(Object i); | ||
39 | abstract void free_look(Object i); | ||
40 | abstract void free_state(Object vs); | ||
41 | abstract int forward(Block vb, Object i, float[] in, float[] out, Object vs); | ||
42 | // abstract int inverse(Block vb, Object i, float[] out); | ||
43 | abstract Object inverse1(Block vb, Object i, Object memo); | ||
44 | abstract int inverse2(Block vb, Object i, Object memo, float[] out); | ||
45 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/FuncMapping.java b/songdbj/com/jcraft/jorbis/FuncMapping.java new file mode 100644 index 0000000000..c8ecf75fe7 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/FuncMapping.java | |||
@@ -0,0 +1,40 @@ | |||
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 | abstract class FuncMapping{ | ||
31 | public static FuncMapping[] mapping_P={new Mapping0()}; | ||
32 | |||
33 | abstract void pack(Info info , Object imap, Buffer buffer); | ||
34 | abstract Object unpack(Info info , Buffer buffer); | ||
35 | abstract Object look(DspState vd, InfoMode vm, Object m); | ||
36 | abstract void free_info(Object imap); | ||
37 | abstract void free_look(Object imap); | ||
38 | // abstract int forward(Block vd, Object lm); | ||
39 | abstract int inverse(Block vd, Object lm); | ||
40 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/FuncResidue.java b/songdbj/com/jcraft/jorbis/FuncResidue.java new file mode 100644 index 0000000000..4cbf6a1d53 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/FuncResidue.java | |||
@@ -0,0 +1,43 @@ | |||
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 | abstract class FuncResidue{ | ||
31 | public static FuncResidue[] residue_P={new Residue0(), | ||
32 | new Residue1(), | ||
33 | new Residue2()}; | ||
34 | |||
35 | abstract void pack(Object vr, Buffer opb); | ||
36 | abstract Object unpack(Info vi, Buffer opb); | ||
37 | abstract Object look(DspState vd, InfoMode vm, Object vr); | ||
38 | abstract void free_info(Object i); | ||
39 | abstract void free_look(Object i); | ||
40 | abstract int forward(Block vb,Object vl, float[][] in, int ch); | ||
41 | // abstract int inverse(Block vb, Object vl, float[][] in, int ch); | ||
42 | abstract int inverse(Block vb, Object vl, float[][] in, int[] nonzero,int ch); | ||
43 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/FuncTime.java b/songdbj/com/jcraft/jorbis/FuncTime.java new file mode 100644 index 0000000000..b3cd080461 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/FuncTime.java | |||
@@ -0,0 +1,40 @@ | |||
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 | abstract class FuncTime{ | ||
31 | public static FuncTime[] time_P={new Time0()}; | ||
32 | |||
33 | abstract void pack(Object i, Buffer opb); | ||
34 | abstract Object unpack(Info vi , Buffer opb); | ||
35 | abstract Object look(DspState vd, InfoMode vm, Object i); | ||
36 | abstract void free_info(Object i); | ||
37 | abstract void free_look(Object i); | ||
38 | abstract int forward(Block vb, Object i); | ||
39 | abstract int inverse(Block vb, Object i, float[] in, float[] out); | ||
40 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Info.java b/songdbj/com/jcraft/jorbis/Info.java new file mode 100644 index 0000000000..dffd4d9de2 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Info.java | |||
@@ -0,0 +1,516 @@ | |||
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 | public class Info{ | ||
31 | private static final int OV_EBADPACKET=-136; | ||
32 | private static final int OV_ENOTAUDIO=-135; | ||
33 | |||
34 | private static byte[] _vorbis="vorbis".getBytes(); | ||
35 | private static final int VI_TIMEB=1; | ||
36 | // private static final int VI_FLOORB=1; | ||
37 | private static final int VI_FLOORB=2; | ||
38 | // private static final int VI_RESB=1; | ||
39 | private static final int VI_RESB=3; | ||
40 | private static final int VI_MAPB=1; | ||
41 | private static final int VI_WINDOWB=1; | ||
42 | |||
43 | public int version; | ||
44 | public int channels; | ||
45 | public int rate; | ||
46 | |||
47 | // The below bitrate declarations are *hints*. | ||
48 | // Combinations of the three values carry the following implications: | ||
49 | // | ||
50 | // all three set to the same value: | ||
51 | // implies a fixed rate bitstream | ||
52 | // only nominal set: | ||
53 | // implies a VBR stream that averages the nominal bitrate. No hard | ||
54 | // upper/lower limit | ||
55 | // upper and or lower set: | ||
56 | // implies a VBR bitstream that obeys the bitrate limits. nominal | ||
57 | // may also be set to give a nominal rate. | ||
58 | // none set: | ||
59 | // the coder does not care to speculate. | ||
60 | |||
61 | int bitrate_upper; | ||
62 | int bitrate_nominal; | ||
63 | int bitrate_lower; | ||
64 | |||
65 | // Vorbis supports only short and long blocks, but allows the | ||
66 | // encoder to choose the sizes | ||
67 | |||
68 | int[] blocksizes=new int[2]; | ||
69 | |||
70 | // modes are the primary means of supporting on-the-fly different | ||
71 | // blocksizes, different channel mappings (LR or mid-side), | ||
72 | // different residue backends, etc. Each mode consists of a | ||
73 | // blocksize flag and a mapping (along with the mapping setup | ||
74 | |||
75 | int modes; | ||
76 | int maps; | ||
77 | int times; | ||
78 | int floors; | ||
79 | int residues; | ||
80 | int books; | ||
81 | int psys; // encode only | ||
82 | |||
83 | InfoMode[] mode_param=null; | ||
84 | |||
85 | int[] map_type=null; | ||
86 | Object[] map_param=null; | ||
87 | |||
88 | int[] time_type=null; | ||
89 | Object[] time_param=null; | ||
90 | |||
91 | int[] floor_type=null; | ||
92 | Object[] floor_param=null; | ||
93 | |||
94 | int[] residue_type=null; | ||
95 | Object[] residue_param=null; | ||
96 | |||
97 | StaticCodeBook[] book_param=null; | ||
98 | |||
99 | PsyInfo[] psy_param=new PsyInfo[64]; // encode only | ||
100 | |||
101 | // for block long/sort tuning; encode only | ||
102 | int envelopesa; | ||
103 | float preecho_thresh; | ||
104 | float preecho_clamp; | ||
105 | |||
106 | // used by synthesis, which has a full, alloced vi | ||
107 | public void init(){ | ||
108 | rate=0; | ||
109 | //memset(vi,0,sizeof(vorbis_info)); | ||
110 | } | ||
111 | |||
112 | public void clear(){ | ||
113 | for(int i=0;i<modes;i++){ mode_param[i]=null; } | ||
114 | mode_param=null; | ||
115 | |||
116 | for(int i=0;i<maps;i++){ // unpack does the range checking | ||
117 | FuncMapping.mapping_P[map_type[i]].free_info(map_param[i]); | ||
118 | } | ||
119 | map_param=null; | ||
120 | |||
121 | for(int i=0;i<times;i++){ // unpack does the range checking | ||
122 | FuncTime.time_P[time_type[i]].free_info(time_param[i]); | ||
123 | } | ||
124 | time_param=null; | ||
125 | |||
126 | for(int i=0;i<floors;i++){ // unpack does the range checking | ||
127 | FuncFloor.floor_P[floor_type[i]].free_info(floor_param[i]); | ||
128 | } | ||
129 | floor_param=null; | ||
130 | |||
131 | for(int i=0;i<residues;i++){ // unpack does the range checking | ||
132 | FuncResidue.residue_P[residue_type[i]].free_info(residue_param[i]); | ||
133 | } | ||
134 | residue_param=null; | ||
135 | |||
136 | // the static codebooks *are* freed if you call info_clear, because | ||
137 | // decode side does alloc a 'static' codebook. Calling clear on the | ||
138 | // full codebook does not clear the static codebook (that's our | ||
139 | // responsibility) | ||
140 | for(int i=0;i<books;i++){ | ||
141 | // just in case the decoder pre-cleared to save space | ||
142 | if(book_param[i]!=null){ | ||
143 | book_param[i].clear(); | ||
144 | book_param[i]=null; | ||
145 | } | ||
146 | } | ||
147 | //if(vi->book_param)free(vi->book_param); | ||
148 | book_param=null; | ||
149 | |||
150 | for(int i=0;i<psys;i++){ | ||
151 | psy_param[i].free(); | ||
152 | } | ||
153 | //if(vi->psy_param)free(vi->psy_param); | ||
154 | //memset(vi,0,sizeof(vorbis_info)); | ||
155 | } | ||
156 | |||
157 | // Header packing/unpacking | ||
158 | int unpack_info(Buffer opb){ | ||
159 | version=opb.read(32); | ||
160 | if(version!=0)return(-1); | ||
161 | |||
162 | channels=opb.read(8); | ||
163 | rate=opb.read(32); | ||
164 | |||
165 | bitrate_upper=opb.read(32); | ||
166 | bitrate_nominal=opb.read(32); | ||
167 | bitrate_lower=opb.read(32); | ||
168 | |||
169 | blocksizes[0]=1<<opb.read(4); | ||
170 | blocksizes[1]=1<<opb.read(4); | ||
171 | |||
172 | if((rate<1) || | ||
173 | (channels<1)|| | ||
174 | (blocksizes[0]<8)|| | ||
175 | (blocksizes[1]<blocksizes[0]) || | ||
176 | (opb.read(1)!=1)){ | ||
177 | //goto err_out; // EOP check | ||
178 | clear(); | ||
179 | return(-1); | ||
180 | } | ||
181 | return(0); | ||
182 | // err_out: | ||
183 | // vorbis_info_clear(vi); | ||
184 | // return(-1); | ||
185 | } | ||
186 | |||
187 | // all of the real encoding details are here. The modes, books, | ||
188 | // everything | ||
189 | int unpack_books(Buffer opb){ | ||
190 | |||
191 | //d* codebooks | ||
192 | books=opb.read(8)+1; | ||
193 | |||
194 | if(book_param==null || book_param.length!=books) | ||
195 | book_param=new StaticCodeBook[books]; | ||
196 | for(int i=0;i<books;i++){ | ||
197 | book_param[i]=new StaticCodeBook(); | ||
198 | if(book_param[i].unpack(opb)!=0){ | ||
199 | //goto err_out; | ||
200 | clear(); | ||
201 | return(-1); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | // time backend settings | ||
206 | times=opb.read(6)+1; | ||
207 | if(time_type==null || time_type.length!=times) time_type=new int[times]; | ||
208 | if(time_param==null || time_param.length!=times) | ||
209 | time_param=new Object[times]; | ||
210 | for(int i=0;i<times;i++){ | ||
211 | time_type[i]=opb.read(16); | ||
212 | if(time_type[i]<0 || time_type[i]>=VI_TIMEB){ | ||
213 | //goto err_out; | ||
214 | clear(); | ||
215 | return(-1); | ||
216 | } | ||
217 | time_param[i]=FuncTime.time_P[time_type[i]].unpack(this, opb); | ||
218 | if(time_param[i]==null){ | ||
219 | //goto err_out; | ||
220 | clear(); | ||
221 | return(-1); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | // floor backend settings | ||
226 | floors=opb.read(6)+1; | ||
227 | if(floor_type==null || floor_type.length!=floors) | ||
228 | floor_type=new int[floors]; | ||
229 | if(floor_param==null || floor_param.length!=floors) | ||
230 | floor_param=new Object[floors]; | ||
231 | |||
232 | for(int i=0;i<floors;i++){ | ||
233 | floor_type[i]=opb.read(16); | ||
234 | if(floor_type[i]<0 || floor_type[i]>=VI_FLOORB){ | ||
235 | //goto err_out; | ||
236 | clear(); | ||
237 | return(-1); | ||
238 | } | ||
239 | |||
240 | floor_param[i]=FuncFloor.floor_P[floor_type[i]].unpack(this,opb); | ||
241 | if(floor_param[i]==null){ | ||
242 | //goto err_out; | ||
243 | clear(); | ||
244 | return(-1); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | // residue backend settings | ||
249 | residues=opb.read(6)+1; | ||
250 | |||
251 | if(residue_type==null || residue_type.length!=residues) | ||
252 | residue_type=new int[residues]; | ||
253 | |||
254 | if(residue_param==null || residue_param.length!=residues) | ||
255 | residue_param=new Object[residues]; | ||
256 | |||
257 | for(int i=0;i<residues;i++){ | ||
258 | residue_type[i]=opb.read(16); | ||
259 | if(residue_type[i]<0 || residue_type[i]>=VI_RESB){ | ||
260 | // goto err_out; | ||
261 | clear(); | ||
262 | return(-1); | ||
263 | } | ||
264 | residue_param[i]=FuncResidue.residue_P[residue_type[i]].unpack(this,opb); | ||
265 | if(residue_param[i]==null){ | ||
266 | // goto err_out; | ||
267 | clear(); | ||
268 | return(-1); | ||
269 | } | ||
270 | } | ||
271 | |||
272 | // map backend settings | ||
273 | maps=opb.read(6)+1; | ||
274 | if(map_type==null || map_type.length!=maps) map_type=new int[maps]; | ||
275 | if(map_param==null || map_param.length!=maps) map_param=new Object[maps]; | ||
276 | for(int i=0;i<maps;i++){ | ||
277 | map_type[i]=opb.read(16); | ||
278 | if(map_type[i]<0 || map_type[i]>=VI_MAPB){ | ||
279 | // goto err_out; | ||
280 | clear(); | ||
281 | return(-1); | ||
282 | } | ||
283 | map_param[i]=FuncMapping.mapping_P[map_type[i]].unpack(this,opb); | ||
284 | if(map_param[i]==null){ | ||
285 | // goto err_out; | ||
286 | clear(); | ||
287 | return(-1); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | // mode settings | ||
292 | modes=opb.read(6)+1; | ||
293 | if(mode_param==null || mode_param.length!=modes) | ||
294 | mode_param=new InfoMode[modes]; | ||
295 | for(int i=0;i<modes;i++){ | ||
296 | mode_param[i]=new InfoMode(); | ||
297 | mode_param[i].blockflag=opb.read(1); | ||
298 | mode_param[i].windowtype=opb.read(16); | ||
299 | mode_param[i].transformtype=opb.read(16); | ||
300 | mode_param[i].mapping=opb.read(8); | ||
301 | |||
302 | if((mode_param[i].windowtype>=VI_WINDOWB)|| | ||
303 | (mode_param[i].transformtype>=VI_WINDOWB)|| | ||
304 | (mode_param[i].mapping>=maps)){ | ||
305 | // goto err_out; | ||
306 | clear(); | ||
307 | return(-1); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | if(opb.read(1)!=1){ | ||
312 | //goto err_out; // top level EOP check | ||
313 | clear(); | ||
314 | return(-1); | ||
315 | } | ||
316 | |||
317 | return(0); | ||
318 | // err_out: | ||
319 | // vorbis_info_clear(vi); | ||
320 | // return(-1); | ||
321 | } | ||
322 | |||
323 | // The Vorbis header is in three packets; the initial small packet in | ||
324 | // the first page that identifies basic parameters, a second packet | ||
325 | // with bitstream comments and a third packet that holds the | ||
326 | // codebook. | ||
327 | |||
328 | public int synthesis_headerin(Comment vc, Packet op){ | ||
329 | Buffer opb=new Buffer(); | ||
330 | |||
331 | if(op!=null){ | ||
332 | opb.readinit(op.packet_base, op.packet, op.bytes); | ||
333 | |||
334 | // Which of the three types of header is this? | ||
335 | // Also verify header-ness, vorbis | ||
336 | { | ||
337 | byte[] buffer=new byte[6]; | ||
338 | int packtype=opb.read(8); | ||
339 | //memset(buffer,0,6); | ||
340 | opb.read(buffer,6); | ||
341 | if(buffer[0]!='v' || buffer[1]!='o' || buffer[2]!='r' || | ||
342 | buffer[3]!='b' || buffer[4]!='i' || buffer[5]!='s'){ | ||
343 | // not a vorbis header | ||
344 | return(-1); | ||
345 | } | ||
346 | switch(packtype){ | ||
347 | case 0x01: // least significant *bit* is read first | ||
348 | if(op.b_o_s==0){ | ||
349 | // Not the initial packet | ||
350 | return(-1); | ||
351 | } | ||
352 | if(rate!=0){ | ||
353 | // previously initialized info header | ||
354 | return(-1); | ||
355 | } | ||
356 | return(unpack_info(opb)); | ||
357 | case 0x03: // least significant *bit* is read first | ||
358 | if(rate==0){ | ||
359 | // um... we didn't get the initial header | ||
360 | return(-1); | ||
361 | } | ||
362 | return(vc.unpack(opb)); | ||
363 | case 0x05: // least significant *bit* is read first | ||
364 | if(rate==0 || vc.vendor==null){ | ||
365 | // um... we didn;t get the initial header or comments yet | ||
366 | return(-1); | ||
367 | } | ||
368 | return(unpack_books(opb)); | ||
369 | default: | ||
370 | // Not a valid vorbis header type | ||
371 | //return(-1); | ||
372 | break; | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | return(-1); | ||
377 | } | ||
378 | |||
379 | // pack side | ||
380 | int pack_info(Buffer opb){ | ||
381 | // preamble | ||
382 | opb.write(0x01,8); | ||
383 | opb.write(_vorbis); | ||
384 | |||
385 | // basic information about the stream | ||
386 | opb.write(0x00,32); | ||
387 | opb.write(channels,8); | ||
388 | opb.write(rate,32); | ||
389 | |||
390 | opb.write(bitrate_upper,32); | ||
391 | opb.write(bitrate_nominal,32); | ||
392 | opb.write(bitrate_lower,32); | ||
393 | |||
394 | opb.write(ilog2(blocksizes[0]),4); | ||
395 | opb.write(ilog2(blocksizes[1]),4); | ||
396 | opb.write(1,1); | ||
397 | return(0); | ||
398 | } | ||
399 | |||
400 | int pack_books(Buffer opb){ | ||
401 | opb.write(0x05,8); | ||
402 | opb.write(_vorbis); | ||
403 | |||
404 | // books | ||
405 | opb.write(books-1,8); | ||
406 | for(int i=0;i<books;i++){ | ||
407 | if(book_param[i].pack(opb)!=0){ | ||
408 | //goto err_out; | ||
409 | return(-1); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | // times | ||
414 | opb.write(times-1,6); | ||
415 | for(int i=0;i<times;i++){ | ||
416 | opb.write(time_type[i],16); | ||
417 | FuncTime.time_P[time_type[i]].pack(this.time_param[i],opb); | ||
418 | } | ||
419 | |||
420 | // floors | ||
421 | opb.write(floors-1,6); | ||
422 | for(int i=0;i<floors;i++){ | ||
423 | opb.write(floor_type[i],16); | ||
424 | FuncFloor.floor_P[floor_type[i]].pack(floor_param[i],opb); | ||
425 | } | ||
426 | |||
427 | // residues | ||
428 | opb.write(residues-1,6); | ||
429 | for(int i=0;i<residues;i++){ | ||
430 | opb.write(residue_type[i],16); | ||
431 | FuncResidue.residue_P[residue_type[i]].pack(residue_param[i],opb); | ||
432 | } | ||
433 | |||
434 | // maps | ||
435 | opb.write(maps-1,6); | ||
436 | for(int i=0;i<maps;i++){ | ||
437 | opb.write(map_type[i],16); | ||
438 | FuncMapping.mapping_P[map_type[i]].pack(this,map_param[i],opb); | ||
439 | } | ||
440 | |||
441 | // modes | ||
442 | opb.write(modes-1,6); | ||
443 | for(int i=0;i<modes;i++){ | ||
444 | opb.write(mode_param[i].blockflag,1); | ||
445 | opb.write(mode_param[i].windowtype,16); | ||
446 | opb.write(mode_param[i].transformtype,16); | ||
447 | opb.write(mode_param[i].mapping,8); | ||
448 | } | ||
449 | opb.write(1,1); | ||
450 | return(0); | ||
451 | //err_out: | ||
452 | //return(-1); | ||
453 | } | ||
454 | |||
455 | // static void v_writestring(Buffer o, byte[] s){ | ||
456 | // int i=0; | ||
457 | // while(s[i]!=0){ | ||
458 | // o.write(s[i++],8); | ||
459 | // } | ||
460 | // } | ||
461 | |||
462 | // static void v_readstring(Buffer o, byte[] buf, int bytes){ | ||
463 | // int i=0 | ||
464 | // while(bytes--!=0){ | ||
465 | // buf[i++]=o.read(8); | ||
466 | // } | ||
467 | // } | ||
468 | |||
469 | // private Buffer opb_blocksize=new Buffer(); | ||
470 | public int blocksize(Packet op){ | ||
471 | //codec_setup_info *ci=vi->codec_setup; | ||
472 | Buffer opb=new Buffer(); | ||
473 | // synchronized(opb_blocksize){ | ||
474 | int mode; | ||
475 | |||
476 | opb.readinit(op.packet_base, op.packet, op.bytes); | ||
477 | |||
478 | /* Check the packet type */ | ||
479 | if(opb.read(1)!=0){ | ||
480 | /* Oops. This is not an audio data packet */ | ||
481 | return(OV_ENOTAUDIO); | ||
482 | } | ||
483 | { | ||
484 | int modebits=0; | ||
485 | int v=modes; | ||
486 | while(v>1){ | ||
487 | modebits++; | ||
488 | v>>>=1; | ||
489 | } | ||
490 | |||
491 | /* read our mode and pre/post windowsize */ | ||
492 | mode=opb.read(modebits); | ||
493 | } | ||
494 | if(mode==-1)return(OV_EBADPACKET); | ||
495 | return(blocksizes[mode_param[mode].blockflag]); | ||
496 | // } | ||
497 | } | ||
498 | |||
499 | private static int ilog2(int v){ | ||
500 | int ret=0; | ||
501 | while(v>1){ | ||
502 | ret++; | ||
503 | v>>>=1; | ||
504 | } | ||
505 | return(ret); | ||
506 | } | ||
507 | |||
508 | public String toString(){ | ||
509 | return "version:"+new Integer(version)+ | ||
510 | ", channels:"+new Integer(channels)+ | ||
511 | ", rate:"+new Integer(rate)+ | ||
512 | ", bitrate:"+new Integer(bitrate_upper)+","+ | ||
513 | new Integer(bitrate_nominal)+","+ | ||
514 | new Integer(bitrate_lower); | ||
515 | } | ||
516 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/InfoMode.java b/songdbj/com/jcraft/jorbis/InfoMode.java new file mode 100644 index 0000000000..b570aa5c21 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/InfoMode.java | |||
@@ -0,0 +1,33 @@ | |||
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 | class InfoMode{ | ||
29 | int blockflag; | ||
30 | int windowtype; | ||
31 | int transformtype; | ||
32 | int mapping; | ||
33 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/JOrbisException.java b/songdbj/com/jcraft/jorbis/JOrbisException.java new file mode 100644 index 0000000000..ce09d4f9fc --- /dev/null +++ b/songdbj/com/jcraft/jorbis/JOrbisException.java | |||
@@ -0,0 +1,35 @@ | |||
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 | public class JOrbisException extends Exception { | ||
29 | public JOrbisException () { | ||
30 | super(); | ||
31 | } | ||
32 | public JOrbisException (String s) { | ||
33 | super ("JOrbis: "+s); | ||
34 | } | ||
35 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Lookup.java b/songdbj/com/jcraft/jorbis/Lookup.java new file mode 100644 index 0000000000..fb7651a19f --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Lookup.java | |||
@@ -0,0 +1,154 @@ | |||
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 | class Lookup{ | ||
29 | static final int COS_LOOKUP_SZ=128; | ||
30 | static final float[] COS_LOOKUP={ | ||
31 | +1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f, | ||
32 | +0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f, | ||
33 | +0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f, | ||
34 | +0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f, | ||
35 | +0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f, | ||
36 | +0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f, | ||
37 | +0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f, | ||
38 | +0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f, | ||
39 | +0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f, | ||
40 | +0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f, | ||
41 | +0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f, | ||
42 | +0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f, | ||
43 | +0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f, | ||
44 | +0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f, | ||
45 | +0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f, | ||
46 | +0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f, | ||
47 | +0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f, | ||
48 | -0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f, | ||
49 | -0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f, | ||
50 | -0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f, | ||
51 | -0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f, | ||
52 | -0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f, | ||
53 | -0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f, | ||
54 | -0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f, | ||
55 | -0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f, | ||
56 | -0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f, | ||
57 | -0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f, | ||
58 | -0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f, | ||
59 | -0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f, | ||
60 | -0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f, | ||
61 | -0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f, | ||
62 | -0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f, | ||
63 | -1.0000000000000f, | ||
64 | }; | ||
65 | /* interpolated lookup based cos function, domain 0 to PI only */ | ||
66 | static float coslook(float a){ | ||
67 | double d=a*(.31830989*(float)COS_LOOKUP_SZ); | ||
68 | int i=(int)d; | ||
69 | return COS_LOOKUP[i]+ ((float)(d-i))*(COS_LOOKUP[i+1]-COS_LOOKUP[i]); | ||
70 | } | ||
71 | |||
72 | static final int INVSQ_LOOKUP_SZ=32; | ||
73 | static final float[] INVSQ_LOOKUP={ | ||
74 | 1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f, | ||
75 | 1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f, | ||
76 | 1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f, | ||
77 | 1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f, | ||
78 | 1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f, | ||
79 | 1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f, | ||
80 | 1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f, | ||
81 | 1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f, | ||
82 | 1.000000000000f, | ||
83 | }; | ||
84 | /* interpolated 1./sqrt(p) where .5 <= p < 1. */ | ||
85 | static float invsqlook(float a){ | ||
86 | // System.out.println(a); | ||
87 | double d=a*(2.f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ; | ||
88 | int i=(int)d; | ||
89 | return INVSQ_LOOKUP[i]+ ((float)(d-i))*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]); | ||
90 | } | ||
91 | |||
92 | static final int INVSQ2EXP_LOOKUP_MIN=-32; | ||
93 | static final int INVSQ2EXP_LOOKUP_MAX=32; | ||
94 | static final float[] INVSQ2EXP_LOOKUP={ | ||
95 | 65536.f, 46340.95001f, 32768.f, 23170.47501f, | ||
96 | 16384.f, 11585.2375f, 8192.f, 5792.618751f, | ||
97 | 4096.f, 2896.309376f, 2048.f, 1448.154688f, | ||
98 | 1024.f, 724.0773439f, 512.f, 362.038672f, | ||
99 | 256.f, 181.019336f, 128.f, 90.50966799f, | ||
100 | 64.f, 45.254834f, 32.f, 22.627417f, | ||
101 | 16.f, 11.3137085f, 8.f, 5.656854249f, | ||
102 | 4.f, 2.828427125f, 2.f, 1.414213562f, | ||
103 | 1.f, 0.7071067812f, 0.5f, 0.3535533906f, | ||
104 | 0.25f, 0.1767766953f, 0.125f, 0.08838834765f, | ||
105 | 0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f, | ||
106 | 0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f, | ||
107 | 0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f, | ||
108 | 0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f, | ||
109 | 0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f, | ||
110 | 6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f, | ||
111 | 1.525878906e-05f, | ||
112 | }; | ||
113 | /* interpolated 1./sqrt(p) where .5 <= p < 1. */ | ||
114 | static float invsq2explook(int a){ | ||
115 | return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN]; | ||
116 | } | ||
117 | |||
118 | static final int FROMdB_LOOKUP_SZ=35; | ||
119 | static final int FROMdB2_LOOKUP_SZ=32; | ||
120 | static final int FROMdB_SHIFT=5; | ||
121 | static final int FROMdB2_SHIFT=3; | ||
122 | static final int FROMdB2_MASK=31; | ||
123 | static final float[] FROMdB_LOOKUP={ | ||
124 | 1.f, 0.6309573445f, 0.3981071706f, 0.2511886432f, | ||
125 | 0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f, | ||
126 | 0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f, | ||
127 | 0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f, | ||
128 | 0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f, | ||
129 | 0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f, | ||
130 | 1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f, | ||
131 | 2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f, | ||
132 | 3.981071706e-07f,2.511886432e-07f,1.584893192e-07f, | ||
133 | }; | ||
134 | static final float[] FROMdB2_LOOKUP={ | ||
135 | 0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f, | ||
136 | 0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f, | ||
137 | 0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f, | ||
138 | 0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f, | ||
139 | 0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f, | ||
140 | 0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f, | ||
141 | 0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f, | ||
142 | 0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f, | ||
143 | }; | ||
144 | /* interpolated lookup based fromdB function, domain -140dB to 0dB only */ | ||
145 | static float fromdBlook(float a){ | ||
146 | int i=(int)(a*((float)(-(1<<FROMdB2_SHIFT)))); | ||
147 | return (i<0)?1.f: | ||
148 | ((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f: | ||
149 | FROMdB_LOOKUP[i>>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]); | ||
150 | } | ||
151 | |||
152 | } | ||
153 | |||
154 | |||
diff --git a/songdbj/com/jcraft/jorbis/Lpc.java b/songdbj/com/jcraft/jorbis/Lpc.java new file mode 100644 index 0000000000..452ed86d91 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Lpc.java | |||
@@ -0,0 +1,254 @@ | |||
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 | class Lpc{ | ||
29 | // en/decode lookups | ||
30 | Drft fft=new Drft();; | ||
31 | |||
32 | int ln; | ||
33 | int m; | ||
34 | |||
35 | // Autocorrelation LPC coeff generation algorithm invented by | ||
36 | // N. Levinson in 1947, modified by J. Durbin in 1959. | ||
37 | |||
38 | // Input : n elements of time doamin data | ||
39 | // Output: m lpc coefficients, excitation energy | ||
40 | |||
41 | static float lpc_from_data(float[] data, float[] lpc,int n,int m){ | ||
42 | float[] aut=new float[m+1]; | ||
43 | float error; | ||
44 | int i,j; | ||
45 | |||
46 | // autocorrelation, p+1 lag coefficients | ||
47 | |||
48 | j=m+1; | ||
49 | while(j--!=0){ | ||
50 | float d=0; | ||
51 | for(i=j;i<n;i++)d+=data[i]*data[i-j]; | ||
52 | aut[j]=d; | ||
53 | } | ||
54 | |||
55 | // Generate lpc coefficients from autocorr values | ||
56 | |||
57 | error=aut[0]; | ||
58 | /* | ||
59 | if(error==0){ | ||
60 | for(int k=0; k<m; k++) lpc[k]=0.0f; | ||
61 | return 0; | ||
62 | } | ||
63 | */ | ||
64 | |||
65 | for(i=0;i<m;i++){ | ||
66 | float r=-aut[i+1]; | ||
67 | |||
68 | if(error==0){ | ||
69 | for(int k=0; k<m; k++) lpc[k]=0.0f; | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | // Sum up this iteration's reflection coefficient; note that in | ||
74 | // Vorbis we don't save it. If anyone wants to recycle this code | ||
75 | // and needs reflection coefficients, save the results of 'r' from | ||
76 | // each iteration. | ||
77 | |||
78 | for(j=0;j<i;j++)r-=lpc[j]*aut[i-j]; | ||
79 | r/=error; | ||
80 | |||
81 | // Update LPC coefficients and total error | ||
82 | |||
83 | lpc[i]=r; | ||
84 | for(j=0;j<i/2;j++){ | ||
85 | float tmp=lpc[j]; | ||
86 | lpc[j]+=r*lpc[i-1-j]; | ||
87 | lpc[i-1-j]+=r*tmp; | ||
88 | } | ||
89 | if(i%2!=0)lpc[j]+=lpc[j]*r; | ||
90 | |||
91 | error*=1.0-r*r; | ||
92 | } | ||
93 | |||
94 | // we need the error value to know how big an impulse to hit the | ||
95 | // filter with later | ||
96 | |||
97 | return error; | ||
98 | } | ||
99 | |||
100 | // Input : n element envelope spectral curve | ||
101 | // Output: m lpc coefficients, excitation energy | ||
102 | |||
103 | float lpc_from_curve(float[] curve, float[] lpc){ | ||
104 | int n=ln; | ||
105 | float[] work=new float[n+n]; | ||
106 | float fscale=(float)(.5/n); | ||
107 | int i,j; | ||
108 | |||
109 | // input is a real curve. make it complex-real | ||
110 | // This mixes phase, but the LPC generation doesn't care. | ||
111 | for(i=0;i<n;i++){ | ||
112 | work[i*2]=curve[i]*fscale; | ||
113 | work[i*2+1]=0; | ||
114 | } | ||
115 | work[n*2-1]=curve[n-1]*fscale; | ||
116 | |||
117 | n*=2; | ||
118 | fft.backward(work); | ||
119 | |||
120 | // The autocorrelation will not be circular. Shift, else we lose | ||
121 | // most of the power in the edges. | ||
122 | |||
123 | for(i=0,j=n/2;i<n/2;){ | ||
124 | float temp=work[i]; | ||
125 | work[i++]=work[j]; | ||
126 | work[j++]=temp; | ||
127 | } | ||
128 | |||
129 | return(lpc_from_data(work,lpc,n,m)); | ||
130 | } | ||
131 | |||
132 | void init(int mapped, int m){ | ||
133 | //memset(l,0,sizeof(lpc_lookup)); | ||
134 | |||
135 | ln=mapped; | ||
136 | this.m=m; | ||
137 | |||
138 | // we cheat decoding the LPC spectrum via FFTs | ||
139 | fft.init(mapped*2); | ||
140 | } | ||
141 | |||
142 | void clear(){ | ||
143 | fft.clear(); | ||
144 | } | ||
145 | |||
146 | static float FAST_HYPOT(float a, float b){ | ||
147 | return (float)Math.sqrt((a)*(a) + (b)*(b)); | ||
148 | } | ||
149 | |||
150 | // One can do this the long way by generating the transfer function in | ||
151 | // the time domain and taking the forward FFT of the result. The | ||
152 | // results from direct calculation are cleaner and faster. | ||
153 | // | ||
154 | // This version does a linear curve generation and then later | ||
155 | // interpolates the log curve from the linear curve. | ||
156 | |||
157 | void lpc_to_curve(float[] curve, float[] lpc, float amp){ | ||
158 | |||
159 | //memset(curve,0,sizeof(float)*l->ln*2); | ||
160 | for(int i=0; i<ln*2; i++)curve[i]=0.0f; | ||
161 | |||
162 | if(amp==0)return; | ||
163 | |||
164 | for(int i=0;i<m;i++){ | ||
165 | curve[i*2+1]=lpc[i]/(4*amp); | ||
166 | curve[i*2+2]=-lpc[i]/(4*amp); | ||
167 | } | ||
168 | |||
169 | fft.backward(curve); // reappropriated ;-) | ||
170 | |||
171 | { | ||
172 | int l2=ln*2; | ||
173 | float unit=(float)(1./amp); | ||
174 | curve[0]=(float)(1./(curve[0]*2+unit)); | ||
175 | for(int i=1;i<ln;i++){ | ||
176 | float real=(curve[i]+curve[l2-i]); | ||
177 | float imag=(curve[i]-curve[l2-i]); | ||
178 | |||
179 | float a = real + unit; | ||
180 | curve[i] = (float)(1.0 / FAST_HYPOT(a, imag)); | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | // subtract or add an lpc filter to data. Vorbis doesn't actually use this. | ||
187 | |||
188 | static void lpc_residue(float[] coeff, float[] prime,int m, | ||
189 | float[] data, int n){ | ||
190 | |||
191 | // in: coeff[0...m-1] LPC coefficients | ||
192 | // prime[0...m-1] initial values | ||
193 | // data[0...n-1] data samples | ||
194 | // out: data[0...n-1] residuals from LPC prediction | ||
195 | |||
196 | float[] work=new float[m+n]; | ||
197 | float y; | ||
198 | |||
199 | if(prime==null){ | ||
200 | for(int i=0;i<m;i++){ | ||
201 | work[i]=0; | ||
202 | } | ||
203 | } | ||
204 | else{ | ||
205 | for(int i=0;i<m;i++){ | ||
206 | work[i]=prime[i]; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | for(int i=0;i<n;i++){ | ||
211 | y=0; | ||
212 | for(int j=0;j<m;j++){ | ||
213 | y-=work[i+j]*coeff[m-j-1]; | ||
214 | } | ||
215 | work[i+m]=data[i]; | ||
216 | data[i]-=y; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static void lpc_predict(float[] coeff, float[] prime,int m, | ||
221 | float[] data, int n){ | ||
222 | |||
223 | // in: coeff[0...m-1] LPC coefficients | ||
224 | // prime[0...m-1] initial values (allocated size of n+m-1) | ||
225 | // data[0...n-1] residuals from LPC prediction | ||
226 | // out: data[0...n-1] data samples | ||
227 | |||
228 | int o,p; | ||
229 | float y; | ||
230 | float[] work=new float[m+n]; | ||
231 | |||
232 | if(prime==null){ | ||
233 | for(int i=0;i<m;i++){ | ||
234 | work[i]=0.f; | ||
235 | } | ||
236 | } | ||
237 | else{ | ||
238 | for(int i=0;i<m;i++){ | ||
239 | work[i]=prime[i]; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | for(int i=0;i<n;i++){ | ||
244 | y=data[i]; | ||
245 | o=i; | ||
246 | p=m; | ||
247 | for(int j=0;j<m;j++){ | ||
248 | y-=work[o++]*coeff[--p]; | ||
249 | } | ||
250 | data[i]=work[o]=y; | ||
251 | } | ||
252 | } | ||
253 | */ | ||
254 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Lsp.java b/songdbj/com/jcraft/jorbis/Lsp.java new file mode 100644 index 0000000000..550c7d62ee --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Lsp.java | |||
@@ -0,0 +1,111 @@ | |||
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 | /* | ||
29 | function: LSP (also called LSF) conversion routines | ||
30 | |||
31 | The LSP generation code is taken (with minimal modification) from | ||
32 | "On the Computation of the LSP Frequencies" by Joseph Rothweiler | ||
33 | <rothwlr@altavista.net>, available at: | ||
34 | |||
35 | http://www2.xtdl.com/~rothwlr/lsfpaper/lsfpage.html | ||
36 | ********************************************************************/ | ||
37 | |||
38 | class Lsp{ | ||
39 | |||
40 | static final float M_PI=(float)(3.1415926539); | ||
41 | |||
42 | static void lsp_to_curve(float[] curve, | ||
43 | int[] map, int n, int ln, | ||
44 | float[] lsp, int m, | ||
45 | float amp, float ampoffset){ | ||
46 | int i; | ||
47 | float wdel=M_PI/ln; | ||
48 | for(i=0;i<m;i++)lsp[i]=Lookup.coslook(lsp[i]); | ||
49 | int m2=(m/2)*2; | ||
50 | |||
51 | i=0; | ||
52 | while(i<n){ | ||
53 | int k=map[i]; | ||
54 | float p=.7071067812f; | ||
55 | float q=.7071067812f; | ||
56 | float w=Lookup.coslook(wdel*k); | ||
57 | int ftmp=0; | ||
58 | int c=m>>>1; | ||
59 | |||
60 | for(int j=0;j<m2;j+=2){ | ||
61 | q*=lsp[j]-w; | ||
62 | p*=lsp[j+1]-w; | ||
63 | } | ||
64 | |||
65 | if((m&1)!=0){ | ||
66 | /* odd order filter; slightly assymetric */ | ||
67 | /* the last coefficient */ | ||
68 | q*=lsp[m-1]-w; | ||
69 | q*=q; | ||
70 | p*=p*(1.f-w*w); | ||
71 | } | ||
72 | else{ | ||
73 | /* even order filter; still symmetric */ | ||
74 | q*=q*(1.f+w); | ||
75 | p*=p*(1.f-w); | ||
76 | } | ||
77 | |||
78 | // q=frexp(p+q,&qexp); | ||
79 | q=p+q; | ||
80 | int hx=Float.floatToIntBits(q); | ||
81 | int ix=0x7fffffff&hx; | ||
82 | int qexp=0; | ||
83 | |||
84 | if(ix>=0x7f800000||(ix==0)){ | ||
85 | // 0,inf,nan | ||
86 | } | ||
87 | else{ | ||
88 | if(ix<0x00800000){ // subnormal | ||
89 | q*=3.3554432000e+07; // 0x4c000000 | ||
90 | hx=Float.floatToIntBits(q); | ||
91 | ix=0x7fffffff&hx; | ||
92 | qexp=-25; | ||
93 | } | ||
94 | qexp += ((ix>>>23)-126); | ||
95 | hx=(hx&0x807fffff)|0x3f000000; | ||
96 | q=Float.intBitsToFloat(hx); | ||
97 | } | ||
98 | |||
99 | q=Lookup.fromdBlook(amp* | ||
100 | Lookup.invsqlook(q)* | ||
101 | Lookup.invsq2explook(qexp+m)-ampoffset); | ||
102 | |||
103 | do{curve[i++]*=q;} | ||
104 | // do{curve[i++]=q;} | ||
105 | while(i<n&&map[i]==k); | ||
106 | |||
107 | } | ||
108 | } | ||
109 | } | ||
110 | |||
111 | |||
diff --git a/songdbj/com/jcraft/jorbis/Mapping0.java b/songdbj/com/jcraft/jorbis/Mapping0.java new file mode 100644 index 0000000000..a2c3d06b5e --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Mapping0.java | |||
@@ -0,0 +1,566 @@ | |||
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 Mapping0 extends FuncMapping{ | ||
31 | static int seq=0; | ||
32 | void free_info(Object imap){}; | ||
33 | void free_look(Object imap){ | ||
34 | /* | ||
35 | LookMapping0 l=(LookMapping0)imap; | ||
36 | InfoMapping0 info=l.map; | ||
37 | if(l!=null){ | ||
38 | for(int i=0;i<l.map.submaps;i++){ | ||
39 | l.time_func[i].free_look(l.time_look[i]); | ||
40 | l.floor_func[i].free_look(l.floor_look[i]); | ||
41 | l.residue_func[i].free_look(l.residue_look[i]); | ||
42 | if(l.psy_look!=null)l.psy_look[i].clear(); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | if(l.floor_state!=null){ | ||
47 | for(int i=0;i<l.ch;i++) | ||
48 | l.floor_func[info.chmuxlist[i]].free_state(l.floor_state[i]); | ||
49 | //free(l.floor_state); | ||
50 | } | ||
51 | |||
52 | if(l.decay!=null){ | ||
53 | for(int i=0;i<l.ch;i++){ | ||
54 | //if(l.decay[i])free(l->decay[i]); | ||
55 | l.decay[i]=null; | ||
56 | } | ||
57 | //free(l->decay); | ||
58 | l.decay=null; | ||
59 | } | ||
60 | //free(l->time_func); | ||
61 | //free(l->floor_func); | ||
62 | //free(l->residue_func); | ||
63 | //free(l->time_look); | ||
64 | //free(l->floor_look); | ||
65 | //free(l->residue_look); | ||
66 | //f(l->psy_look)free(l->psy_look); | ||
67 | l.time_func=null; | ||
68 | l.floor_func=null; | ||
69 | l.residue_func=null; | ||
70 | l.time_look=null; | ||
71 | l.floor_look=null; | ||
72 | l.residue_look=null; | ||
73 | //memset(l,0,sizeof(vorbis_look_mapping0)); | ||
74 | //free(l); | ||
75 | */ | ||
76 | } | ||
77 | |||
78 | Object look(DspState vd, InfoMode vm, Object m){ | ||
79 | //System.err.println("Mapping0.look"); | ||
80 | Info vi=vd.vi; | ||
81 | LookMapping0 look=new LookMapping0(); | ||
82 | InfoMapping0 info=look.map=(InfoMapping0)m; | ||
83 | look.mode=vm; | ||
84 | |||
85 | look.time_look=new Object[info.submaps]; | ||
86 | look.floor_look=new Object[info.submaps]; | ||
87 | look.residue_look=new Object[info.submaps]; | ||
88 | |||
89 | /* | ||
90 | if(vd.analysisp!=0){ | ||
91 | look.floor_state=new Object[vi.channels]; | ||
92 | } | ||
93 | if(vi.psys!=0){ | ||
94 | look.psy_look=new PsyLook[info.submaps]; | ||
95 | for(int i=0; i<info.submaps; i++){ look.psy_look[i]=new PsyLook(); } | ||
96 | } | ||
97 | */ | ||
98 | |||
99 | look.time_func=new FuncTime[info.submaps]; | ||
100 | look.floor_func=new FuncFloor[info.submaps]; | ||
101 | look.residue_func=new FuncResidue[info.submaps]; | ||
102 | |||
103 | for(int i=0;i<info.submaps;i++){ | ||
104 | int timenum=info.timesubmap[i]; | ||
105 | int floornum=info.floorsubmap[i]; | ||
106 | int resnum=info.residuesubmap[i]; | ||
107 | |||
108 | look.time_func[i]=FuncTime.time_P[vi.time_type[timenum]]; | ||
109 | look.time_look[i]=look.time_func[i].look(vd,vm,vi.time_param[timenum]); | ||
110 | look.floor_func[i]=FuncFloor.floor_P[vi.floor_type[floornum]]; | ||
111 | look.floor_look[i]=look.floor_func[i]. | ||
112 | look(vd,vm,vi.floor_param[floornum]); | ||
113 | look.residue_func[i]=FuncResidue.residue_P[vi.residue_type[resnum]]; | ||
114 | look.residue_look[i]=look.residue_func[i]. | ||
115 | look(vd,vm,vi.residue_param[resnum]); | ||
116 | |||
117 | /* | ||
118 | if(vi.psys!=0 && vd.analysisp!=0){ | ||
119 | int psynum=info.psysubmap[i]; | ||
120 | look.psy_look[i].init(vi.psy_param[psynum], | ||
121 | vi.blocksizes[vm.blockflag]/2,vi.rate); | ||
122 | } | ||
123 | */ | ||
124 | } | ||
125 | |||
126 | if(vi.psys!=0 && vd.analysisp!=0){ | ||
127 | /* | ||
128 | if(info->psy[0] != info->psy[1]){ | ||
129 | |||
130 | int psynum=info->psy[0]; | ||
131 | look->psy_look[0]=_ogg_calloc(1,sizeof(vorbis_look_psy)); | ||
132 | _vp_psy_init(look->psy_look[0],ci->psy_param[psynum], | ||
133 | ci->psy_g_param, | ||
134 | ci->blocksizes[vm->blockflag]/2,vi->rate); | ||
135 | |||
136 | psynum=info->psy[1]; | ||
137 | look->psy_look[1]=_ogg_calloc(1,sizeof(vorbis_look_psy)); | ||
138 | _vp_psy_init(look->psy_look[1],ci->psy_param[psynum], | ||
139 | ci->psy_g_param, | ||
140 | ci->blocksizes[vm->blockflag]/2,vi->rate); | ||
141 | }else{ | ||
142 | |||
143 | int psynum=info->psy[0]; | ||
144 | look->psy_look[0]=_ogg_calloc(1,sizeof(vorbis_look_psy)); | ||
145 | look->psy_look[1]=look->psy_look[0]; | ||
146 | _vp_psy_init(look->psy_look[0],ci->psy_param[psynum], | ||
147 | ci->psy_g_param, | ||
148 | ci->blocksizes[vm->blockflag]/2,vi->rate); | ||
149 | |||
150 | } | ||
151 | */ | ||
152 | } | ||
153 | |||
154 | look.ch=vi.channels; | ||
155 | // if(vd->analysisp)drft_init(&look->fft_look,ci->blocksizes[vm->blockflag]); | ||
156 | |||
157 | return(look); | ||
158 | //return null; | ||
159 | } | ||
160 | |||
161 | void pack(Info vi, Object imap, Buffer opb){ | ||
162 | InfoMapping0 info=(InfoMapping0)imap; | ||
163 | |||
164 | /* another 'we meant to do it this way' hack... up to beta 4, we | ||
165 | packed 4 binary zeros here to signify one submapping in use. We | ||
166 | now redefine that to mean four bitflags that indicate use of | ||
167 | deeper features; bit0:submappings, bit1:coupling, | ||
168 | bit2,3:reserved. This is backward compatable with all actual uses | ||
169 | of the beta code. */ | ||
170 | |||
171 | if(info.submaps>1){ | ||
172 | opb.write(1,1); | ||
173 | opb.write(info.submaps-1,4); | ||
174 | } | ||
175 | else{ | ||
176 | opb.write(0,1); | ||
177 | } | ||
178 | |||
179 | if(info.coupling_steps>0){ | ||
180 | opb.write(1,1); | ||
181 | opb.write(info.coupling_steps-1,8); | ||
182 | for(int i=0;i<info.coupling_steps;i++){ | ||
183 | opb.write(info.coupling_mag[i],ilog2(vi.channels)); | ||
184 | opb.write(info.coupling_ang[i],ilog2(vi.channels)); | ||
185 | } | ||
186 | } | ||
187 | else{ | ||
188 | opb.write(0,1); | ||
189 | } | ||
190 | |||
191 | opb.write(0,2); /* 2,3:reserved */ | ||
192 | |||
193 | /* we don't write the channel submappings if we only have one... */ | ||
194 | if(info.submaps>1){ | ||
195 | for(int i=0;i<vi.channels;i++) | ||
196 | opb.write(info.chmuxlist[i],4); | ||
197 | } | ||
198 | for(int i=0;i<info.submaps;i++){ | ||
199 | opb.write(info.timesubmap[i],8); | ||
200 | opb.write(info.floorsubmap[i],8); | ||
201 | opb.write(info.residuesubmap[i],8); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | // also responsible for range checking | ||
206 | Object unpack(Info vi, Buffer opb){ | ||
207 | InfoMapping0 info=new InfoMapping0(); | ||
208 | |||
209 | // !!!! | ||
210 | if(opb.read(1)!=0){ | ||
211 | info.submaps=opb.read(4)+1; | ||
212 | } | ||
213 | else{ | ||
214 | info.submaps=1; | ||
215 | } | ||
216 | |||
217 | if(opb.read(1)!=0){ | ||
218 | info.coupling_steps=opb.read(8)+1; | ||
219 | |||
220 | for(int i=0;i<info.coupling_steps;i++){ | ||
221 | int testM=info.coupling_mag[i]=opb.read(ilog2(vi.channels)); | ||
222 | int testA=info.coupling_ang[i]=opb.read(ilog2(vi.channels)); | ||
223 | |||
224 | if(testM<0 || | ||
225 | testA<0 || | ||
226 | testM==testA || | ||
227 | testM>=vi.channels || | ||
228 | testA>=vi.channels){ | ||
229 | //goto err_out; | ||
230 | info.free(); | ||
231 | return(null); | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | |||
236 | if(opb.read(2)>0){ /* 2,3:reserved */ | ||
237 | //goto err_out; | ||
238 | info.free(); | ||
239 | return(null); | ||
240 | } | ||
241 | |||
242 | if(info.submaps>1){ | ||
243 | for(int i=0;i<vi.channels;i++){ | ||
244 | info.chmuxlist[i]=opb.read(4); | ||
245 | if(info.chmuxlist[i]>=info.submaps){ | ||
246 | //goto err_out; | ||
247 | info.free(); | ||
248 | return(null); | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | for(int i=0;i<info.submaps;i++){ | ||
254 | info.timesubmap[i]=opb.read(8); | ||
255 | if(info.timesubmap[i]>=vi.times){ | ||
256 | //goto err_out; | ||
257 | info.free(); | ||
258 | return(null); | ||
259 | } | ||
260 | info.floorsubmap[i]=opb.read(8); | ||
261 | if(info.floorsubmap[i]>=vi.floors){ | ||
262 | //goto err_out; | ||
263 | info.free(); | ||
264 | return(null); | ||
265 | } | ||
266 | info.residuesubmap[i]=opb.read(8); | ||
267 | if(info.residuesubmap[i]>=vi.residues){ | ||
268 | //goto err_out; | ||
269 | info.free(); | ||
270 | return(null); | ||
271 | } | ||
272 | } | ||
273 | return info; | ||
274 | //err_out: | ||
275 | //free_info(info); | ||
276 | //return(NULL); | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | // no time mapping implementation for now | ||
281 | static int seq=0; | ||
282 | int forward(Block vb, Object l){ | ||
283 | DspState vd=vb.vd; | ||
284 | Info vi=vd.vi; | ||
285 | LookMapping0 look=(LookMapping0)l; | ||
286 | InfoMapping0 info=look.map; | ||
287 | InfoMode mode=look.mode; | ||
288 | int n=vb.pcmend; | ||
289 | float[] window=vd.window[vb.W][vb.lW][vb.nW][mode.windowtype]; | ||
290 | |||
291 | float[][] pcmbundle=new float[vi.channles][]; | ||
292 | int[] nonzero=new int[vi.channels]; | ||
293 | |||
294 | // time domain pre-window: NONE IMPLEMENTED | ||
295 | |||
296 | // window the PCM data: takes PCM vector, vb; modifies PCM vector | ||
297 | |||
298 | for(int i=0;i<vi.channels;i++){ | ||
299 | float[] pcm=vb.pcm[i]; | ||
300 | for(int j=0;j<n;j++) | ||
301 | pcm[j]*=window[j]; | ||
302 | } | ||
303 | |||
304 | // time-domain post-window: NONE IMPLEMENTED | ||
305 | |||
306 | // transform the PCM data; takes PCM vector, vb; modifies PCM vector | ||
307 | // only MDCT right now.... | ||
308 | for(int i=0;i<vi.channels;i++){ | ||
309 | float[] pcm=vb.pcm[i]; | ||
310 | mdct_forward(vd.transform[vb.W][0],pcm,pcm); | ||
311 | } | ||
312 | |||
313 | { | ||
314 | float[] floor=_vorbis_block_alloc(vb,n*sizeof(float)/2); | ||
315 | |||
316 | for(int i=0;i<vi.channels;i++){ | ||
317 | float[] pcm=vb.pcm[i]; | ||
318 | float[] decay=look.decay[i]; | ||
319 | int submap=info.chmuxlist[i]; | ||
320 | |||
321 | // if some other mode/mapping was called last frame, our decay | ||
322 | // accumulator is out of date. Clear it. | ||
323 | //if(look.lastframe+1 != vb->sequence) | ||
324 | // memset(decay,0,n*sizeof(float)/2); | ||
325 | |||
326 | // perform psychoacoustics; do masking | ||
327 | _vp_compute_mask(look.psy_look[submap],pcm,floor,decay); | ||
328 | |||
329 | _analysis_output("mdct",seq,pcm,n/2,0,1); | ||
330 | _analysis_output("lmdct",seq,pcm,n/2,0,0); | ||
331 | _analysis_output("prefloor",seq,floor,n/2,0,1); | ||
332 | |||
333 | // perform floor encoding | ||
334 | nonzero[i]=look.floor_func[submap]. | ||
335 | forward(vb,look.floor_look[submap],floor,floor,look.floor_state[i]); | ||
336 | |||
337 | _analysis_output("floor",seq,floor,n/2,0,1); | ||
338 | |||
339 | // apply the floor, do optional noise levelling | ||
340 | _vp_apply_floor(look->psy_look+submap,pcm,floor); | ||
341 | |||
342 | _analysis_output("res",seq++,pcm,n/2,0,0); | ||
343 | } | ||
344 | |||
345 | // perform residue encoding with residue mapping; this is | ||
346 | // multiplexed. All the channels belonging to one submap are | ||
347 | // encoded (values interleaved), then the next submap, etc | ||
348 | |||
349 | for(int i=0;i<info.submaps;i++){ | ||
350 | int ch_in_bundle=0; | ||
351 | for(int j=0;j<vi.channels;j++){ | ||
352 | if(info.chmuxlist[j]==i && nonzero[j]==1){ | ||
353 | pcmbundle[ch_in_bundle++]=vb.pcm[j]; | ||
354 | } | ||
355 | } | ||
356 | look.residue_func[i].forward(vb,look.residue_look[i], pcmbundle,ch_in_bundle); | ||
357 | } | ||
358 | } | ||
359 | look.lastframe=vb.sequence; | ||
360 | return(0); | ||
361 | } | ||
362 | */ | ||
363 | |||
364 | float[][] pcmbundle=null; | ||
365 | int[] zerobundle=null; | ||
366 | int[] nonzero=null; | ||
367 | Object[] floormemo=null; | ||
368 | |||
369 | synchronized int inverse(Block vb, Object l){ | ||
370 | //System.err.println("Mapping0.inverse"); | ||
371 | DspState vd=vb.vd; | ||
372 | Info vi=vd.vi; | ||
373 | LookMapping0 look=(LookMapping0)l; | ||
374 | InfoMapping0 info=look.map; | ||
375 | InfoMode mode=look.mode; | ||
376 | int n=vb.pcmend=vi.blocksizes[vb.W]; | ||
377 | |||
378 | float[] window=vd.window[vb.W][vb.lW][vb.nW][mode.windowtype]; | ||
379 | // float[][] pcmbundle=new float[vi.channels][]; | ||
380 | // int[] nonzero=new int[vi.channels]; | ||
381 | if(pcmbundle==null || pcmbundle.length<vi.channels){ | ||
382 | pcmbundle=new float[vi.channels][]; | ||
383 | nonzero=new int[vi.channels]; | ||
384 | zerobundle=new int[vi.channels]; | ||
385 | floormemo=new Object[vi.channels]; | ||
386 | } | ||
387 | |||
388 | // time domain information decode (note that applying the | ||
389 | // information would have to happen later; we'll probably add a | ||
390 | // function entry to the harness for that later | ||
391 | // NOT IMPLEMENTED | ||
392 | |||
393 | // recover the spectral envelope; store it in the PCM vector for now | ||
394 | for(int i=0;i<vi.channels;i++){ | ||
395 | float[] pcm=vb.pcm[i]; | ||
396 | int submap=info.chmuxlist[i]; | ||
397 | |||
398 | floormemo[i]=look.floor_func[submap].inverse1(vb,look. | ||
399 | floor_look[submap], | ||
400 | floormemo[i] | ||
401 | ); | ||
402 | if(floormemo[i]!=null){ nonzero[i]=1; } | ||
403 | else{ nonzero[i]=0; } | ||
404 | for(int j=0; j<n/2; j++){ | ||
405 | pcm[j]=0; | ||
406 | } | ||
407 | |||
408 | //_analysis_output("ifloor",seq+i,pcm,n/2,0,1); | ||
409 | } | ||
410 | |||
411 | for(int i=0; i<info.coupling_steps; i++){ | ||
412 | if(nonzero[info.coupling_mag[i]]!=0 || | ||
413 | nonzero[info.coupling_ang[i]]!=0){ | ||
414 | nonzero[info.coupling_mag[i]]=1; | ||
415 | nonzero[info.coupling_ang[i]]=1; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | // recover the residue, apply directly to the spectral envelope | ||
420 | |||
421 | for(int i=0;i<info.submaps;i++){ | ||
422 | int ch_in_bundle=0; | ||
423 | for(int j=0;j<vi.channels;j++){ | ||
424 | if(info.chmuxlist[j]==i){ | ||
425 | if(nonzero[j]!=0){ | ||
426 | zerobundle[ch_in_bundle]=1; | ||
427 | } | ||
428 | else{ | ||
429 | zerobundle[ch_in_bundle]=0; | ||
430 | } | ||
431 | pcmbundle[ch_in_bundle++]=vb.pcm[j]; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | look.residue_func[i].inverse(vb,look.residue_look[i], | ||
436 | pcmbundle,zerobundle,ch_in_bundle); | ||
437 | } | ||
438 | |||
439 | |||
440 | for(int i=info.coupling_steps-1;i>=0;i--){ | ||
441 | float[] pcmM=vb.pcm[info.coupling_mag[i]]; | ||
442 | float[] pcmA=vb.pcm[info.coupling_ang[i]]; | ||
443 | |||
444 | for(int j=0;j<n/2;j++){ | ||
445 | float mag=pcmM[j]; | ||
446 | float ang=pcmA[j]; | ||
447 | |||
448 | if(mag>0){ | ||
449 | if(ang>0){ | ||
450 | pcmM[j]=mag; | ||
451 | pcmA[j]=mag-ang; | ||
452 | } | ||
453 | else{ | ||
454 | pcmA[j]=mag; | ||
455 | pcmM[j]=mag+ang; | ||
456 | } | ||
457 | } | ||
458 | else{ | ||
459 | if(ang>0){ | ||
460 | pcmM[j]=mag; | ||
461 | pcmA[j]=mag+ang; | ||
462 | } | ||
463 | else{ | ||
464 | pcmA[j]=mag; | ||
465 | pcmM[j]=mag-ang; | ||
466 | } | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | |||
471 | // /* compute and apply spectral envelope */ | ||
472 | |||
473 | for(int i=0;i<vi.channels;i++){ | ||
474 | float[] pcm=vb.pcm[i]; | ||
475 | int submap=info.chmuxlist[i]; | ||
476 | look.floor_func[submap].inverse2(vb,look.floor_look[submap],floormemo[i],pcm); | ||
477 | } | ||
478 | |||
479 | // transform the PCM data; takes PCM vector, vb; modifies PCM vector | ||
480 | // only MDCT right now.... | ||
481 | |||
482 | for(int i=0;i<vi.channels;i++){ | ||
483 | float[] pcm=vb.pcm[i]; | ||
484 | //_analysis_output("out",seq+i,pcm,n/2,0,0); | ||
485 | ((Mdct)vd.transform[vb.W][0]).backward(pcm,pcm); | ||
486 | } | ||
487 | |||
488 | // now apply the decoded pre-window time information | ||
489 | // NOT IMPLEMENTED | ||
490 | |||
491 | // window the data | ||
492 | for(int i=0;i<vi.channels;i++){ | ||
493 | float[] pcm=vb.pcm[i]; | ||
494 | if(nonzero[i]!=0){ | ||
495 | for(int j=0;j<n;j++){ | ||
496 | pcm[j]*=window[j]; | ||
497 | } | ||
498 | } | ||
499 | else{ | ||
500 | for(int j=0;j<n;j++){ | ||
501 | pcm[j]=0.f; | ||
502 | } | ||
503 | } | ||
504 | //_analysis_output("final",seq++,pcm,n,0,0); | ||
505 | } | ||
506 | |||
507 | // now apply the decoded post-window time information | ||
508 | // NOT IMPLEMENTED | ||
509 | // all done! | ||
510 | return(0); | ||
511 | } | ||
512 | |||
513 | |||
514 | private static int ilog2(int v){ | ||
515 | int ret=0; | ||
516 | while(v>1){ | ||
517 | ret++; | ||
518 | v>>>=1; | ||
519 | } | ||
520 | return(ret); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | class InfoMapping0{ | ||
525 | int submaps; // <= 16 | ||
526 | int[] chmuxlist=new int[256]; // up to 256 channels in a Vorbis stream | ||
527 | |||
528 | int[] timesubmap=new int[16]; // [mux] | ||
529 | int[] floorsubmap=new int[16]; // [mux] submap to floors | ||
530 | int[] residuesubmap=new int[16];// [mux] submap to residue | ||
531 | int[] psysubmap=new int[16]; // [mux]; encode only | ||
532 | |||
533 | int coupling_steps; | ||
534 | int[] coupling_mag=new int[256]; | ||
535 | int[] coupling_ang=new int[256]; | ||
536 | |||
537 | void free(){ | ||
538 | chmuxlist=null; | ||
539 | timesubmap=null; | ||
540 | floorsubmap=null; | ||
541 | residuesubmap=null; | ||
542 | psysubmap=null; | ||
543 | |||
544 | coupling_mag=null; | ||
545 | coupling_ang=null; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | class LookMapping0{ | ||
550 | InfoMode mode; | ||
551 | InfoMapping0 map; | ||
552 | Object[] time_look; | ||
553 | Object[] floor_look; | ||
554 | Object[] floor_state; | ||
555 | Object[] residue_look; | ||
556 | PsyLook[] psy_look; | ||
557 | |||
558 | FuncTime[] time_func; | ||
559 | FuncFloor[] floor_func; | ||
560 | FuncResidue[] residue_func; | ||
561 | |||
562 | int ch; | ||
563 | float[][] decay; | ||
564 | int lastframe; // if a different mode is called, we need to | ||
565 | // invalidate decay and floor state | ||
566 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Mdct.java b/songdbj/com/jcraft/jorbis/Mdct.java new file mode 100644 index 0000000000..bd5cc38fb7 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Mdct.java | |||
@@ -0,0 +1,249 @@ | |||
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 | class Mdct{ | ||
29 | |||
30 | static private final float cPI3_8=0.38268343236508977175f; | ||
31 | static private final float cPI2_8=0.70710678118654752441f; | ||
32 | static private final float cPI1_8=0.92387953251128675613f; | ||
33 | |||
34 | int n; | ||
35 | int log2n; | ||
36 | |||
37 | float[] trig; | ||
38 | int[] bitrev; | ||
39 | |||
40 | float scale; | ||
41 | |||
42 | void init(int n){ | ||
43 | bitrev=new int[n/4]; | ||
44 | trig=new float[n+n/4]; | ||
45 | |||
46 | int n2=n>>>1; | ||
47 | log2n=(int)Math.rint(Math.log(n)/Math.log(2)); | ||
48 | this.n=n; | ||
49 | |||
50 | |||
51 | int AE=0; | ||
52 | int AO=1; | ||
53 | int BE=AE+n/2; | ||
54 | int BO=BE+1; | ||
55 | int CE=BE+n/2; | ||
56 | int CO=CE+1; | ||
57 | // trig lookups... | ||
58 | for(int i=0;i<n/4;i++){ | ||
59 | trig[AE+i*2]=(float)Math.cos((Math.PI/n)*(4*i)); | ||
60 | trig[AO+i*2]=(float)-Math.sin((Math.PI/n)*(4*i)); | ||
61 | trig[BE+i*2]=(float)Math.cos((Math.PI/(2*n))*(2*i+1)); | ||
62 | trig[BO+i*2]=(float)Math.sin((Math.PI/(2*n))*(2*i+1)); | ||
63 | } | ||
64 | for(int i=0;i<n/8;i++){ | ||
65 | trig[CE+i*2]=(float)Math.cos((Math.PI/n)*(4*i+2)); | ||
66 | trig[CO+i*2]=(float)-Math.sin((Math.PI/n)*(4*i+2)); | ||
67 | } | ||
68 | |||
69 | { | ||
70 | int mask=(1<<(log2n-1))-1; | ||
71 | int msb=1<<(log2n-2); | ||
72 | for(int i=0;i<n/8;i++){ | ||
73 | int acc=0; | ||
74 | for(int j=0;msb>>>j!=0;j++) | ||
75 | if(((msb>>>j)&i)!=0)acc|=1<<j; | ||
76 | bitrev[i*2]=((~acc)&mask); | ||
77 | // bitrev[i*2]=((~acc)&mask)-1; | ||
78 | bitrev[i*2+1]=acc; | ||
79 | } | ||
80 | } | ||
81 | scale=4.f/n; | ||
82 | } | ||
83 | |||
84 | void clear(){ | ||
85 | } | ||
86 | |||
87 | void forward(float[] in, float[] out){ | ||
88 | } | ||
89 | |||
90 | float[] _x=new float[1024]; | ||
91 | float[] _w=new float[1024]; | ||
92 | |||
93 | synchronized void backward(float[] in, float[] out){ | ||
94 | if(_x.length<n/2){_x=new float[n/2];} | ||
95 | if(_w.length<n/2){_w=new float[n/2];} | ||
96 | float[] x=_x; | ||
97 | float[] w=_w; | ||
98 | int n2=n>>>1; | ||
99 | int n4=n>>>2; | ||
100 | int n8=n>>>3; | ||
101 | |||
102 | // rotate + step 1 | ||
103 | { | ||
104 | int inO=1; | ||
105 | int xO=0; | ||
106 | int A=n2; | ||
107 | |||
108 | int i; | ||
109 | for(i=0;i<n8;i++){ | ||
110 | A-=2; | ||
111 | x[xO++]=-in[inO+2]*trig[A+1] - in[inO]*trig[A]; | ||
112 | x[xO++]= in[inO]*trig[A+1] - in[inO+2]*trig[A]; | ||
113 | inO+=4; | ||
114 | } | ||
115 | |||
116 | inO=n2-4; | ||
117 | |||
118 | for(i=0;i<n8;i++){ | ||
119 | A-=2; | ||
120 | x[xO++]=in[inO]*trig[A+1] + in[inO+2]*trig[A]; | ||
121 | x[xO++]=in[inO]*trig[A] - in[inO+2]*trig[A+1]; | ||
122 | inO-=4; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | float[] xxx=mdct_kernel(x,w,n,n2,n4,n8); | ||
127 | int xx=0; | ||
128 | |||
129 | // step 8 | ||
130 | |||
131 | { | ||
132 | int B=n2; | ||
133 | int o1=n4,o2=o1-1; | ||
134 | int o3=n4+n2,o4=o3-1; | ||
135 | |||
136 | for(int i=0;i<n4;i++){ | ||
137 | float temp1= (xxx[xx] * trig[B+1] - xxx[xx+1] * trig[B]); | ||
138 | float temp2=-(xxx[xx] * trig[B] + xxx[xx+1] * trig[B+1]); | ||
139 | |||
140 | out[o1]=-temp1; | ||
141 | out[o2]= temp1; | ||
142 | out[o3]= temp2; | ||
143 | out[o4]= temp2; | ||
144 | |||
145 | o1++; | ||
146 | o2--; | ||
147 | o3++; | ||
148 | o4--; | ||
149 | xx+=2; | ||
150 | B+=2; | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | private float[] mdct_kernel(float[] x, float[] w, | ||
155 | int n, int n2, int n4, int n8){ | ||
156 | // step 2 | ||
157 | |||
158 | int xA=n4; | ||
159 | int xB=0; | ||
160 | int w2=n4; | ||
161 | int A=n2; | ||
162 | |||
163 | for(int i=0;i<n4;){ | ||
164 | float x0=x[xA] - x[xB]; | ||
165 | float x1; | ||
166 | w[w2+i]=x[xA++]+x[xB++]; | ||
167 | |||
168 | x1=x[xA]-x[xB]; | ||
169 | A-=4; | ||
170 | |||
171 | w[i++]= x0 * trig[A] + x1 * trig[A+1]; | ||
172 | w[i]= x1 * trig[A] - x0 * trig[A+1]; | ||
173 | |||
174 | w[w2+i]=x[xA++]+x[xB++]; | ||
175 | i++; | ||
176 | } | ||
177 | |||
178 | // step 3 | ||
179 | |||
180 | { | ||
181 | for(int i=0;i<log2n-3;i++){ | ||
182 | int k0=n>>>(i+2); | ||
183 | int k1=1<<(i+3); | ||
184 | int wbase=n2-2; | ||
185 | |||
186 | A=0; | ||
187 | float[] temp; | ||
188 | |||
189 | for(int r=0;r<(k0>>>2);r++){ | ||
190 | int w1=wbase; | ||
191 | w2=w1-(k0>>1); | ||
192 | float AEv= trig[A],wA; | ||
193 | float AOv= trig[A+1],wB; | ||
194 | wbase-=2; | ||
195 | |||
196 | k0++; | ||
197 | for(int s=0;s<(2<<i);s++){ | ||
198 | wB =w[w1] -w[w2]; | ||
199 | x[w1] =w[w1] +w[w2]; | ||
200 | |||
201 | wA =w[++w1] -w[++w2]; | ||
202 | x[w1] =w[w1] +w[w2]; | ||
203 | |||
204 | x[w2] =wA*AEv - wB*AOv; | ||
205 | x[w2-1]=wB*AEv + wA*AOv; | ||
206 | |||
207 | w1-=k0; | ||
208 | w2-=k0; | ||
209 | } | ||
210 | k0--; | ||
211 | A+=k1; | ||
212 | } | ||
213 | |||
214 | temp=w; | ||
215 | w=x; | ||
216 | x=temp; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | // step 4, 5, 6, 7 | ||
221 | { | ||
222 | int C=n; | ||
223 | int bit=0; | ||
224 | int x1=0; | ||
225 | int x2=n2-1; | ||
226 | |||
227 | for(int i=0;i<n8;i++){ | ||
228 | int t1=bitrev[bit++]; | ||
229 | int t2=bitrev[bit++]; | ||
230 | |||
231 | float wA=w[t1]-w[t2+1]; | ||
232 | float wB=w[t1-1]+w[t2]; | ||
233 | float wC=w[t1]+w[t2+1]; | ||
234 | float wD=w[t1-1]-w[t2]; | ||
235 | |||
236 | float wACE=wA* trig[C]; | ||
237 | float wBCE=wB* trig[C++]; | ||
238 | float wACO=wA* trig[C]; | ||
239 | float wBCO=wB* trig[C++]; | ||
240 | |||
241 | x[x1++]=( wC+wACO+wBCE)*.5f; | ||
242 | x[x2--]=(-wD+wBCO-wACE)*.5f; | ||
243 | x[x1++]=( wD+wBCO-wACE)*.5f; | ||
244 | x[x2--]=( wC-wACO-wBCE)*.5f; | ||
245 | } | ||
246 | } | ||
247 | return(x); | ||
248 | } | ||
249 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/PsyInfo.java b/songdbj/com/jcraft/jorbis/PsyInfo.java new file mode 100644 index 0000000000..599c41e52d --- /dev/null +++ b/songdbj/com/jcraft/jorbis/PsyInfo.java | |||
@@ -0,0 +1,72 @@ | |||
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 | // psychoacoustic setup | ||
29 | class PsyInfo{ | ||
30 | int athp; | ||
31 | int decayp; | ||
32 | int smoothp; | ||
33 | int noisefitp; | ||
34 | int noisefit_subblock; | ||
35 | float noisefit_threshdB; | ||
36 | |||
37 | float ath_att; | ||
38 | |||
39 | int tonemaskp; | ||
40 | float[] toneatt_125Hz=new float[5]; | ||
41 | float[] toneatt_250Hz=new float[5]; | ||
42 | float[] toneatt_500Hz=new float[5]; | ||
43 | float[] toneatt_1000Hz=new float[5]; | ||
44 | float[] toneatt_2000Hz=new float[5]; | ||
45 | float[] toneatt_4000Hz=new float[5]; | ||
46 | float[] toneatt_8000Hz=new float[5]; | ||
47 | |||
48 | int peakattp; | ||
49 | float[] peakatt_125Hz=new float[5]; | ||
50 | float[] peakatt_250Hz=new float[5]; | ||
51 | float[] peakatt_500Hz=new float[5]; | ||
52 | float[] peakatt_1000Hz=new float[5]; | ||
53 | float[] peakatt_2000Hz=new float[5]; | ||
54 | float[] peakatt_4000Hz=new float[5]; | ||
55 | float[] peakatt_8000Hz=new float[5]; | ||
56 | |||
57 | int noisemaskp; | ||
58 | float[] noiseatt_125Hz=new float[5]; | ||
59 | float[] noiseatt_250Hz=new float[5]; | ||
60 | float[] noiseatt_500Hz=new float[5]; | ||
61 | float[] noiseatt_1000Hz=new float[5]; | ||
62 | float[] noiseatt_2000Hz=new float[5]; | ||
63 | float[] noiseatt_4000Hz=new float[5]; | ||
64 | float[] noiseatt_8000Hz=new float[5]; | ||
65 | |||
66 | float max_curve_dB; | ||
67 | |||
68 | float attack_coeff; | ||
69 | float decay_coeff; | ||
70 | |||
71 | void free(){} | ||
72 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/PsyLook.java b/songdbj/com/jcraft/jorbis/PsyLook.java new file mode 100644 index 0000000000..9da85edfb1 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/PsyLook.java | |||
@@ -0,0 +1,187 @@ | |||
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 | class PsyLook { | ||
29 | int n; | ||
30 | PsyInfo vi; | ||
31 | |||
32 | float[][][] tonecurves; | ||
33 | float[][] peakatt; | ||
34 | float[][][] noisecurves; | ||
35 | |||
36 | float[] ath; | ||
37 | int[] octave; | ||
38 | |||
39 | void init(PsyInfo vi, int n, int rate){ | ||
40 | /* | ||
41 | float rate2=rate/2.; | ||
42 | //memset(p,0,sizeof(vorbis_look_psy)); | ||
43 | ath=new float[n]; | ||
44 | octave=new int[n]; | ||
45 | this.vi=vi; | ||
46 | this.n=n; | ||
47 | |||
48 | // set up the lookups for a given blocksize and sample rate | ||
49 | // Vorbis max sample rate is limited by 26 Bark (54kHz) | ||
50 | set_curve(ATH_Bark_dB, ath,n,rate); | ||
51 | for(int i=0;i<n;i++) | ||
52 | ath[i]=fromdB(ath[i]+vi.ath_att); | ||
53 | |||
54 | for(int i=0;i<n;i++){ | ||
55 | int oc=rint(toOC((i+.5)*rate2/n)*2.); | ||
56 | if(oc<0)oc=0; | ||
57 | if(oc>12)oc=12; | ||
58 | octave[i]=oc; | ||
59 | } | ||
60 | |||
61 | tonecurves=malloc(13*sizeof(float **)); | ||
62 | noisecurves=malloc(13*sizeof(float **)); | ||
63 | peakatt=malloc(7*sizeof(float *)); | ||
64 | for(int i=0;i<13;i++){ | ||
65 | tonecurves[i]=malloc(9*sizeof(float *)); | ||
66 | noisecurves[i]=malloc(9*sizeof(float *)); | ||
67 | } | ||
68 | for(i=0;i<7;i++) | ||
69 | peakatt[i]=malloc(5*sizeof(float)); | ||
70 | |||
71 | for(i=0;i<13;i++){ | ||
72 | for(j=0;j<9;j++){ | ||
73 | tonecurves[i][j]=malloc(EHMER_MAX*sizeof(float)); | ||
74 | noisecurves[i][j]=malloc(EHMER_MAX*sizeof(float)); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // OK, yeah, this was a silly way to do it | ||
79 | memcpy(tonecurves[0][2],tone_125_80dB_SL,sizeof(float)*EHMER_MAX); | ||
80 | memcpy(tonecurves[0][4],tone_125_80dB_SL,sizeof(float)*EHMER_MAX); | ||
81 | memcpy(tonecurves[0][6],tone_125_80dB_SL,sizeof(float)*EHMER_MAX); | ||
82 | memcpy(tonecurves[0][8],tone_125_100dB_SL,sizeof(float)*EHMER_MAX); | ||
83 | |||
84 | memcpy(tonecurves[2][2],tone_250_40dB_SL,sizeof(float)*EHMER_MAX); | ||
85 | memcpy(tonecurves[2][4],tone_250_60dB_SL,sizeof(float)*EHMER_MAX); | ||
86 | memcpy(tonecurves[2][6],tone_250_80dB_SL,sizeof(float)*EHMER_MAX); | ||
87 | memcpy(tonecurves[2][8],tone_250_80dB_SL,sizeof(float)*EHMER_MAX); | ||
88 | |||
89 | memcpy(tonecurves[4][2],tone_500_40dB_SL,sizeof(float)*EHMER_MAX); | ||
90 | memcpy(tonecurves[4][4],tone_500_60dB_SL,sizeof(float)*EHMER_MAX); | ||
91 | memcpy(tonecurves[4][6],tone_500_80dB_SL,sizeof(float)*EHMER_MAX); | ||
92 | memcpy(tonecurves[4][8],tone_500_100dB_SL,sizeof(float)*EHMER_MAX); | ||
93 | |||
94 | memcpy(tonecurves[6][2],tone_1000_40dB_SL,sizeof(float)*EHMER_MAX); | ||
95 | memcpy(tonecurves[6][4],tone_1000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
96 | memcpy(tonecurves[6][6],tone_1000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
97 | memcpy(tonecurves[6][8],tone_1000_100dB_SL,sizeof(float)*EHMER_MAX); | ||
98 | |||
99 | memcpy(tonecurves[8][2],tone_2000_40dB_SL,sizeof(float)*EHMER_MAX); | ||
100 | memcpy(tonecurves[8][4],tone_2000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
101 | memcpy(tonecurves[8][6],tone_2000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
102 | memcpy(tonecurves[8][8],tone_2000_100dB_SL,sizeof(float)*EHMER_MAX); | ||
103 | |||
104 | memcpy(tonecurves[10][2],tone_4000_40dB_SL,sizeof(float)*EHMER_MAX); | ||
105 | memcpy(tonecurves[10][4],tone_4000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
106 | memcpy(tonecurves[10][6],tone_4000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
107 | memcpy(tonecurves[10][8],tone_4000_100dB_SL,sizeof(float)*EHMER_MAX); | ||
108 | |||
109 | memcpy(tonecurves[12][2],tone_4000_40dB_SL,sizeof(float)*EHMER_MAX); | ||
110 | memcpy(tonecurves[12][4],tone_4000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
111 | memcpy(tonecurves[12][6],tone_8000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
112 | memcpy(tonecurves[12][8],tone_8000_100dB_SL,sizeof(float)*EHMER_MAX); | ||
113 | |||
114 | |||
115 | memcpy(noisecurves[0][2],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); | ||
116 | memcpy(noisecurves[0][4],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); | ||
117 | memcpy(noisecurves[0][6],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); | ||
118 | memcpy(noisecurves[0][8],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); | ||
119 | |||
120 | memcpy(noisecurves[2][2],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); | ||
121 | memcpy(noisecurves[2][4],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); | ||
122 | memcpy(noisecurves[2][6],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); | ||
123 | memcpy(noisecurves[2][8],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); | ||
124 | |||
125 | memcpy(noisecurves[4][2],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); | ||
126 | memcpy(noisecurves[4][4],noise_500_60dB_SL,sizeof(float)*EHMER_MAX); | ||
127 | memcpy(noisecurves[4][6],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); | ||
128 | memcpy(noisecurves[4][8],noise_500_80dB_SL,sizeof(float)*EHMER_MAX); | ||
129 | |||
130 | memcpy(noisecurves[6][2],noise_1000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
131 | memcpy(noisecurves[6][4],noise_1000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
132 | memcpy(noisecurves[6][6],noise_1000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
133 | memcpy(noisecurves[6][8],noise_1000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
134 | |||
135 | memcpy(noisecurves[8][2],noise_2000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
136 | memcpy(noisecurves[8][4],noise_2000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
137 | memcpy(noisecurves[8][6],noise_2000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
138 | memcpy(noisecurves[8][8],noise_2000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
139 | |||
140 | memcpy(noisecurves[10][2],noise_4000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
141 | memcpy(noisecurves[10][4],noise_4000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
142 | memcpy(noisecurves[10][6],noise_4000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
143 | memcpy(noisecurves[10][8],noise_4000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
144 | |||
145 | memcpy(noisecurves[12][2],noise_4000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
146 | memcpy(noisecurves[12][4],noise_4000_60dB_SL,sizeof(float)*EHMER_MAX); | ||
147 | memcpy(noisecurves[12][6],noise_4000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
148 | memcpy(noisecurves[12][8],noise_4000_80dB_SL,sizeof(float)*EHMER_MAX); | ||
149 | |||
150 | setup_curve(tonecurves[0],0,vi.toneatt_125Hz); | ||
151 | setup_curve(tonecurves[2],2,vi.toneatt_250Hz); | ||
152 | setup_curve(tonecurves[4],4,vi.toneatt_500Hz); | ||
153 | setup_curve(tonecurves[6],6,vi.toneatt_1000Hz); | ||
154 | setup_curve(tonecurves[8],8,vi.toneatt_2000Hz); | ||
155 | setup_curve(tonecurves[10],10,vi.toneatt_4000Hz); | ||
156 | setup_curve(tonecurves[12],12,vi.toneatt_8000Hz); | ||
157 | |||
158 | setup_curve(noisecurves[0],0,vi.noiseatt_125Hz); | ||
159 | setup_curve(noisecurves[2],2,vi.noiseatt_250Hz); | ||
160 | setup_curve(noisecurves[4],4,vi.noiseatt_500Hz); | ||
161 | setup_curve(noisecurves[6],6,vi.noiseatt_1000Hz); | ||
162 | setup_curve(noisecurves[8],8,vi.noiseatt_2000Hz); | ||
163 | setup_curve(noisecurves[10],10,vi.noiseatt_4000Hz); | ||
164 | setup_curve(noisecurves[12],12,vi.noiseatt_8000Hz); | ||
165 | |||
166 | for(i=1;i<13;i+=2){ | ||
167 | for(j=0;j<9;j++){ | ||
168 | interp_curve_dB(tonecurves[i][j], | ||
169 | tonecurves[i-1][j], | ||
170 | tonecurves[i+1][j],.5); | ||
171 | interp_curve_dB(noisecurves[i][j], | ||
172 | noisecurves[i-1][j], | ||
173 | noisecurves[i+1][j],.5); | ||
174 | } | ||
175 | } | ||
176 | for(i=0;i<5;i++){ | ||
177 | peakatt[0][i]=fromdB(vi.peakatt_125Hz[i]); | ||
178 | peakatt[1][i]=fromdB(vi.peakatt_250Hz[i]); | ||
179 | peakatt[2][i]=fromdB(vi.peakatt_500Hz[i]); | ||
180 | peakatt[3][i]=fromdB(vi.peakatt_1000Hz[i]); | ||
181 | peakatt[4][i]=fromdB(vi.peakatt_2000Hz[i]); | ||
182 | peakatt[5][i]=fromdB(vi.peakatt_4000Hz[i]); | ||
183 | peakatt[6][i]=fromdB(vi.peakatt_8000Hz[i]); | ||
184 | } | ||
185 | */ | ||
186 | } | ||
187 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Residue0.java b/songdbj/com/jcraft/jorbis/Residue0.java new file mode 100644 index 0000000000..be42518f1c --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Residue0.java | |||
@@ -0,0 +1,454 @@ | |||
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 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Residue1.java b/songdbj/com/jcraft/jorbis/Residue1.java new file mode 100644 index 0000000000..c29ed8d671 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Residue1.java | |||
@@ -0,0 +1,51 @@ | |||
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 Residue1 extends Residue0{ | ||
31 | int forward(Block vb,Object vl, float[][] in, int ch){ | ||
32 | System.err.println("Residue0.forward: not implemented"); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | int inverse(Block vb, Object vl, float[][] in, int[] nonzero, int ch){ | ||
37 | //System.err.println("Residue0.inverse"); | ||
38 | int used=0; | ||
39 | for(int i=0; i<ch; i++){ | ||
40 | if(nonzero[i]!=0){ | ||
41 | in[used++]=in[i]; | ||
42 | } | ||
43 | } | ||
44 | if(used!=0){ | ||
45 | return(_01inverse(vb,vl,in,used,1)); | ||
46 | } | ||
47 | else{ | ||
48 | return 0; | ||
49 | } | ||
50 | } | ||
51 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/Residue2.java b/songdbj/com/jcraft/jorbis/Residue2.java new file mode 100644 index 0000000000..146a8341e5 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Residue2.java | |||
@@ -0,0 +1,44 @@ | |||
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 Residue2 extends Residue0{ | ||
31 | int forward(Block vb,Object vl, float[][] in, int ch){ | ||
32 | System.err.println("Residue0.forward: not implemented"); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | int inverse(Block vb, Object vl, float[][] in, int[] nonzero, int ch){ | ||
37 | //System.err.println("Residue0.inverse"); | ||
38 | int i=0; | ||
39 | for(i=0;i<ch;i++)if(nonzero[i]!=0)break; | ||
40 | if(i==ch)return(0); /* no nonzero vectors */ | ||
41 | |||
42 | return(_2inverse(vb,vl,in, ch)); | ||
43 | } | ||
44 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/StaticCodeBook.java b/songdbj/com/jcraft/jorbis/StaticCodeBook.java new file mode 100644 index 0000000000..7d9d6dc232 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/StaticCodeBook.java | |||
@@ -0,0 +1,588 @@ | |||
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 StaticCodeBook{ | ||
31 | int dim; // codebook dimensions (elements per vector) | ||
32 | int entries; // codebook entries | ||
33 | int[] lengthlist; // codeword lengths in bits | ||
34 | |||
35 | // mapping | ||
36 | int maptype; // 0=none | ||
37 | // 1=implicitly populated values from map column | ||
38 | // 2=listed arbitrary values | ||
39 | |||
40 | // The below does a linear, single monotonic sequence mapping. | ||
41 | int q_min; // packed 32 bit float; quant value 0 maps to minval | ||
42 | int q_delta; // packed 32 bit float; val 1 - val 0 == delta | ||
43 | int q_quant; // bits: 0 < quant <= 16 | ||
44 | int q_sequencep; // bitflag | ||
45 | |||
46 | // additional information for log (dB) mapping; the linear mapping | ||
47 | // is assumed to actually be values in dB. encodebias is used to | ||
48 | // assign an error weight to 0 dB. We have two additional flags: | ||
49 | // zeroflag indicates if entry zero is to represent -Inf dB; negflag | ||
50 | // indicates if we're to represent negative linear values in a | ||
51 | // mirror of the positive mapping. | ||
52 | |||
53 | int[] quantlist; // map == 1: (int)(entries/dim) element column map | ||
54 | // map == 2: list of dim*entries quantized entry vals | ||
55 | |||
56 | // encode helpers | ||
57 | EncodeAuxNearestMatch nearest_tree; | ||
58 | EncodeAuxThreshMatch thresh_tree; | ||
59 | |||
60 | StaticCodeBook(){} | ||
61 | StaticCodeBook(int dim, int entries, int[] lengthlist, | ||
62 | int maptype, int q_min, int q_delta, | ||
63 | int q_quant, int q_sequencep, int[] quantlist, | ||
64 | //EncodeAuxNearestmatch nearest_tree, | ||
65 | Object nearest_tree, | ||
66 | // EncodeAuxThreshmatch thresh_tree, | ||
67 | Object thresh_tree | ||
68 | ){ | ||
69 | this(); | ||
70 | this.dim=dim; this.entries=entries; this.lengthlist=lengthlist; | ||
71 | this.maptype=maptype; this.q_min=q_min; this.q_delta=q_delta; | ||
72 | this.q_quant=q_quant; this.q_sequencep=q_sequencep; | ||
73 | this.quantlist=quantlist; | ||
74 | } | ||
75 | |||
76 | int pack(Buffer opb){ | ||
77 | int i; | ||
78 | boolean ordered=false; | ||
79 | |||
80 | opb.write(0x564342,24); | ||
81 | opb.write(dim, 16); | ||
82 | opb.write(entries, 24); | ||
83 | |||
84 | // pack the codewords. There are two packings; length ordered and | ||
85 | // length random. Decide between the two now. | ||
86 | |||
87 | for(i=1;i<entries;i++){ | ||
88 | if(lengthlist[i]<lengthlist[i-1])break; | ||
89 | } | ||
90 | if(i==entries)ordered=true; | ||
91 | |||
92 | if(ordered){ | ||
93 | // length ordered. We only need to say how many codewords of | ||
94 | // each length. The actual codewords are generated | ||
95 | // deterministically | ||
96 | |||
97 | int count=0; | ||
98 | opb.write(1,1); // ordered | ||
99 | opb.write(lengthlist[0]-1,5); // 1 to 32 | ||
100 | |||
101 | for(i=1;i<entries;i++){ | ||
102 | int _this=lengthlist[i]; | ||
103 | int _last=lengthlist[i-1]; | ||
104 | if(_this>_last){ | ||
105 | for(int j=_last;j<_this;j++){ | ||
106 | opb.write(i-count,ilog(entries-count)); | ||
107 | count=i; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | opb.write(i-count,ilog(entries-count)); | ||
112 | } | ||
113 | else{ | ||
114 | // length random. Again, we don't code the codeword itself, just | ||
115 | // the length. This time, though, we have to encode each length | ||
116 | opb.write(0,1); // unordered | ||
117 | |||
118 | // algortihmic mapping has use for 'unused entries', which we tag | ||
119 | // here. The algorithmic mapping happens as usual, but the unused | ||
120 | // entry has no codeword. | ||
121 | for(i=0;i<entries;i++){ | ||
122 | if(lengthlist[i]==0)break; | ||
123 | } | ||
124 | |||
125 | if(i==entries){ | ||
126 | opb.write(0,1); // no unused entries | ||
127 | for(i=0;i<entries;i++){ | ||
128 | opb.write(lengthlist[i]-1,5); | ||
129 | } | ||
130 | } | ||
131 | else{ | ||
132 | opb.write(1,1); // we have unused entries; thus we tag | ||
133 | for(i=0;i<entries;i++){ | ||
134 | if(lengthlist[i]==0){ | ||
135 | opb.write(0,1); | ||
136 | } | ||
137 | else{ | ||
138 | opb.write(1,1); | ||
139 | opb.write(lengthlist[i]-1,5); | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
145 | // is the entry number the desired return value, or do we have a | ||
146 | // mapping? If we have a mapping, what type? | ||
147 | opb.write(maptype,4); | ||
148 | switch(maptype){ | ||
149 | case 0: | ||
150 | // no mapping | ||
151 | break; | ||
152 | case 1: | ||
153 | case 2: | ||
154 | // implicitly populated value mapping | ||
155 | // explicitly populated value mapping | ||
156 | if(quantlist==null){ | ||
157 | // no quantlist? error | ||
158 | return(-1); | ||
159 | } | ||
160 | |||
161 | // values that define the dequantization | ||
162 | opb.write(q_min,32); | ||
163 | opb.write(q_delta,32); | ||
164 | opb.write(q_quant-1,4); | ||
165 | opb.write(q_sequencep,1); | ||
166 | |||
167 | { | ||
168 | int quantvals=0; | ||
169 | switch(maptype){ | ||
170 | case 1: | ||
171 | // a single column of (c->entries/c->dim) quantized values for | ||
172 | // building a full value list algorithmically (square lattice) | ||
173 | quantvals=maptype1_quantvals(); | ||
174 | break; | ||
175 | case 2: | ||
176 | // every value (c->entries*c->dim total) specified explicitly | ||
177 | quantvals=entries*dim; | ||
178 | break; | ||
179 | } | ||
180 | |||
181 | // quantized values | ||
182 | for(i=0;i<quantvals;i++){ | ||
183 | opb.write(Math.abs(quantlist[i]),q_quant); | ||
184 | } | ||
185 | } | ||
186 | break; | ||
187 | default: | ||
188 | // error case; we don't have any other map types now | ||
189 | return(-1); | ||
190 | } | ||
191 | return(0); | ||
192 | } | ||
193 | /* | ||
194 | */ | ||
195 | |||
196 | // unpacks a codebook from the packet buffer into the codebook struct, | ||
197 | // readies the codebook auxiliary structures for decode | ||
198 | int unpack(Buffer opb){ | ||
199 | int i; | ||
200 | //memset(s,0,sizeof(static_codebook)); | ||
201 | |||
202 | // make sure alignment is correct | ||
203 | if(opb.read(24)!=0x564342){ | ||
204 | // goto _eofout; | ||
205 | clear(); | ||
206 | return(-1); | ||
207 | } | ||
208 | |||
209 | // first the basic parameters | ||
210 | dim=opb.read(16); | ||
211 | entries=opb.read(24); | ||
212 | if(entries==-1){ | ||
213 | // goto _eofout; | ||
214 | clear(); | ||
215 | return(-1); | ||
216 | } | ||
217 | |||
218 | // codeword ordering.... length ordered or unordered? | ||
219 | switch(opb.read(1)){ | ||
220 | case 0: | ||
221 | // unordered | ||
222 | lengthlist=new int[entries]; | ||
223 | |||
224 | // allocated but unused entries? | ||
225 | if(opb.read(1)!=0){ | ||
226 | // yes, unused entries | ||
227 | |||
228 | for(i=0;i<entries;i++){ | ||
229 | if(opb.read(1)!=0){ | ||
230 | int num=opb.read(5); | ||
231 | if(num==-1){ | ||
232 | // goto _eofout; | ||
233 | clear(); | ||
234 | return(-1); | ||
235 | } | ||
236 | lengthlist[i]=num+1; | ||
237 | } | ||
238 | else{ | ||
239 | lengthlist[i]=0; | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | else{ | ||
244 | // all entries used; no tagging | ||
245 | for(i=0;i<entries;i++){ | ||
246 | int num=opb.read(5); | ||
247 | if(num==-1){ | ||
248 | // goto _eofout; | ||
249 | clear(); | ||
250 | return(-1); | ||
251 | } | ||
252 | lengthlist[i]=num+1; | ||
253 | } | ||
254 | } | ||
255 | break; | ||
256 | case 1: | ||
257 | // ordered | ||
258 | { | ||
259 | int length=opb.read(5)+1; | ||
260 | lengthlist=new int[entries]; | ||
261 | |||
262 | for(i=0;i<entries;){ | ||
263 | int num=opb.read(ilog(entries-i)); | ||
264 | if(num==-1){ | ||
265 | // goto _eofout; | ||
266 | clear(); | ||
267 | return(-1); | ||
268 | } | ||
269 | for(int j=0;j<num;j++,i++){ | ||
270 | lengthlist[i]=length; | ||
271 | } | ||
272 | length++; | ||
273 | } | ||
274 | } | ||
275 | break; | ||
276 | default: | ||
277 | // EOF | ||
278 | return(-1); | ||
279 | } | ||
280 | |||
281 | // Do we have a mapping to unpack? | ||
282 | switch((maptype=opb.read(4))){ | ||
283 | case 0: | ||
284 | // no mapping | ||
285 | break; | ||
286 | case 1: | ||
287 | case 2: | ||
288 | // implicitly populated value mapping | ||
289 | // explicitly populated value mapping | ||
290 | q_min=opb.read(32); | ||
291 | q_delta=opb.read(32); | ||
292 | q_quant=opb.read(4)+1; | ||
293 | q_sequencep=opb.read(1); | ||
294 | |||
295 | { | ||
296 | int quantvals=0; | ||
297 | switch(maptype){ | ||
298 | case 1: | ||
299 | quantvals=maptype1_quantvals(); | ||
300 | break; | ||
301 | case 2: | ||
302 | quantvals=entries*dim; | ||
303 | break; | ||
304 | } | ||
305 | |||
306 | // quantized values | ||
307 | quantlist=new int[quantvals]; | ||
308 | for(i=0;i<quantvals;i++){ | ||
309 | quantlist[i]=opb.read(q_quant); | ||
310 | } | ||
311 | if(quantlist[quantvals-1]==-1){ | ||
312 | // goto _eofout; | ||
313 | clear(); | ||
314 | return(-1); | ||
315 | } | ||
316 | } | ||
317 | break; | ||
318 | default: | ||
319 | // goto _eofout; | ||
320 | clear(); | ||
321 | return(-1); | ||
322 | } | ||
323 | // all set | ||
324 | return(0); | ||
325 | // _errout: | ||
326 | // _eofout: | ||
327 | // vorbis_staticbook_clear(s); | ||
328 | // return(-1); | ||
329 | } | ||
330 | |||
331 | // there might be a straightforward one-line way to do the below | ||
332 | // that's portable and totally safe against roundoff, but I haven't | ||
333 | // thought of it. Therefore, we opt on the side of caution | ||
334 | private int maptype1_quantvals(){ | ||
335 | int vals=(int)(Math.floor(Math.pow(entries,1./dim))); | ||
336 | |||
337 | // the above *should* be reliable, but we'll not assume that FP is | ||
338 | // ever reliable when bitstream sync is at stake; verify via integer | ||
339 | // means that vals really is the greatest value of dim for which | ||
340 | // vals^b->bim <= b->entries | ||
341 | // treat the above as an initial guess | ||
342 | while(true){ | ||
343 | int acc=1; | ||
344 | int acc1=1; | ||
345 | for(int i=0;i<dim;i++){ | ||
346 | acc*=vals; | ||
347 | acc1*=vals+1; | ||
348 | } | ||
349 | if(acc<=entries && acc1>entries){ return(vals); } | ||
350 | else{ | ||
351 | if(acc>entries){ vals--; } | ||
352 | else{ vals++; } | ||
353 | } | ||
354 | } | ||
355 | } | ||
356 | |||
357 | void clear(){ | ||
358 | // if(quantlist!=null)free(b->quantlist); | ||
359 | // if(lengthlist!=null)free(b->lengthlist); | ||
360 | // if(nearest_tree!=null){ | ||
361 | // free(b->nearest_tree->ptr0); | ||
362 | // free(b->nearest_tree->ptr1); | ||
363 | // free(b->nearest_tree->p); | ||
364 | // free(b->nearest_tree->q); | ||
365 | // memset(b->nearest_tree,0,sizeof(encode_aux_nearestmatch)); | ||
366 | // free(b->nearest_tree); | ||
367 | // } | ||
368 | // if(thresh_tree!=null){ | ||
369 | // free(b->thresh_tree->quantthresh); | ||
370 | // free(b->thresh_tree->quantmap); | ||
371 | // memset(b->thresh_tree,0,sizeof(encode_aux_threshmatch)); | ||
372 | // free(b->thresh_tree); | ||
373 | // } | ||
374 | // memset(b,0,sizeof(static_codebook)); | ||
375 | } | ||
376 | |||
377 | // unpack the quantized list of values for encode/decode | ||
378 | // we need to deal with two map types: in map type 1, the values are | ||
379 | // generated algorithmically (each column of the vector counts through | ||
380 | // the values in the quant vector). in map type 2, all the values came | ||
381 | // in in an explicit list. Both value lists must be unpacked | ||
382 | float[] unquantize(){ | ||
383 | |||
384 | if(maptype==1 || maptype==2){ | ||
385 | int quantvals; | ||
386 | float mindel=float32_unpack(q_min); | ||
387 | float delta=float32_unpack(q_delta); | ||
388 | float[] r=new float[entries*dim]; | ||
389 | |||
390 | //System.err.println("q_min="+q_min+", mindel="+mindel); | ||
391 | |||
392 | // maptype 1 and 2 both use a quantized value vector, but | ||
393 | // different sizes | ||
394 | switch(maptype){ | ||
395 | case 1: | ||
396 | // most of the time, entries%dimensions == 0, but we need to be | ||
397 | // well defined. We define that the possible vales at each | ||
398 | // scalar is values == entries/dim. If entries%dim != 0, we'll | ||
399 | // have 'too few' values (values*dim<entries), which means that | ||
400 | // we'll have 'left over' entries; left over entries use zeroed | ||
401 | // values (and are wasted). So don't generate codebooks like that | ||
402 | quantvals=maptype1_quantvals(); | ||
403 | for(int j=0;j<entries;j++){ | ||
404 | float last=0.f; | ||
405 | int indexdiv=1; | ||
406 | for(int k=0;k<dim;k++){ | ||
407 | int index=(j/indexdiv)%quantvals; | ||
408 | float val=quantlist[index]; | ||
409 | val=Math.abs(val)*delta+mindel+last; | ||
410 | if(q_sequencep!=0)last=val; | ||
411 | r[j*dim+k]=val; | ||
412 | indexdiv*=quantvals; | ||
413 | } | ||
414 | } | ||
415 | break; | ||
416 | case 2: | ||
417 | for(int j=0;j<entries;j++){ | ||
418 | float last=0.f; | ||
419 | for(int k=0;k<dim;k++){ | ||
420 | float val=quantlist[j*dim+k]; | ||
421 | //if((j*dim+k)==0){System.err.println(" | 0 -> "+val+" | ");} | ||
422 | val=Math.abs(val)*delta+mindel+last; | ||
423 | if(q_sequencep!=0)last=val; | ||
424 | r[j*dim+k]=val; | ||
425 | //if((j*dim+k)==0){System.err.println(" $ r[0] -> "+r[0]+" | ");} | ||
426 | } | ||
427 | } | ||
428 | //System.err.println("\nr[0]="+r[0]); | ||
429 | } | ||
430 | return(r); | ||
431 | } | ||
432 | return(null); | ||
433 | } | ||
434 | |||
435 | private static int ilog(int v){ | ||
436 | int ret=0; | ||
437 | while(v!=0){ | ||
438 | ret++; | ||
439 | v>>>=1; | ||
440 | } | ||
441 | return(ret); | ||
442 | } | ||
443 | |||
444 | // 32 bit float (not IEEE; nonnormalized mantissa + | ||
445 | // biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm | ||
446 | // Why not IEEE? It's just not that important here. | ||
447 | |||
448 | static final int VQ_FEXP=10; | ||
449 | static final int VQ_FMAN=21; | ||
450 | static final int VQ_FEXP_BIAS=768; // bias toward values smaller than 1. | ||
451 | |||
452 | // doesn't currently guard under/overflow | ||
453 | static long float32_pack(float val){ | ||
454 | int sign=0; | ||
455 | int exp; | ||
456 | int mant; | ||
457 | if(val<0){ | ||
458 | sign=0x80000000; | ||
459 | val= -val; | ||
460 | } | ||
461 | exp=(int)Math.floor(Math.log(val)/Math.log(2)); | ||
462 | mant=(int)Math.rint(Math.pow(val,(VQ_FMAN-1)-exp)); | ||
463 | exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN; | ||
464 | return(sign|exp|mant); | ||
465 | } | ||
466 | |||
467 | static float float32_unpack(int val){ | ||
468 | float mant=val&0x1fffff; | ||
469 | float sign=val&0x80000000; | ||
470 | float exp =(val&0x7fe00000)>>>VQ_FMAN; | ||
471 | //System.err.println("mant="+mant+", sign="+sign+", exp="+exp); | ||
472 | //if(sign!=0.0)mant= -mant; | ||
473 | if((val&0x80000000)!=0)mant= -mant; | ||
474 | //System.err.println("mant="+mant); | ||
475 | return(ldexp(mant,((int)exp)-(VQ_FMAN-1)-VQ_FEXP_BIAS)); | ||
476 | } | ||
477 | |||
478 | static float ldexp(float foo, int e){ | ||
479 | return (float)(foo*Math.pow(2, e)); | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | // TEST | ||
484 | // Unit tests of the dequantizer; this stuff will be OK | ||
485 | // cross-platform, I simply want to be sure that special mapping cases | ||
486 | // actually work properly; a bug could go unnoticed for a while | ||
487 | |||
488 | // cases: | ||
489 | // | ||
490 | // no mapping | ||
491 | // full, explicit mapping | ||
492 | // algorithmic mapping | ||
493 | // | ||
494 | // nonsequential | ||
495 | // sequential | ||
496 | |||
497 | static int[] full_quantlist1={0,1,2,3, 4,5,6,7, 8,3,6,1}; | ||
498 | static int[] partial_quantlist1={0,7,2}; | ||
499 | |||
500 | // no mapping | ||
501 | static StaticCodeBook test1=new StaticCodeBook(4,16,null, | ||
502 | 0,0,0,0,0, | ||
503 | null,null,null); | ||
504 | static float[] test1_result=null; | ||
505 | |||
506 | // linear, full mapping, nonsequential | ||
507 | static StaticCodeBook test2=new StaticCodeBook(4,3,null, | ||
508 | 2,-533200896,1611661312,4,0, | ||
509 | full_quantlist1, null, null); | ||
510 | static float[] test2_result={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2}; | ||
511 | |||
512 | // linear, full mapping, sequential | ||
513 | static StaticCodeBook test3=new StaticCodeBook(4,3,null, | ||
514 | 2, -533200896,1611661312,4,1, | ||
515 | full_quantlist1,null, null); | ||
516 | static float[] test3_result={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6}; | ||
517 | |||
518 | // linear, algorithmic mapping, nonsequential | ||
519 | static StaticCodeBook test4=new StaticCodeBook(3,27,null, | ||
520 | 1,-533200896,1611661312,4,0, | ||
521 | partial_quantlist1,null,null); | ||
522 | static float[] test4_result={-3,-3,-3, 4,-3,-3, -1,-3,-3, | ||
523 | -3, 4,-3, 4, 4,-3, -1, 4,-3, | ||
524 | -3,-1,-3, 4,-1,-3, -1,-1,-3, | ||
525 | -3,-3, 4, 4,-3, 4, -1,-3, 4, | ||
526 | -3, 4, 4, 4, 4, 4, -1, 4, 4, | ||
527 | -3,-1, 4, 4,-1, 4, -1,-1, 4, | ||
528 | -3,-3,-1, 4,-3,-1, -1,-3,-1, | ||
529 | -3, 4,-1, 4, 4,-1, -1, 4,-1, | ||
530 | -3,-1,-1, 4,-1,-1, -1,-1,-1}; | ||
531 | |||
532 | // linear, algorithmic mapping, sequential | ||
533 | static StaticCodeBook test5=new StaticCodeBook(3,27,null, | ||
534 | 1,-533200896,1611661312,4,1, | ||
535 | partial_quantlist1,null,null); | ||
536 | static float[] test5_result={-3,-6,-9, 4, 1,-2, -1,-4,-7, | ||
537 | -3, 1,-2, 4, 8, 5, -1, 3, 0, | ||
538 | -3,-4,-7, 4, 3, 0, -1,-2,-5, | ||
539 | -3,-6,-2, 4, 1, 5, -1,-4, 0, | ||
540 | -3, 1, 5, 4, 8,12, -1, 3, 7, | ||
541 | -3,-4, 0, 4, 3, 7, -1,-2, 2, | ||
542 | -3,-6,-7, 4, 1, 0, -1,-4,-5, | ||
543 | -3, 1, 0, 4, 8, 7, -1, 3, 2, | ||
544 | -3,-4,-5, 4, 3, 2, -1,-2,-3}; | ||
545 | |||
546 | void run_test(float[] comp){ | ||
547 | float[] out=unquantize(); | ||
548 | if(comp!=null){ | ||
549 | if(out==null){ | ||
550 | System.err.println("_book_unquantize incorrectly returned NULL"); | ||
551 | System.exit(1); | ||
552 | } | ||
553 | for(int i=0;i<entries*dim;i++){ | ||
554 | if(Math.abs(out[i]-comp[i])>.0001){ | ||
555 | System.err.println("disagreement in unquantized and reference data:\nposition "+i+": "+out[i]+" != "+comp[i]); | ||
556 | System.exit(1); | ||
557 | } | ||
558 | } | ||
559 | } | ||
560 | else{ | ||
561 | if(out!=null){ | ||
562 | System.err.println("_book_unquantize returned a value array:\n correct result should have been NULL"); | ||
563 | System.exit(1); | ||
564 | } | ||
565 | } | ||
566 | } | ||
567 | |||
568 | public static void main(String[] arg){ | ||
569 | // run the nine dequant tests, and compare to the hand-rolled results | ||
570 | System.err.print("Dequant test 1... "); | ||
571 | test1.run_test(test1_result); | ||
572 | System.err.print("OK\nDequant test 2... "); | ||
573 | test2.run_test(test2_result); | ||
574 | System.err.print("OK\nDequant test 3... "); | ||
575 | test3.run_test(test3_result); | ||
576 | System.err.print("OK\nDequant test 4... "); | ||
577 | test4.run_test(test4_result); | ||
578 | System.err.print("OK\nDequant test 5... "); | ||
579 | test5.run_test(test5_result); | ||
580 | System.err.print("OK\n\n"); | ||
581 | } | ||
582 | */ | ||
583 | } | ||
584 | |||
585 | |||
586 | |||
587 | |||
588 | |||
diff --git a/songdbj/com/jcraft/jorbis/Time0.java b/songdbj/com/jcraft/jorbis/Time0.java new file mode 100644 index 0000000000..f6a9fcb077 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/Time0.java | |||
@@ -0,0 +1,38 @@ | |||
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 Time0 extends FuncTime{ | ||
31 | void pack(Object i, Buffer opb){} | ||
32 | Object unpack(Info vi , Buffer opb){return "";} | ||
33 | Object look(DspState vd, InfoMode mi, Object i){return "";} | ||
34 | void free_info(Object i){} | ||
35 | void free_look(Object i){} | ||
36 | int forward(Block vb, Object i){return 0;} | ||
37 | int inverse(Block vb, Object i, float[] in, float[] out){return 0;} | ||
38 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/VorbisFile.java b/songdbj/com/jcraft/jorbis/VorbisFile.java new file mode 100644 index 0000000000..64edff006e --- /dev/null +++ b/songdbj/com/jcraft/jorbis/VorbisFile.java | |||
@@ -0,0 +1,1361 @@ | |||
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 | import java.io.InputStream; | ||
31 | import java.io.IOException; | ||
32 | |||
33 | public class VorbisFile{ | ||
34 | static final int CHUNKSIZE=8500; | ||
35 | static final int SEEK_SET=0; | ||
36 | static final int SEEK_CUR=1; | ||
37 | static final int SEEK_END=2; | ||
38 | |||
39 | static final int OV_FALSE=-1; | ||
40 | static final int OV_EOF=-2; | ||
41 | static final int OV_HOLE=-3; | ||
42 | |||
43 | static final int OV_EREAD=-128; | ||
44 | static final int OV_EFAULT=-129; | ||
45 | static final int OV_EIMPL=-130; | ||
46 | static final int OV_EINVAL=-131; | ||
47 | static final int OV_ENOTVORBIS=-132; | ||
48 | static final int OV_EBADHEADER=-133; | ||
49 | static final int OV_EVERSION=-134; | ||
50 | static final int OV_ENOTAUDIO=-135; | ||
51 | static final int OV_EBADPACKET=-136; | ||
52 | static final int OV_EBADLINK=-137; | ||
53 | static final int OV_ENOSEEK=-138; | ||
54 | |||
55 | InputStream datasource; | ||
56 | boolean seekable=false; | ||
57 | long offset; | ||
58 | long end; | ||
59 | |||
60 | SyncState oy=new SyncState(); | ||
61 | |||
62 | int links; | ||
63 | long[] offsets; | ||
64 | long[] dataoffsets; | ||
65 | int[] serialnos; | ||
66 | long[] pcmlengths; | ||
67 | Info[] vi; | ||
68 | Comment[] vc; | ||
69 | |||
70 | // Decoding working state local storage | ||
71 | long pcm_offset; | ||
72 | boolean decode_ready=false; | ||
73 | int current_serialno; | ||
74 | int current_link; | ||
75 | |||
76 | float bittrack; | ||
77 | float samptrack; | ||
78 | |||
79 | StreamState os=new StreamState(); // take physical pages, weld into a logical | ||
80 | // stream of packets | ||
81 | DspState vd=new DspState(); // central working state for | ||
82 | // the packet->PCM decoder | ||
83 | Block vb=new Block(vd); // local working space for packet->PCM decode | ||
84 | |||
85 | //ov_callbacks callbacks; | ||
86 | |||
87 | public VorbisFile(String file) throws JOrbisException { | ||
88 | super(); | ||
89 | InputStream is=null; | ||
90 | try{ | ||
91 | is=new SeekableInputStream(file); | ||
92 | int ret=open(is, null, 0); | ||
93 | if(ret==-1){ | ||
94 | throw new JOrbisException("VorbisFile: open return -1"); | ||
95 | } | ||
96 | } | ||
97 | catch(Exception e){ | ||
98 | throw new JOrbisException("VorbisFile: "+e.toString()); | ||
99 | } | ||
100 | finally{ | ||
101 | if(is != null){ | ||
102 | try { | ||
103 | is.close(); | ||
104 | } | ||
105 | catch (IOException e) { | ||
106 | e.printStackTrace(); | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | public VorbisFile(InputStream is, byte[] initial, int ibytes) | ||
113 | throws JOrbisException { | ||
114 | super(); | ||
115 | int ret=open(is, initial, ibytes); | ||
116 | if(ret==-1){ | ||
117 | } | ||
118 | } | ||
119 | |||
120 | private int get_data(){ | ||
121 | int index=oy.buffer(CHUNKSIZE); | ||
122 | byte[] buffer=oy.data; | ||
123 | // int bytes=callbacks.read_func(buffer, index, 1, CHUNKSIZE, datasource); | ||
124 | int bytes=0; | ||
125 | try{ | ||
126 | bytes=datasource.read(buffer, index, CHUNKSIZE); | ||
127 | } | ||
128 | catch(Exception e){ | ||
129 | //System.err.println(e); | ||
130 | return OV_EREAD; | ||
131 | } | ||
132 | oy.wrote(bytes); | ||
133 | if(bytes==-1){ | ||
134 | // System.out.println("bytes="+bytes); | ||
135 | bytes=0; | ||
136 | } | ||
137 | return bytes; | ||
138 | } | ||
139 | |||
140 | private void seek_helper(long offst){ | ||
141 | //callbacks.seek_func(datasource, offst, SEEK_SET); | ||
142 | fseek(datasource, offst, SEEK_SET); | ||
143 | this.offset=offst; | ||
144 | oy.reset(); | ||
145 | } | ||
146 | |||
147 | private int get_next_page(Page page, long boundary){ | ||
148 | if(boundary>0) boundary+=offset; | ||
149 | while(true){ | ||
150 | int more; | ||
151 | if(boundary>0 && offset>=boundary)return OV_FALSE; | ||
152 | more=oy.pageseek(page); | ||
153 | if(more<0){offset-=more;} | ||
154 | else{ | ||
155 | if(more==0){ | ||
156 | if(boundary==0)return OV_FALSE; | ||
157 | // if(get_data()<=0)return -1; | ||
158 | int ret=get_data(); | ||
159 | if(ret==0) return OV_EOF; | ||
160 | if(ret<0) return OV_EREAD; | ||
161 | } | ||
162 | else{ | ||
163 | int ret=(int)offset; //!!! | ||
164 | offset+=more; | ||
165 | return ret; | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | |||
171 | private int get_prev_page(Page page) throws JOrbisException { | ||
172 | long begin=offset; //!!! | ||
173 | int ret; | ||
174 | int offst=-1; | ||
175 | while(offst==-1){ | ||
176 | begin-=CHUNKSIZE; | ||
177 | if(begin<0) | ||
178 | begin=0; | ||
179 | seek_helper(begin); | ||
180 | while(offset<begin+CHUNKSIZE){ | ||
181 | ret=get_next_page(page, begin+CHUNKSIZE-offset); | ||
182 | if(ret==OV_EREAD){ return OV_EREAD; } | ||
183 | if(ret<0){ | ||
184 | if(offst == -1) | ||
185 | throw new JOrbisException(); | ||
186 | break; | ||
187 | } | ||
188 | else{ offst=ret; } | ||
189 | } | ||
190 | } | ||
191 | seek_helper(offst); //!!! | ||
192 | ret=get_next_page(page, CHUNKSIZE); | ||
193 | if(ret<0){ | ||
194 | //System.err.println("Missed page fencepost at end of logical bitstream Exiting"); | ||
195 | //System.exit(1); | ||
196 | return OV_EFAULT; | ||
197 | } | ||
198 | return offst; | ||
199 | } | ||
200 | |||
201 | int bisect_forward_serialno(long begin, long searched, long end, int currentno, int m){ | ||
202 | long endsearched=end; | ||
203 | long next=end; | ||
204 | Page page=new Page(); | ||
205 | int ret; | ||
206 | |||
207 | while(searched<endsearched){ | ||
208 | long bisect; | ||
209 | if(endsearched-searched<CHUNKSIZE){ | ||
210 | bisect=searched; | ||
211 | } | ||
212 | else{ | ||
213 | bisect=(searched+endsearched)/2; | ||
214 | } | ||
215 | |||
216 | seek_helper(bisect); | ||
217 | ret=get_next_page(page, -1); | ||
218 | if(ret==OV_EREAD) return OV_EREAD; | ||
219 | if(ret<0 || page.serialno()!=currentno){ | ||
220 | endsearched=bisect; | ||
221 | if(ret>=0)next=ret; | ||
222 | } | ||
223 | else{ | ||
224 | searched=ret+page.header_len+page.body_len; | ||
225 | } | ||
226 | } | ||
227 | seek_helper(next); | ||
228 | ret=get_next_page(page, -1); | ||
229 | if(ret==OV_EREAD) return OV_EREAD; | ||
230 | |||
231 | if(searched>=end || ret==-1){ | ||
232 | links=m+1; | ||
233 | offsets=new long[m+2]; | ||
234 | offsets[m+1]=searched; | ||
235 | } | ||
236 | else{ | ||
237 | ret=bisect_forward_serialno(next, offset, end, page.serialno(), m+1); | ||
238 | if(ret==OV_EREAD)return OV_EREAD; | ||
239 | } | ||
240 | offsets[m]=begin; | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | // uses the local ogg_stream storage in vf; this is important for | ||
245 | // non-streaming input sources | ||
246 | int fetch_headers(Info vi, Comment vc, int[] serialno, Page og_ptr){ | ||
247 | //System.err.println("fetch_headers"); | ||
248 | Page og=new Page(); | ||
249 | Packet op=new Packet(); | ||
250 | int ret; | ||
251 | |||
252 | if(og_ptr==null){ | ||
253 | ret=get_next_page(og, CHUNKSIZE); | ||
254 | if(ret==OV_EREAD)return OV_EREAD; | ||
255 | if(ret<0) return OV_ENOTVORBIS; | ||
256 | og_ptr=og; | ||
257 | } | ||
258 | |||
259 | if(serialno!=null)serialno[0]=og_ptr.serialno(); | ||
260 | |||
261 | os.init(og_ptr.serialno()); | ||
262 | |||
263 | // extract the initial header from the first page and verify that the | ||
264 | // Ogg bitstream is in fact Vorbis data | ||
265 | |||
266 | vi.init(); | ||
267 | vc.init(); | ||
268 | |||
269 | int i=0; | ||
270 | while(i<3){ | ||
271 | os.pagein(og_ptr); | ||
272 | while(i<3){ | ||
273 | int result=os.packetout(op); | ||
274 | if(result==0)break; | ||
275 | if(result==-1){ | ||
276 | //System.err.println("Corrupt header in logical bitstream."); | ||
277 | //goto bail_header; | ||
278 | vi.clear(); | ||
279 | vc.clear(); | ||
280 | os.clear(); | ||
281 | return -1; | ||
282 | } | ||
283 | if(vi.synthesis_headerin(vc, op)!=0){ | ||
284 | //System.err.println("Illegal header in logical bitstream."); | ||
285 | //goto bail_header; | ||
286 | vi.clear(); | ||
287 | vc.clear(); | ||
288 | os.clear(); | ||
289 | return -1; | ||
290 | } | ||
291 | i++; | ||
292 | } | ||
293 | if(i<3) | ||
294 | if(get_next_page(og_ptr, 1)<0){ | ||
295 | //System.err.println("Missing header in logical bitstream."); | ||
296 | //goto bail_header; | ||
297 | vi.clear(); | ||
298 | vc.clear(); | ||
299 | os.clear(); | ||
300 | return -1; | ||
301 | } | ||
302 | } | ||
303 | return 0; | ||
304 | |||
305 | // bail_header: | ||
306 | // vorbis_info_clear(vi); | ||
307 | // vorbis_comment_clear(vc); | ||
308 | // ogg_stream_clear(&vf->os); | ||
309 | // return -1; | ||
310 | } | ||
311 | |||
312 | // last step of the OggVorbis_File initialization; get all the | ||
313 | // vorbis_info structs and PCM positions. Only called by the seekable | ||
314 | // initialization (local stream storage is hacked slightly; pay | ||
315 | // attention to how that's done) | ||
316 | void prefetch_all_headers(Info first_i,Comment first_c, | ||
317 | int dataoffset) throws JOrbisException { | ||
318 | Page og=new Page(); | ||
319 | int ret; | ||
320 | |||
321 | vi=new Info[links]; | ||
322 | vc=new Comment[links]; | ||
323 | dataoffsets=new long[links]; | ||
324 | pcmlengths=new long[links]; | ||
325 | serialnos=new int[links]; | ||
326 | |||
327 | for(int i=0;i<links;i++){ | ||
328 | if(first_i!=null && first_c!=null && i==0){ | ||
329 | // we already grabbed the initial header earlier. This just | ||
330 | // saves the waste of grabbing it again | ||
331 | // !!!!!!!!!!!!! | ||
332 | vi[i]=first_i; | ||
333 | //memcpy(vf->vi+i,first_i,sizeof(vorbis_info)); | ||
334 | vc[i]=first_c; | ||
335 | //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); | ||
336 | dataoffsets[i]=dataoffset; | ||
337 | } | ||
338 | else{ | ||
339 | // seek to the location of the initial header | ||
340 | seek_helper(offsets[i]); //!!! | ||
341 | vi[i]=new Info(); | ||
342 | vc[i]=new Comment(); | ||
343 | if(fetch_headers(vi[i], vc[i], null, null)==-1){ | ||
344 | //System.err.println("Error opening logical bitstream #"+(i+1)+"\n"); | ||
345 | dataoffsets[i]=-1; | ||
346 | } | ||
347 | else{ | ||
348 | dataoffsets[i]=offset; | ||
349 | os.clear(); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | // get the serial number and PCM length of this link. To do this, | ||
354 | // get the last page of the stream | ||
355 | { | ||
356 | long end=offsets[i+1]; //!!! | ||
357 | seek_helper(end); | ||
358 | |||
359 | while(true){ | ||
360 | ret=get_prev_page(og); | ||
361 | if(ret==-1){ | ||
362 | // this should not be possible | ||
363 | //System.err.println("Could not find last page of logical "+ | ||
364 | // "bitstream #"+(i)+"\n"); | ||
365 | vi[i].clear(); | ||
366 | vc[i].clear(); | ||
367 | break; | ||
368 | } | ||
369 | if(og.granulepos()!=-1){ | ||
370 | serialnos[i]=og.serialno(); | ||
371 | pcmlengths[i]=og.granulepos(); | ||
372 | break; | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | } | ||
378 | |||
379 | int make_decode_ready(){ | ||
380 | if(decode_ready)System.exit(1); | ||
381 | vd.synthesis_init(vi[0]); | ||
382 | vb.init(vd); | ||
383 | decode_ready=true; | ||
384 | return(0); | ||
385 | } | ||
386 | |||
387 | int open_seekable() throws JOrbisException { | ||
388 | Info initial_i=new Info(); | ||
389 | Comment initial_c=new Comment(); | ||
390 | int serialno; | ||
391 | long end; | ||
392 | int ret; | ||
393 | int dataoffset; | ||
394 | Page og=new Page(); | ||
395 | // is this even vorbis...? | ||
396 | int[] foo=new int[1]; | ||
397 | ret=fetch_headers(initial_i, initial_c, foo, null); | ||
398 | serialno=foo[0]; | ||
399 | dataoffset=(int)offset; //!! | ||
400 | os.clear(); | ||
401 | if(ret==-1)return(-1); | ||
402 | // we can seek, so set out learning all about this file | ||
403 | seekable=true; | ||
404 | //(callbacks.seek_func)(datasource, 0, SEEK_END); | ||
405 | fseek(datasource, 0, SEEK_END); | ||
406 | //offset=end=(callbacks.tell_func)(datasource); | ||
407 | offset=ftell(datasource); | ||
408 | end=offset; | ||
409 | // We get the offset for the last page of the physical bitstream. | ||
410 | // Most OggVorbis files will contain a single logical bitstream | ||
411 | end=get_prev_page(og); | ||
412 | // moer than one logical bitstream? | ||
413 | if(og.serialno()!=serialno){ | ||
414 | // Chained bitstream. Bisect-search each logical bitstream | ||
415 | // section. Do so based on serial number only | ||
416 | if(bisect_forward_serialno(0,0,end+1,serialno,0)<0){ | ||
417 | clear(); | ||
418 | return OV_EREAD; | ||
419 | } | ||
420 | } | ||
421 | else{ | ||
422 | // Only one logical bitstream | ||
423 | if(bisect_forward_serialno(0,end,end+1,serialno,0)<0){ | ||
424 | clear(); | ||
425 | return OV_EREAD; | ||
426 | } | ||
427 | } | ||
428 | prefetch_all_headers(initial_i, initial_c, dataoffset); | ||
429 | return(raw_seek(0)); | ||
430 | } | ||
431 | |||
432 | int open_nonseekable(){ | ||
433 | //System.err.println("open_nonseekable"); | ||
434 | // we cannot seek. Set up a 'single' (current) logical bitstream entry | ||
435 | links=1; | ||
436 | vi=new Info[links]; vi[0]=new Info(); // ?? | ||
437 | vc=new Comment[links]; vc[0]=new Comment(); // ?? bug? | ||
438 | |||
439 | // Try to fetch the headers, maintaining all the storage | ||
440 | int[]foo=new int[1]; | ||
441 | if(fetch_headers(vi[0], vc[0], foo, null)==-1)return(-1); | ||
442 | current_serialno=foo[0]; | ||
443 | make_decode_ready(); | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | // clear out the current logical bitstream decoder | ||
448 | void decode_clear(){ | ||
449 | os.clear(); | ||
450 | vd.clear(); | ||
451 | vb.clear(); | ||
452 | decode_ready=false; | ||
453 | bittrack=0.f; | ||
454 | samptrack=0.f; | ||
455 | } | ||
456 | |||
457 | // fetch and process a packet. Handles the case where we're at a | ||
458 | // bitstream boundary and dumps the decoding machine. If the decoding | ||
459 | // machine is unloaded, it loads it. It also keeps pcm_offset up to | ||
460 | // date (seek and read both use this. seek uses a special hack with | ||
461 | // readp). | ||
462 | // | ||
463 | // return: -1) hole in the data (lost packet) | ||
464 | // 0) need more date (only if readp==0)/eof | ||
465 | // 1) got a packet | ||
466 | |||
467 | int process_packet(int readp){ | ||
468 | Page og=new Page(); | ||
469 | |||
470 | // handle one packet. Try to fetch it from current stream state | ||
471 | // extract packets from page | ||
472 | while(true){ | ||
473 | // process a packet if we can. If the machine isn't loaded, | ||
474 | // neither is a page | ||
475 | if(decode_ready){ | ||
476 | Packet op=new Packet(); | ||
477 | int result=os.packetout(op); | ||
478 | long granulepos; | ||
479 | // if(result==-1)return(-1); // hole in the data. For now, swallow | ||
480 | // and go. We'll need to add a real | ||
481 | // error code in a bit. | ||
482 | if(result>0){ | ||
483 | // got a packet. process it | ||
484 | granulepos=op.granulepos; | ||
485 | if(vb.synthesis(op)==0){ // lazy check for lazy | ||
486 | // header handling. The | ||
487 | // header packets aren't | ||
488 | // audio, so if/when we | ||
489 | // submit them, | ||
490 | // vorbis_synthesis will | ||
491 | // reject them | ||
492 | // suck in the synthesis data and track bitrate | ||
493 | { | ||
494 | int oldsamples=vd.synthesis_pcmout(null, null); | ||
495 | vd.synthesis_blockin(vb); | ||
496 | samptrack+=vd.synthesis_pcmout(null, null)-oldsamples; | ||
497 | bittrack+=op.bytes*8; | ||
498 | } | ||
499 | |||
500 | // update the pcm offset. | ||
501 | if(granulepos!=-1 && op.e_o_s==0){ | ||
502 | int link=(seekable?current_link:0); | ||
503 | int samples; | ||
504 | // this packet has a pcm_offset on it (the last packet | ||
505 | // completed on a page carries the offset) After processing | ||
506 | // (above), we know the pcm position of the *last* sample | ||
507 | // ready to be returned. Find the offset of the *first* | ||
508 | // | ||
509 | // As an aside, this trick is inaccurate if we begin | ||
510 | // reading anew right at the last page; the end-of-stream | ||
511 | // granulepos declares the last frame in the stream, and the | ||
512 | // last packet of the last page may be a partial frame. | ||
513 | // So, we need a previous granulepos from an in-sequence page | ||
514 | // to have a reference point. Thus the !op.e_o_s clause above | ||
515 | |||
516 | samples=vd.synthesis_pcmout(null, null); | ||
517 | granulepos-=samples; | ||
518 | for(int i=0;i<link;i++){ | ||
519 | granulepos+=pcmlengths[i]; | ||
520 | } | ||
521 | pcm_offset=granulepos; | ||
522 | } | ||
523 | return(1); | ||
524 | } | ||
525 | } | ||
526 | } | ||
527 | |||
528 | if(readp==0)return(0); | ||
529 | if(get_next_page(og,-1)<0)return(0); // eof. leave unitialized | ||
530 | |||
531 | // bitrate tracking; add the header's bytes here, the body bytes | ||
532 | // are done by packet above | ||
533 | bittrack+=og.header_len*8; | ||
534 | |||
535 | // has our decoding just traversed a bitstream boundary? | ||
536 | if(decode_ready){ | ||
537 | if(current_serialno!=og.serialno()){ | ||
538 | decode_clear(); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | // Do we need to load a new machine before submitting the page? | ||
543 | // This is different in the seekable and non-seekable cases. | ||
544 | // | ||
545 | // In the seekable case, we already have all the header | ||
546 | // information loaded and cached; we just initialize the machine | ||
547 | // with it and continue on our merry way. | ||
548 | // | ||
549 | // In the non-seekable (streaming) case, we'll only be at a | ||
550 | // boundary if we just left the previous logical bitstream and | ||
551 | // we're now nominally at the header of the next bitstream | ||
552 | |||
553 | if(!decode_ready){ | ||
554 | int i; | ||
555 | if(seekable){ | ||
556 | current_serialno=og.serialno(); | ||
557 | |||
558 | // match the serialno to bitstream section. We use this rather than | ||
559 | // offset positions to avoid problems near logical bitstream | ||
560 | // boundaries | ||
561 | for(i=0;i<links;i++){ | ||
562 | if(serialnos[i]==current_serialno)break; | ||
563 | } | ||
564 | if(i==links)return(-1); // sign of a bogus stream. error out, | ||
565 | // leave machine uninitialized | ||
566 | current_link=i; | ||
567 | |||
568 | os.init(current_serialno); | ||
569 | os.reset(); | ||
570 | |||
571 | } | ||
572 | else{ | ||
573 | // we're streaming | ||
574 | // fetch the three header packets, build the info struct | ||
575 | int foo[]=new int[1]; | ||
576 | int ret=fetch_headers(vi[0], vc[0], foo, og); | ||
577 | current_serialno=foo[0]; | ||
578 | if(ret!=0)return ret; | ||
579 | current_link++; | ||
580 | i=0; | ||
581 | } | ||
582 | make_decode_ready(); | ||
583 | } | ||
584 | os.pagein(og); | ||
585 | } | ||
586 | } | ||
587 | |||
588 | //The helpers are over; it's all toplevel interface from here on out | ||
589 | // clear out the OggVorbis_File struct | ||
590 | int clear(){ | ||
591 | vb.clear(); | ||
592 | vd.clear(); | ||
593 | os.clear(); | ||
594 | |||
595 | if(vi!=null && links!=0){ | ||
596 | for(int i=0;i<links;i++){ | ||
597 | vi[i].clear(); | ||
598 | vc[i].clear(); | ||
599 | } | ||
600 | vi=null; | ||
601 | vc=null; | ||
602 | } | ||
603 | if(dataoffsets!=null)dataoffsets=null; | ||
604 | if(pcmlengths!=null)pcmlengths=null; | ||
605 | if(serialnos!=null)serialnos=null; | ||
606 | if(offsets!=null)offsets=null; | ||
607 | oy.clear(); | ||
608 | //if(datasource!=null)(vf->callbacks.close_func)(vf->datasource); | ||
609 | //memset(vf,0,sizeof(OggVorbis_File)); | ||
610 | return(0); | ||
611 | } | ||
612 | |||
613 | static int fseek(InputStream fis, | ||
614 | //int64_t off, | ||
615 | long off, | ||
616 | int whence){ | ||
617 | if(fis instanceof SeekableInputStream){ | ||
618 | SeekableInputStream sis=(SeekableInputStream)fis; | ||
619 | try{ | ||
620 | if(whence==SEEK_SET){ | ||
621 | sis.seek(off); | ||
622 | } | ||
623 | else if(whence==SEEK_END){ | ||
624 | sis.seek(sis.getLength()-off); | ||
625 | } | ||
626 | else{ | ||
627 | //System.out.println("seek: "+whence+" is not supported"); | ||
628 | } | ||
629 | } | ||
630 | catch(Exception e){ | ||
631 | } | ||
632 | return 0; | ||
633 | } | ||
634 | try{ | ||
635 | if(whence==0){ fis.reset(); } | ||
636 | fis.skip(off); | ||
637 | } | ||
638 | catch(Exception e){return -1;} | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | static long ftell(InputStream fis){ | ||
643 | try{ | ||
644 | if(fis instanceof SeekableInputStream){ | ||
645 | SeekableInputStream sis=(SeekableInputStream)fis; | ||
646 | return (sis.tell()); | ||
647 | } | ||
648 | } | ||
649 | catch(Exception e){ | ||
650 | } | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | // inspects the OggVorbis file and finds/documents all the logical | ||
655 | // bitstreams contained in it. Tries to be tolerant of logical | ||
656 | // bitstream sections that are truncated/woogie. | ||
657 | // | ||
658 | // return: -1) error | ||
659 | // 0) OK | ||
660 | |||
661 | int open(InputStream is, byte[] initial, int ibytes) throws JOrbisException { | ||
662 | //callbacks callbacks = { | ||
663 | // (size_t (*)(void *, size_t, size_t, void *)) fread, | ||
664 | // (int (*)(void *, int64_t, int)) _fseek, | ||
665 | // (int (*)(void *)) fclose, | ||
666 | // (long (*)(void *)) ftell | ||
667 | // }; | ||
668 | return open_callbacks(is, initial, ibytes//, callbacks | ||
669 | ); | ||
670 | } | ||
671 | |||
672 | int open_callbacks(InputStream is, byte[] initial, | ||
673 | int ibytes//, callbacks callbacks | ||
674 | ) throws JOrbisException { | ||
675 | int ret; | ||
676 | datasource=is; | ||
677 | //callbacks = _callbacks; | ||
678 | // init the framing state | ||
679 | oy.init(); | ||
680 | |||
681 | // perhaps some data was previously read into a buffer for testing | ||
682 | // against other stream types. Allow initialization from this | ||
683 | // previously read data (as we may be reading from a non-seekable | ||
684 | // stream) | ||
685 | if(initial!=null){ | ||
686 | int index=oy.buffer(ibytes); | ||
687 | System.arraycopy(initial, 0, oy.data, index, ibytes); | ||
688 | oy.wrote(ibytes); | ||
689 | } | ||
690 | // can we seek? Stevens suggests the seek test was portable | ||
691 | if(is instanceof SeekableInputStream){ ret=open_seekable(); } | ||
692 | else{ ret=open_nonseekable(); } | ||
693 | if(ret!=0){ | ||
694 | datasource=null; | ||
695 | clear(); | ||
696 | } | ||
697 | return ret; | ||
698 | } | ||
699 | |||
700 | // How many logical bitstreams in this physical bitstream? | ||
701 | public int streams(){ | ||
702 | return links; | ||
703 | } | ||
704 | |||
705 | // Is the FILE * associated with vf seekable? | ||
706 | public boolean seekable(){ | ||
707 | return seekable; | ||
708 | } | ||
709 | |||
710 | // returns the bitrate for a given logical bitstream or the entire | ||
711 | // physical bitstream. If the file is open for random access, it will | ||
712 | // find the *actual* average bitrate. If the file is streaming, it | ||
713 | // returns the nominal bitrate (if set) else the average of the | ||
714 | // upper/lower bounds (if set) else -1 (unset). | ||
715 | // | ||
716 | // If you want the actual bitrate field settings, get them from the | ||
717 | // vorbis_info structs | ||
718 | |||
719 | public int bitrate(int i){ | ||
720 | if(i>=links)return(-1); | ||
721 | if(!seekable && i!=0)return(bitrate(0)); | ||
722 | if(i<0){ | ||
723 | long bits=0; | ||
724 | for(int j=0;j<links;j++){ | ||
725 | bits+=(offsets[j+1]-dataoffsets[j])*8; | ||
726 | } | ||
727 | return((int)Math.rint(bits/time_total(-1))); | ||
728 | } | ||
729 | else{ | ||
730 | if(seekable){ | ||
731 | // return the actual bitrate | ||
732 | return((int)Math.rint((offsets[i+1]-dataoffsets[i])*8/time_total(i))); | ||
733 | } | ||
734 | else{ | ||
735 | // return nominal if set | ||
736 | if(vi[i].bitrate_nominal>0){ | ||
737 | return vi[i].bitrate_nominal; | ||
738 | } | ||
739 | else{ | ||
740 | if(vi[i].bitrate_upper>0){ | ||
741 | if(vi[i].bitrate_lower>0){ | ||
742 | return (vi[i].bitrate_upper+vi[i].bitrate_lower)/2; | ||
743 | }else{ | ||
744 | return vi[i].bitrate_upper; | ||
745 | } | ||
746 | } | ||
747 | return(-1); | ||
748 | } | ||
749 | } | ||
750 | } | ||
751 | } | ||
752 | |||
753 | // returns the actual bitrate since last call. returns -1 if no | ||
754 | // additional data to offer since last call (or at beginning of stream) | ||
755 | public int bitrate_instant(){ | ||
756 | int _link=(seekable?current_link:0); | ||
757 | if(samptrack==0)return(-1); | ||
758 | int ret=(int)(bittrack/samptrack*vi[_link].rate+.5); | ||
759 | bittrack=0.f; | ||
760 | samptrack=0.f; | ||
761 | return(ret); | ||
762 | } | ||
763 | |||
764 | public int serialnumber(int i){ | ||
765 | if(i>=links)return(-1); | ||
766 | if(!seekable && i>=0)return(serialnumber(-1)); | ||
767 | if(i<0){ | ||
768 | return(current_serialno); | ||
769 | } | ||
770 | else{ | ||
771 | return(serialnos[i]); | ||
772 | } | ||
773 | } | ||
774 | |||
775 | // returns: total raw (compressed) length of content if i==-1 | ||
776 | // raw (compressed) length of that logical bitstream for i==0 to n | ||
777 | // -1 if the stream is not seekable (we can't know the length) | ||
778 | |||
779 | public long raw_total(int i){ | ||
780 | if(!seekable || i>=links)return(-1); | ||
781 | if(i<0){ | ||
782 | long acc=0; // bug? | ||
783 | for(int j=0;j<links;j++){ | ||
784 | acc+=raw_total(j); | ||
785 | } | ||
786 | return(acc); | ||
787 | } | ||
788 | else{ | ||
789 | return(offsets[i+1]-offsets[i]); | ||
790 | } | ||
791 | } | ||
792 | |||
793 | // returns: total PCM length (samples) of content if i==-1 | ||
794 | // PCM length (samples) of that logical bitstream for i==0 to n | ||
795 | // -1 if the stream is not seekable (we can't know the length) | ||
796 | public long pcm_total(int i){ | ||
797 | if(!seekable || i>=links)return(-1); | ||
798 | if(i<0){ | ||
799 | long acc=0; | ||
800 | for(int j=0;j<links;j++){ | ||
801 | acc+=pcm_total(j); | ||
802 | } | ||
803 | return(acc); | ||
804 | } | ||
805 | else{ | ||
806 | return(pcmlengths[i]); | ||
807 | } | ||
808 | } | ||
809 | |||
810 | // returns: total seconds of content if i==-1 | ||
811 | // seconds in that logical bitstream for i==0 to n | ||
812 | // -1 if the stream is not seekable (we can't know the length) | ||
813 | public float time_total(int i){ | ||
814 | if(!seekable || i>=links)return(-1); | ||
815 | if(i<0){ | ||
816 | float acc=0; | ||
817 | for(int j=0;j<links;j++){ | ||
818 | acc+=time_total(j); | ||
819 | } | ||
820 | return(acc); | ||
821 | } | ||
822 | else{ | ||
823 | return((float)(pcmlengths[i])/vi[i].rate); | ||
824 | } | ||
825 | } | ||
826 | |||
827 | // seek to an offset relative to the *compressed* data. This also | ||
828 | // immediately sucks in and decodes pages to update the PCM cursor. It | ||
829 | // will cross a logical bitstream boundary, but only if it can't get | ||
830 | // any packets out of the tail of the bitstream we seek to (so no | ||
831 | // surprises). | ||
832 | // | ||
833 | // returns zero on success, nonzero on failure | ||
834 | |||
835 | public int raw_seek(int pos){ | ||
836 | if(!seekable)return(-1); // don't dump machine if we can't seek | ||
837 | if(pos<0 || pos>offsets[links]){ | ||
838 | //goto seek_error; | ||
839 | pcm_offset=-1; | ||
840 | decode_clear(); | ||
841 | return -1; | ||
842 | } | ||
843 | |||
844 | // clear out decoding machine state | ||
845 | pcm_offset=-1; | ||
846 | decode_clear(); | ||
847 | |||
848 | // seek | ||
849 | seek_helper(pos); | ||
850 | |||
851 | // we need to make sure the pcm_offset is set. We use the | ||
852 | // _fetch_packet helper to process one packet with readp set, then | ||
853 | // call it until it returns '0' with readp not set (the last packet | ||
854 | // from a page has the 'granulepos' field set, and that's how the | ||
855 | // helper updates the offset | ||
856 | |||
857 | switch(process_packet(1)){ | ||
858 | case 0: | ||
859 | // oh, eof. There are no packets remaining. Set the pcm offset to | ||
860 | // the end of file | ||
861 | pcm_offset=pcm_total(-1); | ||
862 | return(0); | ||
863 | case -1: | ||
864 | // error! missing data or invalid bitstream structure | ||
865 | //goto seek_error; | ||
866 | pcm_offset=-1; | ||
867 | decode_clear(); | ||
868 | return -1; | ||
869 | default: | ||
870 | // all OK | ||
871 | break; | ||
872 | } | ||
873 | while(true){ | ||
874 | switch(process_packet(0)){ | ||
875 | case 0: | ||
876 | // the offset is set. If it's a bogus bitstream with no offset | ||
877 | // information, it's not but that's not our fault. We still run | ||
878 | // gracefully, we're just missing the offset | ||
879 | return(0); | ||
880 | case -1: | ||
881 | // error! missing data or invalid bitstream structure | ||
882 | //goto seek_error; | ||
883 | pcm_offset=-1; | ||
884 | decode_clear(); | ||
885 | return -1; | ||
886 | default: | ||
887 | // continue processing packets | ||
888 | break; | ||
889 | } | ||
890 | } | ||
891 | |||
892 | // seek_error: | ||
893 | // dump the machine so we're in a known state | ||
894 | //pcm_offset=-1; | ||
895 | //decode_clear(); | ||
896 | //return -1; | ||
897 | } | ||
898 | |||
899 | // seek to a sample offset relative to the decompressed pcm stream | ||
900 | // returns zero on success, nonzero on failure | ||
901 | |||
902 | public int pcm_seek(long pos){ | ||
903 | int link=-1; | ||
904 | long total=pcm_total(-1); | ||
905 | |||
906 | if(!seekable)return(-1); // don't dump machine if we can't seek | ||
907 | if(pos<0 || pos>total){ | ||
908 | //goto seek_error; | ||
909 | pcm_offset=-1; | ||
910 | decode_clear(); | ||
911 | return -1; | ||
912 | } | ||
913 | |||
914 | // which bitstream section does this pcm offset occur in? | ||
915 | for(link=links-1;link>=0;link--){ | ||
916 | total-=pcmlengths[link]; | ||
917 | if(pos>=total)break; | ||
918 | } | ||
919 | |||
920 | // search within the logical bitstream for the page with the highest | ||
921 | // pcm_pos preceeding (or equal to) pos. There is a danger here; | ||
922 | // missing pages or incorrect frame number information in the | ||
923 | // bitstream could make our task impossible. Account for that (it | ||
924 | // would be an error condition) | ||
925 | { | ||
926 | long target=pos-total; | ||
927 | long end=offsets[link+1]; | ||
928 | long begin=offsets[link]; | ||
929 | int best=(int)begin; | ||
930 | |||
931 | Page og=new Page(); | ||
932 | while(begin<end){ | ||
933 | long bisect; | ||
934 | int ret; | ||
935 | |||
936 | if(end-begin<CHUNKSIZE){ | ||
937 | bisect=begin; | ||
938 | } | ||
939 | else{ | ||
940 | bisect=(end+begin)/2; | ||
941 | } | ||
942 | |||
943 | seek_helper(bisect); | ||
944 | ret=get_next_page(og,end-bisect); | ||
945 | |||
946 | if(ret==-1){ | ||
947 | end=bisect; | ||
948 | } | ||
949 | else{ | ||
950 | long granulepos=og.granulepos(); | ||
951 | if(granulepos<target){ | ||
952 | best=ret; // raw offset of packet with granulepos | ||
953 | begin=offset; // raw offset of next packet | ||
954 | } | ||
955 | else{ | ||
956 | end=bisect; | ||
957 | } | ||
958 | } | ||
959 | } | ||
960 | // found our page. seek to it (call raw_seek). | ||
961 | if(raw_seek(best)!=0){ | ||
962 | //goto seek_error; | ||
963 | pcm_offset=-1; | ||
964 | decode_clear(); | ||
965 | return -1; | ||
966 | } | ||
967 | } | ||
968 | |||
969 | // verify result | ||
970 | if(pcm_offset>=pos){ | ||
971 | //goto seek_error; | ||
972 | pcm_offset=-1; | ||
973 | decode_clear(); | ||
974 | return -1; | ||
975 | } | ||
976 | if(pos>pcm_total(-1)){ | ||
977 | //goto seek_error; | ||
978 | pcm_offset=-1; | ||
979 | decode_clear(); | ||
980 | return -1; | ||
981 | } | ||
982 | |||
983 | // discard samples until we reach the desired position. Crossing a | ||
984 | // logical bitstream boundary with abandon is OK. | ||
985 | while(pcm_offset<pos){ | ||
986 | float[][] pcm; | ||
987 | int target=(int)(pos-pcm_offset); | ||
988 | float[][][] _pcm=new float[1][][]; | ||
989 | int[] _index=new int[getInfo(-1).channels]; | ||
990 | int samples=vd.synthesis_pcmout(_pcm, _index); | ||
991 | pcm=_pcm[0]; | ||
992 | |||
993 | if(samples>target)samples=target; | ||
994 | vd.synthesis_read(samples); | ||
995 | pcm_offset+=samples; | ||
996 | |||
997 | if(samples<target) | ||
998 | if(process_packet(1)==0){ | ||
999 | pcm_offset=pcm_total(-1); // eof | ||
1000 | } | ||
1001 | } | ||
1002 | return 0; | ||
1003 | |||
1004 | // seek_error: | ||
1005 | // dump machine so we're in a known state | ||
1006 | //pcm_offset=-1; | ||
1007 | //decode_clear(); | ||
1008 | //return -1; | ||
1009 | } | ||
1010 | |||
1011 | // seek to a playback time relative to the decompressed pcm stream | ||
1012 | // returns zero on success, nonzero on failure | ||
1013 | int time_seek(float seconds){ | ||
1014 | // translate time to PCM position and call pcm_seek | ||
1015 | |||
1016 | int link=-1; | ||
1017 | long pcm_total=pcm_total(-1); | ||
1018 | float time_total=time_total(-1); | ||
1019 | |||
1020 | if(!seekable)return(-1); // don't dump machine if we can't seek | ||
1021 | if(seconds<0 || seconds>time_total){ | ||
1022 | //goto seek_error; | ||
1023 | pcm_offset=-1; | ||
1024 | decode_clear(); | ||
1025 | return -1; | ||
1026 | } | ||
1027 | |||
1028 | // which bitstream section does this time offset occur in? | ||
1029 | for(link=links-1;link>=0;link--){ | ||
1030 | pcm_total-=pcmlengths[link]; | ||
1031 | time_total-=time_total(link); | ||
1032 | if(seconds>=time_total)break; | ||
1033 | } | ||
1034 | |||
1035 | // enough information to convert time offset to pcm offset | ||
1036 | { | ||
1037 | long target=(long)(pcm_total+(seconds-time_total)*vi[link].rate); | ||
1038 | return(pcm_seek(target)); | ||
1039 | } | ||
1040 | |||
1041 | //seek_error: | ||
1042 | // dump machine so we're in a known state | ||
1043 | //pcm_offset=-1; | ||
1044 | //decode_clear(); | ||
1045 | //return -1; | ||
1046 | } | ||
1047 | |||
1048 | // tell the current stream offset cursor. Note that seek followed by | ||
1049 | // tell will likely not give the set offset due to caching | ||
1050 | public long raw_tell(){ | ||
1051 | return(offset); | ||
1052 | } | ||
1053 | |||
1054 | // return PCM offset (sample) of next PCM sample to be read | ||
1055 | public long pcm_tell(){ | ||
1056 | return(pcm_offset); | ||
1057 | } | ||
1058 | |||
1059 | // return time offset (seconds) of next PCM sample to be read | ||
1060 | public float time_tell(){ | ||
1061 | // translate time to PCM position and call pcm_seek | ||
1062 | |||
1063 | int link=-1; | ||
1064 | long pcm_total=0; | ||
1065 | float time_total=0.f; | ||
1066 | |||
1067 | if(seekable){ | ||
1068 | pcm_total=pcm_total(-1); | ||
1069 | time_total=time_total(-1); | ||
1070 | |||
1071 | // which bitstream section does this time offset occur in? | ||
1072 | for(link=links-1;link>=0;link--){ | ||
1073 | pcm_total-=pcmlengths[link]; | ||
1074 | time_total-=time_total(link); | ||
1075 | if(pcm_offset>=pcm_total)break; | ||
1076 | } | ||
1077 | } | ||
1078 | |||
1079 | return((float)time_total+(float)(pcm_offset-pcm_total)/vi[link].rate); | ||
1080 | } | ||
1081 | |||
1082 | // link: -1) return the vorbis_info struct for the bitstream section | ||
1083 | // currently being decoded | ||
1084 | // 0-n) to request information for a specific bitstream section | ||
1085 | // | ||
1086 | // In the case of a non-seekable bitstream, any call returns the | ||
1087 | // current bitstream. NULL in the case that the machine is not | ||
1088 | // initialized | ||
1089 | |||
1090 | public Info getInfo(int link){ | ||
1091 | if(seekable){ | ||
1092 | if(link<0){ | ||
1093 | if(decode_ready){ | ||
1094 | return vi[current_link]; | ||
1095 | } | ||
1096 | else{ | ||
1097 | return null; | ||
1098 | } | ||
1099 | } | ||
1100 | else{ | ||
1101 | if(link>=links){ | ||
1102 | return null; | ||
1103 | } | ||
1104 | else{ | ||
1105 | return vi[link]; | ||
1106 | } | ||
1107 | } | ||
1108 | } | ||
1109 | else{ | ||
1110 | if(decode_ready){ | ||
1111 | return vi[0]; | ||
1112 | } | ||
1113 | else{ | ||
1114 | return null; | ||
1115 | } | ||
1116 | } | ||
1117 | } | ||
1118 | |||
1119 | public Comment getComment(int link){ | ||
1120 | if(seekable){ | ||
1121 | if(link<0){ | ||
1122 | if(decode_ready){ return vc[current_link]; } | ||
1123 | else{ return null; } | ||
1124 | } | ||
1125 | else{ | ||
1126 | if(link>=links){ return null;} | ||
1127 | else{ return vc[link]; } | ||
1128 | } | ||
1129 | } | ||
1130 | else{ | ||
1131 | if(decode_ready){ return vc[0]; } | ||
1132 | else{ return null; } | ||
1133 | } | ||
1134 | } | ||
1135 | |||
1136 | int host_is_big_endian() { | ||
1137 | return 1; | ||
1138 | // short pattern = 0xbabe; | ||
1139 | // unsigned char *bytewise = (unsigned char *)&pattern; | ||
1140 | // if (bytewise[0] == 0xba) return 1; | ||
1141 | // assert(bytewise[0] == 0xbe); | ||
1142 | // return 0; | ||
1143 | } | ||
1144 | |||
1145 | // up to this point, everything could more or less hide the multiple | ||
1146 | // logical bitstream nature of chaining from the toplevel application | ||
1147 | // if the toplevel application didn't particularly care. However, at | ||
1148 | // the point that we actually read audio back, the multiple-section | ||
1149 | // nature must surface: Multiple bitstream sections do not necessarily | ||
1150 | // have to have the same number of channels or sampling rate. | ||
1151 | // | ||
1152 | // read returns the sequential logical bitstream number currently | ||
1153 | // being decoded along with the PCM data in order that the toplevel | ||
1154 | // application can take action on channel/sample rate changes. This | ||
1155 | // number will be incremented even for streamed (non-seekable) streams | ||
1156 | // (for seekable streams, it represents the actual logical bitstream | ||
1157 | // index within the physical bitstream. Note that the accessor | ||
1158 | // functions above are aware of this dichotomy). | ||
1159 | // | ||
1160 | // input values: buffer) a buffer to hold packed PCM data for return | ||
1161 | // length) the byte length requested to be placed into buffer | ||
1162 | // bigendianp) should the data be packed LSB first (0) or | ||
1163 | // MSB first (1) | ||
1164 | // word) word size for output. currently 1 (byte) or | ||
1165 | // 2 (16 bit short) | ||
1166 | // | ||
1167 | // return values: -1) error/hole in data | ||
1168 | // 0) EOF | ||
1169 | // n) number of bytes of PCM actually returned. The | ||
1170 | // below works on a packet-by-packet basis, so the | ||
1171 | // return length is not related to the 'length' passed | ||
1172 | // in, just guaranteed to fit. | ||
1173 | // | ||
1174 | // *section) set to the logical bitstream number | ||
1175 | |||
1176 | int read(byte[] buffer,int length, | ||
1177 | int bigendianp, int word, int sgned, int[] bitstream){ | ||
1178 | int host_endian = host_is_big_endian(); | ||
1179 | int index=0; | ||
1180 | |||
1181 | while(true){ | ||
1182 | if(decode_ready){ | ||
1183 | float[][] pcm; | ||
1184 | float[][][] _pcm=new float[1][][]; | ||
1185 | int[] _index=new int[getInfo(-1).channels]; | ||
1186 | int samples=vd.synthesis_pcmout(_pcm, _index); | ||
1187 | pcm=_pcm[0]; | ||
1188 | if(samples!=0){ | ||
1189 | // yay! proceed to pack data into the byte buffer | ||
1190 | int channels=getInfo(-1).channels; | ||
1191 | int bytespersample=word * channels; | ||
1192 | if(samples>length/bytespersample)samples=length/bytespersample; | ||
1193 | |||
1194 | // a tight loop to pack each size | ||
1195 | { | ||
1196 | int val; | ||
1197 | if(word==1){ | ||
1198 | int off=(sgned!=0?0:128); | ||
1199 | for(int j=0;j<samples;j++){ | ||
1200 | for(int i=0;i<channels;i++){ | ||
1201 | val=(int)(pcm[i][_index[i]+j]*128. + 0.5); | ||
1202 | if(val>127)val=127; | ||
1203 | else if(val<-128)val=-128; | ||
1204 | buffer[index++]=(byte)(val+off); | ||
1205 | } | ||
1206 | } | ||
1207 | } | ||
1208 | else{ | ||
1209 | int off=(sgned!=0?0:32768); | ||
1210 | |||
1211 | if(host_endian==bigendianp){ | ||
1212 | if(sgned!=0){ | ||
1213 | for(int i=0;i<channels;i++) { // It's faster in this order | ||
1214 | int src=_index[i]; | ||
1215 | int dest=i; | ||
1216 | for(int j=0;j<samples;j++) { | ||
1217 | val=(int)(pcm[i][src+j]*32768. + 0.5); | ||
1218 | if(val>32767)val=32767; | ||
1219 | else if(val<-32768)val=-32768; | ||
1220 | buffer[dest]=(byte)(val>>>8); | ||
1221 | buffer[dest+1]=(byte)(val); | ||
1222 | dest+=channels*2; | ||
1223 | } | ||
1224 | } | ||
1225 | } | ||
1226 | else{ | ||
1227 | for(int i=0;i<channels;i++) { | ||
1228 | float[] src=pcm[i]; | ||
1229 | int dest=i; | ||
1230 | for(int j=0;j<samples;j++) { | ||
1231 | val=(int)(src[j]*32768. + 0.5); | ||
1232 | if(val>32767)val=32767; | ||
1233 | else if(val<-32768)val=-32768; | ||
1234 | buffer[dest]=(byte)((val+off)>>>8); | ||
1235 | buffer[dest+1]=(byte)(val+off); | ||
1236 | dest+=channels*2; | ||
1237 | } | ||
1238 | } | ||
1239 | } | ||
1240 | } | ||
1241 | else if(bigendianp!=0){ | ||
1242 | for(int j=0;j<samples;j++){ | ||
1243 | for(int i=0;i<channels;i++){ | ||
1244 | val=(int)(pcm[i][j]*32768. + 0.5); | ||
1245 | if(val>32767)val=32767; | ||
1246 | else if(val<-32768)val=-32768; | ||
1247 | val+=off; | ||
1248 | buffer[index++]=(byte)(val>>>8); | ||
1249 | buffer[index++]=(byte)val; | ||
1250 | } | ||
1251 | } | ||
1252 | } | ||
1253 | else{ | ||
1254 | //int val; | ||
1255 | for(int j=0;j<samples;j++){ | ||
1256 | for(int i=0;i<channels;i++){ | ||
1257 | val=(int)(pcm[i][j]*32768. + 0.5); | ||
1258 | if(val>32767)val=32767; | ||
1259 | else if(val<-32768)val=-32768; | ||
1260 | val+=off; | ||
1261 | buffer[index++]=(byte)val; | ||
1262 | buffer[index++]=(byte)(val>>>8); | ||
1263 | } | ||
1264 | } | ||
1265 | } | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | vd.synthesis_read(samples); | ||
1270 | pcm_offset+=samples; | ||
1271 | if(bitstream!=null)bitstream[0]=current_link; | ||
1272 | return(samples*bytespersample); | ||
1273 | } | ||
1274 | } | ||
1275 | |||
1276 | // suck in another packet | ||
1277 | switch(process_packet(1)){ | ||
1278 | case 0: | ||
1279 | return(0); | ||
1280 | case -1: | ||
1281 | return -1; | ||
1282 | default: | ||
1283 | break; | ||
1284 | } | ||
1285 | } | ||
1286 | } | ||
1287 | |||
1288 | public Info[] getInfo(){return vi;} | ||
1289 | public Comment[] getComment(){return vc;} | ||
1290 | |||
1291 | /* | ||
1292 | public static void main(String[] arg){ | ||
1293 | try{ | ||
1294 | VorbisFile foo=new VorbisFile(arg[0]); | ||
1295 | int links=foo.streams(); | ||
1296 | System.out.println("links="+links); | ||
1297 | Comment[] comment=foo.getComment(); | ||
1298 | Info[] info=foo.getInfo(); | ||
1299 | for(int i=0; i<links; i++){ | ||
1300 | System.out.println(info[i]); | ||
1301 | System.out.println(comment[i]); | ||
1302 | } | ||
1303 | System.out.println("raw_total: "+foo.raw_total(-1)); | ||
1304 | System.out.println("pcm_total: "+foo.pcm_total(-1)); | ||
1305 | System.out.println("time_total: "+foo.time_total(-1)); | ||
1306 | } | ||
1307 | catch(Exception e){ | ||
1308 | System.err.println(e); | ||
1309 | } | ||
1310 | } | ||
1311 | */ | ||
1312 | |||
1313 | public void close() throws java.io.IOException { | ||
1314 | datasource.close(); | ||
1315 | } | ||
1316 | |||
1317 | class SeekableInputStream extends InputStream { | ||
1318 | java.io.RandomAccessFile raf=null; | ||
1319 | final String mode="r"; | ||
1320 | private SeekableInputStream(){ | ||
1321 | } | ||
1322 | SeekableInputStream(String file) throws java.io.IOException{ | ||
1323 | raf=new java.io.RandomAccessFile(file, mode); | ||
1324 | } | ||
1325 | public int read() throws java.io.IOException{ | ||
1326 | return raf.read(); | ||
1327 | } | ||
1328 | public int read(byte[] buf) throws java.io.IOException{ | ||
1329 | return raf.read(buf); | ||
1330 | } | ||
1331 | public int read(byte[] buf , int s, int len) throws java.io.IOException{ | ||
1332 | return raf.read(buf, s, len); | ||
1333 | } | ||
1334 | public long skip(long n) throws java.io.IOException{ | ||
1335 | return (long)(raf.skipBytes((int)n)); | ||
1336 | } | ||
1337 | public long getLength() throws java.io.IOException{ | ||
1338 | return raf.length(); | ||
1339 | } | ||
1340 | public long tell() throws java.io.IOException{ | ||
1341 | return raf.getFilePointer(); | ||
1342 | } | ||
1343 | public int available() throws java.io.IOException{ | ||
1344 | return (raf.length()==raf.getFilePointer())? 0 : 1; | ||
1345 | } | ||
1346 | public void close() throws java.io.IOException{ | ||
1347 | raf.close(); | ||
1348 | } | ||
1349 | public synchronized void mark(int m){ | ||
1350 | } | ||
1351 | public synchronized void reset() throws java.io.IOException{ | ||
1352 | } | ||
1353 | public boolean markSupported(){ | ||
1354 | return false; | ||
1355 | } | ||
1356 | public void seek(long pos) throws java.io.IOException{ | ||
1357 | raf.seek(pos); | ||
1358 | } | ||
1359 | } | ||
1360 | |||
1361 | } | ||
diff --git a/songdbj/com/jcraft/jorbis/VorbisFile.java.new b/songdbj/com/jcraft/jorbis/VorbisFile.java.new new file mode 100644 index 0000000000..1f822b0991 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/VorbisFile.java.new | |||
@@ -0,0 +1,1240 @@ | |||
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 | import java.io.InputStream; | ||
30 | |||
31 | public class VorbisFile{ | ||
32 | static final int CHUNKSIZE=4096; | ||
33 | static final int SEEK_SET=0; | ||
34 | |||
35 | InputStream datasource; | ||
36 | boolean seekable=false; | ||
37 | long offset; | ||
38 | long end; | ||
39 | |||
40 | SyncState oy=new SyncState(); | ||
41 | |||
42 | int links; | ||
43 | Comment[] vc; | ||
44 | Info[] vi; | ||
45 | |||
46 | long[] offsets; | ||
47 | long[] dataoffsets; | ||
48 | int[] serialnos; | ||
49 | long[] pcmlengths; | ||
50 | |||
51 | |||
52 | |||
53 | // Decoding working state local storage | ||
54 | long pcm_offset; | ||
55 | boolean decode_ready=false; | ||
56 | int current_serialno; | ||
57 | int current_link; | ||
58 | |||
59 | float bittrack; | ||
60 | float samptrack; | ||
61 | |||
62 | StreamState os=new StreamState(); // take physical pages, weld into a logical | ||
63 | // stream of packets | ||
64 | DspState vd=new DspState(); // central working state for | ||
65 | // the packet->PCM decoder | ||
66 | Block vb=new Block(vd); // local working space for packet->PCM decode | ||
67 | |||
68 | //ov_callbacks callbacks; | ||
69 | |||
70 | public VorbisFile(String file) throws JOrbisException { | ||
71 | super(); | ||
72 | InputStream is=null; | ||
73 | try{ is=new java.io.BufferedInputStream(new java.io.FileInputStream(file));} | ||
74 | catch(Exception e){ | ||
75 | throw new JOrbisException("VorbisFile: "+e.toString()); | ||
76 | } | ||
77 | int ret=open(is, null, 0); | ||
78 | if(ret==-1){ | ||
79 | throw new JOrbisException("VorbisFile: open return -1"); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | public VorbisFile(InputStream is, byte[] initial, int ibytes) | ||
84 | throws JOrbisException { | ||
85 | super(); | ||
86 | int ret=open(is, initial, ibytes); | ||
87 | if(ret==-1){ | ||
88 | } | ||
89 | } | ||
90 | |||
91 | private int get_data(){ | ||
92 | int index=oy.buffer(CHUNKSIZE); | ||
93 | byte[] buffer=oy.data; | ||
94 | // int bytes=callbacks.read_func(buffer, index, 1, CHUNKSIZE, datasource); | ||
95 | int bytes=0; | ||
96 | try{ | ||
97 | bytes=datasource.read(buffer, index, CHUNKSIZE); | ||
98 | } | ||
99 | catch(Exception e){System.err.println(e);} | ||
100 | oy.wrote(bytes); | ||
101 | return bytes; | ||
102 | } | ||
103 | |||
104 | private void seek_helper(int offst){ | ||
105 | //callbacks.seek_func(datasource, offst, SEEK_SET); | ||
106 | fseek64_wrap(datasource, offst, SEEK_SET); | ||
107 | this.offset=offst; | ||
108 | oy.reset(); | ||
109 | } | ||
110 | |||
111 | private int get_next_page(Page page, int boundary){ | ||
112 | if(boundary>0) boundary+=offset; | ||
113 | while(true){ | ||
114 | int more; | ||
115 | if(boundary>0 && offset>=boundary)return -1; | ||
116 | more=oy.pageseek(page); | ||
117 | if(more<0){offset-=more;} | ||
118 | else{ | ||
119 | if(more==0){ | ||
120 | if(boundary==0)return -1; | ||
121 | if(get_data()<=0)return -1; | ||
122 | } | ||
123 | else{ | ||
124 | int ret=(int)offset; //!!! | ||
125 | offset+=more; | ||
126 | return ret; | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | } | ||
131 | |||
132 | private int get_prev_page(Page page){ | ||
133 | int begin=(int)offset; //!!! | ||
134 | int ret; | ||
135 | int offst=-1; | ||
136 | while(offst==-1){ | ||
137 | begin-=CHUNKSIZE; | ||
138 | seek_helper(begin); | ||
139 | while(offset<begin+CHUNKSIZE){ | ||
140 | ret=get_next_page(page, begin+CHUNKSIZE-((int)offset)); | ||
141 | if(ret==-1){ break; } | ||
142 | else{ offst=ret; } | ||
143 | } | ||
144 | } | ||
145 | seek_helper((int)offset); //!!! | ||
146 | ret=get_next_page(page, CHUNKSIZE); | ||
147 | if(ret==-1){ | ||
148 | System.err.println("Missed page fencepost at end of logical bitstream Exiting"); | ||
149 | System.exit(1); | ||
150 | } | ||
151 | return offst; | ||
152 | } | ||
153 | |||
154 | void bisect_forward_serialno(int begin, int searched, int end, int currentno, int m){ | ||
155 | int endsearched=end; | ||
156 | int next=end; | ||
157 | Page page=new Page(); | ||
158 | int ret; | ||
159 | while(searched<endsearched){ | ||
160 | int bisect; | ||
161 | if(endsearched-searched<CHUNKSIZE){ | ||
162 | bisect=searched; | ||
163 | } | ||
164 | else{ | ||
165 | bisect=(searched+endsearched)/2; | ||
166 | } | ||
167 | |||
168 | seek_helper(bisect); | ||
169 | ret=get_next_page(page, -1); | ||
170 | if(ret<0 || page.serialno()!=currentno){ | ||
171 | endsearched=bisect; | ||
172 | if(ret>=0)next=ret; | ||
173 | } | ||
174 | else{ | ||
175 | searched=ret+page.header_len+page.body_len; | ||
176 | } | ||
177 | } | ||
178 | seek_helper(next); | ||
179 | ret=get_next_page(page, -1); | ||
180 | |||
181 | if(searched>=end || ret==-1){ | ||
182 | links=m+1; | ||
183 | offsets=new long[m+2]; | ||
184 | offsets[m+1]=searched; | ||
185 | } | ||
186 | else{ | ||
187 | bisect_forward_serialno(next, (int)offset, end, page.serialno(), m+1); | ||
188 | } | ||
189 | offsets[m]=begin; | ||
190 | } | ||
191 | |||
192 | // uses the local ogg_stream storage in vf; this is important for | ||
193 | // non-streaming input sources | ||
194 | int fetch_headers(Info vi, Comment vc, int[] serialno){ | ||
195 | //System.err.println("fetch_headers"); | ||
196 | Page og=new Page(); | ||
197 | Packet op=new Packet(); | ||
198 | int ret; | ||
199 | |||
200 | ret=get_next_page(og, CHUNKSIZE); | ||
201 | if(ret==-1){ | ||
202 | System.err.println("Did not find initial header for bitstream."); | ||
203 | return -1; | ||
204 | } | ||
205 | |||
206 | if(serialno!=null)serialno[0]=og.serialno(); | ||
207 | |||
208 | os.init(og.serialno()); | ||
209 | |||
210 | // extract the initial header from the first page and verify that the | ||
211 | // Ogg bitstream is in fact Vorbis data | ||
212 | |||
213 | vi.init(); | ||
214 | vc.init(); | ||
215 | |||
216 | int i=0; | ||
217 | while(i<3){ | ||
218 | os.pagein(og); | ||
219 | while(i<3){ | ||
220 | int result=os.packetout(op); | ||
221 | if(result==0)break; | ||
222 | if(result==-1){ | ||
223 | System.err.println("Corrupt header in logical bitstream."); | ||
224 | //goto bail_header; | ||
225 | vi.clear(); | ||
226 | vc.clear(); | ||
227 | os.clear(); | ||
228 | return -1; | ||
229 | } | ||
230 | if(vi.synthesis_headerin(vc, op)!=0){ | ||
231 | System.err.println("Illegal header in logical bitstream."); | ||
232 | //goto bail_header; | ||
233 | vi.clear(); | ||
234 | vc.clear(); | ||
235 | os.clear(); | ||
236 | return -1; | ||
237 | } | ||
238 | i++; | ||
239 | } | ||
240 | if(i<3) | ||
241 | if(get_next_page(og, 1)<0){ | ||
242 | System.err.println("Missing header in logical bitstream."); | ||
243 | //goto bail_header; | ||
244 | vi.clear(); | ||
245 | vc.clear(); | ||
246 | os.clear(); | ||
247 | return -1; | ||
248 | } | ||
249 | } | ||
250 | return 0; | ||
251 | |||
252 | // bail_header: | ||
253 | // vorbis_info_clear(vi); | ||
254 | // vorbis_comment_clear(vc); | ||
255 | // ogg_stream_clear(&vf->os); | ||
256 | // return -1; | ||
257 | } | ||
258 | |||
259 | // last step of the OggVorbis_File initialization; get all the | ||
260 | // vorbis_info structs and PCM positions. Only called by the seekable | ||
261 | // initialization (local stream storage is hacked slightly; pay | ||
262 | // attention to how that's done) | ||
263 | void prefetch_all_headers(Info first_i,Comment first_c, int dataoffset){ | ||
264 | Page og=new Page(); | ||
265 | int ret; | ||
266 | |||
267 | vi=new Info[links]; | ||
268 | vc=new Comment[links]; | ||
269 | dataoffsets=new long[links]; | ||
270 | pcmlengths=new long[links]; | ||
271 | serialnos=new int[links]; | ||
272 | |||
273 | for(int i=0;i<links;i++){ | ||
274 | if(first_i!=null && first_c!=null && i==0){ | ||
275 | // we already grabbed the initial header earlier. This just | ||
276 | // saves the waste of grabbing it again | ||
277 | // !!!!!!!!!!!!! | ||
278 | vi[i]=first_i; | ||
279 | //memcpy(vf->vi+i,first_i,sizeof(vorbis_info)); | ||
280 | vc[i]=first_c; | ||
281 | //memcpy(vf->vc+i,first_c,sizeof(vorbis_comment)); | ||
282 | dataoffsets[i]=dataoffset; | ||
283 | } | ||
284 | else{ | ||
285 | // seek to the location of the initial header | ||
286 | seek_helper((int)offsets[i]); //!!! | ||
287 | if(fetch_headers(vi[i], vc[i], null)==-1){ | ||
288 | System.err.println("Error opening logical bitstream #"+(i+1)+"\n"); | ||
289 | dataoffsets[i]=-1; | ||
290 | } | ||
291 | else{ | ||
292 | dataoffsets[i]=offset; | ||
293 | os.clear(); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | // get the serial number and PCM length of this link. To do this, | ||
298 | // get the last page of the stream | ||
299 | { | ||
300 | int end=(int)offsets[i+1]; //!!! | ||
301 | seek_helper(end); | ||
302 | |||
303 | while(true){ | ||
304 | ret=get_prev_page(og); | ||
305 | if(ret==-1){ | ||
306 | // this should not be possible | ||
307 | System.err.println("Could not find last page of logical "+ | ||
308 | "bitstream #"+(i)+"\n"); | ||
309 | vi[i].clear(); | ||
310 | vc[i].clear(); | ||
311 | break; | ||
312 | } | ||
313 | if(og.granulepos()!=-1){ | ||
314 | serialnos[i]=og.serialno(); | ||
315 | pcmlengths[i]=og.granulepos(); | ||
316 | break; | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | } | ||
322 | |||
323 | int make_decode_ready(){ | ||
324 | if(decode_ready)System.exit(1); | ||
325 | vd.synthesis_init(vi[0]); | ||
326 | vb.init(vd); | ||
327 | decode_ready=true; | ||
328 | return(0); | ||
329 | } | ||
330 | |||
331 | int open_seekable(){ | ||
332 | Info initial_i=new Info(); | ||
333 | Comment initial_c=new Comment(); | ||
334 | int serialno,end; | ||
335 | int ret; | ||
336 | int dataoffset; | ||
337 | Page og=new Page(); | ||
338 | System.out.println("open_seekable"); | ||
339 | // is this even vorbis...? | ||
340 | int[] foo=new int[1]; | ||
341 | ret=fetch_headers(initial_i, initial_c, foo); | ||
342 | serialno=foo[0]; | ||
343 | dataoffset=(int)offset; //!! | ||
344 | os.clear(); | ||
345 | if(ret==-1)return(-1); | ||
346 | |||
347 | // we can seek, so set out learning all about this file | ||
348 | seekable=true; | ||
349 | //(callbacks.seek_func)(datasource, 0, SEEK_END); | ||
350 | fseek64_wrap(datasource, (int)offset, SEEK_SET); | ||
351 | //offset=end=(callbacks.tell_func)(datasource); | ||
352 | end=(int)offset; | ||
353 | |||
354 | // We get the offset for the last page of the physical bitstream. | ||
355 | // Most OggVorbis files will contain a single logical bitstream | ||
356 | end=get_prev_page(og); | ||
357 | |||
358 | // moer than one logical bitstream? | ||
359 | if(og.serialno()!=serialno){ | ||
360 | // Chained bitstream. Bisect-search each logical bitstream | ||
361 | // section. Do so based on serial number only | ||
362 | bisect_forward_serialno(0,0,end+1,serialno,0); | ||
363 | } | ||
364 | else{ | ||
365 | // Only one logical bitstream | ||
366 | bisect_forward_serialno(0,end,end+1,serialno,0); | ||
367 | } | ||
368 | prefetch_all_headers(initial_i, initial_c, dataoffset); | ||
369 | |||
370 | System.out.println("?"); | ||
371 | return(raw_seek(0)); | ||
372 | } | ||
373 | |||
374 | int open_nonseekable(){ | ||
375 | //System.err.println("open_nonseekable"); | ||
376 | // we cannot seek. Set up a 'single' (current) logical bitstream entry | ||
377 | links=1; | ||
378 | vi=new Info[links]; vi[0]=new Info(); // ?? | ||
379 | vc=new Comment[links]; vc[0]=new Comment(); // ?? bug? | ||
380 | |||
381 | // Try to fetch the headers, maintaining all the storage | ||
382 | int[]foo=new int[1]; | ||
383 | if(fetch_headers(vi[0], vc[0], foo)==-1)return(-1); | ||
384 | current_serialno=foo[0]; | ||
385 | make_decode_ready(); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | // clear out the current logical bitstream decoder | ||
390 | void decode_clear(){ | ||
391 | os.clear(); | ||
392 | vd.clear(); | ||
393 | vb.clear(); | ||
394 | decode_ready=false; | ||
395 | bittrack=0.f; | ||
396 | samptrack=0.f; | ||
397 | } | ||
398 | |||
399 | // fetch and process a packet. Handles the case where we're at a | ||
400 | // bitstream boundary and dumps the decoding machine. If the decoding | ||
401 | // machine is unloaded, it loads it. It also keeps pcm_offset up to | ||
402 | // date (seek and read both use this. seek uses a special hack with | ||
403 | // readp). | ||
404 | // | ||
405 | // return: -1) hole in the data (lost packet) | ||
406 | // 0) need more date (only if readp==0)/eof | ||
407 | // 1) got a packet | ||
408 | |||
409 | int process_packet(int readp){ | ||
410 | System.out.println("porcess_packet:"+ readp+" , decode_ready="+decode_ready); | ||
411 | Page og=new Page(); | ||
412 | |||
413 | // handle one packet. Try to fetch it from current stream state | ||
414 | // extract packets from page | ||
415 | while(true){ | ||
416 | // process a packet if we can. If the machine isn't loaded, | ||
417 | // neither is a page | ||
418 | if(decode_ready){ | ||
419 | Packet op=new Packet(); | ||
420 | int result=os.packetout(op); | ||
421 | long granulepos; | ||
422 | // if(result==-1)return(-1); // hole in the data. For now, swallow | ||
423 | // and go. We'll need to add a real | ||
424 | // error code in a bit. | ||
425 | if(result>0){ | ||
426 | // got a packet. process it | ||
427 | granulepos=op.granulepos; | ||
428 | if(vb.synthesis(op)==0){ // lazy check for lazy | ||
429 | // header handling. The | ||
430 | // header packets aren't | ||
431 | // audio, so if/when we | ||
432 | // submit them, | ||
433 | // vorbis_synthesis will | ||
434 | // reject them | ||
435 | // suck in the synthesis data and track bitrate | ||
436 | { | ||
437 | int oldsamples=vd.synthesis_pcmout(null, null); | ||
438 | vd.synthesis_blockin(vb); | ||
439 | samptrack+=vd.synthesis_pcmout(null, null)-oldsamples; | ||
440 | bittrack+=op.bytes*8; | ||
441 | } | ||
442 | |||
443 | // update the pcm offset. | ||
444 | if(granulepos!=-1 && op.e_o_s==0){ | ||
445 | int link=(seekable?current_link:0); | ||
446 | int samples; | ||
447 | // this packet has a pcm_offset on it (the last packet | ||
448 | // completed on a page carries the offset) After processing | ||
449 | // (above), we know the pcm position of the *last* sample | ||
450 | // ready to be returned. Find the offset of the *first* | ||
451 | // | ||
452 | // As an aside, this trick is inaccurate if we begin | ||
453 | // reading anew right at the last page; the end-of-stream | ||
454 | // granulepos declares the last frame in the stream, and the | ||
455 | // last packet of the last page may be a partial frame. | ||
456 | // So, we need a previous granulepos from an in-sequence page | ||
457 | // to have a reference point. Thus the !op.e_o_s clause above | ||
458 | |||
459 | samples=vd.synthesis_pcmout(null, null); | ||
460 | granulepos-=samples; | ||
461 | for(int i=0;i<link;i++){ | ||
462 | granulepos+=pcmlengths[i]; | ||
463 | } | ||
464 | pcm_offset=granulepos; | ||
465 | } | ||
466 | return(1); | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | |||
471 | if(readp==0)return(0); | ||
472 | if(get_next_page(og,-1)<0)return(0); // eof. leave unitialized | ||
473 | |||
474 | // bitrate tracking; add the header's bytes here, the body bytes | ||
475 | // are done by packet above | ||
476 | bittrack+=og.header_len*8; | ||
477 | |||
478 | // has our decoding just traversed a bitstream boundary? | ||
479 | if(decode_ready){ | ||
480 | if(current_serialno!=og.serialno()){ | ||
481 | decode_clear(); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | // Do we need to load a new machine before submitting the page? | ||
486 | // This is different in the seekable and non-seekable cases. | ||
487 | // | ||
488 | // In the seekable case, we already have all the header | ||
489 | // information loaded and cached; we just initialize the machine | ||
490 | // with it and continue on our merry way. | ||
491 | // | ||
492 | // In the non-seekable (streaming) case, we'll only be at a | ||
493 | // boundary if we just left the previous logical bitstream and | ||
494 | // we're now nominally at the header of the next bitstream | ||
495 | |||
496 | if(!decode_ready){ | ||
497 | int i; | ||
498 | if(seekable){ | ||
499 | current_serialno=og.serialno(); | ||
500 | |||
501 | // match the serialno to bitstream section. We use this rather than | ||
502 | // offset positions to avoid problems near logical bitstream | ||
503 | // boundaries | ||
504 | for(i=0;i<links;i++){ | ||
505 | if(serialnos[i]==current_serialno)break; | ||
506 | } | ||
507 | if(i==links)return(-1); // sign of a bogus stream. error out, | ||
508 | // leave machine uninitialized | ||
509 | current_link=i; | ||
510 | |||
511 | os.init(current_serialno); | ||
512 | os.reset(); | ||
513 | |||
514 | } | ||
515 | else{ | ||
516 | // we're streaming | ||
517 | // fetch the three header packets, build the info struct | ||
518 | int foo[]=new int[1]; | ||
519 | fetch_headers(vi[0], vc[0], foo); | ||
520 | current_serialno=foo[0]; | ||
521 | current_link++; | ||
522 | i=0; | ||
523 | } | ||
524 | make_decode_ready(); | ||
525 | } | ||
526 | os.pagein(og); | ||
527 | } | ||
528 | } | ||
529 | |||
530 | //The helpers are over; it's all toplevel interface from here on out | ||
531 | // clear out the OggVorbis_File struct | ||
532 | int clear(){ | ||
533 | vb.clear(); | ||
534 | vd.clear(); | ||
535 | os.clear(); | ||
536 | |||
537 | if(vi!=null && links!=0){ | ||
538 | for(int i=0;i<links;i++){ | ||
539 | vi[i].clear(); | ||
540 | vc[i].clear(); | ||
541 | } | ||
542 | vi=null; | ||
543 | vc=null; | ||
544 | } | ||
545 | if(dataoffsets!=null)dataoffsets=null; | ||
546 | if(pcmlengths!=null)pcmlengths=null; | ||
547 | if(serialnos!=null)serialnos=null; | ||
548 | if(offsets!=null)offsets=null; | ||
549 | oy.clear(); | ||
550 | //if(datasource!=null)(vf->callbacks.close_func)(vf->datasource); | ||
551 | //memset(vf,0,sizeof(OggVorbis_File)); | ||
552 | return(0); | ||
553 | } | ||
554 | |||
555 | static int fseek64_wrap(InputStream fis, | ||
556 | //int64_t off, | ||
557 | int off, | ||
558 | int whence){ | ||
559 | |||
560 | if(!fis.markSupported()){ return -1; } | ||
561 | try{ | ||
562 | try{if(whence==0){ fis.reset(); }} | ||
563 | catch(Exception ee){System.out.println(ee);} | ||
564 | fis.skip(off); | ||
565 | } | ||
566 | catch(Exception e){ System.out.println(e); | ||
567 | //return -1; | ||
568 | } | ||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | // inspects the OggVorbis file and finds/documents all the logical | ||
573 | // bitstreams contained in it. Tries to be tolerant of logical | ||
574 | // bitstream sections that are truncated/woogie. | ||
575 | // | ||
576 | // return: -1) error | ||
577 | // 0) OK | ||
578 | |||
579 | int open(InputStream is, byte[] initial, int ibytes){ | ||
580 | return open_callbacks(is, initial, ibytes//, callbacks | ||
581 | ); | ||
582 | } | ||
583 | |||
584 | int open_callbacks(InputStream is, byte[] initial, | ||
585 | int ibytes//, callbacks callbacks | ||
586 | ){ | ||
587 | // int offset=callbacks.seek_func(f,0,SEEK_CUR); | ||
588 | int _offset=fseek64_wrap(is, (int)offset, SEEK_SET); | ||
589 | int ret; | ||
590 | // memset(vf,0,sizeof(OggVorbis_File)); | ||
591 | datasource=is; | ||
592 | //callbacks = _callbacks; | ||
593 | |||
594 | // init the framing state | ||
595 | oy.init(); | ||
596 | |||
597 | // perhaps some data was previously read into a buffer for testing | ||
598 | // against other stream types. Allow initialization from this | ||
599 | // previously read data (as we may be reading from a non-seekable | ||
600 | // stream) | ||
601 | if(initial!=null){ | ||
602 | int index=oy.buffer(ibytes); | ||
603 | System.arraycopy(initial, 0, oy.data, index, ibytes); | ||
604 | oy.wrote(ibytes); | ||
605 | } | ||
606 | |||
607 | System.out.println("open_callbacks="+_offset); | ||
608 | // can we seek? Stevens suggests the seek test was portable | ||
609 | if(_offset!=-1){ ret=open_seekable(); } | ||
610 | else{ ret=open_nonseekable(); } | ||
611 | |||
612 | System.out.println("ret="+ret); | ||
613 | |||
614 | if(ret!=0){ | ||
615 | datasource=null; | ||
616 | clear(); | ||
617 | } | ||
618 | |||
619 | return(ret); | ||
620 | } | ||
621 | |||
622 | // How many logical bitstreams in this physical bitstream? | ||
623 | public int streams(){ | ||
624 | return links; | ||
625 | } | ||
626 | |||
627 | // Is the FILE * associated with vf seekable? | ||
628 | public boolean seekable(){ | ||
629 | return seekable; | ||
630 | } | ||
631 | |||
632 | // returns the bitrate for a given logical bitstream or the entire | ||
633 | // physical bitstream. If the file is open for random access, it will | ||
634 | // find the *actual* average bitrate. If the file is streaming, it | ||
635 | // returns the nominal bitrate (if set) else the average of the | ||
636 | // upper/lower bounds (if set) else -1 (unset). | ||
637 | // | ||
638 | // If you want the actual bitrate field settings, get them from the | ||
639 | // vorbis_info structs | ||
640 | |||
641 | public int bitrate(int i){ | ||
642 | if(i>=links)return(-1); | ||
643 | if(!seekable && i!=0)return(bitrate(0)); | ||
644 | if(i<0){ | ||
645 | long bits=0; | ||
646 | for(int j=0;j<links;j++){ | ||
647 | bits+=(offsets[j+1]-dataoffsets[j])*8; | ||
648 | } | ||
649 | return((int)Math.rint(bits/time_total(-1))); | ||
650 | } | ||
651 | else{ | ||
652 | if(seekable){ | ||
653 | // return the actual bitrate | ||
654 | return((int)Math.rint((offsets[i+1]-dataoffsets[i])*8/time_total(i))); | ||
655 | } | ||
656 | else{ | ||
657 | // return nominal if set | ||
658 | if(vi[i].bitrate_nominal>0){ | ||
659 | return vi[i].bitrate_nominal; | ||
660 | } | ||
661 | else{ | ||
662 | if(vi[i].bitrate_upper>0){ | ||
663 | if(vi[i].bitrate_lower>0){ | ||
664 | return (vi[i].bitrate_upper+vi[i].bitrate_lower)/2; | ||
665 | }else{ | ||
666 | return vi[i].bitrate_upper; | ||
667 | } | ||
668 | } | ||
669 | return(-1); | ||
670 | } | ||
671 | } | ||
672 | } | ||
673 | } | ||
674 | |||
675 | // returns the actual bitrate since last call. returns -1 if no | ||
676 | // additional data to offer since last call (or at beginning of stream) | ||
677 | public int bitrate_instant(){ | ||
678 | int _link=(seekable?current_link:0); | ||
679 | if(samptrack==0)return(-1); | ||
680 | int ret=(int)(bittrack/samptrack*vi[_link].rate+.5); | ||
681 | bittrack=0.f; | ||
682 | samptrack=0.f; | ||
683 | return(ret); | ||
684 | } | ||
685 | |||
686 | public int serialnumber(int i){ | ||
687 | if(i>=links)return(-1); | ||
688 | if(!seekable && i>=0)return(serialnumber(-1)); | ||
689 | if(i<0){ | ||
690 | return(current_serialno); | ||
691 | } | ||
692 | else{ | ||
693 | return(serialnos[i]); | ||
694 | } | ||
695 | } | ||
696 | |||
697 | // returns: total raw (compressed) length of content if i==-1 | ||
698 | // raw (compressed) length of that logical bitstream for i==0 to n | ||
699 | // -1 if the stream is not seekable (we can't know the length) | ||
700 | |||
701 | public long raw_total(int i){ | ||
702 | System.out.println("raw_total: "+seekable); | ||
703 | if(!seekable || i>=links)return(-1); | ||
704 | if(i<0){ | ||
705 | long acc=0; // bug? | ||
706 | for(int j=0;j<links;j++){ | ||
707 | acc+=raw_total(j); | ||
708 | } | ||
709 | return(acc); | ||
710 | } | ||
711 | else{ | ||
712 | return(offsets[i+1]-offsets[i]); | ||
713 | } | ||
714 | } | ||
715 | |||
716 | // returns: total PCM length (samples) of content if i==-1 | ||
717 | // PCM length (samples) of that logical bitstream for i==0 to n | ||
718 | // -1 if the stream is not seekable (we can't know the length) | ||
719 | public long pcm_total(int i){ | ||
720 | if(!seekable || i>=links)return(-1); | ||
721 | if(i<0){ | ||
722 | long acc=0; | ||
723 | for(int j=0;j<links;j++){ | ||
724 | acc+=pcm_total(j); | ||
725 | } | ||
726 | return(acc); | ||
727 | } | ||
728 | else{ | ||
729 | return(pcmlengths[i]); | ||
730 | } | ||
731 | } | ||
732 | |||
733 | // returns: total seconds of content if i==-1 | ||
734 | // seconds in that logical bitstream for i==0 to n | ||
735 | // -1 if the stream is not seekable (we can't know the length) | ||
736 | public float time_total(int i){ | ||
737 | if(!seekable || i>=links)return(-1); | ||
738 | if(i<0){ | ||
739 | float acc=0; | ||
740 | for(int j=0;j<links;j++){ | ||
741 | acc+=time_total(j); | ||
742 | } | ||
743 | return(acc); | ||
744 | } | ||
745 | else{ | ||
746 | return((float)(pcmlengths[i])/vi[i].rate); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | // seek to an offset relative to the *compressed* data. This also | ||
751 | // immediately sucks in and decodes pages to update the PCM cursor. It | ||
752 | // will cross a logical bitstream boundary, but only if it can't get | ||
753 | // any packets out of the tail of the bitstream we seek to (so no | ||
754 | // surprises). | ||
755 | // | ||
756 | // returns zero on success, nonzero on failure | ||
757 | |||
758 | public int raw_seek(int pos){ | ||
759 | System.out.println("raw_seek: "+pos); | ||
760 | if(!seekable)return(-1); // don't dump machine if we can't seek | ||
761 | if(pos<0 || pos>offsets[links]){ | ||
762 | //goto seek_error; | ||
763 | pcm_offset=-1; | ||
764 | decode_clear(); | ||
765 | return -1; | ||
766 | } | ||
767 | System.out.println("#1"); | ||
768 | // clear out decoding machine state | ||
769 | pcm_offset=-1; | ||
770 | System.out.println("#2"); | ||
771 | decode_clear(); | ||
772 | System.out.println("#3"); | ||
773 | // seek | ||
774 | seek_helper(pos); | ||
775 | |||
776 | // we need to make sure the pcm_offset is set. We use the | ||
777 | // _fetch_packet helper to process one packet with readp set, then | ||
778 | // call it until it returns '0' with readp not set (the last packet | ||
779 | // from a page has the 'granulepos' field set, and that's how the | ||
780 | // helper updates the offset | ||
781 | System.out.println("#4"); | ||
782 | switch(process_packet(1)){ | ||
783 | case 0: | ||
784 | System.out.println("?0"); | ||
785 | // oh, eof. There are no packets remaining. Set the pcm offset to | ||
786 | // the end of file | ||
787 | pcm_offset=pcm_total(-1); | ||
788 | return(0); | ||
789 | case -1: | ||
790 | System.out.println("?-1"); | ||
791 | // error! missing data or invalid bitstream structure | ||
792 | //goto seek_error; | ||
793 | pcm_offset=-1; | ||
794 | decode_clear(); | ||
795 | return -1; | ||
796 | default: | ||
797 | System.out.println("?break"); | ||
798 | // all OK | ||
799 | break; | ||
800 | } | ||
801 | System.out.println("pcm_offset="+pcm_offset); | ||
802 | while(true){ | ||
803 | switch(process_packet(0)){ | ||
804 | case 0: | ||
805 | // the offset is set. If it's a bogus bitstream with no offset | ||
806 | // information, it's not but that's not our fault. We still run | ||
807 | // gracefully, we're just missing the offset | ||
808 | return(0); | ||
809 | case -1: | ||
810 | // error! missing data or invalid bitstream structure | ||
811 | //goto seek_error; | ||
812 | pcm_offset=-1; | ||
813 | decode_clear(); | ||
814 | return -1; | ||
815 | default: | ||
816 | // continue processing packets | ||
817 | break; | ||
818 | } | ||
819 | } | ||
820 | |||
821 | // seek_error: | ||
822 | // dump the machine so we're in a known state | ||
823 | //pcm_offset=-1; | ||
824 | //decode_clear(); | ||
825 | //return -1; | ||
826 | } | ||
827 | |||
828 | // seek to a sample offset relative to the decompressed pcm stream | ||
829 | // returns zero on success, nonzero on failure | ||
830 | |||
831 | public int pcm_seek(long pos){ | ||
832 | int link=-1; | ||
833 | long total=pcm_total(-1); | ||
834 | |||
835 | if(!seekable)return(-1); // don't dump machine if we can't seek | ||
836 | if(pos<0 || pos>total){ | ||
837 | //goto seek_error; | ||
838 | pcm_offset=-1; | ||
839 | decode_clear(); | ||
840 | return -1; | ||
841 | } | ||
842 | |||
843 | // which bitstream section does this pcm offset occur in? | ||
844 | for(link=links-1;link>=0;link--){ | ||
845 | total-=pcmlengths[link]; | ||
846 | if(pos>=total)break; | ||
847 | } | ||
848 | |||
849 | // search within the logical bitstream for the page with the highest | ||
850 | // pcm_pos preceeding (or equal to) pos. There is a danger here; | ||
851 | // missing pages or incorrect frame number information in the | ||
852 | // bitstream could make our task impossible. Account for that (it | ||
853 | // would be an error condition) | ||
854 | { | ||
855 | long target=pos-total; | ||
856 | int end=(int)offsets[link+1]; | ||
857 | int begin=(int)offsets[link]; | ||
858 | int best=begin; | ||
859 | |||
860 | Page og=new Page(); | ||
861 | while(begin<end){ | ||
862 | int bisect; | ||
863 | int ret; | ||
864 | |||
865 | if(end-begin<CHUNKSIZE){ | ||
866 | bisect=begin; | ||
867 | } | ||
868 | else{ | ||
869 | bisect=(end+begin)/2; | ||
870 | } | ||
871 | |||
872 | seek_helper(bisect); | ||
873 | ret=get_next_page(og,end-bisect); | ||
874 | |||
875 | if(ret==-1){ | ||
876 | end=bisect; | ||
877 | } | ||
878 | else{ | ||
879 | long granulepos=og.granulepos(); | ||
880 | if(granulepos<target){ | ||
881 | best=ret; // raw offset of packet with granulepos | ||
882 | begin=(int)offset; // raw offset of next packet | ||
883 | } | ||
884 | else{ | ||
885 | end=bisect; | ||
886 | } | ||
887 | } | ||
888 | } | ||
889 | // found our page. seek to it (call raw_seek). | ||
890 | if(raw_seek(best)!=0){ | ||
891 | //goto seek_error; | ||
892 | pcm_offset=-1; | ||
893 | decode_clear(); | ||
894 | return -1; | ||
895 | } | ||
896 | } | ||
897 | |||
898 | // verify result | ||
899 | if(pcm_offset>=pos){ | ||
900 | //goto seek_error; | ||
901 | pcm_offset=-1; | ||
902 | decode_clear(); | ||
903 | return -1; | ||
904 | } | ||
905 | if(pos>pcm_total(-1)){ | ||
906 | //goto seek_error; | ||
907 | pcm_offset=-1; | ||
908 | decode_clear(); | ||
909 | return -1; | ||
910 | } | ||
911 | |||
912 | // discard samples until we reach the desired position. Crossing a | ||
913 | // logical bitstream boundary with abandon is OK. | ||
914 | while(pcm_offset<pos){ | ||
915 | float[][] pcm; | ||
916 | int target=(int)(pos-pcm_offset); | ||
917 | float[][][] _pcm=new float[1][][]; | ||
918 | int[] _index=new int[info(-1).channels]; | ||
919 | int samples=vd.synthesis_pcmout(_pcm, _index); | ||
920 | pcm=_pcm[0]; | ||
921 | |||
922 | if(samples>target)samples=target; | ||
923 | vd.synthesis_read(samples); | ||
924 | pcm_offset+=samples; | ||
925 | |||
926 | if(samples<target) | ||
927 | if(process_packet(1)==0){ | ||
928 | pcm_offset=pcm_total(-1); // eof | ||
929 | } | ||
930 | } | ||
931 | return 0; | ||
932 | |||
933 | // seek_error: | ||
934 | // dump machine so we're in a known state | ||
935 | //pcm_offset=-1; | ||
936 | //decode_clear(); | ||
937 | //return -1; | ||
938 | } | ||
939 | |||
940 | // seek to a playback time relative to the decompressed pcm stream | ||
941 | // returns zero on success, nonzero on failure | ||
942 | public int time_seek(float seconds){ | ||
943 | // translate time to PCM position and call pcm_seek | ||
944 | |||
945 | int link=-1; | ||
946 | long pcm_total=pcm_total(-1); | ||
947 | float time_total=time_total(-1); | ||
948 | |||
949 | if(!seekable)return(-1); // don't dump machine if we can't seek | ||
950 | if(seconds<0 || seconds>time_total){ | ||
951 | //goto seek_error; | ||
952 | pcm_offset=-1; | ||
953 | decode_clear(); | ||
954 | return -1; | ||
955 | } | ||
956 | |||
957 | // which bitstream section does this time offset occur in? | ||
958 | for(link=links-1;link>=0;link--){ | ||
959 | pcm_total-=pcmlengths[link]; | ||
960 | time_total-=time_total(link); | ||
961 | if(seconds>=time_total)break; | ||
962 | } | ||
963 | |||
964 | // enough information to convert time offset to pcm offset | ||
965 | { | ||
966 | long target=(long)(pcm_total+(seconds-time_total)*vi[link].rate); | ||
967 | return(pcm_seek(target)); | ||
968 | } | ||
969 | |||
970 | //seek_error: | ||
971 | // dump machine so we're in a known state | ||
972 | //pcm_offset=-1; | ||
973 | //decode_clear(); | ||
974 | //return -1; | ||
975 | } | ||
976 | |||
977 | // tell the current stream offset cursor. Note that seek followed by | ||
978 | // tell will likely not give the set offset due to caching | ||
979 | public long raw_tell(){ | ||
980 | return(offset); | ||
981 | } | ||
982 | |||
983 | // return PCM offset (sample) of next PCM sample to be read | ||
984 | public long pcm_tell(){ | ||
985 | return(pcm_offset); | ||
986 | } | ||
987 | |||
988 | // return time offset (seconds) of next PCM sample to be read | ||
989 | public float time_tell(){ | ||
990 | // translate time to PCM position and call pcm_seek | ||
991 | |||
992 | int link=-1; | ||
993 | long pcm_total=0; | ||
994 | float time_total=0.f; | ||
995 | |||
996 | if(seekable){ | ||
997 | pcm_total=pcm_total(-1); | ||
998 | time_total=time_total(-1); | ||
999 | |||
1000 | // which bitstream section does this time offset occur in? | ||
1001 | for(link=links-1;link>=0;link--){ | ||
1002 | pcm_total-=pcmlengths[link]; | ||
1003 | time_total-=time_total(link); | ||
1004 | if(pcm_offset>=pcm_total)break; | ||
1005 | } | ||
1006 | } | ||
1007 | |||
1008 | return((float)time_total+(float)(pcm_offset-pcm_total)/vi[link].rate); | ||
1009 | } | ||
1010 | |||
1011 | // link: -1) return the vorbis_info struct for the bitstream section | ||
1012 | // currently being decoded | ||
1013 | // 0-n) to request information for a specific bitstream section | ||
1014 | // | ||
1015 | // In the case of a non-seekable bitstream, any call returns the | ||
1016 | // current bitstream. NULL in the case that the machine is not | ||
1017 | // initialized | ||
1018 | |||
1019 | public Info info(int link){ | ||
1020 | if(seekable){ | ||
1021 | if(link<0){ | ||
1022 | if(decode_ready){ | ||
1023 | return vi[current_link]; | ||
1024 | } | ||
1025 | else{ | ||
1026 | return null; | ||
1027 | } | ||
1028 | } | ||
1029 | else{ | ||
1030 | if(link>=links){ | ||
1031 | return null; | ||
1032 | } | ||
1033 | else{ | ||
1034 | return vi[link]; | ||
1035 | } | ||
1036 | } | ||
1037 | } | ||
1038 | else{ | ||
1039 | if(decode_ready){ | ||
1040 | return vi[0]; | ||
1041 | } | ||
1042 | else{ | ||
1043 | return null; | ||
1044 | } | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1048 | public Comment comment(int link){ | ||
1049 | if(seekable){ | ||
1050 | if(link<0){ | ||
1051 | if(decode_ready){ return vc[current_link]; } | ||
1052 | else{ return null; } | ||
1053 | } | ||
1054 | else{ | ||
1055 | if(link>=links){ return null;} | ||
1056 | else{ return vc[link]; } | ||
1057 | } | ||
1058 | } | ||
1059 | else{ | ||
1060 | if(decode_ready){ return vc[0]; } | ||
1061 | else{ return null; } | ||
1062 | } | ||
1063 | } | ||
1064 | |||
1065 | int host_is_big_endian() { | ||
1066 | return 1; | ||
1067 | // short pattern = 0xbabe; | ||
1068 | // unsigned char *bytewise = (unsigned char *)&pattern; | ||
1069 | // if (bytewise[0] == 0xba) return 1; | ||
1070 | // assert(bytewise[0] == 0xbe); | ||
1071 | // return 0; | ||
1072 | } | ||
1073 | |||
1074 | // up to this point, everything could more or less hide the multiple | ||
1075 | // logical bitstream nature of chaining from the toplevel application | ||
1076 | // if the toplevel application didn't particularly care. However, at | ||
1077 | // the point that we actually read audio back, the multiple-section | ||
1078 | // nature must surface: Multiple bitstream sections do not necessarily | ||
1079 | // have to have the same number of channels or sampling rate. | ||
1080 | // | ||
1081 | // read returns the sequential logical bitstream number currently | ||
1082 | // being decoded along with the PCM data in order that the toplevel | ||
1083 | // application can take action on channel/sample rate changes. This | ||
1084 | // number will be incremented even for streamed (non-seekable) streams | ||
1085 | // (for seekable streams, it represents the actual logical bitstream | ||
1086 | // index within the physical bitstream. Note that the accessor | ||
1087 | // functions above are aware of this dichotomy). | ||
1088 | // | ||
1089 | // input values: buffer) a buffer to hold packed PCM data for return | ||
1090 | // length) the byte length requested to be placed into buffer | ||
1091 | // bigendianp) should the data be packed LSB first (0) or | ||
1092 | // MSB first (1) | ||
1093 | // word) word size for output. currently 1 (byte) or | ||
1094 | // 2 (16 bit short) | ||
1095 | // | ||
1096 | // return values: -1) error/hole in data | ||
1097 | // 0) EOF | ||
1098 | // n) number of bytes of PCM actually returned. The | ||
1099 | // below works on a packet-by-packet basis, so the | ||
1100 | // return length is not related to the 'length' passed | ||
1101 | // in, just guaranteed to fit. | ||
1102 | // | ||
1103 | // *section) set to the logical bitstream number | ||
1104 | |||
1105 | int read(byte[] buffer,int length, | ||
1106 | int bigendianp, int word, int sgned, int[] bitstream){ | ||
1107 | int host_endian = host_is_big_endian(); | ||
1108 | int index=0; | ||
1109 | |||
1110 | while(true){ | ||
1111 | if(decode_ready){ | ||
1112 | float[][] pcm; | ||
1113 | float[][][] _pcm=new float[1][][]; | ||
1114 | int[] _index=new int[info(-1).channels]; | ||
1115 | int samples=vd.synthesis_pcmout(_pcm, _index); | ||
1116 | pcm=_pcm[0]; | ||
1117 | if(samples!=0){ | ||
1118 | // yay! proceed to pack data into the byte buffer | ||
1119 | int channels=info(-1).channels; | ||
1120 | int bytespersample=word * channels; | ||
1121 | if(samples>length/bytespersample)samples=length/bytespersample; | ||
1122 | |||
1123 | // a tight loop to pack each size | ||
1124 | { | ||
1125 | int val; | ||
1126 | if(word==1){ | ||
1127 | int off=(sgned!=0?0:128); | ||
1128 | for(int j=0;j<samples;j++){ | ||
1129 | for(int i=0;i<channels;i++){ | ||
1130 | val=(int)(pcm[i][_index[i]+j]*128. + 0.5); | ||
1131 | if(val>127)val=127; | ||
1132 | else if(val<-128)val=-128; | ||
1133 | buffer[index++]=(byte)(val+off); | ||
1134 | } | ||
1135 | } | ||
1136 | } | ||
1137 | else{ | ||
1138 | int off=(sgned!=0?0:32768); | ||
1139 | |||
1140 | if(host_endian==bigendianp){ | ||
1141 | if(sgned!=0){ | ||
1142 | for(int i=0;i<channels;i++) { // It's faster in this order | ||
1143 | int src=_index[i]; | ||
1144 | int dest=i; | ||
1145 | for(int j=0;j<samples;j++) { | ||
1146 | val=(int)(pcm[i][src+j]*32768. + 0.5); | ||
1147 | if(val>32767)val=32767; | ||
1148 | else if(val<-32768)val=-32768; | ||
1149 | buffer[dest]=(byte)(val>>>8); | ||
1150 | buffer[dest+1]=(byte)(val); | ||
1151 | dest+=channels*2; | ||
1152 | } | ||
1153 | } | ||
1154 | } | ||
1155 | else{ | ||
1156 | for(int i=0;i<channels;i++) { | ||
1157 | float[] src=pcm[i]; | ||
1158 | int dest=i; | ||
1159 | for(int j=0;j<samples;j++) { | ||
1160 | val=(int)(src[j]*32768. + 0.5); | ||
1161 | if(val>32767)val=32767; | ||
1162 | else if(val<-32768)val=-32768; | ||
1163 | buffer[dest]=(byte)((val+off)>>>8); | ||
1164 | buffer[dest+1]=(byte)(val+off); | ||
1165 | dest+=channels*2; | ||
1166 | } | ||
1167 | } | ||
1168 | } | ||
1169 | } | ||
1170 | else if(bigendianp!=0){ | ||
1171 | for(int j=0;j<samples;j++){ | ||
1172 | for(int i=0;i<channels;i++){ | ||
1173 | val=(int)(pcm[i][j]*32768. + 0.5); | ||
1174 | if(val>32767)val=32767; | ||
1175 | else if(val<-32768)val=-32768; | ||
1176 | val+=off; | ||
1177 | buffer[index++]=(byte)(val>>>8); | ||
1178 | buffer[index++]=(byte)val; | ||
1179 | } | ||
1180 | } | ||
1181 | } | ||
1182 | else{ | ||
1183 | //int val; | ||
1184 | for(int j=0;j<samples;j++){ | ||
1185 | for(int i=0;i<channels;i++){ | ||
1186 | val=(int)(pcm[i][j]*32768. + 0.5); | ||
1187 | if(val>32767)val=32767; | ||
1188 | else if(val<-32768)val=-32768; | ||
1189 | val+=off; | ||
1190 | buffer[index++]=(byte)val; | ||
1191 | buffer[index++]=(byte)(val>>>8); | ||
1192 | } | ||
1193 | } | ||
1194 | } | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | vd.synthesis_read(samples); | ||
1199 | pcm_offset+=samples; | ||
1200 | if(bitstream!=null)bitstream[0]=current_link; | ||
1201 | return(samples*bytespersample); | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | // suck in another packet | ||
1206 | switch(process_packet(1)){ | ||
1207 | case 0: | ||
1208 | return(0); | ||
1209 | case -1: | ||
1210 | return -1; | ||
1211 | default: | ||
1212 | break; | ||
1213 | } | ||
1214 | } | ||
1215 | } | ||
1216 | |||
1217 | public int getLinks(){return links;} | ||
1218 | public Info[] getInfo(){return vi;} | ||
1219 | public Comment[] getComment(){return vc;} | ||
1220 | |||
1221 | public static void main(String[] arg){ | ||
1222 | try{ | ||
1223 | VorbisFile foo=new VorbisFile(arg[0]); | ||
1224 | int links=foo.getLinks(); | ||
1225 | System.out.println("links="+links); | ||
1226 | Comment[] comment=foo.getComment(); | ||
1227 | Info[] info=foo.getInfo(); | ||
1228 | for(int i=0; i<links; i++){ | ||
1229 | System.out.println(info[i]); | ||
1230 | System.out.println(comment[i]); | ||
1231 | } | ||
1232 | System.out.println("raw_total: "+foo.raw_total(-1)); | ||
1233 | System.out.println("pcm_total: "+foo.pcm_total(-1)); | ||
1234 | System.out.println("time_total: "+foo.time_total(-1)); | ||
1235 | } | ||
1236 | catch(Exception e){ | ||
1237 | System.err.println(e); | ||
1238 | } | ||
1239 | } | ||
1240 | } | ||