summaryrefslogtreecommitdiff
path: root/songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java
diff options
context:
space:
mode:
authorMichiel Van Der Kolk <not.valid@email.address>2005-07-11 15:42:37 +0000
committerMichiel Van Der Kolk <not.valid@email.address>2005-07-11 15:42:37 +0000
commit9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e (patch)
tree4c304cd4151020bd5494d279ee68a105ae3a5a3a /songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java
parentdfa8ecbe609ca8ea194d08560a44fb9a92e94b4b (diff)
downloadrockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.tar.gz
rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.zip
Songdb java version, source. only 1.5 compatible
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java')
-rw-r--r--songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java510
1 files changed, 510 insertions, 0 deletions
diff --git a/songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java b/songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java
new file mode 100644
index 0000000000..ee79becf20
--- /dev/null
+++ b/songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java
@@ -0,0 +1,510 @@
1/*
2 * TAudioFileReader.java
3 *
4 * This file is part of Tritonus: http://www.tritonus.org/
5 */
6
7/*
8 * Copyright (c) 1999 by Matthias Pfisterer
9 * Copyright (c) 2001 by Florian Bomers <http://www.bomers.de>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Library General Public License as published
13 * by the Free Software Foundation; either version 2 of the License, or
14 * (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/*
27|<--- this code is formatted to fit into 80 columns --->|
28*/
29
30package org.tritonus.share.sampled.file;
31
32import java.io.BufferedInputStream;
33import java.io.File;
34import java.io.FileInputStream;
35import java.io.DataInputStream;
36import java.io.InputStream;
37import java.io.IOException;
38import java.io.EOFException;
39
40import java.net.URL;
41import java.net.URLConnection;
42
43import javax.sound.sampled.AudioFormat;
44import javax.sound.sampled.AudioInputStream;
45import javax.sound.sampled.AudioFileFormat;
46import javax.sound.sampled.AudioSystem;
47import javax.sound.sampled.UnsupportedAudioFileException;
48import javax.sound.sampled.spi.AudioFileReader;
49
50import org.tritonus.share.TDebug;
51
52
53
54/** Base class for audio file readers.
55 This is Tritonus' base class for classes that provide the facility
56 of detecting an audio file type and reading its header.
57 Classes should be derived from this class or one of its subclasses
58 rather than from javax.sound.sampled.spi.AudioFileReader.
59
60 @author Matthias Pfisterer
61 @author Florian Bomers
62*/
63public abstract class TAudioFileReader
64extends AudioFileReader
65{
66 private int m_nMarkLimit = -1;
67 private boolean m_bRereading;
68
69
70 protected TAudioFileReader(int nMarkLimit)
71 {
72 this(nMarkLimit, false);
73 }
74
75
76
77 protected TAudioFileReader(int nMarkLimit, boolean bRereading)
78 {
79 m_nMarkLimit = nMarkLimit;
80 m_bRereading = bRereading;
81 }
82
83
84
85 private int getMarkLimit()
86 {
87 return m_nMarkLimit;
88 }
89
90
91
92 private boolean isRereading()
93 {
94 return m_bRereading;
95 }
96
97
98
99 /** Get an AudioFileFormat object for a File.
100 This method calls getAudioFileFormat(InputStream, long).
101 Subclasses should not override this method unless there are
102 really severe reasons. Normally, it is sufficient to
103 implement getAudioFileFormat(InputStream, long).
104
105 @param file the file to read from.
106 @return an AudioFileFormat instance containing
107 information from the header of the file passed in.
108 */
109 public AudioFileFormat getAudioFileFormat(File file)
110 throws UnsupportedAudioFileException, IOException
111 {
112 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioFileFormat(File): begin"); }
113 long lFileLengthInBytes = file.length();
114 InputStream inputStream = new FileInputStream(file);
115 AudioFileFormat audioFileFormat = null;
116 try
117 {
118 audioFileFormat = getAudioFileFormat(inputStream, lFileLengthInBytes);
119 }
120 finally
121 {
122 inputStream.close();
123 }
124 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioFileFormat(File): end"); }
125 return audioFileFormat;
126 }
127
128
129
130 /** Get an AudioFileFormat object for a URL.
131 This method calls getAudioFileFormat(InputStream, long).
132 Subclasses should not override this method unless there are
133 really severe reasons. Normally, it is sufficient to
134 implement getAudioFileFormat(InputStream, long).
135
136 @param url the URL to read from.
137 @return an AudioFileFormat instance containing
138 information from the header of the URL passed in.
139 */
140 public AudioFileFormat getAudioFileFormat(URL url)
141 throws UnsupportedAudioFileException, IOException
142
143 {
144 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioFileFormat(URL): begin"); }
145 long lFileLengthInBytes = getDataLength(url);
146 InputStream inputStream = url.openStream();
147 AudioFileFormat audioFileFormat = null;
148 try
149 {
150 audioFileFormat = getAudioFileFormat(inputStream, lFileLengthInBytes);
151 }
152 finally
153 {
154 inputStream.close();
155 }
156 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioFileFormat(URL): end"); }
157 return audioFileFormat;
158 }
159
160
161
162 /** Get an AudioFileFormat object for an InputStream.
163 This method calls getAudioFileFormat(InputStream, long).
164 Subclasses should not override this method unless there are
165 really severe reasons. Normally, it is sufficient to
166 implement getAudioFileFormat(InputStream, long).
167
168 @param inputStream the stream to read from.
169 @return an AudioFileFormat instance containing
170 information from the header of the stream passed in.
171 */
172 public AudioFileFormat getAudioFileFormat(InputStream inputStream)
173 throws UnsupportedAudioFileException, IOException
174
175 {
176 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioFileFormat(InputStream): begin"); }
177 long lFileLengthInBytes = AudioSystem.NOT_SPECIFIED;
178 inputStream.mark(getMarkLimit());
179 AudioFileFormat audioFileFormat = null;
180 try
181 {
182 audioFileFormat = getAudioFileFormat(inputStream, lFileLengthInBytes);
183 }
184 finally
185 {
186 /* TODO: required semantics is unclear: should reset()
187 be executed only when there is an exception or
188 should it be done always?
189 */
190 inputStream.reset();
191 }
192 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioFileFormat(InputStream): end"); }
193 return audioFileFormat;
194 }
195
196
197
198 /** Get an AudioFileFormat (internal implementation).
199 Subclasses must implement this method in a way specific
200 to the file format they handle.
201
202 Note that depending on the implementation of this method,
203 you should or should not override
204 getAudioInputStream(InputStream, long), too (see comment
205 there).
206
207 @param inputStream The InputStream to read from.
208 @param lFileLengthInBytes The size of the originating
209 file, if known. If it isn't known, AudioSystem.NOT_SPECIFIED
210 should be passed. This value may be used for byteLength in
211 AudioFileFormat, if this value can't be derived from the
212 informmation in the file header.
213
214 @return an AudioFileFormat instance containing
215 information from the header of the stream passed in as
216 inputStream.
217 */
218 protected abstract AudioFileFormat getAudioFileFormat(
219 InputStream inputStream,
220 long lFileLengthInBytes)
221 throws UnsupportedAudioFileException, IOException;
222
223
224
225 /** Get an AudioInputStream object for a file.
226 This method calls getAudioInputStream(InputStream, long).
227 Subclasses should not override this method unless there are
228 really severe reasons. Normally, it is sufficient to
229 implement getAudioFileFormat(InputStream, long) and perhaps
230 override getAudioInputStream(InputStream, long).
231
232 @param file the File object to read from.
233 @return an AudioInputStream instance containing
234 the audio data from this file.
235 */
236 public AudioInputStream getAudioInputStream(File file)
237 throws UnsupportedAudioFileException, IOException
238 {
239 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioInputStream(File): begin"); }
240 long lFileLengthInBytes = file.length();
241 InputStream inputStream = new FileInputStream(file);
242 AudioInputStream audioInputStream = null;
243 try
244 {
245 audioInputStream = getAudioInputStream(inputStream, lFileLengthInBytes);
246 }
247 catch (UnsupportedAudioFileException e)
248 {
249 inputStream.close();
250 throw e;
251 }
252 catch (IOException e)
253 {
254 inputStream.close();
255 throw e;
256 }
257 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioInputStream(File): end"); }
258 return audioInputStream;
259 }
260
261
262
263 /** Get an AudioInputStream object for a URL.
264 This method calls getAudioInputStream(InputStream, long).
265 Subclasses should not override this method unless there are
266 really severe reasons. Normally, it is sufficient to
267 implement getAudioFileFormat(InputStream, long) and perhaps
268 override getAudioInputStream(InputStream, long).
269
270 @param url the URL to read from.
271 @return an AudioInputStream instance containing
272 the audio data from this URL.
273 */
274 public AudioInputStream getAudioInputStream(URL url)
275 throws UnsupportedAudioFileException, IOException
276 {
277 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioInputStream(URL): begin"); }
278 long lFileLengthInBytes = getDataLength(url);
279 InputStream inputStream = url.openStream();
280 AudioInputStream audioInputStream = null;
281 try
282 {
283 audioInputStream = getAudioInputStream(inputStream, lFileLengthInBytes);
284 }
285 catch (UnsupportedAudioFileException e)
286 {
287 inputStream.close();
288 throw e;
289 }
290 catch (IOException e)
291 {
292 inputStream.close();
293 throw e;
294 }
295 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioInputStream(URL): end"); }
296 return audioInputStream;
297 }
298
299
300
301 /** Get an AudioInputStream object for an InputStream.
302 This method calls getAudioInputStream(InputStream, long).
303 Subclasses should not override this method unless there are
304 really severe reasons. Normally, it is sufficient to
305 implement getAudioFileFormat(InputStream, long) and perhaps
306 override getAudioInputStream(InputStream, long).
307
308 @param inputStream the stream to read from.
309 @return an AudioInputStream instance containing
310 the audio data from this stream.
311 */
312 public AudioInputStream getAudioInputStream(InputStream inputStream)
313 throws UnsupportedAudioFileException, IOException
314 {
315 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioInputStream(InputStream): begin"); }
316 long lFileLengthInBytes = AudioSystem.NOT_SPECIFIED;
317 AudioInputStream audioInputStream = null;
318 inputStream.mark(getMarkLimit());
319 try
320 {
321 audioInputStream = getAudioInputStream(inputStream, lFileLengthInBytes);
322 }
323 catch (UnsupportedAudioFileException e)
324 {
325 inputStream.reset();
326 throw e;
327 }
328 catch (IOException e)
329 {
330 inputStream.reset();
331 throw e;
332 }
333 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioInputStream(InputStream): end"); }
334 return audioInputStream;
335 }
336
337
338
339 /** Get an AudioInputStream (internal implementation).
340 This implementation calls getAudioFileFormat() with the
341 same arguments as passed in here. Then, it constructs
342 an AudioInputStream instance. This instance takes the passed
343 inputStream in the state it is left after getAudioFileFormat()
344 did its work. In other words, the implementation here
345 assumes that getAudioFileFormat() reads the entire header
346 up to a position exactely where the audio data starts.
347 If this can't be realized for a certain format, this method
348 should be overridden.
349
350 @param inputStream The InputStream to read from.
351 @param lFileLengthInBytes The size of the originating
352 file, if known. If it isn't known, AudioSystem.NOT_SPECIFIED
353 should be passed. This value may be used for byteLength in
354 AudioFileFormat, if this value can't be derived from the
355 informmation in the file header.
356 */
357 protected AudioInputStream getAudioInputStream(InputStream inputStream, long lFileLengthInBytes)
358 throws UnsupportedAudioFileException, IOException
359 {
360 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioInputStream(InputStream, long): begin"); }
361 if (isRereading())
362 {
363 inputStream = new BufferedInputStream(inputStream, getMarkLimit());
364 inputStream.mark(getMarkLimit());
365 }
366 AudioFileFormat audioFileFormat = getAudioFileFormat(inputStream, lFileLengthInBytes);
367 if (isRereading())
368 {
369 inputStream.reset();
370 }
371 AudioInputStream audioInputStream =
372 new AudioInputStream(inputStream,
373 audioFileFormat.getFormat(),
374 audioFileFormat.getFrameLength());
375 if (TDebug.TraceAudioFileReader) {TDebug.out("TAudioFileReader.getAudioInputStream(InputStream, long): end"); }
376 return audioInputStream;
377 }
378
379
380
381 protected static int calculateFrameSize(int nSampleSize, int nNumChannels)
382 {
383 return ((nSampleSize + 7) / 8) * nNumChannels;
384 }
385
386
387
388 private static long getDataLength(URL url)
389 throws IOException
390 {
391 long lFileLengthInBytes = AudioSystem.NOT_SPECIFIED;
392 URLConnection connection = url.openConnection();
393 connection.connect();
394 int nLength = connection.getContentLength();
395 if (nLength > 0)
396 {
397 lFileLengthInBytes = nLength;
398 }
399 return lFileLengthInBytes;
400 }
401
402
403
404 public static int readLittleEndianInt(InputStream is)
405 throws IOException
406 {
407 int b0 = is.read();
408 int b1 = is.read();
409 int b2 = is.read();
410 int b3 = is.read();
411 if ((b0 | b1 | b2 | b3) < 0)
412 {
413 throw new EOFException();
414 }
415 return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
416 }
417
418
419
420 public static short readLittleEndianShort(InputStream is)
421 throws IOException
422 {
423 int b0 = is.read();
424 int b1 = is.read();
425 if ((b0 | b1) < 0)
426 {
427 throw new EOFException();
428 }
429 return (short) ((b1 << 8) + (b0 << 0));
430 }
431
432
433/*
434 * C O N V E R T F R O M I E E E E X T E N D E D
435 */
436
437/*
438 * Copyright (C) 1988-1991 Apple Computer, Inc.
439 * All rights reserved.
440 *
441 * Machine-independent I/O routines for IEEE floating-point numbers.
442 *
443 * NaN's and infinities are converted to HUGE_VAL or HUGE, which
444 * happens to be infinity on IEEE machines. Unfortunately, it is
445 * impossible to preserve NaN's in a machine-independent way.
446 * Infinities are, however, preserved on IEEE machines.
447 *
448 * These routines have been tested on the following machines:
449 * Apple Macintosh, MPW 3.1 C compiler
450 * Apple Macintosh, THINK C compiler
451 * Silicon Graphics IRIS, MIPS compiler
452 * Cray X/MP and Y/MP
453 * Digital Equipment VAX
454 *
455 *
456 * Implemented by Malcolm Slaney and Ken Turkowski.
457 *
458 * Malcolm Slaney contributions during 1988-1990 include big- and little-
459 * endian file I/O, conversion to and from Motorola's extended 80-bit
460 * floating-point format, and conversions to and from IEEE single-
461 * precision floating-point format.
462 *
463 * In 1991, Ken Turkowski implemented the conversions to and from
464 * IEEE double-precision format, added more precision to the extended
465 * conversions, and accommodated conversions involving +/- infinity,
466 * NaN's, and denormalized numbers.
467 */
468
469 public static double readIeeeExtended(DataInputStream dis)
470 throws IOException
471 {
472 double f = 0.0D;
473 int expon = 0;
474 long hiMant = 0L;
475 long loMant = 0L;
476 double HUGE = 3.4028234663852886E+038D;
477 expon = dis.readUnsignedShort();
478 long t1 = dis.readUnsignedShort();
479 long t2 = dis.readUnsignedShort();
480 hiMant = t1 << 16 | t2;
481 t1 = dis.readUnsignedShort();
482 t2 = dis.readUnsignedShort();
483 loMant = t1 << 16 | t2;
484 if(expon == 0 && hiMant == 0L && loMant == 0L)
485 {
486 f = 0.0D;
487 }
488 else
489 {
490 if(expon == 32767)
491 {
492 f = HUGE;
493 }
494 else
495 {
496 expon -= 16383;
497 expon -= 31;
498 f = hiMant * Math.pow(2D, expon);
499 expon -= 32;
500 f += loMant * Math.pow(2D, expon);
501 }
502 }
503 return f;
504 }
505}
506
507
508
509/*** TAudioFileReader.java ***/
510