Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lDEVinux
GitHub Repository: lDEVinux/eaglercraft
Path: blob/main/src/lwjgl/java/javazoom/jl/decoder/Bitstream.java
8650 views
1
/*
2
* 11/19/04 1.0 moved to LGPL.
3
*
4
* 11/17/04 Uncomplete frames discarded. E.B, [email protected]
5
*
6
* 12/05/03 ID3v2 tag returned. E.B, [email protected]
7
*
8
* 12/12/99 Based on Ibitstream. Exceptions thrown on errors,
9
* Temporary removed seek functionality. [email protected]
10
*
11
* 02/12/99 : Java Conversion by E.B , [email protected]
12
*
13
* 04/14/97 : Added function prototypes for new syncing and seeking
14
* mechanisms. Also made this file portable. Changes made by Jeff Tsay
15
*
16
* @(#) ibitstream.h 1.5, last edit: 6/15/94 16:55:34
17
* @(#) Copyright (C) 1993, 1994 Tobias Bading ([email protected])
18
* @(#) Berlin University of Technology
19
*-----------------------------------------------------------------------
20
* This program is free software; you can redistribute it and/or modify
21
* it under the terms of the GNU Library General Public License as published
22
* by the Free Software Foundation; either version 2 of the License, or
23
* (at your option) any later version.
24
*
25
* This program is distributed in the hope that it will be useful,
26
* but WITHOUT ANY WARRANTY; without even the implied warranty of
27
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
* GNU Library General Public License for more details.
29
*
30
* You should have received a copy of the GNU Library General Public
31
* License along with this program; if not, write to the Free Software
32
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33
*----------------------------------------------------------------------
34
*/
35
36
package javazoom.jl.decoder;
37
38
import java.io.BufferedInputStream;
39
import java.io.ByteArrayInputStream;
40
import java.io.IOException;
41
import java.io.InputStream;
42
import java.io.PushbackInputStream;
43
44
45
/**
46
* The <code>Bistream</code> class is responsible for parsing
47
* an MPEG audio bitstream.
48
*
49
* <b>REVIEW:</b> much of the parsing currently occurs in the
50
* various decoders. This should be moved into this class and associated
51
* inner classes.
52
*/
53
public final class Bitstream implements BitstreamErrors
54
{
55
/**
56
* Synchronization control constant for the initial
57
* synchronization to the start of a frame.
58
*/
59
static byte INITIAL_SYNC = 0;
60
61
/**
62
* Synchronization control constant for non-initial frame
63
* synchronizations.
64
*/
65
static byte STRICT_SYNC = 1;
66
67
// max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC
68
/**
69
* Maximum size of the frame buffer.
70
*/
71
private static final int BUFFER_INT_SIZE = 433;
72
73
/**
74
* The frame buffer that holds the data for the current frame.
75
*/
76
private final int[] framebuffer = new int[BUFFER_INT_SIZE];
77
78
/**
79
* Number of valid bytes in the frame buffer.
80
*/
81
private int framesize;
82
83
/**
84
* The bytes read from the stream.
85
*/
86
private byte[] frame_bytes = new byte[BUFFER_INT_SIZE*4];
87
88
/**
89
* Index into <code>framebuffer</code> where the next bits are
90
* retrieved.
91
*/
92
private int wordpointer;
93
94
/**
95
* Number (0-31, from MSB to LSB) of next bit for get_bits()
96
*/
97
private int bitindex;
98
99
/**
100
* The current specified syncword
101
*/
102
private int syncword;
103
104
/**
105
* Audio header position in stream.
106
*/
107
private int header_pos = 0;
108
109
/**
110
*
111
*/
112
private boolean single_ch_mode;
113
//private int current_frame_number;
114
//private int last_frame_number;
115
116
private final int bitmask[] = {0, // dummy
117
0x00000001, 0x00000003, 0x00000007, 0x0000000F,
118
0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
119
0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
120
0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
121
0x0001FFFF };
122
123
private final PushbackInputStream source;
124
125
private final Header header = new Header();
126
127
private final byte syncbuf[] = new byte[4];
128
129
private Crc16[] crc = new Crc16[1];
130
131
private byte[] rawid3v2 = null;
132
133
private boolean firstframe = true;
134
135
136
/**
137
* Construct a IBitstream that reads data from a
138
* given InputStream.
139
*
140
* @param in The InputStream to read from.
141
*/
142
public Bitstream(InputStream in)
143
{
144
if (in==null) throw new NullPointerException("in");
145
in = new BufferedInputStream(in);
146
loadID3v2(in);
147
firstframe = true;
148
//source = new PushbackInputStream(in, 1024);
149
source = new PushbackInputStream(in, BUFFER_INT_SIZE*4);
150
151
closeFrame();
152
//current_frame_number = -1;
153
//last_frame_number = -1;
154
}
155
156
/**
157
* Return position of the first audio header.
158
* @return size of ID3v2 tag frames.
159
*/
160
public int header_pos()
161
{
162
return header_pos;
163
}
164
165
/**
166
* Load ID3v2 frames.
167
* @param in MP3 InputStream.
168
* @author JavaZOOM
169
*/
170
private void loadID3v2(InputStream in)
171
{
172
int size = -1;
173
try
174
{
175
// Read ID3v2 header (10 bytes).
176
in.mark(10);
177
size = readID3v2Header(in);
178
header_pos = size;
179
}
180
catch (IOException e)
181
{}
182
finally
183
{
184
try
185
{
186
// Unread ID3v2 header (10 bytes).
187
in.reset();
188
}
189
catch (IOException e)
190
{}
191
}
192
// Load ID3v2 tags.
193
try
194
{
195
if (size > 0)
196
{
197
rawid3v2 = new byte[size];
198
in.read(rawid3v2,0,rawid3v2.length);
199
}
200
}
201
catch (IOException e)
202
{}
203
}
204
205
/**
206
* Parse ID3v2 tag header to find out size of ID3v2 frames.
207
* @param in MP3 InputStream
208
* @return size of ID3v2 frames + header
209
* @throws IOException
210
* @author JavaZOOM
211
*/
212
private int readID3v2Header(InputStream in) throws IOException
213
{
214
byte[] id3header = new byte[4];
215
int size = -10;
216
in.read(id3header,0,3);
217
// Look for ID3v2
218
if ( (id3header[0]=='I') && (id3header[1]=='D') && (id3header[2]=='3'))
219
{
220
in.read(id3header,0,3);
221
int majorVersion = id3header[0];
222
int revision = id3header[1];
223
in.read(id3header,0,4);
224
size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]);
225
}
226
return (size+10);
227
}
228
229
/**
230
* Return raw ID3v2 frames + header.
231
* @return ID3v2 InputStream or null if ID3v2 frames are not available.
232
*/
233
public InputStream getRawID3v2()
234
{
235
if (rawid3v2 == null) return null;
236
else
237
{
238
ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2);
239
return bain;
240
}
241
}
242
243
/**
244
* Close the Bitstream.
245
* @throws BitstreamException
246
*/
247
public void close() throws BitstreamException
248
{
249
try
250
{
251
source.close();
252
}
253
catch (IOException ex)
254
{
255
throw newBitstreamException(STREAM_ERROR, ex);
256
}
257
}
258
259
/**
260
* Reads and parses the next frame from the input source.
261
*
262
* @return the Header describing details of the frame read,
263
* or null if the end of the stream has been reached.
264
*/
265
public Header readFrame() throws BitstreamException
266
{
267
Header result = null;
268
try
269
{
270
result = readNextFrame();
271
// E.B, Parse VBR (if any) first frame.
272
if (firstframe == true)
273
{
274
result.parseVBR(frame_bytes);
275
firstframe = false;
276
}
277
}
278
catch (BitstreamException ex)
279
{
280
if ((ex.getErrorCode()==INVALIDFRAME))
281
{
282
// Try to skip this frame.
283
//System.out.println("INVALIDFRAME");
284
try
285
{
286
closeFrame();
287
result = readNextFrame();
288
}
289
catch (BitstreamException e)
290
{
291
if ((e.getErrorCode()!=STREAM_EOF))
292
{
293
// wrap original exception so stack trace is maintained.
294
throw newBitstreamException(e.getErrorCode(), e);
295
}
296
}
297
}
298
else if ((ex.getErrorCode()!=STREAM_EOF))
299
{
300
// wrap original exception so stack trace is maintained.
301
throw newBitstreamException(ex.getErrorCode(), ex);
302
}
303
}
304
return result;
305
}
306
307
/**
308
* Read next MP3 frame.
309
*
310
* @return MP3 frame header.
311
* @throws BitstreamException
312
*/
313
private Header readNextFrame() throws BitstreamException
314
{
315
if (framesize == -1)
316
{
317
nextFrame();
318
}
319
return header;
320
}
321
322
323
/**
324
* Read next MP3 frame.
325
*
326
* @throws BitstreamException
327
*/
328
private void nextFrame() throws BitstreamException
329
{
330
// entire frame is read by the header class.
331
header.read_header(this, crc);
332
}
333
334
/**
335
* Unreads the bytes read from the frame.
336
*
337
* @throws BitstreamException
338
*/
339
// REVIEW: add new error codes for this.
340
public void unreadFrame() throws BitstreamException
341
{
342
if (wordpointer==-1 && bitindex==-1 && (framesize>0))
343
{
344
try
345
{
346
source.unread(frame_bytes, 0, framesize);
347
}
348
catch (IOException ex)
349
{
350
throw newBitstreamException(STREAM_ERROR);
351
}
352
}
353
}
354
355
/**
356
* Close MP3 frame.
357
*/
358
public void closeFrame()
359
{
360
framesize = -1;
361
wordpointer = -1;
362
bitindex = -1;
363
}
364
365
/**
366
* Determines if the next 4 bytes of the stream represent a
367
* frame header.
368
*/
369
public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException
370
{
371
int read = readBytes(syncbuf, 0, 4);
372
int headerstring = ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000) | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF);
373
374
try
375
{
376
source.unread(syncbuf, 0, read);
377
}
378
catch (IOException ex)
379
{
380
}
381
382
boolean sync = false;
383
switch (read)
384
{
385
case 0:
386
sync = true;
387
break;
388
case 4:
389
sync = isSyncMark(headerstring, syncmode, syncword);
390
break;
391
}
392
393
return sync;
394
}
395
396
397
// REVIEW: this class should provide inner classes to
398
// parse the frame contents. Eventually, readBits will
399
// be removed.
400
public int readBits(int n)
401
{
402
return get_bits(n);
403
}
404
405
public int readCheckedBits(int n)
406
{
407
// REVIEW: implement CRC check.
408
return get_bits(n);
409
}
410
411
protected BitstreamException newBitstreamException(int errorcode)
412
{
413
return new BitstreamException(errorcode, null);
414
}
415
protected BitstreamException newBitstreamException(int errorcode, Throwable throwable)
416
{
417
return new BitstreamException(errorcode, throwable);
418
}
419
420
/**
421
* Get next 32 bits from bitstream.
422
* They are stored in the headerstring.
423
* syncmod allows Synchro flag ID
424
* The returned value is False at the end of stream.
425
*/
426
427
int syncHeader(byte syncmode) throws BitstreamException
428
{
429
boolean sync;
430
int headerstring;
431
// read additional 2 bytes
432
int bytesRead = readBytes(syncbuf, 0, 3);
433
434
if (bytesRead!=3) throw newBitstreamException(STREAM_EOF, null);
435
436
headerstring = ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00) | ((syncbuf[2] << 0) & 0x000000FF);
437
438
do
439
{
440
headerstring <<= 8;
441
442
if (readBytes(syncbuf, 3, 1)!=1)
443
throw newBitstreamException(STREAM_EOF, null);
444
445
headerstring |= (syncbuf[3] & 0x000000FF);
446
447
sync = isSyncMark(headerstring, syncmode, syncword);
448
}
449
while (!sync);
450
451
//current_frame_number++;
452
//if (last_frame_number < current_frame_number) last_frame_number = current_frame_number;
453
454
return headerstring;
455
}
456
457
public boolean isSyncMark(int headerstring, int syncmode, int word)
458
{
459
boolean sync = false;
460
461
if (syncmode == INITIAL_SYNC)
462
{
463
//sync = ((headerstring & 0xFFF00000) == 0xFFF00000);
464
sync = ((headerstring & 0xFFE00000) == 0xFFE00000); // SZD: MPEG 2.5
465
}
466
else
467
{
468
sync = ((headerstring & 0xFFF80C00) == word) &&
469
(((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode);
470
}
471
472
// filter out invalid sample rate
473
if (sync)
474
sync = (((headerstring >>> 10) & 3)!=3);
475
// filter out invalid layer
476
if (sync)
477
sync = (((headerstring >>> 17) & 3)!=0);
478
// filter out invalid version
479
if (sync)
480
sync = (((headerstring >>> 19) & 3)!=1);
481
482
return sync;
483
}
484
485
/**
486
* Reads the data for the next frame. The frame is not parsed
487
* until parse frame is called.
488
*/
489
int read_frame_data(int bytesize) throws BitstreamException
490
{
491
int numread = 0;
492
numread = readFully(frame_bytes, 0, bytesize);
493
framesize = bytesize;
494
wordpointer = -1;
495
bitindex = -1;
496
return numread;
497
}
498
499
/**
500
* Parses the data previously read with read_frame_data().
501
*/
502
void parse_frame() throws BitstreamException
503
{
504
// Convert Bytes read to int
505
int b=0;
506
byte[] byteread = frame_bytes;
507
int bytesize = framesize;
508
509
// Check ID3v1 TAG (True only if last frame).
510
//for (int t=0;t<(byteread.length)-2;t++)
511
//{
512
// if ((byteread[t]=='T') && (byteread[t+1]=='A') && (byteread[t+2]=='G'))
513
// {
514
// System.out.println("ID3v1 detected at offset "+t);
515
// throw newBitstreamException(INVALIDFRAME, null);
516
// }
517
//}
518
519
for (int k=0;k<bytesize;k=k+4)
520
{
521
int convert = 0;
522
byte b0 = 0;
523
byte b1 = 0;
524
byte b2 = 0;
525
byte b3 = 0;
526
b0 = byteread[k];
527
if (k+1<bytesize) b1 = byteread[k+1];
528
if (k+2<bytesize) b2 = byteread[k+2];
529
if (k+3<bytesize) b3 = byteread[k+3];
530
framebuffer[b++] = ((b0 << 24) &0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF);
531
}
532
wordpointer = 0;
533
bitindex = 0;
534
}
535
536
/**
537
* Read bits from buffer into the lower bits of an unsigned int.
538
* The LSB contains the latest read bit of the stream.
539
* (1 <= number_of_bits <= 16)
540
*/
541
public int get_bits(int number_of_bits)
542
{
543
int returnvalue = 0;
544
int sum = bitindex + number_of_bits;
545
546
// E.B
547
// There is a problem here, wordpointer could be -1 ?!
548
if (wordpointer < 0) wordpointer = 0;
549
// E.B : End.
550
551
if (sum <= 32)
552
{
553
// all bits contained in *wordpointer
554
returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits];
555
// returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits];
556
if ((bitindex += number_of_bits) == 32)
557
{
558
bitindex = 0;
559
wordpointer++; // added by me!
560
}
561
return returnvalue;
562
}
563
564
// E.B : Check that ?
565
//((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0];
566
//wordpointer++; // Added by me!
567
//((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0];
568
int Right = (framebuffer[wordpointer] & 0x0000FFFF);
569
wordpointer++;
570
int Left = (framebuffer[wordpointer] & 0xFFFF0000);
571
returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16)& 0x0000FFFF);
572
573
returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 - bitindex))
574
returnvalue &= bitmask[number_of_bits];
575
bitindex = sum - 32;
576
return returnvalue;
577
}
578
579
/**
580
* Set the word we want to sync the header to.
581
* In Big-Endian byte order
582
*/
583
void set_syncword(int syncword0)
584
{
585
syncword = syncword0 & 0xFFFFFF3F;
586
single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0);
587
}
588
/**
589
* Reads the exact number of bytes from the source
590
* input stream into a byte array.
591
*
592
* @param b The byte array to read the specified number
593
* of bytes into.
594
* @param offs The index in the array where the first byte
595
* read should be stored.
596
* @param len the number of bytes to read.
597
*
598
* @exception BitstreamException is thrown if the specified
599
* number of bytes could not be read from the stream.
600
*/
601
private int readFully(byte[] b, int offs, int len)
602
throws BitstreamException
603
{
604
int nRead = 0;
605
try
606
{
607
while (len > 0)
608
{
609
int bytesread = source.read(b, offs, len);
610
if (bytesread == -1)
611
{
612
while (len-->0)
613
{
614
b[offs++] = 0;
615
}
616
break;
617
//throw newBitstreamException(UNEXPECTED_EOF, new EOFException());
618
}
619
nRead = nRead + bytesread;
620
offs += bytesread;
621
len -= bytesread;
622
}
623
}
624
catch (IOException ex)
625
{
626
throw newBitstreamException(STREAM_ERROR, ex);
627
}
628
return nRead;
629
}
630
631
/**
632
* Similar to readFully, but doesn't throw exception when
633
* EOF is reached.
634
*/
635
private int readBytes(byte[] b, int offs, int len)
636
throws BitstreamException
637
{
638
int totalBytesRead = 0;
639
try
640
{
641
while (len > 0)
642
{
643
int bytesread = source.read(b, offs, len);
644
if (bytesread == -1)
645
{
646
break;
647
}
648
totalBytesRead += bytesread;
649
offs += bytesread;
650
len -= bytesread;
651
}
652
}
653
catch (IOException ex)
654
{
655
throw newBitstreamException(STREAM_ERROR, ex);
656
}
657
return totalBytesRead;
658
}
659
}
660
661