diff options
Diffstat (limited to 'songdbj/javazoom/spi')
24 files changed, 0 insertions, 3878 deletions
diff --git a/songdbj/javazoom/spi/PropertiesContainer.java b/songdbj/javazoom/spi/PropertiesContainer.java deleted file mode 100644 index 27ed85f904..0000000000 --- a/songdbj/javazoom/spi/PropertiesContainer.java +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | /* | ||
2 | * PropertiesContainer. | ||
3 | * | ||
4 | * JavaZOOM : mp3spi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | *----------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | *---------------------------------------------------------------------- | ||
22 | */ | ||
23 | |||
24 | package javazoom.spi; | ||
25 | |||
26 | import java.util.Map; | ||
27 | |||
28 | public interface PropertiesContainer | ||
29 | { | ||
30 | public Map properties(); | ||
31 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java b/songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java deleted file mode 100644 index e4e6fed00a..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java +++ /dev/null | |||
@@ -1,334 +0,0 @@ | |||
1 | /* | ||
2 | * DecodedMpegAudioInputStream. | ||
3 | * | ||
4 | * JavaZOOM : mp3spi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | *----------------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | *------------------------------------------------------------------------ | ||
22 | */ | ||
23 | |||
24 | package javazoom.spi.mpeg.sampled.convert; | ||
25 | import java.io.IOException; | ||
26 | import java.io.InputStream; | ||
27 | import java.util.HashMap; | ||
28 | import java.util.Map; | ||
29 | |||
30 | import javax.sound.sampled.AudioFormat; | ||
31 | import javax.sound.sampled.AudioInputStream; | ||
32 | |||
33 | import javazoom.jl.decoder.Bitstream; | ||
34 | import javazoom.jl.decoder.BitstreamException; | ||
35 | import javazoom.jl.decoder.Decoder; | ||
36 | import javazoom.jl.decoder.DecoderException; | ||
37 | import javazoom.jl.decoder.Equalizer; | ||
38 | import javazoom.jl.decoder.Header; | ||
39 | import javazoom.jl.decoder.Obuffer; | ||
40 | import javazoom.spi.PropertiesContainer; | ||
41 | import javazoom.spi.mpeg.sampled.file.IcyListener; | ||
42 | import javazoom.spi.mpeg.sampled.file.tag.TagParseEvent; | ||
43 | import javazoom.spi.mpeg.sampled.file.tag.TagParseListener; | ||
44 | |||
45 | import org.tritonus.share.TDebug; | ||
46 | import org.tritonus.share.sampled.convert.TAsynchronousFilteredAudioInputStream; | ||
47 | |||
48 | /** | ||
49 | * Main decoder. | ||
50 | */ | ||
51 | public class DecodedMpegAudioInputStream extends TAsynchronousFilteredAudioInputStream implements PropertiesContainer, TagParseListener | ||
52 | { | ||
53 | private InputStream m_encodedStream; | ||
54 | private Bitstream m_bitstream; | ||
55 | private Decoder m_decoder; | ||
56 | private Equalizer m_equalizer; | ||
57 | private float[] m_equalizer_values; | ||
58 | private Header m_header; | ||
59 | private DMAISObuffer m_oBuffer; | ||
60 | |||
61 | // Bytes info. | ||
62 | private long byteslength = -1; | ||
63 | private long currentByte = 0; | ||
64 | // Frame info. | ||
65 | private int frameslength = -1; | ||
66 | private long currentFrame = 0; | ||
67 | private int currentFramesize = 0; | ||
68 | private int currentBitrate = -1; | ||
69 | // Time info. | ||
70 | private long currentMicrosecond = 0; | ||
71 | // Shoutcast stream info | ||
72 | private IcyListener shoutlst = null; | ||
73 | |||
74 | |||
75 | private HashMap properties = null; | ||
76 | |||
77 | public DecodedMpegAudioInputStream(AudioFormat outputFormat, AudioInputStream inputStream) | ||
78 | { | ||
79 | super(outputFormat, -1); | ||
80 | if (TDebug.TraceAudioConverter) | ||
81 | { | ||
82 | TDebug.out(">DecodedMpegAudioInputStream(AudioFormat outputFormat, AudioInputStream inputStream)"); | ||
83 | } | ||
84 | try | ||
85 | { | ||
86 | // Try to find out inputstream length to allow skip. | ||
87 | byteslength = inputStream.available(); | ||
88 | } | ||
89 | catch (IOException e) | ||
90 | { | ||
91 | TDebug.out("DecodedMpegAudioInputStream : Cannot run inputStream.available() : "+e.getMessage()); | ||
92 | byteslength = -1; | ||
93 | } | ||
94 | m_encodedStream = inputStream; | ||
95 | shoutlst = IcyListener.getInstance(); | ||
96 | shoutlst.reset(); | ||
97 | m_bitstream = new Bitstream(inputStream); | ||
98 | m_decoder = new Decoder(null); | ||
99 | m_equalizer = new Equalizer(); | ||
100 | m_equalizer_values = new float[32]; | ||
101 | for (int b=0;b<m_equalizer.getBandCount();b++) | ||
102 | { | ||
103 | m_equalizer_values[b] = m_equalizer.getBand(b); | ||
104 | } | ||
105 | m_decoder.setEqualizer(m_equalizer); | ||
106 | m_oBuffer = new DMAISObuffer(outputFormat.getChannels()); | ||
107 | m_decoder.setOutputBuffer(m_oBuffer); | ||
108 | try | ||
109 | { | ||
110 | m_header = m_bitstream.readFrame(); | ||
111 | if ((m_header != null) && (frameslength == -1) && (byteslength > 0)) frameslength = m_header.max_number_of_frames((int)byteslength); | ||
112 | } | ||
113 | catch (BitstreamException e) | ||
114 | { | ||
115 | TDebug.out("DecodedMpegAudioInputStream : Cannot read first frame : "+e.getMessage()); | ||
116 | byteslength = -1; | ||
117 | } | ||
118 | properties = new HashMap(); | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Return dynamic properties. | ||
123 | * | ||
124 | * <ul> | ||
125 | * <li><b>mp3.frame</b> [Long], current frame position. | ||
126 | * <li><b>mp3.frame.bitrate</b> [Integer], bitrate of the current frame. | ||
127 | * <li><b>mp3.frame.size.bytes</b> [Integer], size in bytes of the current frame. | ||
128 | * <li><b>mp3.position.byte</b> [Long], current position in bytes in the stream. | ||
129 | * <li><b>mp3.position.microseconds</b> [Long], elapsed microseconds. | ||
130 | * <li><b>mp3.equalizer</b> float[32], interactive equalizer array, values could be in [-1.0, +1.0]. | ||
131 | * <li><b>mp3.shoutcast.metadata.key</b> [String], Shoutcast meta key with matching value. | ||
132 | * <br>For instance : | ||
133 | * <br>mp3.shoutcast.metadata.StreamTitle=Current song playing in stream. | ||
134 | * <br>mp3.shoutcast.metadata.StreamUrl=Url info. | ||
135 | * </ul> | ||
136 | */ | ||
137 | public Map properties() | ||
138 | { | ||
139 | properties.put("mp3.frame",new Long(currentFrame)); | ||
140 | properties.put("mp3.frame.bitrate",new Integer(currentBitrate)); | ||
141 | properties.put("mp3.frame.size.bytes",new Integer(currentFramesize)); | ||
142 | properties.put("mp3.position.byte",new Long(currentByte)); | ||
143 | properties.put("mp3.position.microseconds",new Long(currentMicrosecond)); | ||
144 | properties.put("mp3.equalizer",m_equalizer_values); | ||
145 | // Optionnal shoutcast stream meta-data. | ||
146 | if (shoutlst != null) | ||
147 | { | ||
148 | String surl = shoutlst.getStreamUrl(); | ||
149 | String stitle = shoutlst.getStreamTitle(); | ||
150 | if ((stitle != null) && (stitle.trim().length()>0)) properties.put("mp3.shoutcast.metadata.StreamTitle",stitle); | ||
151 | if ((surl != null) && (surl.trim().length()>0)) properties.put("mp3.shoutcast.metadata.StreamUrl",surl); | ||
152 | } | ||
153 | return properties; | ||
154 | } | ||
155 | |||
156 | public void execute() | ||
157 | { | ||
158 | if (TDebug.TraceAudioConverter) TDebug.out("execute() : begin"); | ||
159 | try | ||
160 | { | ||
161 | // Following line hangs when FrameSize is available in AudioFormat. | ||
162 | Header header = null; | ||
163 | if (m_header == null) header = m_bitstream.readFrame(); | ||
164 | else header = m_header; | ||
165 | if (TDebug.TraceAudioConverter) TDebug.out("execute() : header = "+header); | ||
166 | if (header == null) | ||
167 | { | ||
168 | if (TDebug.TraceAudioConverter) | ||
169 | { | ||
170 | TDebug.out("header is null (end of mpeg stream)"); | ||
171 | } | ||
172 | getCircularBuffer().close(); | ||
173 | return; | ||
174 | } | ||
175 | currentFrame++; | ||
176 | currentBitrate = header.bitrate_instant(); | ||
177 | currentFramesize = header.calculate_framesize(); | ||
178 | currentByte = currentByte + currentFramesize; | ||
179 | currentMicrosecond = (long) (currentFrame* header.ms_per_frame()*1000.0f); | ||
180 | for (int b=0;b<m_equalizer_values.length;b++) | ||
181 | { | ||
182 | m_equalizer.setBand(b,m_equalizer_values[b]); | ||
183 | } | ||
184 | m_decoder.setEqualizer(m_equalizer); | ||
185 | Obuffer decoderOutput = m_decoder.decodeFrame(header, m_bitstream); | ||
186 | m_bitstream.closeFrame(); | ||
187 | getCircularBuffer().write(m_oBuffer.getBuffer(), 0, m_oBuffer.getCurrentBufferSize()); | ||
188 | m_oBuffer.reset(); | ||
189 | if (m_header != null) m_header = null; | ||
190 | } | ||
191 | catch (BitstreamException e) | ||
192 | { | ||
193 | if (TDebug.TraceAudioConverter) | ||
194 | { | ||
195 | TDebug.out(e); | ||
196 | } | ||
197 | } | ||
198 | catch (DecoderException e) | ||
199 | { | ||
200 | if (TDebug.TraceAudioConverter) | ||
201 | { | ||
202 | TDebug.out(e); | ||
203 | } | ||
204 | } | ||
205 | if (TDebug.TraceAudioConverter) TDebug.out("execute() : end"); | ||
206 | } | ||
207 | |||
208 | public long skip(long bytes) | ||
209 | { | ||
210 | if ((byteslength > 0) && (frameslength > 0)) | ||
211 | { | ||
212 | float ratio = bytes*1.0f/byteslength*1.0f; | ||
213 | long bytesread = skipFrames((long) (ratio*frameslength)); | ||
214 | currentByte = currentByte + bytesread; | ||
215 | return bytesread; | ||
216 | } | ||
217 | else return -1; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * Skip frames. | ||
222 | * You don't need to call it severals times, it will exactly skip given frames number. | ||
223 | * @param frames | ||
224 | * @return bytes length skipped matching to frames skipped. | ||
225 | */ | ||
226 | public long skipFrames(long frames) | ||
227 | { | ||
228 | if (TDebug.TraceAudioConverter) TDebug.out("skip(long frames) : begin"); | ||
229 | int framesRead = 0; | ||
230 | int bytesReads = 0; | ||
231 | try | ||
232 | { | ||
233 | for (int i=0;i<frames;i++) | ||
234 | { | ||
235 | Header header = m_bitstream.readFrame(); | ||
236 | if (header != null) | ||
237 | { | ||
238 | int fsize = header.calculate_framesize(); | ||
239 | bytesReads = bytesReads + fsize; | ||
240 | } | ||
241 | m_bitstream.closeFrame(); | ||
242 | framesRead++; | ||
243 | } | ||
244 | } | ||
245 | catch (BitstreamException e) | ||
246 | { | ||
247 | if (TDebug.TraceAudioConverter) TDebug.out(e); | ||
248 | } | ||
249 | if (TDebug.TraceAudioConverter) TDebug.out("skip(long frames) : end"); | ||
250 | currentFrame = currentFrame + framesRead; | ||
251 | return bytesReads; | ||
252 | } | ||
253 | |||
254 | private boolean isBigEndian() | ||
255 | { | ||
256 | return getFormat().isBigEndian(); | ||
257 | } | ||
258 | |||
259 | public void close() throws IOException | ||
260 | { | ||
261 | super.close(); | ||
262 | m_encodedStream.close(); | ||
263 | } | ||
264 | |||
265 | private class DMAISObuffer extends Obuffer | ||
266 | { | ||
267 | private int m_nChannels; | ||
268 | private byte[] m_abBuffer; | ||
269 | private int[] m_anBufferPointers; | ||
270 | private boolean m_bIsBigEndian; | ||
271 | public DMAISObuffer(int nChannels) | ||
272 | { | ||
273 | m_nChannels = nChannels; | ||
274 | m_abBuffer = new byte[OBUFFERSIZE * nChannels]; | ||
275 | m_anBufferPointers = new int[nChannels]; | ||
276 | reset(); | ||
277 | m_bIsBigEndian = DecodedMpegAudioInputStream.this.isBigEndian(); | ||
278 | } | ||
279 | public void append(int nChannel, short sValue) | ||
280 | { | ||
281 | byte bFirstByte; | ||
282 | byte bSecondByte; | ||
283 | if (m_bIsBigEndian) | ||
284 | { | ||
285 | bFirstByte = (byte) ((sValue >>> 8) & 0xFF); | ||
286 | bSecondByte = (byte) (sValue & 0xFF); | ||
287 | } | ||
288 | else // little endian | ||
289 | { | ||
290 | bFirstByte = (byte) (sValue & 0xFF); | ||
291 | bSecondByte = (byte) ((sValue >>> 8) & 0xFF); | ||
292 | } | ||
293 | m_abBuffer[m_anBufferPointers[nChannel]] = bFirstByte; | ||
294 | m_abBuffer[m_anBufferPointers[nChannel] + 1] = bSecondByte; | ||
295 | m_anBufferPointers[nChannel] += m_nChannels * 2; | ||
296 | } | ||
297 | public void set_stop_flag() | ||
298 | { | ||
299 | } | ||
300 | public void close() | ||
301 | { | ||
302 | } | ||
303 | public void write_buffer(int nValue) | ||
304 | { | ||
305 | } | ||
306 | public void clear_buffer() | ||
307 | { | ||
308 | } | ||
309 | public byte[] getBuffer() | ||
310 | { | ||
311 | return m_abBuffer; | ||
312 | } | ||
313 | public int getCurrentBufferSize() | ||
314 | { | ||
315 | return m_anBufferPointers[0]; | ||
316 | } | ||
317 | public void reset() | ||
318 | { | ||
319 | for (int i = 0; i < m_nChannels; i++) | ||
320 | { | ||
321 | /* Points to byte location, | ||
322 | * implicitely assuming 16 bit | ||
323 | * samples. | ||
324 | */ | ||
325 | m_anBufferPointers[i] = i * 2; | ||
326 | } | ||
327 | } | ||
328 | } | ||
329 | |||
330 | public void tagParsed(TagParseEvent tpe) | ||
331 | { | ||
332 | System.out.println("TAG:"+tpe.getTag()); | ||
333 | } | ||
334 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/convert/MpegFormatConversionProvider.java b/songdbj/javazoom/spi/mpeg/sampled/convert/MpegFormatConversionProvider.java deleted file mode 100644 index 1a3d51d9ad..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/convert/MpegFormatConversionProvider.java +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | /* | ||
2 | * MpegFormatConversionProvider. | ||
3 | * | ||
4 | * JavaZOOM : mp3spi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | * --------------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * -------------------------------------------------------------------------- | ||
22 | */ | ||
23 | |||
24 | |||
25 | package javazoom.spi.mpeg.sampled.convert; | ||
26 | |||
27 | |||
28 | import java.util.Arrays; | ||
29 | |||
30 | import javax.sound.sampled.AudioFormat; | ||
31 | import javax.sound.sampled.AudioInputStream; | ||
32 | import javax.sound.sampled.AudioSystem; | ||
33 | |||
34 | import javazoom.spi.mpeg.sampled.file.MpegEncoding; | ||
35 | |||
36 | import org.tritonus.share.TDebug; | ||
37 | import org.tritonus.share.sampled.Encodings; | ||
38 | import org.tritonus.share.sampled.convert.TEncodingFormatConversionProvider; | ||
39 | |||
40 | /** | ||
41 | * ConversionProvider for MPEG files. | ||
42 | */ | ||
43 | public class MpegFormatConversionProvider extends TEncodingFormatConversionProvider | ||
44 | { | ||
45 | private static final AudioFormat.Encoding MP3 = Encodings.getEncoding("MP3"); | ||
46 | private static final AudioFormat.Encoding PCM_SIGNED = Encodings.getEncoding("PCM_SIGNED"); | ||
47 | |||
48 | private static final AudioFormat[] INPUT_FORMATS = | ||
49 | { | ||
50 | // mono | ||
51 | new AudioFormat(MP3, -1.0F, -1, 1, -1, -1.0F, false), | ||
52 | new AudioFormat(MP3, -1.0F, -1, 1, -1, -1.0F, true), | ||
53 | // stereo | ||
54 | new AudioFormat(MP3, -1.0F, -1, 2, -1, -1.0F, false), | ||
55 | new AudioFormat(MP3, -1.0F, -1, 2, -1, -1.0F, true), | ||
56 | }; | ||
57 | |||
58 | |||
59 | private static final AudioFormat[] OUTPUT_FORMATS = | ||
60 | { | ||
61 | // mono, 16 bit signed | ||
62 | new AudioFormat(PCM_SIGNED, -1.0F, 16, 1, 2, -1.0F, false), | ||
63 | new AudioFormat(PCM_SIGNED, -1.0F, 16, 1, 2, -1.0F, true), | ||
64 | // stereo, 16 bit signed | ||
65 | new AudioFormat(PCM_SIGNED, -1.0F, 16, 2, 4, -1.0F, false), | ||
66 | new AudioFormat(PCM_SIGNED, -1.0F, 16, 2, 4, -1.0F, true), | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * Constructor. | ||
71 | */ | ||
72 | public MpegFormatConversionProvider() | ||
73 | { | ||
74 | super(Arrays.asList(INPUT_FORMATS), Arrays.asList(OUTPUT_FORMATS)); | ||
75 | if (TDebug.TraceAudioConverter) | ||
76 | { | ||
77 | TDebug.out(">MpegFormatConversionProvider()"); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream audioInputStream) | ||
82 | { | ||
83 | if (TDebug.TraceAudioConverter) | ||
84 | { | ||
85 | TDebug.out(">MpegFormatConversionProvider.getAudioInputStream(AudioFormat targetFormat, AudioInputStream audioInputStream):"); | ||
86 | } | ||
87 | return new DecodedMpegAudioInputStream(targetFormat, audioInputStream); | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * Add conversion support for any MpegEncoding source with FrameRate or FrameSize not empty. | ||
92 | * @param targetFormat | ||
93 | * @param sourceFormat | ||
94 | * @return | ||
95 | */ | ||
96 | public boolean isConversionSupported(AudioFormat targetFormat, AudioFormat sourceFormat) | ||
97 | { | ||
98 | if (TDebug.TraceAudioConverter) | ||
99 | { | ||
100 | TDebug.out(">MpegFormatConversionProvider.isConversionSupported(AudioFormat targetFormat, AudioFormat sourceFormat):"); | ||
101 | TDebug.out("checking if conversion possible"); | ||
102 | TDebug.out("from: " + sourceFormat); | ||
103 | TDebug.out("to: " + targetFormat); | ||
104 | } | ||
105 | |||
106 | boolean conversion = super.isConversionSupported(targetFormat, sourceFormat); | ||
107 | if (conversion == false) | ||
108 | { | ||
109 | AudioFormat.Encoding enc = sourceFormat.getEncoding(); | ||
110 | if (enc instanceof MpegEncoding) | ||
111 | { | ||
112 | if ((sourceFormat.getFrameRate() != AudioSystem.NOT_SPECIFIED) || (sourceFormat.getFrameSize() != AudioSystem.NOT_SPECIFIED)) | ||
113 | { | ||
114 | conversion = true; | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | return conversion; | ||
119 | } | ||
120 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/IcyListener.java b/songdbj/javazoom/spi/mpeg/sampled/file/IcyListener.java deleted file mode 100644 index 8e49e6e2ef..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/IcyListener.java +++ /dev/null | |||
@@ -1,131 +0,0 @@ | |||
1 | /* | ||
2 | * IcyListener. | ||
3 | * | ||
4 | * JavaZOOM : mp3spi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | *----------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | *---------------------------------------------------------------------- | ||
22 | */ | ||
23 | |||
24 | package javazoom.spi.mpeg.sampled.file; | ||
25 | |||
26 | import javazoom.spi.mpeg.sampled.file.tag.MP3Tag; | ||
27 | import javazoom.spi.mpeg.sampled.file.tag.TagParseEvent; | ||
28 | import javazoom.spi.mpeg.sampled.file.tag.TagParseListener; | ||
29 | |||
30 | /** | ||
31 | * This class (singleton) allow to be notified on shoutcast meta data | ||
32 | * while playing the stream (such as song title). | ||
33 | */ | ||
34 | public class IcyListener implements TagParseListener | ||
35 | { | ||
36 | private static IcyListener instance = null; | ||
37 | private MP3Tag lastTag = null; | ||
38 | private String streamTitle = null; | ||
39 | private String streamUrl = null; | ||
40 | |||
41 | |||
42 | private IcyListener() | ||
43 | { | ||
44 | super(); | ||
45 | } | ||
46 | |||
47 | public static synchronized IcyListener getInstance() | ||
48 | { | ||
49 | if (instance == null) | ||
50 | { | ||
51 | instance = new IcyListener(); | ||
52 | } | ||
53 | return instance; | ||
54 | } | ||
55 | |||
56 | /* (non-Javadoc) | ||
57 | * @see javazoom.spi.mpeg.sampled.file.tag.TagParseListener#tagParsed(javazoom.spi.mpeg.sampled.file.tag.TagParseEvent) | ||
58 | */ | ||
59 | public void tagParsed(TagParseEvent tpe) | ||
60 | { | ||
61 | lastTag = tpe.getTag(); | ||
62 | String name = lastTag.getName(); | ||
63 | if ((name != null) && (name.equalsIgnoreCase("streamtitle"))) | ||
64 | { | ||
65 | streamTitle = (String) lastTag.getValue(); | ||
66 | } | ||
67 | else if ((name != null) && (name.equalsIgnoreCase("streamurl"))) | ||
68 | { | ||
69 | streamUrl = (String) lastTag.getValue(); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * @return | ||
75 | */ | ||
76 | public MP3Tag getLastTag() | ||
77 | { | ||
78 | return lastTag; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * @param tag | ||
83 | */ | ||
84 | public void setLastTag(MP3Tag tag) | ||
85 | { | ||
86 | lastTag = tag; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * @return | ||
91 | */ | ||
92 | public String getStreamTitle() | ||
93 | { | ||
94 | return streamTitle; | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * @return | ||
99 | */ | ||
100 | public String getStreamUrl() | ||
101 | { | ||
102 | return streamUrl; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * @param string | ||
107 | */ | ||
108 | public void setStreamTitle(String string) | ||
109 | { | ||
110 | streamTitle = string; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * @param string | ||
115 | */ | ||
116 | public void setStreamUrl(String string) | ||
117 | { | ||
118 | streamUrl = string; | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Reset all properties. | ||
123 | */ | ||
124 | public void reset() | ||
125 | { | ||
126 | lastTag = null; | ||
127 | streamTitle = null; | ||
128 | streamUrl = null; | ||
129 | } | ||
130 | |||
131 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFileFormat.java b/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFileFormat.java deleted file mode 100644 index afdc4c5e9c..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFileFormat.java +++ /dev/null | |||
@@ -1,103 +0,0 @@ | |||
1 | /* | ||
2 | * MpegAudioFileFormat. | ||
3 | * | ||
4 | * JavaZOOM : mp3spi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | *----------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | *---------------------------------------------------------------------- | ||
22 | */ | ||
23 | package javazoom.spi.mpeg.sampled.file; | ||
24 | |||
25 | import java.util.Map; | ||
26 | |||
27 | import javax.sound.sampled.AudioFormat; | ||
28 | |||
29 | import org.tritonus.share.sampled.file.TAudioFileFormat; | ||
30 | |||
31 | /** | ||
32 | * @author JavaZOOM | ||
33 | */ | ||
34 | public class MpegAudioFileFormat extends TAudioFileFormat | ||
35 | { | ||
36 | /** | ||
37 | * Contructor. | ||
38 | * @param type | ||
39 | * @param audioFormat | ||
40 | * @param nLengthInFrames | ||
41 | * @param nLengthInBytes | ||
42 | */ | ||
43 | public MpegAudioFileFormat(Type type, AudioFormat audioFormat, int nLengthInFrames, int nLengthInBytes, Map properties) | ||
44 | { | ||
45 | super(type, audioFormat, nLengthInFrames, nLengthInBytes, properties); | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * MP3 audio file format parameters. | ||
50 | * Some parameters might be unavailable. So availability test is required before reading any parameter. | ||
51 | * | ||
52 | * <br>AudioFileFormat parameters. | ||
53 | * <ul> | ||
54 | * <li><b>duration</b> [Long], duration in microseconds. | ||
55 | * <li><b>title</b> [String], Title of the stream. | ||
56 | * <li><b>author</b> [String], Name of the artist of the stream. | ||
57 | * <li><b>album</b> [String], Name of the album of the stream. | ||
58 | * <li><b>date</b> [String], The date (year) of the recording or release of the stream. | ||
59 | * <li><b>copyright</b> [String], Copyright message of the stream. | ||
60 | * <li><b>comment</b> [String], Comment of the stream. | ||
61 | * </ul> | ||
62 | * <br>MP3 parameters. | ||
63 | * <ul> | ||
64 | * <li><b>mp3.version.mpeg</b> [String], mpeg version : 1,2 or 2.5 | ||
65 | * <li><b>mp3.version.layer</b> [String], layer version 1, 2 or 3 | ||
66 | * <li><b>mp3.version.encoding</b> [String], mpeg encoding : MPEG1, MPEG2-LSF, MPEG2.5-LSF | ||
67 | * <li><b>mp3.channels</b> [Integer], number of channels 1 : mono, 2 : stereo. | ||
68 | * <li><b>mp3.frequency.hz</b> [Integer], sampling rate in hz. | ||
69 | * <li><b>mp3.bitrate.nominal.bps</b> [Integer], nominal bitrate in bps. | ||
70 | * <li><b>mp3.length.bytes</b> [Integer], length in bytes. | ||
71 | * <li><b>mp3.length.frames</b> [Integer], length in frames. | ||
72 | * <li><b>mp3.framesize.bytes</b> [Integer], framesize of the first frame. framesize is not constant for VBR streams. | ||
73 | * <li><b>mp3.framerate.fps</b> [Float], framerate in frames per seconds. | ||
74 | * <li><b>mp3.header.pos</b> [Integer], position of first audio header (or ID3v2 size). | ||
75 | * <li><b>mp3.vbr</b> [Boolean], vbr flag. | ||
76 | * <li><b>mp3.vbr.scale</b> [Integer], vbr scale. | ||
77 | * <li><b>mp3.crc</b> [Boolean], crc flag. | ||
78 | * <li><b>mp3.original</b> [Boolean], original flag. | ||
79 | * <li><b>mp3.copyright</b> [Boolean], copyright flag. | ||
80 | * <li><b>mp3.padding</b> [Boolean], padding flag. | ||
81 | * <li><b>mp3.mode</b> [Integer], mode 0:STEREO 1:JOINT_STEREO 2:DUAL_CHANNEL 3:SINGLE_CHANNEL | ||
82 | * <li><b>mp3.id3tag.genre</b> [String], ID3 tag (v1 or v2) genre. | ||
83 | * <li><b>mp3.id3tag.track</b> [String], ID3 tag (v1 or v2) track info. | ||
84 | * <li><b>mp3.id3tag.encoded</b> [String], ID3 tag v2 encoded by info. | ||
85 | * <li><b>mp3.id3tag.composer</b> [String], ID3 tag v2 composer info. | ||
86 | * <li><b>mp3.id3tag.grouping</b> [String], ID3 tag v2 grouping info. | ||
87 | * <li><b>mp3.id3tag.disc</b> [String], ID3 tag v2 track info. | ||
88 | * <li><b>mp3.id3tag.v2</b> [InputStream], ID3v2 frames. | ||
89 | * <li><b>mp3.id3tag.v2.version</b> [String], ID3v2 major version (2=v2.2.0, 3=v2.3.0, 4=v2.4.0). | ||
90 | * <li><b>mp3.shoutcast.metadata.key</b> [String], Shoutcast meta key with matching value. | ||
91 | * <br>For instance : | ||
92 | * <br>mp3.shoutcast.metadata.icy-irc=#shoutcast | ||
93 | * <br>mp3.shoutcast.metadata.icy-metaint=8192 | ||
94 | * <br>mp3.shoutcast.metadata.icy-genre=Trance Techno Dance | ||
95 | * <br>mp3.shoutcast.metadata.icy-url=http://www.di.fm | ||
96 | * <br>and so on ... | ||
97 | * </ul> | ||
98 | */ | ||
99 | public Map properties() | ||
100 | { | ||
101 | return super.properties(); | ||
102 | } | ||
103 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFileReader.java b/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFileReader.java deleted file mode 100644 index 54440551a1..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFileReader.java +++ /dev/null | |||
@@ -1,772 +0,0 @@ | |||
1 | /* | ||
2 | * MpegAudioFileReader. | ||
3 | * | ||
4 | * 12/31/04 : mp3spi.weak system property added to skip controls. | ||
5 | * | ||
6 | * 11/29/04 : ID3v2.2, v2.3 & v2.4 support improved. | ||
7 | * "mp3.id3tag.composer" (TCOM/TCM) added | ||
8 | * "mp3.id3tag.grouping" (TIT1/TT1) added | ||
9 | * "mp3.id3tag.disc" (TPA/TPOS) added | ||
10 | * "mp3.id3tag.encoded" (TEN/TENC) added | ||
11 | * "mp3.id3tag.v2.version" added | ||
12 | * | ||
13 | * 11/28/04 : String encoding bug fix in chopSubstring method. | ||
14 | * | ||
15 | * JavaZOOM : mp3spi@javazoom.net | ||
16 | * http://www.javazoom.net | ||
17 | * | ||
18 | *----------------------------------------------------------------------- | ||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU Library General Public License as published | ||
21 | * by the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU Library General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU Library General Public | ||
30 | * License along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
32 | *---------------------------------------------------------------------- | ||
33 | */ | ||
34 | |||
35 | package javazoom.spi.mpeg.sampled.file; | ||
36 | |||
37 | |||
38 | import java.io.BufferedInputStream; | ||
39 | import java.io.File; | ||
40 | import java.io.FileInputStream; | ||
41 | import java.io.IOException; | ||
42 | import java.io.InputStream; | ||
43 | import java.io.PushbackInputStream; | ||
44 | import java.io.UnsupportedEncodingException; | ||
45 | import java.net.URL; | ||
46 | import java.net.URLConnection; | ||
47 | import java.security.AccessControlException; | ||
48 | import java.util.HashMap; | ||
49 | |||
50 | import javax.sound.sampled.AudioFileFormat; | ||
51 | import javax.sound.sampled.AudioFormat; | ||
52 | import javax.sound.sampled.AudioInputStream; | ||
53 | import javax.sound.sampled.AudioSystem; | ||
54 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
55 | |||
56 | import javazoom.jl.decoder.Bitstream; | ||
57 | import javazoom.jl.decoder.Header; | ||
58 | import javazoom.spi.mpeg.sampled.file.tag.IcyInputStream; | ||
59 | import javazoom.spi.mpeg.sampled.file.tag.MP3Tag; | ||
60 | |||
61 | import org.tritonus.share.TDebug; | ||
62 | import org.tritonus.share.sampled.file.TAudioFileReader; | ||
63 | |||
64 | /** | ||
65 | * This class implements AudioFileReader for MP3 SPI. | ||
66 | */ | ||
67 | public class MpegAudioFileReader extends TAudioFileReader | ||
68 | { | ||
69 | private final int SYNC = 0xFFE00000; | ||
70 | private String weak = null; | ||
71 | private final AudioFormat.Encoding[][] sm_aEncodings = | ||
72 | { | ||
73 | {MpegEncoding.MPEG2L1, MpegEncoding.MPEG2L2, MpegEncoding.MPEG2L3}, | ||
74 | {MpegEncoding.MPEG1L1, MpegEncoding.MPEG1L2, MpegEncoding.MPEG1L3}, | ||
75 | {MpegEncoding.MPEG2DOT5L1, MpegEncoding.MPEG2DOT5L2, MpegEncoding.MPEG2DOT5L3}, | ||
76 | |||
77 | }; | ||
78 | |||
79 | private static final int INITAL_READ_LENGTH = 64000; | ||
80 | private static final int MARK_LIMIT = INITAL_READ_LENGTH + 1; | ||
81 | |||
82 | private static final String[] id3v1genres = { | ||
83 | "Blues" | ||
84 | , "Classic Rock" | ||
85 | , "Country" | ||
86 | , "Dance" | ||
87 | , "Disco" | ||
88 | , "Funk" | ||
89 | , "Grunge" | ||
90 | , "Hip-Hop" | ||
91 | , "Jazz" | ||
92 | , "Metal" | ||
93 | , "New Age" | ||
94 | , "Oldies" | ||
95 | , "Other" | ||
96 | , "Pop" | ||
97 | , "R&B" | ||
98 | , "Rap" | ||
99 | , "Reggae" | ||
100 | , "Rock" | ||
101 | , "Techno" | ||
102 | , "Industrial" | ||
103 | , "Alternative" | ||
104 | , "Ska" | ||
105 | , "Death Metal" | ||
106 | , "Pranks" | ||
107 | , "Soundtrack" | ||
108 | , "Euro-Techno" | ||
109 | , "Ambient" | ||
110 | , "Trip-Hop" | ||
111 | , "Vocal" | ||
112 | , "Jazz+Funk" | ||
113 | , "Fusion" | ||
114 | , "Trance" | ||
115 | , "Classical" | ||
116 | , "Instrumental" | ||
117 | , "Acid" | ||
118 | , "House" | ||
119 | , "Game" | ||
120 | , "Sound Clip" | ||
121 | , "Gospel" | ||
122 | , "Noise" | ||
123 | , "AlternRock" | ||
124 | , "Bass" | ||
125 | , "Soul" | ||
126 | , "Punk" | ||
127 | , "Space" | ||
128 | , "Meditative" | ||
129 | , "Instrumental Pop" | ||
130 | , "Instrumental Rock" | ||
131 | , "Ethnic" | ||
132 | , "Gothic" | ||
133 | , "Darkwave" | ||
134 | , "Techno-Industrial" | ||
135 | , "Electronic" | ||
136 | , "Pop-Folk" | ||
137 | , "Eurodance" | ||
138 | , "Dream" | ||
139 | , "Southern Rock" | ||
140 | , "Comedy" | ||
141 | , "Cult" | ||
142 | , "Gangsta" | ||
143 | , "Top 40" | ||
144 | , "Christian Rap" | ||
145 | , "Pop/Funk" | ||
146 | , "Jungle" | ||
147 | , "Native American" | ||
148 | , "Cabaret" | ||
149 | , "New Wave" | ||
150 | , "Psychadelic" | ||
151 | , "Rave" | ||
152 | , "Showtunes" | ||
153 | , "Trailer" | ||
154 | , "Lo-Fi" | ||
155 | , "Tribal" | ||
156 | , "Acid Punk" | ||
157 | , "Acid Jazz" | ||
158 | , "Polka" | ||
159 | , "Retro" | ||
160 | , "Musical" | ||
161 | , "Rock & Roll" | ||
162 | , "Hard Rock" | ||
163 | , "Folk" | ||
164 | , "Folk-Rock" | ||
165 | , "National Folk" | ||
166 | , "Swing" | ||
167 | , "Fast Fusion" | ||
168 | , "Bebob" | ||
169 | , "Latin" | ||
170 | , "Revival" | ||
171 | , "Celtic" | ||
172 | , "Bluegrass" | ||
173 | , "Avantgarde" | ||
174 | , "Gothic Rock" | ||
175 | , "Progressive Rock" | ||
176 | , "Psychedelic Rock" | ||
177 | , "Symphonic Rock" | ||
178 | , "Slow Rock" | ||
179 | , "Big Band" | ||
180 | , "Chorus" | ||
181 | , "Easy Listening" | ||
182 | , "Acoustic" | ||
183 | , "Humour" | ||
184 | , "Speech" | ||
185 | , "Chanson" | ||
186 | , "Opera" | ||
187 | , "Chamber Music" | ||
188 | , "Sonata" | ||
189 | , "Symphony" | ||
190 | , "Booty Brass" | ||
191 | , "Primus" | ||
192 | , "Porn Groove" | ||
193 | , "Satire" | ||
194 | , "Slow Jam" | ||
195 | , "Club" | ||
196 | , "Tango" | ||
197 | , "Samba" | ||
198 | , "Folklore" | ||
199 | , "Ballad" | ||
200 | , "Power Ballad" | ||
201 | , "Rhythmic Soul" | ||
202 | , "Freestyle" | ||
203 | , "Duet" | ||
204 | , "Punk Rock" | ||
205 | , "Drum Solo" | ||
206 | , "A Capela" | ||
207 | , "Euro-House" | ||
208 | , "Dance Hall" | ||
209 | , "Goa" | ||
210 | , "Drum & Bass" | ||
211 | , "Club-House" | ||
212 | , "Hardcore" | ||
213 | , "Terror" | ||
214 | , "Indie" | ||
215 | , "BritPop" | ||
216 | , "Negerpunk" | ||
217 | , "Polsk Punk" | ||
218 | , "Beat" | ||
219 | , "Christian Gangsta Rap" | ||
220 | , "Heavy Metal" | ||
221 | , "Black Metal" | ||
222 | , "Crossover" | ||
223 | , "Contemporary Christian" | ||
224 | , "Christian Rock" | ||
225 | , "Merengue" | ||
226 | , "Salsa" | ||
227 | , "Thrash Metal" | ||
228 | , "Anime" | ||
229 | , "JPop" | ||
230 | , "SynthPop" | ||
231 | }; | ||
232 | |||
233 | public MpegAudioFileReader() | ||
234 | { | ||
235 | super(MARK_LIMIT, true); | ||
236 | if (TDebug.TraceAudioFileReader) TDebug.out(">MpegAudioFileReader(1.9.2-FINAL)"); | ||
237 | try | ||
238 | { | ||
239 | weak = System.getProperty("mp3spi.weak"); | ||
240 | } | ||
241 | catch(AccessControlException e) | ||
242 | {} | ||
243 | } | ||
244 | |||
245 | /** | ||
246 | * Returns AudioFileFormat from File. | ||
247 | */ | ||
248 | public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException | ||
249 | { | ||
250 | return super.getAudioFileFormat(file); | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * Returns AudioFileFormat from URL. | ||
255 | */ | ||
256 | public AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException | ||
257 | { | ||
258 | if (TDebug.TraceAudioFileReader) {TDebug.out("MpegAudioFileReader.getAudioFileFormat(URL): begin"); } | ||
259 | long lFileLengthInBytes = AudioSystem.NOT_SPECIFIED; | ||
260 | URLConnection conn = url.openConnection(); | ||
261 | // Tell shoucast server (if any) that SPI support shoutcast stream. | ||
262 | conn.setRequestProperty ("Icy-Metadata", "1"); | ||
263 | InputStream inputStream = conn.getInputStream(); | ||
264 | AudioFileFormat audioFileFormat = null; | ||
265 | try | ||
266 | { | ||
267 | audioFileFormat = getAudioFileFormat(inputStream, lFileLengthInBytes); | ||
268 | } | ||
269 | finally | ||
270 | { | ||
271 | inputStream.close(); | ||
272 | } | ||
273 | if (TDebug.TraceAudioFileReader) {TDebug.out("MpegAudioFileReader.getAudioFileFormat(URL): end"); } | ||
274 | return audioFileFormat; | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * Returns AudioFileFormat from inputstream and medialength. | ||
279 | */ | ||
280 | public AudioFileFormat getAudioFileFormat(InputStream inputStream, long mediaLength) throws UnsupportedAudioFileException, IOException | ||
281 | { | ||
282 | if (TDebug.TraceAudioFileReader) TDebug.out(">MpegAudioFileReader.getAudioFileFormat(InputStream inputStream, long mediaLength): begin"); | ||
283 | HashMap aff_properties = new HashMap(); | ||
284 | HashMap af_properties = new HashMap(); | ||
285 | int mLength = (int) mediaLength; | ||
286 | int size = inputStream.available(); | ||
287 | PushbackInputStream pis = new PushbackInputStream(inputStream, MARK_LIMIT); | ||
288 | byte head[] = new byte[12]; | ||
289 | pis.read(head); | ||
290 | if (TDebug.TraceAudioFileReader) | ||
291 | { | ||
292 | TDebug.out("InputStream : "+inputStream + " =>" + new String(head)); | ||
293 | } | ||
294 | /* | ||
295 | * Check for WAV, AU, and AIFF file formats. | ||
296 | * | ||
297 | * Next check for Shoutcast (supported) and OGG (unsupported) streams. | ||
298 | * | ||
299 | * Note -- the check for WAV files will reject Broadcast WAV files. | ||
300 | * This may be incorrect as broadcast WAV files may contain MPEG data. | ||
301 | * Need to investigate. | ||
302 | * | ||
303 | */ | ||
304 | if ((head[0] == 'R') && (head[1] == 'I') && (head[2] == 'F') && (head[3] == 'F') && (head[8] == 'W') && (head[9] == 'A') && (head[10] == 'V') && (head[11] == 'E')) | ||
305 | { | ||
306 | if (TDebug.TraceAudioFileReader) TDebug.out("WAV stream found"); | ||
307 | if (weak == null) throw new UnsupportedAudioFileException("WAV stream found"); | ||
308 | } | ||
309 | else if ((head[0] == '.') && (head[1] == 's') && (head[2] == 'n') && (head[3] == 'd')) | ||
310 | { | ||
311 | if (TDebug.TraceAudioFileReader) TDebug.out("AU stream found"); | ||
312 | if (weak == null) throw new UnsupportedAudioFileException("AU stream found"); | ||
313 | } | ||
314 | else if ((head[0] == 'F') && (head[1] == 'O') && (head[2] == 'R') && (head[3] == 'M') && (head[8] == 'A') && (head[9] == 'I') && (head[10] == 'F') && (head[11] == 'F')) | ||
315 | { | ||
316 | if (TDebug.TraceAudioFileReader) TDebug.out("AIFF stream found"); | ||
317 | if (weak == null) throw new UnsupportedAudioFileException("AIFF stream found"); | ||
318 | } | ||
319 | // Shoutcast stream ? | ||
320 | else if (((head[0] == 'I') | (head[0] == 'i')) && ((head[1] == 'C') | (head[1] == 'c')) && ((head[2] == 'Y') | (head[2] == 'y'))) | ||
321 | { | ||
322 | pis.unread(head); | ||
323 | // Load shoutcast meta data. | ||
324 | loadShoutcastInfo(pis, aff_properties); | ||
325 | } | ||
326 | // Ogg stream ? | ||
327 | else if (((head[0] == 'O') | (head[0] == 'o')) && ((head[1] == 'G') | (head[1] == 'g')) && ((head[2] == 'G') | (head[2] == 'g'))) | ||
328 | { | ||
329 | if (TDebug.TraceAudioFileReader) TDebug.out("Ogg stream found"); | ||
330 | if (weak == null) throw new UnsupportedAudioFileException("Ogg stream found"); | ||
331 | } | ||
332 | // No, so pushback. | ||
333 | else | ||
334 | { | ||
335 | pis.unread(head); | ||
336 | } | ||
337 | // MPEG header info. | ||
338 | int nVersion = AudioSystem.NOT_SPECIFIED; | ||
339 | int nLayer = AudioSystem.NOT_SPECIFIED; | ||
340 | int nSFIndex = AudioSystem.NOT_SPECIFIED; | ||
341 | int nMode = AudioSystem.NOT_SPECIFIED; | ||
342 | int FrameSize = AudioSystem.NOT_SPECIFIED; | ||
343 | int nFrameSize = AudioSystem.NOT_SPECIFIED; | ||
344 | int nFrequency = AudioSystem.NOT_SPECIFIED; | ||
345 | int nTotalFrames = AudioSystem.NOT_SPECIFIED; | ||
346 | float FrameRate = AudioSystem.NOT_SPECIFIED; | ||
347 | int BitRate = AudioSystem.NOT_SPECIFIED; | ||
348 | int nChannels = AudioSystem.NOT_SPECIFIED; | ||
349 | int nHeader = AudioSystem.NOT_SPECIFIED; | ||
350 | int nTotalMS = AudioSystem.NOT_SPECIFIED; | ||
351 | boolean nVBR = false; | ||
352 | AudioFormat.Encoding encoding = null; | ||
353 | try | ||
354 | { | ||
355 | Bitstream m_bitstream = new Bitstream(pis); | ||
356 | aff_properties.put("mp3.header.pos",new Integer(m_bitstream.header_pos())); | ||
357 | Header m_header = m_bitstream.readFrame(); | ||
358 | // nVersion = 0 => MPEG2-LSF (Including MPEG2.5), nVersion = 1 => MPEG1 | ||
359 | nVersion = m_header.version(); | ||
360 | if (nVersion == 2) aff_properties.put("mp3.version.mpeg",Float.toString(2.5f)); | ||
361 | else aff_properties.put("mp3.version.mpeg",Integer.toString(2-nVersion)); | ||
362 | // nLayer = 1,2,3 | ||
363 | nLayer = m_header.layer(); | ||
364 | aff_properties.put("mp3.version.layer",Integer.toString(nLayer)); | ||
365 | nSFIndex = m_header.sample_frequency(); | ||
366 | nMode = m_header.mode(); | ||
367 | aff_properties.put("mp3.mode",new Integer(nMode)); | ||
368 | nChannels = nMode == 3 ? 1 : 2; | ||
369 | aff_properties.put("mp3.channels",new Integer(nChannels)); | ||
370 | nVBR = m_header.vbr(); | ||
371 | af_properties.put("vbr",new Boolean(nVBR)); | ||
372 | aff_properties.put("mp3.vbr",new Boolean(nVBR)); | ||
373 | aff_properties.put("mp3.vbr.scale",new Integer(m_header.vbr_scale())); | ||
374 | FrameSize = m_header.calculate_framesize(); | ||
375 | aff_properties.put("mp3.framesize.bytes",new Integer(FrameSize)); | ||
376 | if (FrameSize < 0) throw new UnsupportedAudioFileException("Invalid FrameSize : " + FrameSize); | ||
377 | nFrequency = m_header.frequency(); | ||
378 | aff_properties.put("mp3.frequency.hz",new Integer(nFrequency)); | ||
379 | FrameRate = (float) ((1.0 / (m_header.ms_per_frame())) * 1000.0); | ||
380 | aff_properties.put("mp3.framerate.fps",new Float(FrameRate)); | ||
381 | if (FrameRate < 0) throw new UnsupportedAudioFileException("Invalid FrameRate : " + FrameRate); | ||
382 | if (mLength != AudioSystem.NOT_SPECIFIED) | ||
383 | { | ||
384 | aff_properties.put("mp3.length.bytes",new Integer(mLength)); | ||
385 | nTotalFrames = m_header.max_number_of_frames(mLength); | ||
386 | aff_properties.put("mp3.length.frames",new Integer(nTotalFrames)); | ||
387 | } | ||
388 | BitRate = m_header.bitrate(); | ||
389 | af_properties.put("bitrate",new Integer(BitRate)); | ||
390 | aff_properties.put("mp3.bitrate.nominal.bps",new Integer(BitRate)); | ||
391 | nHeader = m_header.getSyncHeader(); | ||
392 | encoding = sm_aEncodings[nVersion][nLayer - 1]; | ||
393 | aff_properties.put("mp3.version.encoding",encoding.toString()); | ||
394 | if (mLength != AudioSystem.NOT_SPECIFIED) | ||
395 | { | ||
396 | nTotalMS = Math.round(m_header.total_ms(mLength)); | ||
397 | aff_properties.put("duration",new Long((long)nTotalMS*1000L)); | ||
398 | } | ||
399 | aff_properties.put("mp3.copyright",new Boolean(m_header.copyright())); | ||
400 | aff_properties.put("mp3.original",new Boolean(m_header.original())); | ||
401 | aff_properties.put("mp3.crc",new Boolean(m_header.checksums())); | ||
402 | aff_properties.put("mp3.padding",new Boolean(m_header.padding())); | ||
403 | InputStream id3v2 = m_bitstream.getRawID3v2(); | ||
404 | if (id3v2 != null) | ||
405 | { | ||
406 | aff_properties.put("mp3.id3tag.v2",id3v2); | ||
407 | parseID3v2Frames(id3v2,aff_properties); | ||
408 | } | ||
409 | if (TDebug.TraceAudioFileReader) TDebug.out(m_header.toString()); | ||
410 | } | ||
411 | catch (Exception e) | ||
412 | { | ||
413 | if (TDebug.TraceAudioFileReader) TDebug.out("not a MPEG stream:" + e.getMessage()); | ||
414 | throw new UnsupportedAudioFileException("not a MPEG stream:" + e.getMessage()); | ||
415 | } | ||
416 | |||
417 | // Deeper checks ? | ||
418 | int cVersion = (nHeader >> 19) & 0x3; | ||
419 | if (cVersion == 1) | ||
420 | { | ||
421 | if (TDebug.TraceAudioFileReader) TDebug.out("not a MPEG stream: wrong version"); | ||
422 | throw new UnsupportedAudioFileException("not a MPEG stream: wrong version"); | ||
423 | } | ||
424 | |||
425 | int cSFIndex = (nHeader >> 10) & 0x3; | ||
426 | if (cSFIndex == 3) | ||
427 | { | ||
428 | if (TDebug.TraceAudioFileReader) TDebug.out("not a MPEG stream: wrong sampling rate"); | ||
429 | throw new UnsupportedAudioFileException("not a MPEG stream: wrong sampling rate"); | ||
430 | } | ||
431 | |||
432 | // Look up for ID3v1 tag | ||
433 | if ((size == mediaLength) && (mediaLength != AudioSystem.NOT_SPECIFIED)) | ||
434 | { | ||
435 | FileInputStream fis = (FileInputStream) inputStream; | ||
436 | byte[] id3v1 = new byte[128]; | ||
437 | long bytesSkipped = fis.skip(inputStream.available()-id3v1.length); | ||
438 | int read = fis.read(id3v1,0,id3v1.length); | ||
439 | if ((id3v1[0]=='T') && (id3v1[1]=='A') && (id3v1[2]=='G')) | ||
440 | { | ||
441 | parseID3v1Frames(id3v1, aff_properties); | ||
442 | } | ||
443 | } | ||
444 | |||
445 | AudioFormat format = new MpegAudioFormat(encoding, (float) nFrequency, AudioSystem.NOT_SPECIFIED // SampleSizeInBits - The size of a sample | ||
446 | , nChannels // Channels - The number of channels | ||
447 | , -1 // The number of bytes in each frame | ||
448 | , FrameRate // FrameRate - The number of frames played or recorded per second | ||
449 | , true | ||
450 | , af_properties); | ||
451 | return new MpegAudioFileFormat(MpegFileFormatType.MP3, format, nTotalFrames, mLength,aff_properties); | ||
452 | } | ||
453 | |||
454 | /** | ||
455 | * Returns AudioInputStream from file. | ||
456 | */ | ||
457 | public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException | ||
458 | { | ||
459 | if (TDebug.TraceAudioFileReader) TDebug.out("getAudioInputStream(File file)"); | ||
460 | InputStream inputStream = new FileInputStream(file); | ||
461 | try | ||
462 | { | ||
463 | return getAudioInputStream(inputStream); | ||
464 | } | ||
465 | catch (UnsupportedAudioFileException e) | ||
466 | { | ||
467 | if (inputStream != null) inputStream.close(); | ||
468 | throw e; | ||
469 | } | ||
470 | catch (IOException e) | ||
471 | { | ||
472 | if (inputStream != null) inputStream.close(); | ||
473 | throw e; | ||
474 | } | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * Returns AudioInputStream from url. | ||
479 | */ | ||
480 | public AudioInputStream getAudioInputStream(URL url) | ||
481 | throws UnsupportedAudioFileException, IOException | ||
482 | { | ||
483 | if (TDebug.TraceAudioFileReader) {TDebug.out("MpegAudioFileReader.getAudioInputStream(URL): begin"); } | ||
484 | long lFileLengthInBytes = AudioSystem.NOT_SPECIFIED; | ||
485 | URLConnection conn = url.openConnection(); | ||
486 | // Tell shoucast server (if any) that SPI support shoutcast stream. | ||
487 | boolean isShout = false; | ||
488 | int toRead=4; | ||
489 | byte[] head = new byte[toRead]; | ||
490 | |||
491 | conn.setRequestProperty ("Icy-Metadata", "1"); | ||
492 | BufferedInputStream bInputStream = new BufferedInputStream(conn.getInputStream()); | ||
493 | bInputStream.mark(toRead); | ||
494 | int read = bInputStream.read(head,0,toRead); | ||
495 | if ((read>2) && (((head[0] == 'I') | (head[0] == 'i')) && ((head[1] == 'C') | (head[1] == 'c')) && ((head[2] == 'Y') | (head[2] == 'y')))) isShout = true; | ||
496 | bInputStream.reset(); | ||
497 | InputStream inputStream = null; | ||
498 | // Is is a shoutcast server ? | ||
499 | if (isShout == true) | ||
500 | { | ||
501 | // Yes | ||
502 | IcyInputStream icyStream = new IcyInputStream(bInputStream); | ||
503 | icyStream.addTagParseListener(IcyListener.getInstance()); | ||
504 | inputStream = icyStream; | ||
505 | } | ||
506 | else | ||
507 | { | ||
508 | // No, is Icecast 2 ? | ||
509 | String metaint = conn.getHeaderField("icy-metaint"); | ||
510 | if (metaint != null) | ||
511 | { | ||
512 | // Yes, it might be icecast 2 mp3 stream. | ||
513 | IcyInputStream icyStream = new IcyInputStream(bInputStream,metaint); | ||
514 | icyStream.addTagParseListener(IcyListener.getInstance()); | ||
515 | inputStream = icyStream; | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | // No | ||
520 | inputStream = bInputStream; | ||
521 | } | ||
522 | } | ||
523 | AudioInputStream audioInputStream = null; | ||
524 | try | ||
525 | { | ||
526 | audioInputStream = getAudioInputStream(inputStream, lFileLengthInBytes); | ||
527 | } | ||
528 | catch (UnsupportedAudioFileException e) | ||
529 | { | ||
530 | inputStream.close(); | ||
531 | throw e; | ||
532 | } | ||
533 | catch (IOException e) | ||
534 | { | ||
535 | inputStream.close(); | ||
536 | throw e; | ||
537 | } | ||
538 | if (TDebug.TraceAudioFileReader) {TDebug.out("MpegAudioFileReader.getAudioInputStream(URL): end"); } | ||
539 | return audioInputStream; | ||
540 | } | ||
541 | |||
542 | /** | ||
543 | * Return the AudioInputStream from the given InputStream. | ||
544 | */ | ||
545 | public AudioInputStream getAudioInputStream(InputStream inputStream) throws UnsupportedAudioFileException, IOException | ||
546 | { | ||
547 | if (TDebug.TraceAudioFileReader) TDebug.out("MpegAudioFileReader.getAudioInputStream(InputStream inputStream)"); | ||
548 | if (!inputStream.markSupported()) inputStream = new BufferedInputStream(inputStream); | ||
549 | return super.getAudioInputStream(inputStream); | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * Parser ID3v1 frames | ||
554 | * @param frames | ||
555 | * @param props | ||
556 | */ | ||
557 | protected void parseID3v1Frames(byte[] frames, HashMap props) | ||
558 | { | ||
559 | if (TDebug.TraceAudioFileReader) TDebug.out("Parsing ID3v1"); | ||
560 | String tag = null; | ||
561 | try | ||
562 | { | ||
563 | tag = new String(frames, 0, frames.length, "ISO-8859-1"); | ||
564 | } | ||
565 | catch (UnsupportedEncodingException e) | ||
566 | { | ||
567 | tag = new String(frames, 0, frames.length); | ||
568 | if (TDebug.TraceAudioFileReader) TDebug.out("Cannot use ISO-8859-1"); | ||
569 | } | ||
570 | if (TDebug.TraceAudioFileReader) TDebug.out("ID3v1 frame dump='"+tag+"'"); | ||
571 | int start = 3; | ||
572 | String titlev1 = chopSubstring(tag, start, start += 30); | ||
573 | String titlev2 = (String) props.get("title"); | ||
574 | if (((titlev2==null) || (titlev2.length()==0)) && (titlev1 != null)) props.put("title",titlev1); | ||
575 | String artistv1 = chopSubstring(tag, start, start += 30); | ||
576 | String artistv2 = (String) props.get("author"); | ||
577 | if (((artistv2==null) || (artistv2.length()==0)) && (artistv1 != null)) props.put("author",artistv1); | ||
578 | String albumv1 = chopSubstring(tag, start, start += 30); | ||
579 | String albumv2 = (String) props.get("album"); | ||
580 | if (((albumv2==null) || (albumv2.length()==0)) && (albumv1 != null)) props.put("album",albumv1); | ||
581 | String yearv1 = chopSubstring(tag, start, start += 4); | ||
582 | String yearv2 = (String) props.get("year"); | ||
583 | if (((yearv2==null) || (yearv2.length()==0)) && (yearv1 != null)) props.put("date",yearv1); | ||
584 | String commentv1 = chopSubstring(tag, start, start += 28); | ||
585 | String commentv2 = (String) props.get("comment"); | ||
586 | if (((commentv2==null) || (commentv2.length()==0)) && (commentv1 != null)) props.put("comment",commentv1); | ||
587 | String trackv1 = ""+((int) (frames[126] & 0xff)); | ||
588 | String trackv2 = (String) props.get("mp3.id3tag.track"); | ||
589 | if (((trackv2==null) || (trackv2.length()==0)) && (trackv1 != null)) props.put("mp3.id3tag.track",trackv1); | ||
590 | |||
591 | int genrev1 = (int) (frames[127] & 0xff); | ||
592 | if ((genrev1 >=0) && (genrev1<id3v1genres.length)) | ||
593 | { | ||
594 | String genrev2 = (String) props.get("mp3.id3tag.genre"); | ||
595 | if (((genrev2==null) || (genrev2.length()==0))) props.put("mp3.id3tag.genre",id3v1genres[genrev1]); | ||
596 | } | ||
597 | if (TDebug.TraceAudioFileReader) TDebug.out("ID3v1 parsed"); | ||
598 | } | ||
599 | |||
600 | /** | ||
601 | * Extract | ||
602 | * @param s | ||
603 | * @param start | ||
604 | * @param end | ||
605 | * @return | ||
606 | */ | ||
607 | private String chopSubstring(String s, int start, int end) | ||
608 | { | ||
609 | String str = null; | ||
610 | // 11/28/04 - String encoding bug fix. | ||
611 | try | ||
612 | { | ||
613 | str = s.substring(start, end); | ||
614 | int loc = str.indexOf('\0'); | ||
615 | if (loc != -1) str = str.substring(0, loc); | ||
616 | } | ||
617 | catch (StringIndexOutOfBoundsException e) | ||
618 | { | ||
619 | // Skip encoding issues. | ||
620 | if (TDebug.TraceAudioFileReader) TDebug.out("Cannot chopSubString "+e.getMessage()); | ||
621 | } | ||
622 | return str; | ||
623 | } | ||
624 | /** | ||
625 | * Parse ID3v2 frames to add album (TALB), title (TIT2), date (TYER), author (TPE1), copyright (TCOP), comment (COMM) ... | ||
626 | * @param frames | ||
627 | * @param props | ||
628 | */ | ||
629 | protected void parseID3v2Frames(InputStream frames, HashMap props) | ||
630 | { | ||
631 | if (TDebug.TraceAudioFileReader) TDebug.out("Parsing ID3v2"); | ||
632 | byte[] bframes = null; | ||
633 | int size = -1; | ||
634 | try | ||
635 | { | ||
636 | size = frames.available(); | ||
637 | bframes = new byte[size]; | ||
638 | frames.mark(size); | ||
639 | frames.read(bframes); | ||
640 | frames.reset(); | ||
641 | } | ||
642 | catch (IOException e) | ||
643 | { | ||
644 | if (TDebug.TraceAudioFileReader) TDebug.out("Cannot parse ID3v2 :"+e.getMessage()); | ||
645 | } | ||
646 | |||
647 | try | ||
648 | { | ||
649 | if (TDebug.TraceAudioFileReader) TDebug.out("ID3v2 frame dump='"+new String(bframes,0,bframes.length)+"'"); | ||
650 | /* ID3 tags : http://www.unixgods.org/~tilo/ID3/docs/ID3_comparison.html */ | ||
651 | String value = null; | ||
652 | for (int i=0;i<bframes.length-4;i++) | ||
653 | { | ||
654 | String code = new String(bframes,i,4); | ||
655 | String scode = new String(bframes,i,3); | ||
656 | // ID3v2.3 & v2.4 | ||
657 | if ((code.equals("TALB")) || (code.equals("TIT2")) || (code.equals("TYER")) || (code.equals("TPE1")) || (code.equals("TCOP")) || (code.equals("COMM")) || (code.equals("TCON")) || (code.equals("TRCK")) || (code.equals("TPOS")) || (code.equals("TDRC")) || (code.equals("TCOM")) || (code.equals("TIT1")) || (code.equals("TENC"))) | ||
658 | { | ||
659 | i=i+10; | ||
660 | size = (int) (bframes[i-6] << 24) + (bframes[i-5] << 16) + (bframes[i-4] << 8) + (bframes[i-3]); | ||
661 | if (code.equals("COMM")) value = parseText(bframes, i, size, 5); | ||
662 | else value = parseText(bframes,i, size, 1); | ||
663 | if ((value != null) && (value.length()>0)) | ||
664 | { | ||
665 | if (code.equals("TALB")) props.put("album",value); | ||
666 | else if (code.equals("TIT2")) props.put("title",value); | ||
667 | else if (code.equals("TYER")) props.put("date",value); | ||
668 | // ID3v2.4 date fix. | ||
669 | else if (code.equals("TDRC")) props.put("date",value); | ||
670 | else if (code.equals("TPE1")) props.put("author",value); | ||
671 | else if (code.equals("TCOP")) props.put("copyright",value); | ||
672 | else if (code.equals("COMM")) props.put("comment",value); | ||
673 | else if (code.equals("TCON")) props.put("mp3.id3tag.genre",value); | ||
674 | else if (code.equals("TRCK")) props.put("mp3.id3tag.track",value); | ||
675 | else if (code.equals("TPOS")) props.put("mp3.id3tag.disc",value); | ||
676 | else if (code.equals("TCOM")) props.put("mp3.id3tag.composer",value); | ||
677 | else if (code.equals("TIT1")) props.put("mp3.id3tag.grouping",value); | ||
678 | else if (code.equals("TENC")) props.put("mp3.id3tag.encoded",value); | ||
679 | } | ||
680 | i=i+size-1; | ||
681 | } | ||
682 | // ID3v2.2. | ||
683 | else if ((scode.equals("TAL")) || (scode.equals("TT2")) || (scode.equals("TP1")) || (scode.equals("TYE")) || (scode.equals("TRK")) || (scode.equals("TPA")) || (scode.equals("TCR")) || (scode.equals("TCO")) || (scode.equals("TCM")) || (scode.equals("COM")) || (scode.equals("TT1")) || (scode.equals("TEN"))) | ||
684 | { | ||
685 | i=i+6; | ||
686 | size = (int) (0x00000000) + (bframes[i-3] << 16) + (bframes[i-2] << 8) + (bframes[i-1]); | ||
687 | if (scode.equals("COM")) value = parseText(bframes, i, size, 5); | ||
688 | else value = parseText(bframes,i, size, 1); | ||
689 | if ((value != null) && (value.length()>0)) | ||
690 | { | ||
691 | if (scode.equals("TAL")) props.put("album",value); | ||
692 | else if (scode.equals("TT2")) props.put("title",value); | ||
693 | else if (scode.equals("TYE")) props.put("date",value); | ||
694 | else if (scode.equals("TP1")) props.put("author",value); | ||
695 | else if (scode.equals("TCR")) props.put("copyright",value); | ||
696 | else if (scode.equals("COM")) props.put("comment",value); | ||
697 | else if (scode.equals("TCO")) props.put("mp3.id3tag.genre",value); | ||
698 | else if (scode.equals("TRK")) props.put("mp3.id3tag.track",value); | ||
699 | else if (scode.equals("TPA")) props.put("mp3.id3tag.disc",value); | ||
700 | else if (scode.equals("TCM")) props.put("mp3.id3tag.composer",value); | ||
701 | else if (scode.equals("TT1")) props.put("mp3.id3tag.grouping",value); | ||
702 | else if (scode.equals("TEN")) props.put("mp3.id3tag.encoded",value); | ||
703 | } | ||
704 | i=i+size-1; | ||
705 | } | ||
706 | else if (code.startsWith("ID3")) | ||
707 | { | ||
708 | // ID3v2 Header. | ||
709 | int v2version = (int) (bframes[3] & 0xFF); | ||
710 | props.put("mp3.id3tag.v2.version",String.valueOf(v2version)); | ||
711 | i=i+4; | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | catch (RuntimeException e) | ||
716 | { | ||
717 | // Ignore all parsing errors. | ||
718 | if (TDebug.TraceAudioFileReader) TDebug.out("Cannot parse ID3v2 :"+e.getMessage()); | ||
719 | } | ||
720 | if (TDebug.TraceAudioFileReader) TDebug.out("ID3v2 parsed"); | ||
721 | } | ||
722 | |||
723 | /** | ||
724 | * Parse Text Frames. | ||
725 | * @param bframes | ||
726 | * @param offset | ||
727 | * @param size | ||
728 | * @param skip | ||
729 | * @return | ||
730 | */ | ||
731 | protected String parseText(byte[] bframes, int offset, int size, int skip) | ||
732 | { | ||
733 | String value = null; | ||
734 | try | ||
735 | { | ||
736 | String[] ENC_TYPES = {"ISO-8859-1", "UTF16","UTF-16BE", "UTF-8"}; | ||
737 | value = new String(bframes,offset+skip,size-skip,ENC_TYPES[bframes[offset]]); | ||
738 | value = chopSubstring(value,0,value.length()); | ||
739 | } | ||
740 | catch (UnsupportedEncodingException e) | ||
741 | { | ||
742 | if (TDebug.TraceAudioFileReader) TDebug.out("ID3v2 Encoding error :"+e.getMessage()); | ||
743 | } | ||
744 | return value; | ||
745 | } | ||
746 | |||
747 | /** | ||
748 | * Load shoutcast (ICY) info. | ||
749 | * @param input | ||
750 | * @param props | ||
751 | * @throws IOException | ||
752 | */ | ||
753 | protected void loadShoutcastInfo(InputStream input, HashMap props) throws IOException | ||
754 | { | ||
755 | IcyInputStream icy = new IcyInputStream(new BufferedInputStream(input)); | ||
756 | HashMap metadata = icy.getTagHash(); | ||
757 | MP3Tag titleMP3Tag = icy.getTag("icy-name"); | ||
758 | if (titleMP3Tag != null) props.put("title",((String) titleMP3Tag.getValue()).trim()); | ||
759 | MP3Tag[] meta = icy.getTags(); | ||
760 | if (meta != null) | ||
761 | { | ||
762 | StringBuffer metaStr = new StringBuffer(); | ||
763 | for (int i=0;i<meta.length;i++) | ||
764 | { | ||
765 | String key = meta[i].getName(); | ||
766 | String value = ((String) icy.getTag(key).getValue()).trim(); | ||
767 | props.put("mp3.shoutcast.metadata."+key, value); | ||
768 | } | ||
769 | } | ||
770 | } | ||
771 | |||
772 | } \ No newline at end of file | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFormat.java b/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFormat.java deleted file mode 100644 index 29a66a3d93..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFormat.java +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | /* | ||
2 | * MpegAudioFormat. | ||
3 | * | ||
4 | * JavaZOOM : mp3spi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | *----------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | *---------------------------------------------------------------------- | ||
22 | */ | ||
23 | |||
24 | package javazoom.spi.mpeg.sampled.file; | ||
25 | |||
26 | import java.util.Map; | ||
27 | |||
28 | import javax.sound.sampled.AudioFormat; | ||
29 | |||
30 | import org.tritonus.share.sampled.TAudioFormat; | ||
31 | |||
32 | /** | ||
33 | * @author JavaZOOM | ||
34 | */ | ||
35 | public class MpegAudioFormat extends TAudioFormat | ||
36 | { | ||
37 | /** | ||
38 | * Constructor. | ||
39 | * @param encoding | ||
40 | * @param nFrequency | ||
41 | * @param SampleSizeInBits | ||
42 | * @param nChannels | ||
43 | * @param FrameSize | ||
44 | * @param FrameRate | ||
45 | * @param isBigEndian | ||
46 | * @param properties | ||
47 | */ | ||
48 | public MpegAudioFormat(AudioFormat.Encoding encoding, float nFrequency, int SampleSizeInBits, int nChannels, int FrameSize, float FrameRate, boolean isBigEndian, Map properties) | ||
49 | { | ||
50 | super(encoding, nFrequency, SampleSizeInBits, nChannels, FrameSize, FrameRate, isBigEndian, properties); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * MP3 audio format parameters. | ||
55 | * Some parameters might be unavailable. So availability test is required before reading any parameter. | ||
56 | * | ||
57 | * <br>AudioFormat parameters. | ||
58 | * <ul> | ||
59 | * <li><b>bitrate</b> [Integer], bitrate in bits per seconds, average bitrate for VBR enabled stream. | ||
60 | * <li><b>vbr</b> [Boolean], VBR flag. | ||
61 | * </ul> | ||
62 | */ | ||
63 | public Map properties() | ||
64 | { | ||
65 | return super.properties(); | ||
66 | } | ||
67 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/MpegEncoding.java b/songdbj/javazoom/spi/mpeg/sampled/file/MpegEncoding.java deleted file mode 100644 index 6306d9ec80..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/MpegEncoding.java +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | * MpegEncoding. | ||
3 | * | ||
4 | * JavaZOOM : mp3spi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | *----------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | *---------------------------------------------------------------------- | ||
22 | */ | ||
23 | |||
24 | package javazoom.spi.mpeg.sampled.file; | ||
25 | |||
26 | import javax.sound.sampled.AudioFormat; | ||
27 | |||
28 | /** | ||
29 | * Encodings used by the MPEG audio decoder. | ||
30 | */ | ||
31 | public class MpegEncoding extends AudioFormat.Encoding | ||
32 | { | ||
33 | public static final AudioFormat.Encoding MPEG1L1 = new MpegEncoding("MPEG1L1"); | ||
34 | public static final AudioFormat.Encoding MPEG1L2 = new MpegEncoding("MPEG1L2"); | ||
35 | public static final AudioFormat.Encoding MPEG1L3 = new MpegEncoding("MPEG1L3"); | ||
36 | public static final AudioFormat.Encoding MPEG2L1 = new MpegEncoding("MPEG2L1"); | ||
37 | public static final AudioFormat.Encoding MPEG2L2 = new MpegEncoding("MPEG2L2"); | ||
38 | public static final AudioFormat.Encoding MPEG2L3 = new MpegEncoding("MPEG2L3"); | ||
39 | public static final AudioFormat.Encoding MPEG2DOT5L1 = new MpegEncoding("MPEG2DOT5L1"); | ||
40 | public static final AudioFormat.Encoding MPEG2DOT5L2 = new MpegEncoding("MPEG2DOT5L2"); | ||
41 | public static final AudioFormat.Encoding MPEG2DOT5L3 = new MpegEncoding("MPEG2DOT5L3"); | ||
42 | |||
43 | public MpegEncoding(String strName) | ||
44 | { | ||
45 | super(strName); | ||
46 | } | ||
47 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/MpegFileFormatType.java b/songdbj/javazoom/spi/mpeg/sampled/file/MpegFileFormatType.java deleted file mode 100644 index 2c59ad8621..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/MpegFileFormatType.java +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * MpegFileFormatType. | ||
3 | * | ||
4 | * JavaZOOM : mp3spi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | *----------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | *---------------------------------------------------------------------- | ||
22 | */ | ||
23 | |||
24 | package javazoom.spi.mpeg.sampled.file; | ||
25 | |||
26 | import javax.sound.sampled.AudioFileFormat; | ||
27 | |||
28 | /** | ||
29 | * FileFormatTypes used by the MPEG audio decoder. | ||
30 | */ | ||
31 | public class MpegFileFormatType extends AudioFileFormat.Type | ||
32 | { | ||
33 | public static final AudioFileFormat.Type MPEG = new MpegFileFormatType("MPEG", "mpeg"); | ||
34 | public static final AudioFileFormat.Type MP3 = new MpegFileFormatType("MP3", "mp3"); | ||
35 | |||
36 | public MpegFileFormatType(String strName, String strExtension) | ||
37 | { | ||
38 | super(strName, strExtension); | ||
39 | } | ||
40 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/tag/IcyInputStream.java b/songdbj/javazoom/spi/mpeg/sampled/file/tag/IcyInputStream.java deleted file mode 100644 index 22aa4439fe..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/tag/IcyInputStream.java +++ /dev/null | |||
@@ -1,412 +0,0 @@ | |||
1 | /* | ||
2 | * IcyInputStream. | ||
3 | * | ||
4 | * jicyshout : http://sourceforge.net/projects/jicyshout/ | ||
5 | * | ||
6 | * JavaZOOM : mp3spi@javazoom.net | ||
7 | * http://www.javazoom.net | ||
8 | * | ||
9 | *----------------------------------------------------------------------- | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | *---------------------------------------------------------------------- | ||
24 | */ | ||
25 | |||
26 | package javazoom.spi.mpeg.sampled.file.tag; | ||
27 | |||
28 | import java.io.BufferedInputStream; | ||
29 | import java.io.IOException; | ||
30 | import java.io.InputStream; | ||
31 | import java.net.URL; | ||
32 | import java.net.URLConnection; | ||
33 | import java.util.HashMap; | ||
34 | import java.util.StringTokenizer; | ||
35 | |||
36 | /** An BufferedInputStream that parses Shoutcast's "icy" metadata | ||
37 | from the stream. Gets headers at the beginning and if the | ||
38 | "icy-metaint" tag is found, it parses and strips in-stream | ||
39 | metadata. | ||
40 | <p> | ||
41 | <b>The deal with metaint</b>: Icy streams don't try to put | ||
42 | tags between MP3 frames the way that ID3 does. Instead, it | ||
43 | requires the client to strip metadata from the stream before | ||
44 | it hits the decoder. You get an | ||
45 | <code>icy-metaint</code> name/val in the beginning of the | ||
46 | stream iff you sent "Icy-Metadata" with value "1" in the | ||
47 | request headers (SimpleMP3DataSource does this if the | ||
48 | "parseStreamMetadata" boolean is true). If this is the case | ||
49 | then the value of icy-metaint is the amount of real data | ||
50 | between metadata blocks. Each block begins with an int | ||
51 | indicating how much metadata there is -- the block is this | ||
52 | value times 16 (it can be, and often is, 0). | ||
53 | <p> | ||
54 | Originally thought that "icy" implied Icecast, but this is | ||
55 | completely wrong -- real Icecast servers, found through | ||
56 | www.icecast.net and typified by URLs with a trailing directory | ||
57 | (like CalArts School of Music - http://65.165.174.100:8000/som) | ||
58 | do not have the "ICY 200 OK" magic string or any of the | ||
59 | CRLF-separated headers. Apparently, "icy" means "Shoutcast". | ||
60 | Yep, that's weird. | ||
61 | @author Chris Adamson, invalidname@mac.com | ||
62 | */ | ||
63 | public class IcyInputStream | ||
64 | extends BufferedInputStream | ||
65 | implements MP3MetadataParser { | ||
66 | |||
67 | public static boolean DEBUG = false; | ||
68 | |||
69 | MP3TagParseSupport tagParseSupport; | ||
70 | /** inline tags are delimited by ';', also filter out | ||
71 | null bytes | ||
72 | */ | ||
73 | protected static final String INLINE_TAG_SEPARATORS = ";\u0000"; | ||
74 | /* looks like icy streams start start with | ||
75 | ICY 200 OK\r\n | ||
76 | then the tags are like | ||
77 | icy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">Winamp</a><BR>\r\n | ||
78 | icy-notice2:SHOUTcast Distributed Network Audio Server/win32 v1.8.2<BR>\r\n | ||
79 | icy-name:Core-upt Radio\r\n | ||
80 | icy-genre:Punk Ska Emo\r\n | ||
81 | icy-url:http://www.core-uptrecords.com\r\n | ||
82 | icy-pub:1\r\n | ||
83 | icy-metaint:8192\r\n | ||
84 | icy-br:56\r\n | ||
85 | \r\n (signifies end of headers) | ||
86 | we only get icy-metaint if the http request that created | ||
87 | this stream sent the header "icy-metadata:1" | ||
88 | // | ||
89 | in in-line metadata, we read a byte that tells us how | ||
90 | many 16-byte blocks there are (presumably, we still use | ||
91 | \r\n for the separator... the block is padded out with | ||
92 | 0x00's that we can ignore) | ||
93 | |||
94 | // when server is full/down/etc, we get the following for | ||
95 | // one of the notice lines: | ||
96 | icy-notice2:This server has reached its user limit<BR> | ||
97 | or | ||
98 | icy-notice2:The resource requested is currently unavailable<BR> | ||
99 | */ | ||
100 | /** Tags that have been discovered in the stream. | ||
101 | */ | ||
102 | HashMap tags; | ||
103 | /** Buffer for readCRLF line... note this limits lines to | ||
104 | 1024 chars (I've read that WinAmp barfs at 128, so | ||
105 | this is generous) | ||
106 | */ | ||
107 | protected byte[] crlfBuffer = new byte[1024]; | ||
108 | /** value of the "metaint" tag, which tells us how many bytes | ||
109 | of real data are between the metadata tags. if -1, this stream | ||
110 | does not have metadata after the header. | ||
111 | */ | ||
112 | protected int metaint = -1; | ||
113 | /** how many bytes of real data remain before the next | ||
114 | block of metadata. Only meaningful if metaint != -1. | ||
115 | */ | ||
116 | protected int bytesUntilNextMetadata = -1; | ||
117 | // TODO: comment for constructor | ||
118 | /** Reads the initial headers of the stream and adds | ||
119 | tags appropriatly. Gets set up to find, read, | ||
120 | and strip blocks of in-line metadata if the | ||
121 | <code>icy-metaint</code> header is found. | ||
122 | */ | ||
123 | public IcyInputStream(InputStream in) throws IOException { | ||
124 | super(in); | ||
125 | tags = new HashMap(); | ||
126 | tagParseSupport = new MP3TagParseSupport(); | ||
127 | // read the initial tags here, including the metaint | ||
128 | // and set the counter for how far we read until | ||
129 | // the next metadata block (if any). | ||
130 | readInitialHeaders(); | ||
131 | IcyTag metaIntTag = (IcyTag) getTag("icy-metaint"); | ||
132 | if (DEBUG) System.out.println("METATAG:"+metaIntTag); | ||
133 | if (metaIntTag != null) { | ||
134 | String metaIntString = metaIntTag.getValueAsString(); | ||
135 | try { | ||
136 | metaint = Integer.parseInt(metaIntString.trim()); | ||
137 | if (DEBUG) System.out.println("METAINT:"+metaint); | ||
138 | bytesUntilNextMetadata = metaint; | ||
139 | } | ||
140 | catch (NumberFormatException nfe) { | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * IcyInputStream constructor for know meta-interval (Icecast 2) | ||
147 | * @param in | ||
148 | * @param metaint | ||
149 | * @throws IOException | ||
150 | */ | ||
151 | public IcyInputStream(InputStream in, String metaIntString) throws IOException { | ||
152 | super(in); | ||
153 | tags = new HashMap(); | ||
154 | tagParseSupport = new MP3TagParseSupport(); | ||
155 | try | ||
156 | { | ||
157 | metaint = Integer.parseInt(metaIntString.trim()); | ||
158 | if (DEBUG) System.out.println("METAINT:"+metaint); | ||
159 | bytesUntilNextMetadata = metaint; | ||
160 | } | ||
161 | catch (NumberFormatException nfe) { | ||
162 | } | ||
163 | } | ||
164 | |||
165 | /** Assuming we're at the top of the stream, read lines one | ||
166 | by one until we hit a completely blank \r\n. Parse the | ||
167 | data as IcyTags. | ||
168 | */ | ||
169 | protected void readInitialHeaders() throws IOException { | ||
170 | String line = null; | ||
171 | while (!((line = readCRLFLine()).equals(""))) { | ||
172 | int colonIndex = line.indexOf(':'); | ||
173 | // does it have a ':' separator | ||
174 | if (colonIndex == -1) | ||
175 | continue; | ||
176 | IcyTag tag = | ||
177 | new IcyTag( | ||
178 | line.substring(0, colonIndex), | ||
179 | line.substring(colonIndex + 1)); | ||
180 | //System.out.println(tag); | ||
181 | addTag(tag); | ||
182 | } | ||
183 | } | ||
184 | /** Read everything up to the next CRLF, return it as | ||
185 | a String. | ||
186 | */ | ||
187 | protected String readCRLFLine() throws IOException { | ||
188 | int i = 0; | ||
189 | for (; i < crlfBuffer.length; i++) { | ||
190 | byte aByte = (byte) read(); | ||
191 | if (aByte == '\r') { | ||
192 | // possible end of line | ||
193 | byte anotherByte = (byte) read(); | ||
194 | i++; // since we read again | ||
195 | if (anotherByte == '\n') { | ||
196 | break; // break out of while | ||
197 | } | ||
198 | else { | ||
199 | // oops, not end of line - put these in array | ||
200 | crlfBuffer[i - 1] = aByte; | ||
201 | crlfBuffer[i] = anotherByte; | ||
202 | } | ||
203 | } | ||
204 | else { | ||
205 | // if not \r | ||
206 | crlfBuffer[i] = aByte; | ||
207 | } | ||
208 | } // for | ||
209 | // get the string from the byte[]. i is 1 too high because of | ||
210 | // read-ahead in crlf block | ||
211 | return new String(crlfBuffer, 0, i - 1); | ||
212 | } | ||
213 | /** Reads and returns a single byte. | ||
214 | If the next byte is a metadata block, then that | ||
215 | block is read, stripped, and parsed before reading | ||
216 | and returning the first byte after the metadata block. | ||
217 | */ | ||
218 | public int read() throws IOException { | ||
219 | if (bytesUntilNextMetadata > 0) { | ||
220 | bytesUntilNextMetadata--; | ||
221 | return super.read(); | ||
222 | } | ||
223 | else if (bytesUntilNextMetadata == 0) { | ||
224 | // we need to read next metadata block | ||
225 | readMetadata(); | ||
226 | bytesUntilNextMetadata = metaint - 1; | ||
227 | // -1 because we read byte on next line | ||
228 | return super.read(); | ||
229 | } | ||
230 | else { | ||
231 | // no metadata in this stream | ||
232 | return super.read(); | ||
233 | } | ||
234 | } | ||
235 | /** Reads a block of bytes. If the next byte is known | ||
236 | to be a block of metadata, then that is read, parsed, | ||
237 | and stripped, and then a block of bytes is read and | ||
238 | returned. | ||
239 | Otherwise, it may read up to but | ||
240 | not into the next metadata block if | ||
241 | <code>bytesUntilNextMetadata < length</code> | ||
242 | */ | ||
243 | public int read(byte[] buf, int offset, int length) throws IOException { | ||
244 | // if not on metadata, do the usual read so long as we | ||
245 | // don't read past metadata | ||
246 | if (bytesUntilNextMetadata > 0) { | ||
247 | int adjLength = Math.min(length, bytesUntilNextMetadata); | ||
248 | int got = super.read(buf, offset, adjLength); | ||
249 | bytesUntilNextMetadata -= got; | ||
250 | return got; | ||
251 | } | ||
252 | else if (bytesUntilNextMetadata == 0) { | ||
253 | // read/parse the metadata | ||
254 | readMetadata(); | ||
255 | // now as above, except that we reset | ||
256 | // bytesUntilNextMetadata differently | ||
257 | |||
258 | //int adjLength = Math.min(length, bytesUntilNextMetadata); | ||
259 | //int got = super.read(buf, offset, adjLength); | ||
260 | //bytesUntilNextMetadata = metaint - got; | ||
261 | |||
262 | // Chop Fix - JavaZOOM (3 lines above seem buggy) | ||
263 | bytesUntilNextMetadata = metaint; | ||
264 | int adjLength = Math.min(length, bytesUntilNextMetadata); | ||
265 | int got = super.read(buf, offset, adjLength); | ||
266 | bytesUntilNextMetadata -= got; | ||
267 | // End fix - JavaZOOM | ||
268 | |||
269 | |||
270 | return got; | ||
271 | } | ||
272 | else { | ||
273 | // not even reading metadata | ||
274 | return super.read(buf, offset, length); | ||
275 | } | ||
276 | } | ||
277 | /** trivial <code>return read (buf, 0, buf.length)</code> | ||
278 | */ | ||
279 | public int read(byte[] buf) throws IOException { | ||
280 | return read(buf, 0, buf.length); | ||
281 | } | ||
282 | /** Read the next segment of metadata. The stream <b>must</b> | ||
283 | be right on the segment, ie, the next byte to read is | ||
284 | the metadata block count. The metadata is parsed and | ||
285 | new tags are added with addTag(), which fires events | ||
286 | */ | ||
287 | protected void readMetadata() throws IOException { | ||
288 | int blockCount = super.read(); | ||
289 | if (DEBUG) System.out.println("BLOCKCOUNT:"+blockCount); | ||
290 | // System.out.println ("blocks to read: " + blockCount); | ||
291 | int byteCount = (blockCount * 16); // 16 bytes per block | ||
292 | if (byteCount < 0) | ||
293 | return; // WTF?! | ||
294 | byte[] metadataBlock = new byte[byteCount]; | ||
295 | int index = 0; | ||
296 | // build an array of this metadata | ||
297 | while (byteCount > 0) { | ||
298 | int bytesRead = super.read(metadataBlock, index, byteCount); | ||
299 | index += bytesRead; | ||
300 | byteCount -= bytesRead; | ||
301 | } | ||
302 | // now parse it | ||
303 | if (blockCount > 0) | ||
304 | parseInlineIcyTags(metadataBlock); | ||
305 | } // readMetadata | ||
306 | /** Parse metadata from an in-stream "block" of bytes, add | ||
307 | a tag for each one. | ||
308 | <p> | ||
309 | Hilariously, the inline data format is totally different | ||
310 | than the top-of-stream header. For example, here's a | ||
311 | block I saw on "Final Fantasy Radio": | ||
312 | <pre> | ||
313 | StreamTitle='Final Fantasy 8 - Nobuo Uematsu - Blue Fields';StreamUrl=''; | ||
314 | </pre> | ||
315 | In other words: | ||
316 | <ol> | ||
317 | <li>Tags are delimited by semicolons | ||
318 | <li>Keys/values are delimited by equals-signs | ||
319 | <li>Values are wrapped in single-quotes | ||
320 | <li>Key names are in SentenceCase, not lowercase-dashed | ||
321 | </ol> | ||
322 | */ | ||
323 | protected void parseInlineIcyTags(byte[] tagBlock) { | ||
324 | String blockString = new String(tagBlock); | ||
325 | if (DEBUG) System.out.println("BLOCKSTR:"+blockString); | ||
326 | StringTokenizer izer = | ||
327 | new StringTokenizer(blockString, INLINE_TAG_SEPARATORS); | ||
328 | int i = 0; | ||
329 | while (izer.hasMoreTokens()) { | ||
330 | String tagString = izer.nextToken(); | ||
331 | int separatorIdx = tagString.indexOf('='); | ||
332 | if (separatorIdx == -1) | ||
333 | continue; // bogus tagString if no '=' | ||
334 | // try to strip single-quotes around value, if present | ||
335 | int valueStartIdx = | ||
336 | (tagString.charAt(separatorIdx + 1) == '\'') | ||
337 | ? separatorIdx + 2 | ||
338 | : separatorIdx + 1; | ||
339 | int valueEndIdx = | ||
340 | (tagString.charAt(tagString.length() - 1)) == '\'' | ||
341 | ? tagString.length() - 1 | ||
342 | : tagString.length(); | ||
343 | String name = tagString.substring(0, separatorIdx); | ||
344 | String value = tagString.substring(valueStartIdx, valueEndIdx); | ||
345 | // System.out.println (i++ + " " + name + ":" + value); | ||
346 | IcyTag tag = new IcyTag(name, value); | ||
347 | addTag(tag); | ||
348 | } | ||
349 | } | ||
350 | /** adds the tag to the HashMap of tags we have encountered | ||
351 | either in-stream or as headers, replacing any previous | ||
352 | tag with this name. | ||
353 | */ | ||
354 | protected void addTag(IcyTag tag) { | ||
355 | tags.put(tag.getName(), tag); | ||
356 | // fire this as an event too | ||
357 | tagParseSupport.fireTagParsed(this, tag); | ||
358 | } | ||
359 | /** Get the named tag from the HashMap of headers and | ||
360 | in-line tags. Null if no such tag has been encountered. | ||
361 | */ | ||
362 | public MP3Tag getTag(String tagName) { | ||
363 | return (MP3Tag) tags.get(tagName); | ||
364 | } | ||
365 | /** Get all tags (headers or in-stream) encountered thus far. | ||
366 | */ | ||
367 | public MP3Tag[] getTags() { | ||
368 | return (MP3Tag[]) tags.values().toArray(new MP3Tag[0]); | ||
369 | } | ||
370 | /** Returns a HashMap of all headers and in-stream tags | ||
371 | parsed so far. | ||
372 | */ | ||
373 | public HashMap getTagHash() { | ||
374 | return tags; | ||
375 | } | ||
376 | /** Adds a TagParseListener to be notified when this stream | ||
377 | parses MP3Tags. | ||
378 | */ | ||
379 | public void addTagParseListener(TagParseListener tpl) { | ||
380 | tagParseSupport.addTagParseListener(tpl); | ||
381 | } | ||
382 | /** Removes a TagParseListener, so it won't be notified when | ||
383 | this stream parses MP3Tags. | ||
384 | */ | ||
385 | public void removeTagParseListener(TagParseListener tpl) { | ||
386 | tagParseSupport.removeTagParseListener(tpl); | ||
387 | } | ||
388 | /** Quickie unit-test. | ||
389 | */ | ||
390 | public static void main(String args[]) { | ||
391 | byte[] chow = new byte[200]; | ||
392 | if (args.length != 1) { | ||
393 | //System.out.println("Usage: IcyInputStream <url>"); | ||
394 | return; | ||
395 | } | ||
396 | try { | ||
397 | URL url = new URL(args[0]); | ||
398 | URLConnection conn = url.openConnection(); | ||
399 | conn.setRequestProperty("Icy-Metadata", "1"); | ||
400 | IcyInputStream icy = | ||
401 | new IcyInputStream( | ||
402 | new BufferedInputStream(conn.getInputStream())); | ||
403 | while (icy.available() > -1) { | ||
404 | // icy.read(); | ||
405 | icy.read(chow, 0, chow.length); | ||
406 | } | ||
407 | } | ||
408 | catch (Exception e) { | ||
409 | e.printStackTrace(); | ||
410 | } | ||
411 | } | ||
412 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/tag/IcyTag.java b/songdbj/javazoom/spi/mpeg/sampled/file/tag/IcyTag.java deleted file mode 100644 index bbe70f1f3c..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/tag/IcyTag.java +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /* | ||
2 | * IcyTag. | ||
3 | * | ||
4 | * jicyshout : http://sourceforge.net/projects/jicyshout/ | ||
5 | * | ||
6 | * JavaZOOM : mp3spi@javazoom.net | ||
7 | * http://www.javazoom.net | ||
8 | * | ||
9 | *----------------------------------------------------------------------- | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | *---------------------------------------------------------------------- | ||
24 | */ | ||
25 | |||
26 | package javazoom.spi.mpeg.sampled.file.tag; | ||
27 | /** | ||
28 | * A tag parsed from an icecast tag. | ||
29 | */ | ||
30 | public class IcyTag extends MP3Tag implements StringableTag { | ||
31 | /** Create a new tag, from the parsed name and (String) value. | ||
32 | It looks like all Icecast tags are Strings (safe to assume | ||
33 | this going forward?) | ||
34 | */ | ||
35 | public IcyTag(String name, String stringValue) { | ||
36 | super(name, stringValue); | ||
37 | } | ||
38 | // so far as I know, all Icecast tags are strings | ||
39 | public String getValueAsString() { | ||
40 | return (String) getValue(); | ||
41 | } | ||
42 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3MetadataParser.java b/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3MetadataParser.java deleted file mode 100644 index 81511064b8..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3MetadataParser.java +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /* | ||
2 | * MP3MetadataParser. | ||
3 | * | ||
4 | * jicyshout : http://sourceforge.net/projects/jicyshout/ | ||
5 | * | ||
6 | * JavaZOOM : mp3spi@javazoom.net | ||
7 | * http://www.javazoom.net | ||
8 | * | ||
9 | *----------------------------------------------------------------------- | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | *---------------------------------------------------------------------- | ||
24 | */ | ||
25 | |||
26 | package javazoom.spi.mpeg.sampled.file.tag; | ||
27 | |||
28 | /** An object that fires off TagParseEvents as they are parsed | ||
29 | from a stream, ServerSocket, or other metadata source | ||
30 | */ | ||
31 | public interface MP3MetadataParser { | ||
32 | /** Adds a TagParseListener to be notified when this object | ||
33 | parses MP3Tags. | ||
34 | */ | ||
35 | public void addTagParseListener(TagParseListener tpl); | ||
36 | /** Removes a TagParseListener, so it won't be notified when | ||
37 | this object parses MP3Tags. | ||
38 | */ | ||
39 | public void removeTagParseListener(TagParseListener tpl); | ||
40 | /** Get all tags (headers or in-stream) encountered thusfar. | ||
41 | This is included in this otherwise Listener-like scheme | ||
42 | because most standards are a mix of start-of-stream | ||
43 | metadata tags (like the http headers or the stuff at the | ||
44 | top of an ice stream) and inline data. Implementations should | ||
45 | hang onto all tags they parse and provide them with this | ||
46 | call. Callers should first use this call to get initial | ||
47 | tags, then subscribe for events as the stream continues. | ||
48 | */ | ||
49 | public MP3Tag[] getTags(); | ||
50 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3Tag.java b/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3Tag.java deleted file mode 100644 index b545356240..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3Tag.java +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | /* | ||
2 | * MP3Tag. | ||
3 | * | ||
4 | * jicyshout : http://sourceforge.net/projects/jicyshout/ | ||
5 | * | ||
6 | * JavaZOOM : mp3spi@javazoom.net | ||
7 | * http://www.javazoom.net | ||
8 | * | ||
9 | *----------------------------------------------------------------------- | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | *---------------------------------------------------------------------- | ||
24 | */ | ||
25 | |||
26 | package javazoom.spi.mpeg.sampled.file.tag; | ||
27 | |||
28 | /** An individual piece of mp3 metadata, as a name/value pair. | ||
29 | Abstract just so that subclasses will indicate their | ||
30 | tagging scheme (Icy, ID3, etc.). | ||
31 | */ | ||
32 | public abstract class MP3Tag extends Object { | ||
33 | protected String name; | ||
34 | protected Object value; | ||
35 | public MP3Tag(String name, Object value) { | ||
36 | this.name = name; | ||
37 | this.value = value; | ||
38 | } | ||
39 | public String getName() { | ||
40 | return name; | ||
41 | } | ||
42 | public Object getValue() { | ||
43 | return value; | ||
44 | } | ||
45 | public String toString() { | ||
46 | return getClass().getName() | ||
47 | + " -- " | ||
48 | + getName() | ||
49 | + ":" | ||
50 | + getValue().toString(); | ||
51 | } | ||
52 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3TagParseSupport.java b/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3TagParseSupport.java deleted file mode 100644 index 1ab6525512..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3TagParseSupport.java +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /* | ||
2 | * MP3TagParseSupport. | ||
3 | * | ||
4 | * jicyshout : http://sourceforge.net/projects/jicyshout/ | ||
5 | * | ||
6 | * JavaZOOM : mp3spi@javazoom.net | ||
7 | * http://www.javazoom.net | ||
8 | * | ||
9 | *----------------------------------------------------------------------- | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | *---------------------------------------------------------------------- | ||
24 | */ | ||
25 | |||
26 | package javazoom.spi.mpeg.sampled.file.tag; | ||
27 | |||
28 | import java.util.ArrayList; | ||
29 | /** | ||
30 | */ | ||
31 | public class MP3TagParseSupport extends Object { | ||
32 | ArrayList tagParseListeners; | ||
33 | /** trivial constructor, sets up listeners list. | ||
34 | */ | ||
35 | public MP3TagParseSupport() { | ||
36 | super(); | ||
37 | tagParseListeners = new ArrayList(); | ||
38 | } | ||
39 | /** Adds a TagParseListener to be notified when a stream | ||
40 | parses MP3Tags. | ||
41 | */ | ||
42 | public void addTagParseListener(TagParseListener tpl) { | ||
43 | tagParseListeners.add(tpl); | ||
44 | } | ||
45 | /** Removes a TagParseListener, so it won't be notified when | ||
46 | a stream parses MP3Tags. | ||
47 | */ | ||
48 | public void removeTagParseListener(TagParseListener tpl) { | ||
49 | tagParseListeners.add(tpl); | ||
50 | } | ||
51 | /** Fires the given event to all registered listeners | ||
52 | */ | ||
53 | public void fireTagParseEvent(TagParseEvent tpe) { | ||
54 | for (int i = 0; i < tagParseListeners.size(); i++) { | ||
55 | TagParseListener l = (TagParseListener) tagParseListeners.get(i); | ||
56 | l.tagParsed(tpe); | ||
57 | } | ||
58 | } | ||
59 | public void fireTagParsed(Object source, MP3Tag tag) { | ||
60 | fireTagParseEvent(new TagParseEvent(source, tag)); | ||
61 | } | ||
62 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/tag/StringableTag.java b/songdbj/javazoom/spi/mpeg/sampled/file/tag/StringableTag.java deleted file mode 100644 index 685c5207f9..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/tag/StringableTag.java +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /* | ||
2 | * StringableTag. | ||
3 | * | ||
4 | * jicyshout : http://sourceforge.net/projects/jicyshout/ | ||
5 | * | ||
6 | * JavaZOOM : mp3spi@javazoom.net | ||
7 | * http://www.javazoom.net | ||
8 | * | ||
9 | *----------------------------------------------------------------------- | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | *---------------------------------------------------------------------- | ||
24 | */ | ||
25 | |||
26 | package javazoom.spi.mpeg.sampled.file.tag; | ||
27 | |||
28 | /** Indicates that the value of a tag is a string, and | ||
29 | provides a getValueAsString() method to get it. | ||
30 | Appropriate for tags like artist, title, etc. | ||
31 | */ | ||
32 | public interface StringableTag { | ||
33 | /** Return the value of this tag as a string. | ||
34 | */ | ||
35 | public String getValueAsString(); | ||
36 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/tag/TagParseEvent.java b/songdbj/javazoom/spi/mpeg/sampled/file/tag/TagParseEvent.java deleted file mode 100644 index 97e9ec1e19..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/tag/TagParseEvent.java +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | /* | ||
2 | * TagParseEvent. | ||
3 | * | ||
4 | * jicyshout : http://sourceforge.net/projects/jicyshout/ | ||
5 | * | ||
6 | * JavaZOOM : mp3spi@javazoom.net | ||
7 | * http://www.javazoom.net | ||
8 | * | ||
9 | *----------------------------------------------------------------------- | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | *---------------------------------------------------------------------- | ||
24 | */ | ||
25 | |||
26 | package javazoom.spi.mpeg.sampled.file.tag; | ||
27 | |||
28 | import java.util.EventObject; | ||
29 | /** Event to indicate that an MP3 tag was received through | ||
30 | some means (parsed in stream, received via UDP, whatever) | ||
31 | and converted into an MP3Tag object. | ||
32 | */ | ||
33 | public class TagParseEvent extends EventObject { | ||
34 | protected MP3Tag tag; | ||
35 | public TagParseEvent(Object source, MP3Tag tag) { | ||
36 | super(source); | ||
37 | this.tag = tag; | ||
38 | } | ||
39 | /** Get the tag that was parsed. | ||
40 | */ | ||
41 | public MP3Tag getTag() { | ||
42 | return tag; | ||
43 | } | ||
44 | } | ||
diff --git a/songdbj/javazoom/spi/mpeg/sampled/file/tag/TagParseListener.java b/songdbj/javazoom/spi/mpeg/sampled/file/tag/TagParseListener.java deleted file mode 100644 index a630827297..0000000000 --- a/songdbj/javazoom/spi/mpeg/sampled/file/tag/TagParseListener.java +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | /* | ||
2 | * TagParseListener. | ||
3 | * | ||
4 | * jicyshout : http://sourceforge.net/projects/jicyshout/ | ||
5 | * | ||
6 | * JavaZOOM : mp3spi@javazoom.net | ||
7 | * http://www.javazoom.net | ||
8 | * | ||
9 | *----------------------------------------------------------------------- | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | *---------------------------------------------------------------------- | ||
24 | */ | ||
25 | |||
26 | package javazoom.spi.mpeg.sampled.file.tag; | ||
27 | |||
28 | import java.util.EventListener; | ||
29 | /** EventListener to be implemented by objects that want to | ||
30 | get callbacks when MP3 tags are received. | ||
31 | */ | ||
32 | public interface TagParseListener extends EventListener { | ||
33 | /** Called when a tag is found (parsed from the stream, | ||
34 | received via UDP, etc.) | ||
35 | */ | ||
36 | public void tagParsed(TagParseEvent tpe); | ||
37 | } | ||
diff --git a/songdbj/javazoom/spi/vorbis/sampled/convert/DecodedVorbisAudioInputStream.java b/songdbj/javazoom/spi/vorbis/sampled/convert/DecodedVorbisAudioInputStream.java deleted file mode 100644 index b8e8577e13..0000000000 --- a/songdbj/javazoom/spi/vorbis/sampled/convert/DecodedVorbisAudioInputStream.java +++ /dev/null | |||
@@ -1,519 +0,0 @@ | |||
1 | /* | ||
2 | * DecodedVorbisAudioInputStream | ||
3 | * | ||
4 | * JavaZOOM : vorbisspi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | * ---------------------------------------------------------------------------- | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Library General Public License as published | ||
10 | * by the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU Library General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Library General Public | ||
19 | * License along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * ---------------------------------------------------------------------------- | ||
22 | */ | ||
23 | |||
24 | package javazoom.spi.vorbis.sampled.convert; | ||
25 | |||
26 | import java.io.IOException; | ||
27 | import java.io.InputStream; | ||
28 | import java.util.HashMap; | ||
29 | import java.util.Map; | ||
30 | |||
31 | import javax.sound.sampled.AudioFormat; | ||
32 | import javax.sound.sampled.AudioInputStream; | ||
33 | |||
34 | import javazoom.spi.PropertiesContainer; | ||
35 | |||
36 | import org.tritonus.share.TDebug; | ||
37 | import org.tritonus.share.sampled.convert.TAsynchronousFilteredAudioInputStream; | ||
38 | |||
39 | import com.jcraft.jogg.Packet; | ||
40 | import com.jcraft.jogg.Page; | ||
41 | import com.jcraft.jogg.StreamState; | ||
42 | import com.jcraft.jogg.SyncState; | ||
43 | import com.jcraft.jorbis.Block; | ||
44 | import com.jcraft.jorbis.Comment; | ||
45 | import com.jcraft.jorbis.DspState; | ||
46 | import com.jcraft.jorbis.Info; | ||
47 | |||
48 | /** | ||
49 | * This class implements the Vorbis decoding. | ||
50 | */ | ||
51 | public class DecodedVorbisAudioInputStream extends TAsynchronousFilteredAudioInputStream implements PropertiesContainer | ||
52 | { | ||
53 | private InputStream oggBitStream_ = null; | ||
54 | |||
55 | private SyncState oggSyncState_ = null; | ||
56 | private StreamState oggStreamState_ = null; | ||
57 | private Page oggPage_ = null; | ||
58 | private Packet oggPacket_ = null; | ||
59 | private Info vorbisInfo = null; | ||
60 | private Comment vorbisComment = null; | ||
61 | private DspState vorbisDspState = null; | ||
62 | private Block vorbisBlock = null; | ||
63 | |||
64 | static final int playState_NeedHeaders = 0; | ||
65 | static final int playState_ReadData = 1; | ||
66 | static final int playState_WriteData = 2; | ||
67 | static final int playState_Done = 3; | ||
68 | static final int playState_BufferFull = 4; | ||
69 | static final int playState_Corrupt = -1; | ||
70 | private int playState; | ||
71 | |||
72 | private int bufferMultiple_ = 4; | ||
73 | private int bufferSize_ = bufferMultiple_ * 256 * 2; | ||
74 | private int convsize = bufferSize_ * 2; | ||
75 | private byte[] convbuffer = new byte[convsize]; | ||
76 | private byte[] buffer = null; | ||
77 | private int bytes = 0; | ||
78 | private float[][][] _pcmf = null; | ||
79 | private int[] _index = null; | ||
80 | private int index = 0; | ||
81 | private int i = 0; | ||
82 | // bout is now a global so that we can continue from when we have a buffer full. | ||
83 | int bout = 0; | ||
84 | |||
85 | private HashMap properties = null; | ||
86 | private long currentBytes = 0; | ||
87 | |||
88 | /** | ||
89 | * Constructor. | ||
90 | */ | ||
91 | public DecodedVorbisAudioInputStream(AudioFormat outputFormat, AudioInputStream bitStream) | ||
92 | { | ||
93 | super(outputFormat, -1); | ||
94 | this.oggBitStream_ = bitStream; | ||
95 | init_jorbis(); | ||
96 | index = 0; | ||
97 | playState = playState_NeedHeaders; | ||
98 | properties = new HashMap(); | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * Initializes all the jOrbis and jOgg vars that are used for song playback. | ||
103 | */ | ||
104 | private void init_jorbis() | ||
105 | { | ||
106 | oggSyncState_ = new SyncState(); | ||
107 | oggStreamState_ = new StreamState(); | ||
108 | oggPage_ = new Page(); | ||
109 | oggPacket_ = new Packet(); | ||
110 | vorbisInfo = new Info(); | ||
111 | vorbisComment = new Comment(); | ||
112 | vorbisDspState = new DspState(); | ||
113 | vorbisBlock = new Block(vorbisDspState); | ||
114 | buffer = null; | ||
115 | bytes = 0; | ||
116 | currentBytes = 0L; | ||
117 | oggSyncState_.init(); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * Return dynamic properties. | ||
122 | * | ||
123 | * <ul> | ||
124 | * <li><b>ogg.position.byte</b> [Long], current position in bytes in the stream. | ||
125 | *</ul> | ||
126 | */ | ||
127 | public Map properties() | ||
128 | { | ||
129 | properties.put("ogg.position.byte",new Long(currentBytes)); | ||
130 | return properties; | ||
131 | } | ||
132 | /** | ||
133 | * Main loop. | ||
134 | */ | ||
135 | public void execute() | ||
136 | { | ||
137 | if(TDebug.TraceAudioConverter) | ||
138 | { | ||
139 | switch(playState) | ||
140 | { | ||
141 | case playState_NeedHeaders: | ||
142 | TDebug.out("playState = playState_NeedHeaders"); | ||
143 | break; | ||
144 | case playState_ReadData: | ||
145 | TDebug.out("playState = playState_ReadData"); | ||
146 | break; | ||
147 | case playState_WriteData: | ||
148 | TDebug.out("playState = playState_WriteData"); | ||
149 | break; | ||
150 | case playState_Done: | ||
151 | TDebug.out("playState = playState_Done"); | ||
152 | break; | ||
153 | case playState_BufferFull: | ||
154 | TDebug.out("playState = playState_BufferFull"); | ||
155 | break; | ||
156 | case playState_Corrupt: | ||
157 | TDebug.out("playState = playState_Corrupt"); | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | // This code was developed by the jCraft group, as JOrbisPlayer.java, slightly | ||
162 | // modified by jOggPlayer developer and adapted by JavaZOOM to suit the JavaSound | ||
163 | // SPI. Then further modified by Tom Kimpton to correctly play ogg files that | ||
164 | // would hang the player. | ||
165 | switch(playState) | ||
166 | { | ||
167 | case playState_NeedHeaders: | ||
168 | try | ||
169 | { | ||
170 | // Headers (+ Comments). | ||
171 | readHeaders(); | ||
172 | } | ||
173 | catch(IOException ioe) | ||
174 | { | ||
175 | playState = playState_Corrupt; | ||
176 | return; | ||
177 | } | ||
178 | playState = playState_ReadData; | ||
179 | break; | ||
180 | |||
181 | case playState_ReadData: | ||
182 | int result; | ||
183 | index = oggSyncState_.buffer(bufferSize_); | ||
184 | buffer = oggSyncState_.data; | ||
185 | bytes = readFromStream(buffer, index, bufferSize_); | ||
186 | if(TDebug.TraceAudioConverter) TDebug.out("More data : " + bytes); | ||
187 | if(bytes == -1) | ||
188 | { | ||
189 | playState = playState_Done; | ||
190 | if(TDebug.TraceAudioConverter) TDebug.out("Ogg Stream empty. Settings playState to playState_Done."); | ||
191 | break; | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | oggSyncState_.wrote(bytes); | ||
196 | if(bytes == 0) | ||
197 | { | ||
198 | if((oggPage_.eos() != 0) || (oggStreamState_.e_o_s != 0) || (oggPacket_.e_o_s != 0)) | ||
199 | { | ||
200 | if(TDebug.TraceAudioConverter) TDebug.out("oggSyncState wrote 0 bytes: settings playState to playState_Done."); | ||
201 | playState = playState_Done; | ||
202 | } | ||
203 | if(TDebug.TraceAudioConverter) TDebug.out("oggSyncState wrote 0 bytes: but stream not yet empty."); | ||
204 | break; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | result = oggSyncState_.pageout(oggPage_); | ||
209 | if(result == 0) | ||
210 | { | ||
211 | if(TDebug.TraceAudioConverter) TDebug.out("Setting playState to playState_ReadData."); | ||
212 | playState = playState_ReadData; | ||
213 | break; | ||
214 | } // need more data | ||
215 | if(result == -1) | ||
216 | { // missing or corrupt data at this page position | ||
217 | if(TDebug.TraceAudioConverter) TDebug.out("Corrupt or missing data in bitstream; setting playState to playState_ReadData"); | ||
218 | playState = playState_ReadData; | ||
219 | break; | ||
220 | } | ||
221 | |||
222 | oggStreamState_.pagein(oggPage_); | ||
223 | |||
224 | if(TDebug.TraceAudioConverter) TDebug.out("Setting playState to playState_WriteData."); | ||
225 | playState = playState_WriteData; | ||
226 | break; | ||
227 | |||
228 | case playState_WriteData: | ||
229 | // Decoding ! | ||
230 | if(TDebug.TraceAudioConverter) TDebug.out("Decoding"); | ||
231 | while(true) | ||
232 | { | ||
233 | result = oggStreamState_.packetout(oggPacket_); | ||
234 | if(result == 0) | ||
235 | { | ||
236 | if(TDebug.TraceAudioConverter) TDebug.out("Packetout returned 0, going to read state."); | ||
237 | playState = playState_ReadData; | ||
238 | break; | ||
239 | } // need more data | ||
240 | else if(result == -1) | ||
241 | { | ||
242 | // missing or corrupt data at this page position | ||
243 | // no reason to complain; already complained above | ||
244 | if(TDebug.TraceAudioConverter) TDebug.out("Corrupt or missing data in packetout bitstream; going to read state..."); | ||
245 | // playState = playState_ReadData; | ||
246 | // break; | ||
247 | continue; | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | // we have a packet. Decode it | ||
252 | if(vorbisBlock.synthesis(oggPacket_) == 0) | ||
253 | { // test for success! | ||
254 | vorbisDspState.synthesis_blockin(vorbisBlock); | ||
255 | } | ||
256 | else | ||
257 | { | ||
258 | //if(TDebug.TraceAudioConverter) TDebug.out("vorbisBlock.synthesis() returned !0, going to read state"); | ||
259 | if(TDebug.TraceAudioConverter) TDebug.out("VorbisBlock.synthesis() returned !0, continuing."); | ||
260 | continue; | ||
261 | } | ||
262 | |||
263 | outputSamples(); | ||
264 | if(playState == playState_BufferFull) | ||
265 | return; | ||
266 | |||
267 | } // else result != -1 | ||
268 | } // while(true) | ||
269 | if(oggPage_.eos() != 0) | ||
270 | { | ||
271 | if(TDebug.TraceAudioConverter) TDebug.out("Settings playState to playState_Done."); | ||
272 | playState = playState_Done; | ||
273 | } | ||
274 | break; | ||
275 | case playState_BufferFull: | ||
276 | continueFromBufferFull(); | ||
277 | break; | ||
278 | |||
279 | case playState_Corrupt: | ||
280 | if(TDebug.TraceAudioConverter) TDebug.out("Corrupt Song."); | ||
281 | // drop through to playState_Done... | ||
282 | case playState_Done: | ||
283 | oggStreamState_.clear(); | ||
284 | vorbisBlock.clear(); | ||
285 | vorbisDspState.clear(); | ||
286 | vorbisInfo.clear(); | ||
287 | oggSyncState_.clear(); | ||
288 | if(TDebug.TraceAudioConverter) TDebug.out("Done Song."); | ||
289 | try | ||
290 | { | ||
291 | if(oggBitStream_ != null) | ||
292 | { | ||
293 | oggBitStream_.close(); | ||
294 | } | ||
295 | getCircularBuffer().close(); | ||
296 | } | ||
297 | catch(Exception e) | ||
298 | { | ||
299 | if(TDebug.TraceAudioConverter) TDebug.out(e.getMessage()); | ||
300 | } | ||
301 | break; | ||
302 | } // switch | ||
303 | } | ||
304 | |||
305 | /** | ||
306 | * This routine was extracted so that when the output buffer fills up, | ||
307 | * we can break out of the loop, let the music channel drain, then | ||
308 | * continue from where we were. | ||
309 | */ | ||
310 | private void outputSamples() | ||
311 | { | ||
312 | int samples; | ||
313 | while((samples = vorbisDspState.synthesis_pcmout(_pcmf, _index)) > 0) | ||
314 | { | ||
315 | float[][] pcmf = _pcmf[0]; | ||
316 | bout = (samples < convsize ? samples : convsize); | ||
317 | double fVal = 0.0; | ||
318 | // convert doubles to 16 bit signed ints (host order) and | ||
319 | // interleave | ||
320 | for(i = 0; i < vorbisInfo.channels; i++) | ||
321 | { | ||
322 | int pointer = i * 2; | ||
323 | //int ptr=i; | ||
324 | int mono = _index[i]; | ||
325 | for(int j = 0; j < bout; j++) | ||
326 | { | ||
327 | fVal = pcmf[i][mono + j] * 32767.; | ||
328 | int val = (int) (fVal); | ||
329 | if(val > 32767) | ||
330 | { | ||
331 | val = 32767; | ||
332 | } | ||
333 | if(val < -32768) | ||
334 | { | ||
335 | val = -32768; | ||
336 | } | ||
337 | if(val < 0) | ||
338 | { | ||
339 | val = val | 0x8000; | ||
340 | } | ||
341 | convbuffer[pointer] = (byte) (val); | ||
342 | convbuffer[pointer + 1] = (byte) (val >>> 8); | ||
343 | pointer += 2 * (vorbisInfo.channels); | ||
344 | } | ||
345 | } | ||
346 | if(TDebug.TraceAudioConverter) TDebug.out("about to write: " + 2 * vorbisInfo.channels * bout); | ||
347 | if(getCircularBuffer().availableWrite() < 2 * vorbisInfo.channels * bout) | ||
348 | { | ||
349 | if(TDebug.TraceAudioConverter) TDebug.out("Too much data in this data packet, better return, let the channel drain, and try again..."); | ||
350 | playState = playState_BufferFull; | ||
351 | return; | ||
352 | } | ||
353 | getCircularBuffer().write(convbuffer, 0, 2 * vorbisInfo.channels * bout); | ||
354 | if(bytes < bufferSize_) | ||
355 | if(TDebug.TraceAudioConverter) TDebug.out("Finished with final buffer of music?"); | ||
356 | if(vorbisDspState.synthesis_read(bout) != 0) | ||
357 | { | ||
358 | if(TDebug.TraceAudioConverter) TDebug.out("VorbisDspState.synthesis_read returned -1."); | ||
359 | } | ||
360 | } // while(samples...) | ||
361 | playState = playState_ReadData; | ||
362 | } | ||
363 | |||
364 | private void continueFromBufferFull() | ||
365 | { | ||
366 | if(getCircularBuffer().availableWrite() < 2 * vorbisInfo.channels * bout) | ||
367 | { | ||
368 | if(TDebug.TraceAudioConverter) TDebug.out("Too much data in this data packet, better return, let the channel drain, and try again..."); | ||
369 | // Don't change play state. | ||
370 | return; | ||
371 | } | ||
372 | getCircularBuffer().write(convbuffer, 0, 2 * vorbisInfo.channels * bout); | ||
373 | // Don't change play state. Let outputSamples change play state, if necessary. | ||
374 | outputSamples(); | ||
375 | } | ||
376 | /** | ||
377 | * Reads headers and comments. | ||
378 | */ | ||
379 | private void readHeaders() throws IOException | ||
380 | { | ||
381 | if(TDebug.TraceAudioConverter) TDebug.out("readHeaders("); | ||
382 | index = oggSyncState_.buffer(bufferSize_); | ||
383 | buffer = oggSyncState_.data; | ||
384 | bytes = readFromStream(buffer, index, bufferSize_); | ||
385 | if(bytes == -1) | ||
386 | { | ||
387 | if(TDebug.TraceAudioConverter) TDebug.out("Cannot get any data from selected Ogg bitstream."); | ||
388 | throw new IOException("Cannot get any data from selected Ogg bitstream."); | ||
389 | } | ||
390 | oggSyncState_.wrote(bytes); | ||
391 | if(oggSyncState_.pageout(oggPage_) != 1) | ||
392 | { | ||
393 | if(bytes < bufferSize_) | ||
394 | { | ||
395 | throw new IOException("EOF"); | ||
396 | } | ||
397 | if(TDebug.TraceAudioConverter) TDebug.out("Input does not appear to be an Ogg bitstream."); | ||
398 | throw new IOException("Input does not appear to be an Ogg bitstream."); | ||
399 | } | ||
400 | oggStreamState_.init(oggPage_.serialno()); | ||
401 | vorbisInfo.init(); | ||
402 | vorbisComment.init(); | ||
403 | if(oggStreamState_.pagein(oggPage_) < 0) | ||
404 | { | ||
405 | // error; stream version mismatch perhaps | ||
406 | if(TDebug.TraceAudioConverter) TDebug.out("Error reading first page of Ogg bitstream data."); | ||
407 | throw new IOException("Error reading first page of Ogg bitstream data."); | ||
408 | } | ||
409 | if(oggStreamState_.packetout(oggPacket_) != 1) | ||
410 | { | ||
411 | // no page? must not be vorbis | ||
412 | if(TDebug.TraceAudioConverter) TDebug.out("Error reading initial header packet."); | ||
413 | throw new IOException("Error reading initial header packet."); | ||
414 | } | ||
415 | if(vorbisInfo.synthesis_headerin(vorbisComment, oggPacket_) < 0) | ||
416 | { | ||
417 | // error case; not a vorbis header | ||
418 | if(TDebug.TraceAudioConverter) TDebug.out("This Ogg bitstream does not contain Vorbis audio data."); | ||
419 | throw new IOException("This Ogg bitstream does not contain Vorbis audio data."); | ||
420 | } | ||
421 | //int i = 0; | ||
422 | i = 0; | ||
423 | while(i < 2) | ||
424 | { | ||
425 | while(i < 2) | ||
426 | { | ||
427 | int result = oggSyncState_.pageout(oggPage_); | ||
428 | if(result == 0) | ||
429 | { | ||
430 | break; | ||
431 | } // Need more data | ||
432 | if(result == 1) | ||
433 | { | ||
434 | oggStreamState_.pagein(oggPage_); | ||
435 | while(i < 2) | ||
436 | { | ||
437 | result = oggStreamState_.packetout(oggPacket_); | ||
438 | if(result == 0) | ||
439 | { | ||
440 | break; | ||
441 | } | ||
442 | if(result == -1) | ||
443 | { | ||
444 | if(TDebug.TraceAudioConverter) TDebug.out("Corrupt secondary header. Exiting."); | ||
445 | throw new IOException("Corrupt secondary header. Exiting."); | ||
446 | } | ||
447 | vorbisInfo.synthesis_headerin(vorbisComment, oggPacket_); | ||
448 | i++; | ||
449 | } | ||
450 | } | ||
451 | } | ||
452 | index = oggSyncState_.buffer(bufferSize_); | ||
453 | buffer = oggSyncState_.data; | ||
454 | bytes = readFromStream(buffer, index, bufferSize_); | ||
455 | if(bytes == -1) | ||
456 | { | ||
457 | break; | ||
458 | } | ||
459 | if(bytes == 0 && i < 2) | ||
460 | { | ||
461 | if(TDebug.TraceAudioConverter) TDebug.out("End of file before finding all Vorbis headers!"); | ||
462 | throw new IOException("End of file before finding all Vorbis headers!"); | ||
463 | } | ||
464 | oggSyncState_.wrote(bytes); | ||
465 | } | ||
466 | |||
467 | byte[][] ptr = vorbisComment.user_comments; | ||
468 | String currComment = ""; | ||
469 | |||
470 | for(int j = 0; j < ptr.length; j++) | ||
471 | { | ||
472 | if(ptr[j] == null) | ||
473 | { | ||
474 | break; | ||
475 | } | ||
476 | currComment = (new String(ptr[j], 0, ptr[j].length - 1)).trim(); | ||
477 | if(TDebug.TraceAudioConverter) TDebug.out("Comment: " + currComment); | ||
478 | } | ||
479 | convsize = bufferSize_ / vorbisInfo.channels; | ||
480 | vorbisDspState.synthesis_init(vorbisInfo); | ||
481 | vorbisBlock.init(vorbisDspState); | ||
482 | _pcmf = new float[1][][]; | ||
483 | _index = new int[vorbisInfo.channels]; | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * Reads from the oggBitStream_ a specified number of Bytes(bufferSize_) worth | ||
488 | * starting at index and puts them in the specified buffer[]. | ||
489 | * | ||
490 | * @param buffer | ||
491 | * @param index | ||
492 | * @param bufferSize_ | ||
493 | * @return the number of bytes read or -1 if error. | ||
494 | */ | ||
495 | private int readFromStream(byte[] buffer, int index, int bufferSize_) | ||
496 | { | ||
497 | int bytes = 0; | ||
498 | try | ||
499 | { | ||
500 | bytes = oggBitStream_.read(buffer, index, bufferSize_); | ||
501 | } | ||
502 | catch(Exception e) | ||
503 | { | ||
504 | if(TDebug.TraceAudioConverter) TDebug.out("Cannot Read Selected Song"); | ||
505 | bytes = -1; | ||
506 | } | ||
507 | currentBytes = currentBytes + bytes; | ||
508 | return bytes; | ||
509 | } | ||
510 | |||
511 | /** | ||
512 | * Close the stream. | ||
513 | */ | ||
514 | public void close() throws IOException | ||
515 | { | ||
516 | super.close(); | ||
517 | oggBitStream_.close(); | ||
518 | } | ||
519 | } | ||
diff --git a/songdbj/javazoom/spi/vorbis/sampled/convert/VorbisFormatConversionProvider.java b/songdbj/javazoom/spi/vorbis/sampled/convert/VorbisFormatConversionProvider.java deleted file mode 100644 index d1321f2590..0000000000 --- a/songdbj/javazoom/spi/vorbis/sampled/convert/VorbisFormatConversionProvider.java +++ /dev/null | |||
@@ -1,244 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisFormatConversionProvider. | ||
3 | * | ||
4 | * JavaZOOM : vorbisspi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Library General Public License as published | ||
9 | * by the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Library General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Library General Public | ||
18 | * License along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | package javazoom.spi.vorbis.sampled.convert; | ||
24 | |||
25 | import java.util.Arrays; | ||
26 | import javazoom.spi.vorbis.sampled.file.VorbisEncoding; | ||
27 | import javax.sound.sampled.AudioFormat; | ||
28 | import javax.sound.sampled.AudioInputStream; | ||
29 | |||
30 | import org.tritonus.share.sampled.convert.TMatrixFormatConversionProvider; | ||
31 | |||
32 | /** | ||
33 | * ConversionProvider for VORBIS files. | ||
34 | */ | ||
35 | public class VorbisFormatConversionProvider extends TMatrixFormatConversionProvider | ||
36 | { | ||
37 | private static final AudioFormat[] INPUT_FORMATS = | ||
38 | { | ||
39 | new AudioFormat(VorbisEncoding.VORBISENC, 32000.0F, -1, 1, -1, -1, false), // 0 | ||
40 | new AudioFormat(VorbisEncoding.VORBISENC, 32000.0F, -1, 2, -1, -1, false), // 1 | ||
41 | new AudioFormat(VorbisEncoding.VORBISENC, 44100.0F, -1, 1, -1, -1, false), // 2 | ||
42 | new AudioFormat(VorbisEncoding.VORBISENC, 44100.0F, -1, 2, -1, -1, false), // 3 | ||
43 | new AudioFormat(VorbisEncoding.VORBISENC, 48000.0F, -1, 1, -1, -1, false), // 4 | ||
44 | new AudioFormat(VorbisEncoding.VORBISENC, 48000.0F, -1, 2, -1, -1, false), // 5 | ||
45 | |||
46 | new AudioFormat(VorbisEncoding.VORBISENC, 16000.0F, -1, 1, -1, -1, false), // 18 | ||
47 | new AudioFormat(VorbisEncoding.VORBISENC, 16000.0F, -1, 2, -1, -1, false), // 19 | ||
48 | new AudioFormat(VorbisEncoding.VORBISENC, 22050.0F, -1, 1, -1, -1, false), // 20 | ||
49 | new AudioFormat(VorbisEncoding.VORBISENC, 22050.0F, -1, 2, -1, -1, false), // 21 | ||
50 | new AudioFormat(VorbisEncoding.VORBISENC, 24000.0F, -1, 1, -1, -1, false), // 22 | ||
51 | new AudioFormat(VorbisEncoding.VORBISENC, 24000.0F, -1, 2, -1, -1, false), // 23 | ||
52 | |||
53 | new AudioFormat(VorbisEncoding.VORBISENC, 8000.0F, -1, 1, -1, -1, false), // 36 | ||
54 | new AudioFormat(VorbisEncoding.VORBISENC, 8000.0F, -1, 2, -1, -1, false), // 37 | ||
55 | new AudioFormat(VorbisEncoding.VORBISENC, 11025.0F, -1, 1, -1, -1, false), // 38 | ||
56 | new AudioFormat(VorbisEncoding.VORBISENC, 11025.0F, -1, 2, -1, -1, false), // 39 | ||
57 | new AudioFormat(VorbisEncoding.VORBISENC, 12000.0F, -1, 1, -1, -1, false), // 40 | ||
58 | new AudioFormat(VorbisEncoding.VORBISENC, 12000.0F, -1, 2, -1, -1, false), // 41 | ||
59 | }; | ||
60 | |||
61 | private static final AudioFormat[] OUTPUT_FORMATS = | ||
62 | { | ||
63 | new AudioFormat(8000.0F, 16, 1, true, false), // 0 | ||
64 | new AudioFormat(8000.0F, 16, 1, true, true), // 1 | ||
65 | new AudioFormat(8000.0F, 16, 2, true, false), // 2 | ||
66 | new AudioFormat(8000.0F, 16, 2, true, true), // 3 | ||
67 | /* 24 and 32 bit not yet possible | ||
68 | new AudioFormat(8000.0F, 24, 1, true, false), | ||
69 | new AudioFormat(8000.0F, 24, 1, true, true), | ||
70 | new AudioFormat(8000.0F, 24, 2, true, false), | ||
71 | new AudioFormat(8000.0F, 24, 2, true, true), | ||
72 | new AudioFormat(8000.0F, 32, 1, true, false), | ||
73 | new AudioFormat(8000.0F, 32, 1, true, true), | ||
74 | new AudioFormat(8000.0F, 32, 2, true, false), | ||
75 | new AudioFormat(8000.0F, 32, 2, true, true), | ||
76 | */ | ||
77 | new AudioFormat(11025.0F, 16, 1, true, false), // 4 | ||
78 | new AudioFormat(11025.0F, 16, 1, true, true), // 5 | ||
79 | new AudioFormat(11025.0F, 16, 2, true, false), // 6 | ||
80 | new AudioFormat(11025.0F, 16, 2, true, true), // 7 | ||
81 | /* 24 and 32 bit not yet possible | ||
82 | new AudioFormat(11025.0F, 24, 1, true, false), | ||
83 | new AudioFormat(11025.0F, 24, 1, true, true), | ||
84 | new AudioFormat(11025.0F, 24, 2, true, false), | ||
85 | new AudioFormat(11025.0F, 24, 2, true, true), | ||
86 | new AudioFormat(11025.0F, 32, 1, true, false), | ||
87 | new AudioFormat(11025.0F, 32, 1, true, true), | ||
88 | new AudioFormat(11025.0F, 32, 2, true, false), | ||
89 | new AudioFormat(11025.0F, 32, 2, true, true), | ||
90 | */ | ||
91 | new AudioFormat(12000.0F, 16, 1, true, false), // 8 | ||
92 | new AudioFormat(12000.0F, 16, 1, true, true), // 9 | ||
93 | new AudioFormat(12000.0F, 16, 2, true, false), // 10 | ||
94 | new AudioFormat(12000.0F, 16, 2, true, true), // 11 | ||
95 | /* 24 and 32 bit not yet possible | ||
96 | new AudioFormat(12000.0F, 24, 1, true, false), | ||
97 | new AudioFormat(12000.0F, 24, 1, true, true), | ||
98 | new AudioFormat(12000.0F, 24, 2, true, false), | ||
99 | new AudioFormat(12000.0F, 24, 2, true, true), | ||
100 | new AudioFormat(12000.0F, 32, 1, true, false), | ||
101 | new AudioFormat(12000.0F, 32, 1, true, true), | ||
102 | new AudioFormat(12000.0F, 32, 2, true, false), | ||
103 | new AudioFormat(12000.0F, 32, 2, true, true), | ||
104 | */ | ||
105 | new AudioFormat(16000.0F, 16, 1, true, false), // 12 | ||
106 | new AudioFormat(16000.0F, 16, 1, true, true), // 13 | ||
107 | new AudioFormat(16000.0F, 16, 2, true, false), // 14 | ||
108 | new AudioFormat(16000.0F, 16, 2, true, true), // 15 | ||
109 | /* 24 and 32 bit not yet possible | ||
110 | new AudioFormat(16000.0F, 24, 1, true, false), | ||
111 | new AudioFormat(16000.0F, 24, 1, true, true), | ||
112 | new AudioFormat(16000.0F, 24, 2, true, false), | ||
113 | new AudioFormat(16000.0F, 24, 2, true, true), | ||
114 | new AudioFormat(16000.0F, 32, 1, true, false), | ||
115 | new AudioFormat(16000.0F, 32, 1, true, true), | ||
116 | new AudioFormat(16000.0F, 32, 2, true, false), | ||
117 | new AudioFormat(16000.0F, 32, 2, true, true), | ||
118 | */ | ||
119 | new AudioFormat(22050.0F, 16, 1, true, false), // 16 | ||
120 | new AudioFormat(22050.0F, 16, 1, true, true), // 17 | ||
121 | new AudioFormat(22050.0F, 16, 2, true, false), // 18 | ||
122 | new AudioFormat(22050.0F, 16, 2, true, true), // 19 | ||
123 | /* 24 and 32 bit not yet possible | ||
124 | new AudioFormat(22050.0F, 24, 1, true, false), | ||
125 | new AudioFormat(22050.0F, 24, 1, true, true), | ||
126 | new AudioFormat(22050.0F, 24, 2, true, false), | ||
127 | new AudioFormat(22050.0F, 24, 2, true, true), | ||
128 | new AudioFormat(22050.0F, 32, 1, true, false), | ||
129 | new AudioFormat(22050.0F, 32, 1, true, true), | ||
130 | new AudioFormat(22050.0F, 32, 2, true, false), | ||
131 | new AudioFormat(22050.0F, 32, 2, true, true), | ||
132 | */ | ||
133 | new AudioFormat(24000.0F, 16, 1, true, false), // 20 | ||
134 | new AudioFormat(24000.0F, 16, 1, true, true), // 21 | ||
135 | new AudioFormat(24000.0F, 16, 2, true, false), // 22 | ||
136 | new AudioFormat(24000.0F, 16, 2, true, true), // 23 | ||
137 | /* 24 and 32 bit not yet possible | ||
138 | new AudioFormat(24000.0F, 24, 1, true, false), | ||
139 | new AudioFormat(24000.0F, 24, 1, true, true), | ||
140 | new AudioFormat(24000.0F, 24, 2, true, false), | ||
141 | new AudioFormat(24000.0F, 24, 2, true, true), | ||
142 | new AudioFormat(24000.0F, 32, 1, true, false), | ||
143 | new AudioFormat(24000.0F, 32, 1, true, true), | ||
144 | new AudioFormat(24000.0F, 32, 2, true, false), | ||
145 | new AudioFormat(24000.0F, 32, 2, true, true), | ||
146 | */ | ||
147 | new AudioFormat(32000.0F, 16, 1, true, false), // 24 | ||
148 | new AudioFormat(32000.0F, 16, 1, true, true), // 25 | ||
149 | new AudioFormat(32000.0F, 16, 2, true, false), // 26 | ||
150 | new AudioFormat(32000.0F, 16, 2, true, true), // 27 | ||
151 | /* 24 and 32 bit not yet possible | ||
152 | new AudioFormat(32000.0F, 24, 1, true, false), | ||
153 | new AudioFormat(32000.0F, 24, 1, true, true), | ||
154 | new AudioFormat(32000.0F, 24, 2, true, false), | ||
155 | new AudioFormat(32000.0F, 24, 2, true, true), | ||
156 | new AudioFormat(32000.0F, 32, 1, true, false), | ||
157 | new AudioFormat(32000.0F, 32, 1, true, true), | ||
158 | new AudioFormat(32000.0F, 32, 2, true, false), | ||
159 | new AudioFormat(32000.0F, 32, 2, true, true), | ||
160 | */ | ||
161 | new AudioFormat(44100.0F, 16, 1, true, false), // 28 | ||
162 | new AudioFormat(44100.0F, 16, 1, true, true), // 29 | ||
163 | new AudioFormat(44100.0F, 16, 2, true, false), // 30 | ||
164 | new AudioFormat(44100.0F, 16, 2, true, true), // 31 | ||
165 | /* 24 and 32 bit not yet possible | ||
166 | new AudioFormat(44100.0F, 24, 1, true, false), | ||
167 | new AudioFormat(44100.0F, 24, 1, true, true), | ||
168 | new AudioFormat(44100.0F, 24, 2, true, false), | ||
169 | new AudioFormat(44100.0F, 24, 2, true, true), | ||
170 | new AudioFormat(44100.0F, 32, 1, true, false), | ||
171 | new AudioFormat(44100.0F, 32, 1, true, true), | ||
172 | new AudioFormat(44100.0F, 32, 2, true, false), | ||
173 | new AudioFormat(44100.0F, 32, 2, true, true), | ||
174 | */ | ||
175 | new AudioFormat(48000.0F, 16, 1, true, false), // 32 | ||
176 | new AudioFormat(48000.0F, 16, 1, true, true), // 33 | ||
177 | new AudioFormat(48000.0F, 16, 2, true, false), // 34 | ||
178 | new AudioFormat(48000.0F, 16, 2, true, true), // 35 | ||
179 | /* 24 and 32 bit not yet possible | ||
180 | new AudioFormat(48000.0F, 24, 1, true, false), | ||
181 | new AudioFormat(48000.0F, 24, 1, true, true), | ||
182 | new AudioFormat(48000.0F, 24, 2, true, false), | ||
183 | new AudioFormat(48000.0F, 24, 2, true, true), | ||
184 | new AudioFormat(48000.0F, 32, 1, true, false), | ||
185 | new AudioFormat(48000.0F, 32, 1, true, true), | ||
186 | new AudioFormat(48000.0F, 32, 2, true, false), | ||
187 | new AudioFormat(48000.0F, 32, 2, true, true), | ||
188 | */ | ||
189 | }; | ||
190 | |||
191 | private static final boolean t = true; | ||
192 | private static final boolean f = false; | ||
193 | |||
194 | /* | ||
195 | * One row for each source format. | ||
196 | */ | ||
197 | private static final boolean[][] CONVERSIONS = | ||
198 | { | ||
199 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,t,t,f,f,f,f, f,f,f,f,f,f}, // 0 | ||
200 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,t,t,f,f, f,f,f,f,f,f}, // 1 | ||
201 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,t,t, f,f,f,f,f,f}, // 2 | ||
202 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, t,t,f,f,f,f}, // 3 | ||
203 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,t,t,f,f}, // 4 | ||
204 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,t,t}, // 5 | ||
205 | |||
206 | {f,f,f,f,f,f,f,f,f,f, f,f,t,t,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 18 | ||
207 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,t,t,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 19 | ||
208 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,t,t,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 20 | ||
209 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,t,t, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 21 | ||
210 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, t,t,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 22 | ||
211 | {f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,t,t,f,f,f,f,f,f, f,f,f,f,f,f}, // 23 | ||
212 | |||
213 | {t,t,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 36 | ||
214 | {f,f,t,t,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 37 | ||
215 | {f,f,f,f,t,t,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 38 | ||
216 | {f,f,f,f,f,f,t,t,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 39 | ||
217 | {f,f,f,f,f,f,f,f,t,t, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 40 | ||
218 | {f,f,f,f,f,f,f,f,f,f, t,t,f,f,f,f,f,f,f,f, f,f,f,f,f,f,f,f,f,f, f,f,f,f,f,f}, // 41 | ||
219 | |||
220 | }; | ||
221 | |||
222 | /** | ||
223 | * Constructor. | ||
224 | */ | ||
225 | public VorbisFormatConversionProvider() | ||
226 | { | ||
227 | super(Arrays.asList(INPUT_FORMATS), Arrays.asList(OUTPUT_FORMATS), CONVERSIONS); | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * Returns converted AudioInputStream. | ||
232 | */ | ||
233 | public AudioInputStream getAudioInputStream(AudioFormat targetFormat, AudioInputStream audioInputStream) | ||
234 | { | ||
235 | if (isConversionSupported(targetFormat, audioInputStream.getFormat())) | ||
236 | { | ||
237 | return new DecodedVorbisAudioInputStream(targetFormat, audioInputStream); | ||
238 | } | ||
239 | else | ||
240 | { | ||
241 | throw new IllegalArgumentException("conversion not supported"); | ||
242 | } | ||
243 | } | ||
244 | } | ||
diff --git a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFileFormat.java b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFileFormat.java deleted file mode 100644 index 28b7c92a2a..0000000000 --- a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFileFormat.java +++ /dev/null | |||
@@ -1,85 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisAudioFileFormat. | ||
3 | * | ||
4 | * JavaZOOM : vorbisspi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Library General Public License as published | ||
9 | * by the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Library General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Library General Public | ||
18 | * License along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | package javazoom.spi.vorbis.sampled.file; | ||
24 | |||
25 | import java.util.Map; | ||
26 | |||
27 | import javax.sound.sampled.AudioFormat; | ||
28 | |||
29 | import org.tritonus.share.sampled.file.TAudioFileFormat; | ||
30 | |||
31 | /** | ||
32 | * @author JavaZOOM | ||
33 | */ | ||
34 | public class VorbisAudioFileFormat extends TAudioFileFormat | ||
35 | { | ||
36 | /** | ||
37 | * Contructor. | ||
38 | * @param type | ||
39 | * @param audioFormat | ||
40 | * @param nLengthInFrames | ||
41 | * @param nLengthInBytes | ||
42 | */ | ||
43 | public VorbisAudioFileFormat(Type type, AudioFormat audioFormat, int nLengthInFrames, int nLengthInBytes, Map properties) | ||
44 | { | ||
45 | super(type, audioFormat, nLengthInFrames, nLengthInBytes, properties); | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Ogg Vorbis audio file format parameters. | ||
50 | * Some parameters might be unavailable. So availability test is required before reading any parameter. | ||
51 | * | ||
52 | * <br>AudioFileFormat parameters. | ||
53 | * <ul> | ||
54 | * <li><b>duration</b> [Long], duration in microseconds. | ||
55 | * <li><b>title</b> [String], Title of the stream. | ||
56 | * <li><b>author</b> [String], Name of the artist of the stream. | ||
57 | * <li><b>album</b> [String], Name of the album of the stream. | ||
58 | * <li><b>date</b> [String], The date (year) of the recording or release of the stream. | ||
59 | * <li><b>copyright</b> [String], Copyright message of the stream. | ||
60 | * <li><b>comment</b> [String], Comment of the stream. | ||
61 | * </ul> | ||
62 | * <br>Ogg Vorbis parameters. | ||
63 | * <ul> | ||
64 | * <li><b>ogg.length.bytes</b> [Integer], length in bytes. | ||
65 | * <li><b>ogg.bitrate.min.bps</b> [Integer], minimum bitrate. | ||
66 | * <li><b>ogg.bitrate.nominal.bps</b> [Integer], nominal bitrate. | ||
67 | * <li><b>ogg.bitrate.max.bps</b> [Integer], maximum bitrate. | ||
68 | * <li><b>ogg.channels</b> [Integer], number of channels 1 : mono, 2 : stereo. | ||
69 | * <li><b>ogg.frequency.hz</b> [Integer], sampling rate in hz. | ||
70 | * <li><b>ogg.version</b> [Integer], version. | ||
71 | * <li><b>ogg.serial</b> [Integer], serial number. | ||
72 | * <li><b>ogg.comment.track</b> [String], track number. | ||
73 | * <li><b>ogg.comment.genre</b> [String], genre field. | ||
74 | * <li><b>ogg.comment.encodedby</b> [String], encoded by field. | ||
75 | * <li><b>ogg.comment.ext</b> [String], extended comments (indexed): | ||
76 | * <br>For instance : | ||
77 | * <br>ogg.comment.ext.1=Something | ||
78 | * <br>ogg.comment.ext.2=Another comment | ||
79 | * </ul> | ||
80 | */ | ||
81 | public Map properties() | ||
82 | { | ||
83 | return super.properties(); | ||
84 | } | ||
85 | } | ||
diff --git a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFileReader.java b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFileReader.java deleted file mode 100644 index 40bc9cadee..0000000000 --- a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFileReader.java +++ /dev/null | |||
@@ -1,502 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisAudioFileReader. | ||
3 | * | ||
4 | * JavaZOOM : vorbisspi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Library General Public License as published | ||
9 | * by the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Library General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Library General Public | ||
18 | * License along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | package javazoom.spi.vorbis.sampled.file; | ||
24 | |||
25 | import java.io.BufferedInputStream; | ||
26 | import java.io.File; | ||
27 | import java.io.FileInputStream; | ||
28 | import java.io.IOException; | ||
29 | import java.io.InputStream; | ||
30 | import java.net.URL; | ||
31 | import java.util.HashMap; | ||
32 | import java.util.StringTokenizer; | ||
33 | |||
34 | import javax.sound.sampled.AudioFileFormat; | ||
35 | import javax.sound.sampled.AudioFormat; | ||
36 | import javax.sound.sampled.AudioInputStream; | ||
37 | import javax.sound.sampled.AudioSystem; | ||
38 | import javax.sound.sampled.UnsupportedAudioFileException; | ||
39 | |||
40 | import org.tritonus.share.TDebug; | ||
41 | import org.tritonus.share.sampled.file.TAudioFileReader; | ||
42 | |||
43 | import com.jcraft.jogg.Packet; | ||
44 | import com.jcraft.jogg.Page; | ||
45 | import com.jcraft.jogg.StreamState; | ||
46 | import com.jcraft.jogg.SyncState; | ||
47 | import com.jcraft.jorbis.Block; | ||
48 | import com.jcraft.jorbis.Comment; | ||
49 | import com.jcraft.jorbis.DspState; | ||
50 | import com.jcraft.jorbis.Info; | ||
51 | import com.jcraft.jorbis.JOrbisException; | ||
52 | import com.jcraft.jorbis.VorbisFile; | ||
53 | |||
54 | /** | ||
55 | * This class implements the AudioFileReader class and provides an | ||
56 | * Ogg Vorbis file reader for use with the Java Sound Service Provider Interface. | ||
57 | */ | ||
58 | public class VorbisAudioFileReader extends TAudioFileReader | ||
59 | { | ||
60 | private SyncState oggSyncState_ = null; | ||
61 | private StreamState oggStreamState_ = null; | ||
62 | private Page oggPage_ = null; | ||
63 | private Packet oggPacket_ = null; | ||
64 | private Info vorbisInfo = null; | ||
65 | private Comment vorbisComment = null; | ||
66 | private DspState vorbisDspState = null; | ||
67 | private Block vorbisBlock = null; | ||
68 | private int bufferMultiple_ = 4; | ||
69 | private int bufferSize_ = bufferMultiple_ * 256 * 2; | ||
70 | private int convsize = bufferSize_ * 2; | ||
71 | private byte[] convbuffer = new byte[convsize]; | ||
72 | private byte[] buffer = null; | ||
73 | private int bytes = 0; | ||
74 | private int rate = 0; | ||
75 | private int channels = 0; | ||
76 | |||
77 | private int index = 0; | ||
78 | private InputStream oggBitStream_ = null; | ||
79 | |||
80 | private static final int INITAL_READ_LENGTH = 64000; | ||
81 | private static final int MARK_LIMIT = INITAL_READ_LENGTH + 1; | ||
82 | |||
83 | public VorbisAudioFileReader() | ||
84 | { | ||
85 | super(MARK_LIMIT, true); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * Return the AudioFileFormat from the given file. | ||
90 | */ | ||
91 | public AudioFileFormat getAudioFileFormat(File file) throws UnsupportedAudioFileException, IOException | ||
92 | { | ||
93 | if (TDebug.TraceAudioFileReader) TDebug.out("getAudioFileFormat(File file)"); | ||
94 | InputStream inputStream = null; | ||
95 | try | ||
96 | { | ||
97 | inputStream = new BufferedInputStream(new FileInputStream(file)); | ||
98 | inputStream.mark(MARK_LIMIT); | ||
99 | AudioFileFormat aff = getAudioFileFormat(inputStream); | ||
100 | inputStream.reset(); | ||
101 | // Get Vorbis file info such as length in seconds. | ||
102 | VorbisFile vf = new VorbisFile(file.getAbsolutePath()); | ||
103 | return getAudioFileFormat(inputStream,(int) file.length(), (int) Math.round((vf.time_total(-1))*1000)); | ||
104 | } | ||
105 | catch (JOrbisException e) | ||
106 | { | ||
107 | throw new IOException(e.getMessage()); | ||
108 | } | ||
109 | finally | ||
110 | { | ||
111 | if (inputStream != null) inputStream.close(); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * Return the AudioFileFormat from the given URL. | ||
117 | */ | ||
118 | public AudioFileFormat getAudioFileFormat(URL url) throws UnsupportedAudioFileException, IOException | ||
119 | { | ||
120 | if (TDebug.TraceAudioFileReader) TDebug.out("getAudioFileFormat(URL url)"); | ||
121 | InputStream inputStream = url.openStream(); | ||
122 | try | ||
123 | { | ||
124 | return getAudioFileFormat(inputStream); | ||
125 | } | ||
126 | finally | ||
127 | { | ||
128 | if (inputStream != null) inputStream.close(); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Return the AudioFileFormat from the given InputStream. | ||
134 | */ | ||
135 | public AudioFileFormat getAudioFileFormat(InputStream inputStream) throws UnsupportedAudioFileException, IOException | ||
136 | { | ||
137 | if (TDebug.TraceAudioFileReader) TDebug.out("getAudioFileFormat(InputStream inputStream)"); | ||
138 | try | ||
139 | { | ||
140 | if (!inputStream.markSupported()) inputStream = new BufferedInputStream(inputStream); | ||
141 | inputStream.mark(MARK_LIMIT); | ||
142 | return getAudioFileFormat(inputStream, AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED); | ||
143 | } | ||
144 | finally | ||
145 | { | ||
146 | inputStream.reset(); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Return the AudioFileFormat from the given InputStream and length in bytes. | ||
152 | */ | ||
153 | public AudioFileFormat getAudioFileFormat(InputStream inputStream, long medialength) throws UnsupportedAudioFileException, IOException | ||
154 | { | ||
155 | return getAudioFileFormat(inputStream, (int) medialength, AudioSystem.NOT_SPECIFIED); | ||
156 | } | ||
157 | |||
158 | |||
159 | /** | ||
160 | * Return the AudioFileFormat from the given InputStream, length in bytes and length in milliseconds. | ||
161 | */ | ||
162 | protected AudioFileFormat getAudioFileFormat(InputStream bitStream, int mediaLength, int totalms) throws UnsupportedAudioFileException, IOException | ||
163 | { | ||
164 | HashMap aff_properties = new HashMap(); | ||
165 | HashMap af_properties = new HashMap(); | ||
166 | if (totalms == AudioSystem.NOT_SPECIFIED) | ||
167 | { | ||
168 | totalms = 0; | ||
169 | } | ||
170 | if (totalms <= 0) | ||
171 | { | ||
172 | totalms = 0; | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | aff_properties.put("duration",new Long(totalms*1000)); | ||
177 | } | ||
178 | oggBitStream_ = bitStream; | ||
179 | init_jorbis(); | ||
180 | index = 0; | ||
181 | try | ||
182 | { | ||
183 | readHeaders(aff_properties, af_properties); | ||
184 | } | ||
185 | catch (IOException ioe) | ||
186 | { | ||
187 | if (TDebug.TraceAudioFileReader) | ||
188 | { | ||
189 | TDebug.out(ioe.getMessage()); | ||
190 | } | ||
191 | throw new UnsupportedAudioFileException(ioe.getMessage()); | ||
192 | } | ||
193 | |||
194 | String dmp = vorbisInfo.toString(); | ||
195 | if (TDebug.TraceAudioFileReader) | ||
196 | { | ||
197 | TDebug.out(dmp); | ||
198 | } | ||
199 | int ind = dmp.lastIndexOf("bitrate:"); | ||
200 | int minbitrate = -1; | ||
201 | int nominalbitrate = -1; | ||
202 | int maxbitrate = -1; | ||
203 | if (ind != -1) | ||
204 | { | ||
205 | dmp = dmp.substring(ind + 8, dmp.length()); | ||
206 | StringTokenizer st = new StringTokenizer(dmp, ","); | ||
207 | if (st.hasMoreTokens()) | ||
208 | { | ||
209 | minbitrate = Integer.parseInt(st.nextToken()); | ||
210 | } | ||
211 | if (st.hasMoreTokens()) | ||
212 | { | ||
213 | nominalbitrate = Integer.parseInt(st.nextToken()); | ||
214 | } | ||
215 | if (st.hasMoreTokens()) | ||
216 | { | ||
217 | maxbitrate = Integer.parseInt(st.nextToken()); | ||
218 | } | ||
219 | } | ||
220 | if (nominalbitrate > 0) af_properties.put("bitrate",new Integer(nominalbitrate)); | ||
221 | af_properties.put("vbr",new Boolean(true)); | ||
222 | |||
223 | if (minbitrate > 0) aff_properties.put("ogg.bitrate.min.bps",new Integer(minbitrate)); | ||
224 | if (maxbitrate > 0) aff_properties.put("ogg.bitrate.max.bps",new Integer(maxbitrate)); | ||
225 | if (nominalbitrate > 0) aff_properties.put("ogg.bitrate.nominal.bps",new Integer(nominalbitrate)); | ||
226 | if (vorbisInfo.channels > 0) aff_properties.put("ogg.channels",new Integer(vorbisInfo.channels)); | ||
227 | if (vorbisInfo.rate > 0) aff_properties.put("ogg.frequency.hz",new Integer(vorbisInfo.rate)); | ||
228 | if (mediaLength > 0) aff_properties.put("ogg.length.bytes",new Integer(mediaLength)); | ||
229 | aff_properties.put("ogg.version",new Integer(vorbisInfo.version)); | ||
230 | |||
231 | AudioFormat.Encoding encoding = VorbisEncoding.VORBISENC; | ||
232 | AudioFormat format = new VorbisAudioFormat(encoding, vorbisInfo.rate, AudioSystem.NOT_SPECIFIED, vorbisInfo.channels, AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED, true,af_properties); | ||
233 | AudioFileFormat.Type type = VorbisFileFormatType.OGG; | ||
234 | return new VorbisAudioFileFormat(VorbisFileFormatType.OGG, format, AudioSystem.NOT_SPECIFIED, mediaLength,aff_properties); | ||
235 | } | ||
236 | |||
237 | /** | ||
238 | * Return the AudioInputStream from the given InputStream. | ||
239 | */ | ||
240 | public AudioInputStream getAudioInputStream(InputStream inputStream) throws UnsupportedAudioFileException, IOException | ||
241 | { | ||
242 | if (TDebug.TraceAudioFileReader) TDebug.out("getAudioInputStream(InputStream inputStream)"); | ||
243 | return getAudioInputStream(inputStream, AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED); | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * Return the AudioInputStream from the given InputStream. | ||
248 | */ | ||
249 | public AudioInputStream getAudioInputStream(InputStream inputStream, int medialength, int totalms) throws UnsupportedAudioFileException, IOException | ||
250 | { | ||
251 | if (TDebug.TraceAudioFileReader) TDebug.out("getAudioInputStream(InputStream inputStreamint medialength, int totalms)"); | ||
252 | try | ||
253 | { | ||
254 | if (!inputStream.markSupported()) inputStream = new BufferedInputStream(inputStream); | ||
255 | inputStream.mark(MARK_LIMIT); | ||
256 | AudioFileFormat audioFileFormat = getAudioFileFormat(inputStream, medialength, totalms); | ||
257 | inputStream.reset(); | ||
258 | return new AudioInputStream(inputStream, audioFileFormat.getFormat(), audioFileFormat.getFrameLength()); | ||
259 | } | ||
260 | catch (UnsupportedAudioFileException e) | ||
261 | { | ||
262 | inputStream.reset(); | ||
263 | throw e; | ||
264 | } | ||
265 | catch (IOException e) | ||
266 | { | ||
267 | inputStream.reset(); | ||
268 | throw e; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * Return the AudioInputStream from the given File. | ||
274 | */ | ||
275 | public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException | ||
276 | { | ||
277 | if (TDebug.TraceAudioFileReader) TDebug.out("getAudioInputStream(File file)"); | ||
278 | InputStream inputStream = new FileInputStream(file); | ||
279 | try | ||
280 | { | ||
281 | return getAudioInputStream(inputStream); | ||
282 | } | ||
283 | catch (UnsupportedAudioFileException e) | ||
284 | { | ||
285 | if (inputStream != null) inputStream.close(); | ||
286 | throw e; | ||
287 | } | ||
288 | catch (IOException e) | ||
289 | { | ||
290 | if (inputStream != null) inputStream.close(); | ||
291 | throw e; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * Return the AudioInputStream from the given URL. | ||
297 | */ | ||
298 | public AudioInputStream getAudioInputStream(URL url) throws UnsupportedAudioFileException, IOException | ||
299 | { | ||
300 | if (TDebug.TraceAudioFileReader) TDebug.out("getAudioInputStream(URL url)"); | ||
301 | InputStream inputStream = url.openStream(); | ||
302 | try | ||
303 | { | ||
304 | return getAudioInputStream(inputStream); | ||
305 | } | ||
306 | catch (UnsupportedAudioFileException e) | ||
307 | { | ||
308 | if (inputStream != null) inputStream.close(); | ||
309 | throw e; | ||
310 | } | ||
311 | catch (IOException e) | ||
312 | { | ||
313 | if (inputStream != null) inputStream.close(); | ||
314 | throw e; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | /** | ||
319 | * Reads headers and comments. | ||
320 | */ | ||
321 | private void readHeaders(HashMap aff_properties, HashMap af_properties) throws IOException | ||
322 | { | ||
323 | if(TDebug.TraceAudioConverter) TDebug.out("readHeaders("); | ||
324 | index = oggSyncState_.buffer(bufferSize_); | ||
325 | buffer = oggSyncState_.data; | ||
326 | bytes = readFromStream(buffer, index, bufferSize_); | ||
327 | if(bytes == -1) | ||
328 | { | ||
329 | if(TDebug.TraceAudioConverter) TDebug.out("Cannot get any data from selected Ogg bitstream."); | ||
330 | throw new IOException("Cannot get any data from selected Ogg bitstream."); | ||
331 | } | ||
332 | oggSyncState_.wrote(bytes); | ||
333 | if(oggSyncState_.pageout(oggPage_) != 1) | ||
334 | { | ||
335 | if(bytes < bufferSize_) | ||
336 | { | ||
337 | throw new IOException("EOF"); | ||
338 | } | ||
339 | if(TDebug.TraceAudioConverter) TDebug.out("Input does not appear to be an Ogg bitstream."); | ||
340 | throw new IOException("Input does not appear to be an Ogg bitstream."); | ||
341 | } | ||
342 | oggStreamState_.init(oggPage_.serialno()); | ||
343 | vorbisInfo.init(); | ||
344 | vorbisComment.init(); | ||
345 | aff_properties.put("ogg.serial",new Integer(oggPage_.serialno())); | ||
346 | if(oggStreamState_.pagein(oggPage_) < 0) | ||
347 | { | ||
348 | // error; stream version mismatch perhaps | ||
349 | if(TDebug.TraceAudioConverter) TDebug.out("Error reading first page of Ogg bitstream data."); | ||
350 | throw new IOException("Error reading first page of Ogg bitstream data."); | ||
351 | } | ||
352 | if(oggStreamState_.packetout(oggPacket_) != 1) | ||
353 | { | ||
354 | // no page? must not be vorbis | ||
355 | if(TDebug.TraceAudioConverter) TDebug.out("Error reading initial header packet."); | ||
356 | throw new IOException("Error reading initial header packet."); | ||
357 | } | ||
358 | if(vorbisInfo.synthesis_headerin(vorbisComment, oggPacket_) < 0) | ||
359 | { | ||
360 | // error case; not a vorbis header | ||
361 | if(TDebug.TraceAudioConverter) TDebug.out("This Ogg bitstream does not contain Vorbis audio data."); | ||
362 | throw new IOException("This Ogg bitstream does not contain Vorbis audio data."); | ||
363 | } | ||
364 | int i = 0; | ||
365 | while(i < 2) | ||
366 | { | ||
367 | while(i < 2) | ||
368 | { | ||
369 | int result = oggSyncState_.pageout(oggPage_); | ||
370 | if(result == 0) | ||
371 | { | ||
372 | break; | ||
373 | } // Need more data | ||
374 | if(result == 1) | ||
375 | { | ||
376 | oggStreamState_.pagein(oggPage_); | ||
377 | while(i < 2) | ||
378 | { | ||
379 | result = oggStreamState_.packetout(oggPacket_); | ||
380 | if(result == 0) | ||
381 | { | ||
382 | break; | ||
383 | } | ||
384 | if(result == -1) | ||
385 | { | ||
386 | if(TDebug.TraceAudioConverter) TDebug.out("Corrupt secondary header. Exiting."); | ||
387 | throw new IOException("Corrupt secondary header. Exiting."); | ||
388 | } | ||
389 | vorbisInfo.synthesis_headerin(vorbisComment, oggPacket_); | ||
390 | i++; | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | index = oggSyncState_.buffer(bufferSize_); | ||
395 | buffer = oggSyncState_.data; | ||
396 | bytes = readFromStream(buffer, index, bufferSize_); | ||
397 | if(bytes == -1) | ||
398 | { | ||
399 | break; | ||
400 | } | ||
401 | if(bytes == 0 && i < 2) | ||
402 | { | ||
403 | if(TDebug.TraceAudioConverter) TDebug.out("End of file before finding all Vorbis headers!"); | ||
404 | throw new IOException("End of file before finding all Vorbis headers!"); | ||
405 | } | ||
406 | oggSyncState_.wrote(bytes); | ||
407 | } | ||
408 | // Read Ogg Vorbis comments. | ||
409 | byte[][] ptr = vorbisComment.user_comments; | ||
410 | String currComment = ""; | ||
411 | int c = 0; | ||
412 | for(int j = 0; j < ptr.length; j++) | ||
413 | { | ||
414 | if(ptr[j] == null) | ||
415 | { | ||
416 | break; | ||
417 | } | ||
418 | currComment = (new String(ptr[j], 0, ptr[j].length - 1)).trim(); | ||
419 | if(TDebug.TraceAudioConverter) TDebug.out(currComment); | ||
420 | if (currComment.toLowerCase().startsWith("artist")) | ||
421 | { | ||
422 | aff_properties.put("author",currComment.substring(7)); | ||
423 | } | ||
424 | else if (currComment.toLowerCase().startsWith("title")) | ||
425 | { | ||
426 | aff_properties.put("title",currComment.substring(6)); | ||
427 | } | ||
428 | else if (currComment.toLowerCase().startsWith("album")) | ||
429 | { | ||
430 | aff_properties.put("album",currComment.substring(6)); | ||
431 | } | ||
432 | else if (currComment.toLowerCase().startsWith("date")) | ||
433 | { | ||
434 | aff_properties.put("date",currComment.substring(5)); | ||
435 | } | ||
436 | else if (currComment.toLowerCase().startsWith("copyright")) | ||
437 | { | ||
438 | aff_properties.put("copyright",currComment.substring(10)); | ||
439 | } | ||
440 | else if (currComment.toLowerCase().startsWith("comment")) | ||
441 | { | ||
442 | aff_properties.put("comment",currComment.substring(8)); | ||
443 | } | ||
444 | else if (currComment.toLowerCase().startsWith("genre")) | ||
445 | { | ||
446 | aff_properties.put("ogg.comment.genre",currComment.substring(6)); | ||
447 | } | ||
448 | else if (currComment.toLowerCase().startsWith("tracknumber")) | ||
449 | { | ||
450 | aff_properties.put("ogg.comment.track",currComment.substring(12)); | ||
451 | } | ||
452 | else | ||
453 | { | ||
454 | c++; | ||
455 | aff_properties.put("ogg.comment.ext."+c,currComment); | ||
456 | } | ||
457 | aff_properties.put("ogg.comment.encodedby",new String(vorbisComment.vendor, 0, vorbisComment.vendor.length - 1)); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | /** | ||
462 | * Reads from the oggBitStream_ a specified number of Bytes(bufferSize_) worth | ||
463 | * starting at index and puts them in the specified buffer[]. | ||
464 | * | ||
465 | * @return the number of bytes read or -1 if error. | ||
466 | */ | ||
467 | private int readFromStream(byte[] buffer, int index, int bufferSize_) | ||
468 | { | ||
469 | int bytes = 0; | ||
470 | try | ||
471 | { | ||
472 | bytes = oggBitStream_.read(buffer, index, bufferSize_); | ||
473 | } | ||
474 | catch (Exception e) | ||
475 | { | ||
476 | if (TDebug.TraceAudioFileReader) | ||
477 | { | ||
478 | TDebug.out("Cannot Read Selected Song"); | ||
479 | } | ||
480 | bytes = -1; | ||
481 | } | ||
482 | return bytes; | ||
483 | } | ||
484 | |||
485 | /** | ||
486 | * Initializes all the jOrbis and jOgg vars that are used for song playback. | ||
487 | */ | ||
488 | private void init_jorbis() | ||
489 | { | ||
490 | oggSyncState_ = new SyncState(); | ||
491 | oggStreamState_ = new StreamState(); | ||
492 | oggPage_ = new Page(); | ||
493 | oggPacket_ = new Packet(); | ||
494 | vorbisInfo = new Info(); | ||
495 | vorbisComment = new Comment(); | ||
496 | vorbisDspState = new DspState(); | ||
497 | vorbisBlock = new Block(vorbisDspState); | ||
498 | buffer = null; | ||
499 | bytes = 0; | ||
500 | oggSyncState_.init(); | ||
501 | } | ||
502 | } | ||
diff --git a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFormat.java b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFormat.java deleted file mode 100644 index 829ab2f8cd..0000000000 --- a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFormat.java +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisAudioFormat. | ||
3 | * | ||
4 | * JavaZOOM : vorbisspi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Library General Public License as published | ||
9 | * by the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Library General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Library General Public | ||
18 | * License along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | package javazoom.spi.vorbis.sampled.file; | ||
24 | |||
25 | import java.util.Map; | ||
26 | |||
27 | import javax.sound.sampled.AudioFormat; | ||
28 | |||
29 | import org.tritonus.share.sampled.TAudioFormat; | ||
30 | |||
31 | /** | ||
32 | * @author JavaZOOM | ||
33 | */ | ||
34 | public class VorbisAudioFormat extends TAudioFormat | ||
35 | { | ||
36 | /** | ||
37 | * Constructor. | ||
38 | * @param encoding | ||
39 | * @param nFrequency | ||
40 | * @param SampleSizeInBits | ||
41 | * @param nChannels | ||
42 | * @param FrameSize | ||
43 | * @param FrameRate | ||
44 | * @param isBigEndian | ||
45 | * @param properties | ||
46 | */ | ||
47 | public VorbisAudioFormat(AudioFormat.Encoding encoding, float nFrequency, int SampleSizeInBits, int nChannels, int FrameSize, float FrameRate, boolean isBigEndian, Map properties) | ||
48 | { | ||
49 | super(encoding, nFrequency, SampleSizeInBits, nChannels, FrameSize, FrameRate, isBigEndian, properties); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Ogg Vorbis audio format parameters. | ||
54 | * Some parameters might be unavailable. So availability test is required before reading any parameter. | ||
55 | * | ||
56 | * <br>AudioFormat parameters. | ||
57 | * <ul> | ||
58 | * <li><b>bitrate</b> [Integer], bitrate in bits per seconds, average bitrate for VBR enabled stream. | ||
59 | * <li><b>vbr</b> [Boolean], VBR flag. | ||
60 | * </ul> | ||
61 | */ | ||
62 | public Map properties() | ||
63 | { | ||
64 | return super.properties(); | ||
65 | } | ||
66 | } | ||
diff --git a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisEncoding.java b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisEncoding.java deleted file mode 100644 index 7800f1556d..0000000000 --- a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisEncoding.java +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisEncoding. | ||
3 | * | ||
4 | * JavaZOOM : vorbisspi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Library General Public License as published | ||
9 | * by the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Library General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Library General Public | ||
18 | * License along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | package javazoom.spi.vorbis.sampled.file; | ||
24 | |||
25 | import javax.sound.sampled.AudioFormat; | ||
26 | |||
27 | /** | ||
28 | * Encodings used by the VORBIS audio decoder. | ||
29 | */ | ||
30 | public class VorbisEncoding extends AudioFormat.Encoding | ||
31 | { | ||
32 | public static final AudioFormat.Encoding VORBISENC = new VorbisEncoding("VORBISENC"); | ||
33 | |||
34 | /** | ||
35 | * Constructors. | ||
36 | */ | ||
37 | public VorbisEncoding(String name) | ||
38 | { | ||
39 | super(name); | ||
40 | } | ||
41 | } | ||
diff --git a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisFileFormatType.java b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisFileFormatType.java deleted file mode 100644 index f006bbfe1d..0000000000 --- a/songdbj/javazoom/spi/vorbis/sampled/file/VorbisFileFormatType.java +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * VorbisFileFormatType. | ||
3 | * | ||
4 | * JavaZOOM : vorbisspi@javazoom.net | ||
5 | * http://www.javazoom.net | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Library General Public License as published | ||
9 | * by the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU Library General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Library General Public | ||
18 | * License along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | package javazoom.spi.vorbis.sampled.file; | ||
24 | |||
25 | import javax.sound.sampled.AudioFileFormat; | ||
26 | |||
27 | /** | ||
28 | * FileFormatTypes used by the VORBIS audio decoder. | ||
29 | */ | ||
30 | public class VorbisFileFormatType extends AudioFileFormat.Type | ||
31 | { | ||
32 | public static final AudioFileFormat.Type VORBIS = new VorbisFileFormatType("VORBIS", "ogg"); | ||
33 | public static final AudioFileFormat.Type OGG = new VorbisFileFormatType("OGG", "ogg"); | ||
34 | /** | ||
35 | * Constructor. | ||
36 | */ | ||
37 | public VorbisFileFormatType(String name, String extension) | ||
38 | { | ||
39 | super(name, extension); | ||
40 | } | ||
41 | } | ||