summaryrefslogtreecommitdiff
path: root/songdbj/org/tritonus/file/AiffAudioFileReader.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/file/AiffAudioFileReader.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/file/AiffAudioFileReader.java')
-rw-r--r--songdbj/org/tritonus/file/AiffAudioFileReader.java244
1 files changed, 244 insertions, 0 deletions
diff --git a/songdbj/org/tritonus/file/AiffAudioFileReader.java b/songdbj/org/tritonus/file/AiffAudioFileReader.java
new file mode 100644
index 0000000000..139ba05425
--- /dev/null
+++ b/songdbj/org/tritonus/file/AiffAudioFileReader.java
@@ -0,0 +1,244 @@
1/*
2 * AiffAudioFileReader.java
3 *
4 * This file is part of Tritonus: http://www.tritonus.org/
5 */
6
7/*
8 * Copyright (c) 2000 by Florian Bomers <http://www.bomers.de>
9 * Copyright (c) 1999 by Matthias Pfisterer
10 *
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as published
14 * by the Free Software Foundation; either version 2 of the License, or
15 * (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
28/*
29|<--- this code is formatted to fit into 80 columns --->|
30*/
31
32package org.tritonus.sampled.file;
33
34import java.io.DataInputStream;
35import java.io.File;
36import java.io.InputStream;
37import java.io.IOException;
38
39import javax.sound.sampled.AudioFormat;
40import javax.sound.sampled.AudioFileFormat;
41import javax.sound.sampled.AudioInputStream;
42import javax.sound.sampled.AudioSystem;
43import javax.sound.sampled.UnsupportedAudioFileException;
44
45import org.tritonus.share.sampled.file.TAudioFileFormat;
46import org.tritonus.share.sampled.file.TAudioFileReader;
47import org.tritonus.share.TDebug;
48
49
50/** Class for reading AIFF and AIFF-C files.
51 *
52 * @author Florian Bomers
53 * @author Matthias Pfisterer
54 */
55public class AiffAudioFileReader extends TAudioFileReader
56{
57 private static final int READ_LIMIT = 1000;
58
59
60
61 public AiffAudioFileReader()
62 {
63 super(READ_LIMIT);
64 }
65
66
67
68 private void skipChunk(DataInputStream dataInputStream, int chunkLength, int chunkRead)
69 throws IOException {
70 chunkLength-=chunkRead;
71 if (chunkLength>0) {
72 dataInputStream.skip(chunkLength + (chunkLength % 2));
73 }
74 }
75
76 private AudioFormat readCommChunk(DataInputStream dataInputStream, int chunkLength)
77 throws IOException, UnsupportedAudioFileException {
78
79 int nNumChannels = dataInputStream.readShort();
80 if (nNumChannels <= 0) {
81 throw new UnsupportedAudioFileException(
82 "not an AIFF file: number of channels must be positive");
83 }
84 if (TDebug.TraceAudioFileReader) {
85 TDebug.out("Found "+nNumChannels+" channels.");
86 }
87 // ignored: frame count
88 dataInputStream.readInt();
89 int nSampleSize = dataInputStream.readShort();
90 float fSampleRate = (float) readIeeeExtended(dataInputStream);
91 if (fSampleRate <= 0.0) {
92 throw new UnsupportedAudioFileException(
93 "not an AIFF file: sample rate must be positive");
94 }
95 if (TDebug.TraceAudioFileReader) {
96 TDebug.out("Found framerate "+fSampleRate);
97 }
98 AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
99 int nRead=18;
100 if (chunkLength>nRead) {
101 int nEncoding=dataInputStream.readInt();
102 nRead+=4;
103 if (nEncoding==AiffTool.AIFF_COMM_PCM) {
104 // PCM - nothing to do
105 }
106 else if (nEncoding==AiffTool.AIFF_COMM_ULAW) {
107 // ULAW
108 encoding=AudioFormat.Encoding.ULAW;
109 nSampleSize=8;
110 }
111 else if (nEncoding==AiffTool.AIFF_COMM_IMA_ADPCM) {
112 encoding = new AudioFormat.Encoding("IMA_ADPCM");
113 nSampleSize=4;
114 }
115 else {
116 throw new UnsupportedAudioFileException(
117 "Encoding 0x"+Integer.toHexString(nEncoding)
118 +" of AIFF file not supported");
119 }
120 }
121 /* In case of IMA ADPCM, frame size is 0.5 bytes (since it is
122 always mono). A value of 1 as frame size would be wrong.
123 Handling of frame size 0 in defined nowhere. So the best
124 solution is to set the frame size to unspecified (-1).
125 */
126 int nFrameSize = (nSampleSize == 4) ?
127 AudioSystem.NOT_SPECIFIED :
128 calculateFrameSize(nSampleSize, nNumChannels);
129 if (TDebug.TraceAudioFileReader) { TDebug.out("calculated frame size: " + nFrameSize); }
130 skipChunk(dataInputStream, chunkLength, nRead);
131 AudioFormat format = new AudioFormat(encoding,
132 fSampleRate,
133 nSampleSize,
134 nNumChannels,
135 nFrameSize,
136 fSampleRate,
137 true);
138 return format;
139 }
140
141 private void readVerChunk(DataInputStream dataInputStream, int chunkLength)
142 throws IOException, UnsupportedAudioFileException {
143 if (chunkLength<4) {
144 throw new UnsupportedAudioFileException(
145 "Corrput AIFF file: FVER chunk too small.");
146 }
147 int nVer=dataInputStream.readInt();
148 if (nVer!=AiffTool.AIFF_FVER_TIME_STAMP) {
149 throw new UnsupportedAudioFileException(
150 "Unsupported AIFF file: version not known.");
151 }
152 skipChunk(dataInputStream, chunkLength, 4);
153 }
154
155
156
157 protected AudioFileFormat getAudioFileFormat(InputStream inputStream, long lFileSizeInBytes)
158 throws UnsupportedAudioFileException, IOException
159 {
160 if (TDebug.TraceAudioFileReader) {TDebug.out("AiffAudioFileReader.getAudioFileFormat(InputStream, long): begin"); }
161 DataInputStream dataInputStream = new DataInputStream(inputStream);
162 int nMagic = dataInputStream.readInt();
163 if (nMagic != AiffTool.AIFF_FORM_MAGIC) {
164 throw new UnsupportedAudioFileException(
165 "not an AIFF file: header magic is not FORM");
166 }
167 int nTotalLength = dataInputStream.readInt();
168 nMagic = dataInputStream.readInt();
169 boolean bIsAifc;
170 if (nMagic == AiffTool.AIFF_AIFF_MAGIC) {
171 bIsAifc = false;
172 } else if (nMagic == AiffTool.AIFF_AIFC_MAGIC) {
173 bIsAifc = true;
174 } else {
175 throw new UnsupportedAudioFileException(
176 "unsupported IFF file: header magic neither AIFF nor AIFC");
177 }
178 boolean bFVerFound=!bIsAifc;
179 boolean bCommFound=false;
180 boolean bSSndFound=false;
181 AudioFormat format=null;
182 int nDataChunkLength=0;
183
184 // walk through the chunks
185 // chunks may be in any order. However, in this implementation, SSND must be last
186 while (!bFVerFound || !bCommFound || !bSSndFound) {
187 nMagic = dataInputStream.readInt();
188 int nChunkLength = dataInputStream.readInt();
189 switch (nMagic) {
190 case AiffTool.AIFF_COMM_MAGIC:
191 format=readCommChunk(dataInputStream, nChunkLength);
192 if (TDebug.TraceAudioFileReader) {
193 TDebug.out("Read COMM chunk with length "+nChunkLength);
194 }
195 bCommFound=true;
196 break;
197 case AiffTool.AIFF_FVER_MAGIC:
198 if (!bFVerFound) {
199 readVerChunk(dataInputStream, nChunkLength);
200 if (TDebug.TraceAudioFileReader) {
201 TDebug.out("Read FVER chunk with length "+nChunkLength);
202 }
203 bFVerFound=true;
204 } else {
205 skipChunk(dataInputStream, nChunkLength, 0);
206 }
207 break;
208 case AiffTool.AIFF_SSND_MAGIC:
209 if (!bCommFound || !bFVerFound) {
210 throw new UnsupportedAudioFileException(
211 "cannot handle AIFF file: SSND not last chunk");
212 }
213 bSSndFound=true;
214 nDataChunkLength=nChunkLength-8;
215 // 8 information bytes of no interest
216 dataInputStream.skip(8);
217 if (TDebug.TraceAudioFileReader) {
218 TDebug.out("Found SSND chunk with length "+nChunkLength);
219 }
220 break;
221 default:
222 if (TDebug.TraceAudioFileReader) {
223 TDebug.out("Skipping unknown chunk: "
224 +Integer.toHexString(nMagic));
225 }
226 skipChunk(dataInputStream, nChunkLength, 0);
227 break;
228 }
229 }
230
231 // TODO: length argument has to be in frames
232 AudioFileFormat audioFileFormat = new TAudioFileFormat(
233 bIsAifc ? AudioFileFormat.Type.AIFC : AudioFileFormat.Type.AIFF,
234 format,
235 nDataChunkLength / format.getFrameSize(),
236 nTotalLength + 8);
237 if (TDebug.TraceAudioFileReader) {TDebug.out("AiffAudioFileReader.getAudioFileFormat(InputStream, long): end"); }
238 return audioFileFormat;
239 }
240}
241
242
243
244/*** AiffAudioFileReader.java ***/