diff options
author | Michiel Van Der Kolk <not.valid@email.address> | 2005-07-11 15:42:37 +0000 |
---|---|---|
committer | Michiel Van Der Kolk <not.valid@email.address> | 2005-07-11 15:42:37 +0000 |
commit | 9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e (patch) | |
tree | 4c304cd4151020bd5494d279ee68a105ae3a5a3a /songdbj/org/tritonus/file/AiffAudioFileReader.java | |
parent | dfa8ecbe609ca8ea194d08560a44fb9a92e94b4b (diff) | |
download | rockbox-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.java | 244 |
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 | |||
32 | package org.tritonus.sampled.file; | ||
33 | |||
34 | import java.io.DataInputStream; | ||
35 | import java.io.File; | ||
36 | import java.io.InputStream; | ||
37 | import java.io.IOException; | ||
38 | |||
39 | import javax.sound.sampled.AudioFormat; | ||
40 | import javax.sound.sampled.AudioFileFormat; | ||
41 | import javax.sound.sampled.AudioInputStream; | ||
42 | import javax.sound.sampled.AudioSystem; | ||
43 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
44 | |||
45 | import org.tritonus.share.sampled.file.TAudioFileFormat; | ||
46 | import org.tritonus.share.sampled.file.TAudioFileReader; | ||
47 | import 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 | */ | ||
55 | public 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 ***/ | ||