diff options
Diffstat (limited to 'songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java')
-rw-r--r-- | songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java | 510 |
1 files changed, 0 insertions, 510 deletions
diff --git a/songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java b/songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java deleted file mode 100644 index ee79becf20..0000000000 --- a/songdbj/org/tritonus/share/sampled/file/TAudioFileReader.java +++ /dev/null | |||
@@ -1,510 +0,0 @@ | |||
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 | |||
30 | package org.tritonus.share.sampled.file; | ||
31 | |||
32 | import java.io.BufferedInputStream; | ||
33 | import java.io.File; | ||
34 | import java.io.FileInputStream; | ||
35 | import java.io.DataInputStream; | ||
36 | import java.io.InputStream; | ||
37 | import java.io.IOException; | ||
38 | import java.io.EOFException; | ||
39 | |||
40 | import java.net.URL; | ||
41 | import java.net.URLConnection; | ||
42 | |||
43 | import javax.sound.sampled.AudioFormat; | ||
44 | import javax.sound.sampled.AudioInputStream; | ||
45 | import javax.sound.sampled.AudioFileFormat; | ||
46 | import javax.sound.sampled.AudioSystem; | ||
47 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
48 | import javax.sound.sampled.spi.AudioFileReader; | ||
49 | |||
50 | import 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 | */ | ||
63 | public abstract class TAudioFileReader | ||
64 | extends 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 | |||