]>
Commit | Line | Data |
---|---|---|
964dd0bc JW |
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 | } |