diff options
Diffstat (limited to 'songdbj/javazoom')
76 files changed, 17550 insertions, 0 deletions
diff --git a/songdbj/javazoom/jl/converter/Converter.java b/songdbj/javazoom/jl/converter/Converter.java new file mode 100644 index 0000000000..845082e626 --- /dev/null +++ b/songdbj/javazoom/jl/converter/Converter.java | |||
@@ -0,0 +1,411 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Original verion. mdm@techie.com. | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.converter; | ||
22 | |||
23 | import java.io.BufferedInputStream; | ||
24 | import java.io.File; | ||
25 | import java.io.FileInputStream; | ||
26 | import java.io.IOException; | ||
27 | import java.io.InputStream; | ||
28 | import java.io.PrintWriter; | ||
29 | |||
30 | import javazoom.jl.decoder.Bitstream; | ||
31 | import javazoom.jl.decoder.Decoder; | ||
32 | import javazoom.jl.decoder.Header; | ||
33 | import javazoom.jl.decoder.JavaLayerException; | ||
34 | import javazoom.jl.decoder.Obuffer; | ||
35 | |||
36 | /** | ||
37 | * The <code>Converter</code> class implements the conversion of | ||
38 | * an MPEG audio file to a .WAV file. To convert an MPEG audio stream, | ||
39 | * just create an instance of this class and call the convert() | ||
40 | * method, passing in the names of the input and output files. You can | ||
41 | * pass in optional <code>ProgressListener</code> and | ||
42 | * <code>Decoder.Params</code> objects also to customize the conversion. | ||
43 | * | ||
44 | * @author MDM 12/12/99 | ||
45 | * @since 0.0.7 | ||
46 | */ | ||
47 | public class Converter | ||
48 | { | ||
49 | /** | ||
50 | * Creates a new converter instance. | ||
51 | */ | ||
52 | public Converter() | ||
53 | { | ||
54 | } | ||
55 | |||
56 | public synchronized void convert(String sourceName, String destName) | ||
57 | throws JavaLayerException | ||
58 | { | ||
59 | convert(sourceName, destName, null, null); | ||
60 | } | ||
61 | |||
62 | public synchronized void convert(String sourceName, String destName, | ||
63 | ProgressListener progressListener) | ||
64 | throws JavaLayerException | ||
65 | { | ||
66 | convert(sourceName, destName, progressListener, null); | ||
67 | } | ||
68 | |||
69 | |||
70 | public void convert(String sourceName, String destName, | ||
71 | ProgressListener progressListener, Decoder.Params decoderParams) | ||
72 | throws JavaLayerException | ||
73 | { | ||
74 | if (destName.length()==0) | ||
75 | destName = null; | ||
76 | try { | ||
77 | InputStream in = openInput(sourceName); | ||
78 | convert(in, destName, progressListener, decoderParams); | ||
79 | in.close(); | ||
80 | } catch(IOException ioe) { | ||
81 | throw new JavaLayerException(ioe.getLocalizedMessage(), ioe); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | public synchronized void convert(InputStream sourceStream, String destName, | ||
86 | ProgressListener progressListener, Decoder.Params decoderParams) | ||
87 | throws JavaLayerException | ||
88 | { | ||
89 | if (progressListener==null) | ||
90 | progressListener = PrintWriterProgressListener.newStdOut( | ||
91 | PrintWriterProgressListener.NO_DETAIL); | ||
92 | try { | ||
93 | if (!(sourceStream instanceof BufferedInputStream)) | ||
94 | sourceStream = new BufferedInputStream(sourceStream); | ||
95 | int frameCount = -1; | ||
96 | if (sourceStream.markSupported()) { | ||
97 | sourceStream.mark(-1); | ||
98 | frameCount = countFrames(sourceStream); | ||
99 | sourceStream.reset(); | ||
100 | } | ||
101 | progressListener.converterUpdate(ProgressListener.UPDATE_FRAME_COUNT, frameCount, 0); | ||
102 | |||
103 | |||
104 | Obuffer output = null; | ||
105 | Decoder decoder = new Decoder(decoderParams); | ||
106 | Bitstream stream = new Bitstream(sourceStream); | ||
107 | |||
108 | if (frameCount==-1) | ||
109 | frameCount = Integer.MAX_VALUE; | ||
110 | |||
111 | int frame = 0; | ||
112 | long startTime = System.currentTimeMillis(); | ||
113 | |||
114 | try | ||
115 | { | ||
116 | for (; frame<frameCount; frame++) | ||
117 | { | ||
118 | try | ||
119 | { | ||
120 | Header header = stream.readFrame(); | ||
121 | if (header==null) | ||
122 | break; | ||
123 | |||
124 | progressListener.readFrame(frame, header); | ||
125 | |||
126 | if (output==null) | ||
127 | { | ||
128 | // REVIEW: Incorrect functionality. | ||
129 | // the decoder should provide decoded | ||
130 | // frequency and channels output as it may differ from | ||
131 | // the source (e.g. when downmixing stereo to mono.) | ||
132 | int channels = (header.mode()==Header.SINGLE_CHANNEL) ? 1 : 2; | ||
133 | int freq = header.frequency(); | ||
134 | output = new WaveFileObuffer(channels, freq, destName); | ||
135 | decoder.setOutputBuffer(output); | ||
136 | } | ||
137 | |||
138 | Obuffer decoderOutput = decoder.decodeFrame(header, stream); | ||
139 | |||
140 | // REVIEW: the way the output buffer is set | ||
141 | // on the decoder is a bit dodgy. Even though | ||
142 | // this exception should never happen, we test to be sure. | ||
143 | if (decoderOutput!=output) | ||
144 | throw new InternalError("Output buffers are different."); | ||
145 | |||
146 | |||
147 | progressListener.decodedFrame(frame, header, output); | ||
148 | |||
149 | stream.closeFrame(); | ||
150 | |||
151 | } | ||
152 | catch (Exception ex) | ||
153 | { | ||
154 | boolean stop = !progressListener.converterException(ex); | ||
155 | |||
156 | if (stop) | ||
157 | { | ||
158 | throw new JavaLayerException(ex.getLocalizedMessage(), ex); | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | } | ||
164 | finally | ||
165 | { | ||
166 | |||
167 | if (output!=null) | ||
168 | output.close(); | ||
169 | } | ||
170 | |||
171 | int time = (int)(System.currentTimeMillis()-startTime); | ||
172 | progressListener.converterUpdate(ProgressListener.UPDATE_CONVERT_COMPLETE, | ||
173 | time, frame); | ||
174 | } | ||
175 | catch (IOException ex) | ||
176 | { | ||
177 | throw new JavaLayerException(ex.getLocalizedMessage(), ex); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | |||
182 | protected int countFrames(InputStream in) | ||
183 | { | ||
184 | return -1; | ||
185 | } | ||
186 | |||
187 | |||
188 | protected InputStream openInput(String fileName) | ||
189 | throws IOException | ||
190 | { | ||
191 | // ensure name is abstract path name | ||
192 | File file = new File(fileName); | ||
193 | InputStream fileIn = new FileInputStream(file); | ||
194 | BufferedInputStream bufIn = new BufferedInputStream(fileIn); | ||
195 | |||
196 | return bufIn; | ||
197 | } | ||
198 | |||
199 | |||
200 | /** | ||
201 | * This interface is used by the Converter to provide | ||
202 | * notification of tasks being carried out by the converter, | ||
203 | * and to provide new information as it becomes available. | ||
204 | */ | ||
205 | |||
206 | static public interface ProgressListener | ||
207 | { | ||
208 | public static final int UPDATE_FRAME_COUNT = 1; | ||
209 | |||
210 | /** | ||
211 | * Conversion is complete. Param1 contains the time | ||
212 | * to convert in milliseconds. Param2 contains the number | ||
213 | * of MPEG audio frames converted. | ||
214 | */ | ||
215 | public static final int UPDATE_CONVERT_COMPLETE = 2; | ||
216 | |||
217 | |||
218 | /** | ||
219 | * Notifies the listener that new information is available. | ||
220 | * | ||
221 | * @param updateID Code indicating the information that has been | ||
222 | * updated. | ||
223 | * | ||
224 | * @param param1 Parameter whose value depends upon the update code. | ||
225 | * @param param2 Parameter whose value depends upon the update code. | ||
226 | * | ||
227 | * The <code>updateID</code> parameter can take these values: | ||
228 | * | ||
229 | * UPDATE_FRAME_COUNT: param1 is the frame count, or -1 if not known. | ||
230 | * UPDATE_CONVERT_COMPLETE: param1 is the conversion time, param2 | ||
231 | * is the number of frames converted. | ||
232 | */ | ||
233 | public void converterUpdate(int updateID, int param1, int param2); | ||
234 | |||
235 | /** | ||
236 | * If the converter wishes to make a first pass over the | ||
237 | * audio frames, this is called as each frame is parsed. | ||
238 | */ | ||
239 | public void parsedFrame(int frameNo, Header header); | ||
240 | |||
241 | /** | ||
242 | * This method is called after each frame has been read, | ||
243 | * but before it has been decoded. | ||
244 | * | ||
245 | * @param frameNo The 0-based sequence number of the frame. | ||
246 | * @param header The Header rerpesenting the frame just read. | ||
247 | */ | ||
248 | public void readFrame(int frameNo, Header header); | ||
249 | |||
250 | /** | ||
251 | * This method is called after a frame has been decoded. | ||
252 | * | ||
253 | * @param frameNo The 0-based sequence number of the frame. | ||
254 | * @param header The Header rerpesenting the frame just read. | ||
255 | * @param o The Obuffer the deocded data was written to. | ||
256 | */ | ||
257 | public void decodedFrame(int frameNo, Header header, Obuffer o); | ||
258 | |||
259 | /** | ||
260 | * Called when an exception is thrown during while converting | ||
261 | * a frame. | ||
262 | * | ||
263 | * @param t The <code>Throwable</code> instance that | ||
264 | * was thrown. | ||
265 | * | ||
266 | * @return <code>true</code> to continue processing, or false | ||
267 | * to abort conversion. | ||
268 | * | ||
269 | * If this method returns <code>false</code>, the exception | ||
270 | * is propagated to the caller of the convert() method. If | ||
271 | * <code>true</code> is returned, the exception is silently | ||
272 | * ignored and the converter moves onto the next frame. | ||
273 | */ | ||
274 | public boolean converterException(Throwable t); | ||
275 | |||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * Implementation of <code>ProgressListener</code> that writes | ||
281 | * notification text to a <code>PrintWriter</code>. | ||
282 | */ | ||
283 | // REVIEW: i18n of text and order required. | ||
284 | static public class PrintWriterProgressListener implements ProgressListener | ||
285 | { | ||
286 | static public final int NO_DETAIL = 0; | ||
287 | |||
288 | /** | ||
289 | * Level of detail typically expected of expert | ||
290 | * users. | ||
291 | */ | ||
292 | static public final int EXPERT_DETAIL = 1; | ||
293 | |||
294 | /** | ||
295 | * Verbose detail. | ||
296 | */ | ||
297 | static public final int VERBOSE_DETAIL = 2; | ||
298 | |||
299 | /** | ||
300 | * Debug detail. All frame read notifications are shown. | ||
301 | */ | ||
302 | static public final int DEBUG_DETAIL = 7; | ||
303 | |||
304 | static public final int MAX_DETAIL = 10; | ||
305 | |||
306 | private PrintWriter pw; | ||
307 | |||
308 | private int detailLevel; | ||
309 | |||
310 | static public PrintWriterProgressListener newStdOut(int detail) | ||
311 | { | ||
312 | return new PrintWriterProgressListener( | ||
313 | new PrintWriter(System.out, true), detail); | ||
314 | } | ||
315 | |||
316 | public PrintWriterProgressListener(PrintWriter writer, int detailLevel) | ||
317 | { | ||
318 | this.pw = writer; | ||
319 | this.detailLevel = detailLevel; | ||
320 | } | ||
321 | |||
322 | |||
323 | public boolean isDetail(int detail) | ||
324 | { | ||
325 | return (this.detailLevel >= detail); | ||
326 | } | ||
327 | |||
328 | public void converterUpdate(int updateID, int param1, int param2) | ||
329 | { | ||
330 | if (isDetail(VERBOSE_DETAIL)) | ||
331 | { | ||
332 | switch (updateID) | ||
333 | { | ||
334 | case UPDATE_CONVERT_COMPLETE: | ||
335 | // catch divide by zero errors. | ||
336 | if (param2==0) | ||
337 | param2 = 1; | ||
338 | |||
339 | pw.println(); | ||
340 | pw.println("Converted "+param2+" frames in "+param1+" ms ("+ | ||
341 | (param1/param2)+" ms per frame.)"); | ||
342 | } | ||
343 | } | ||
344 | } | ||
345 | |||
346 | public void parsedFrame(int frameNo, Header header) | ||
347 | { | ||
348 | if ((frameNo==0) && isDetail(VERBOSE_DETAIL)) | ||
349 | { | ||
350 | String headerString = header.toString(); | ||
351 | pw.println("File is a "+headerString); | ||
352 | } | ||
353 | else if (isDetail(MAX_DETAIL)) | ||
354 | { | ||
355 | String headerString = header.toString(); | ||
356 | pw.println("Prased frame "+frameNo+": "+headerString); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | public void readFrame(int frameNo, Header header) | ||
361 | { | ||
362 | if ((frameNo==0) && isDetail(VERBOSE_DETAIL)) | ||
363 | { | ||
364 | String headerString = header.toString(); | ||
365 | pw.println("File is a "+headerString); | ||
366 | } | ||
367 | else if (isDetail(MAX_DETAIL)) | ||
368 | { | ||
369 | String headerString = header.toString(); | ||
370 | pw.println("Read frame "+frameNo+": "+headerString); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | public void decodedFrame(int frameNo, Header header, Obuffer o) | ||
375 | { | ||
376 | if (isDetail(MAX_DETAIL)) | ||
377 | { | ||
378 | String headerString = header.toString(); | ||
379 | pw.println("Decoded frame "+frameNo+": "+headerString); | ||
380 | pw.println("Output: "+o); | ||
381 | } | ||
382 | else if (isDetail(VERBOSE_DETAIL)) | ||
383 | { | ||
384 | if (frameNo==0) | ||
385 | { | ||
386 | pw.print("Converting."); | ||
387 | pw.flush(); | ||
388 | } | ||
389 | |||
390 | if ((frameNo % 10)==0) | ||
391 | { | ||
392 | pw.print('.'); | ||
393 | pw.flush(); | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | |||
398 | public boolean converterException(Throwable t) | ||
399 | { | ||
400 | if (this.detailLevel>NO_DETAIL) | ||
401 | { | ||
402 | t.printStackTrace(pw); | ||
403 | pw.flush(); | ||
404 | } | ||
405 | return false; | ||
406 | } | ||
407 | |||
408 | } | ||
409 | |||
410 | |||
411 | } \ No newline at end of file | ||
diff --git a/songdbj/javazoom/jl/converter/RiffFile.java b/songdbj/javazoom/jl/converter/RiffFile.java new file mode 100644 index 0000000000..fb5d9e53c6 --- /dev/null +++ b/songdbj/javazoom/jl/converter/RiffFile.java | |||
@@ -0,0 +1,495 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 02/23/99 JavaConversion by E.B | ||
4 | * Don Cross, April 1993. | ||
5 | * RIFF file format classes. | ||
6 | * See Chapter 8 of "Multimedia Programmer's Reference" in | ||
7 | * the Microsoft Windows SDK. | ||
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.jl.converter; | ||
27 | |||
28 | import java.io.IOException; | ||
29 | import java.io.RandomAccessFile; | ||
30 | |||
31 | |||
32 | /** | ||
33 | * Class to manage RIFF files | ||
34 | */ | ||
35 | public class RiffFile | ||
36 | { | ||
37 | class RiffChunkHeader | ||
38 | { | ||
39 | public int ckID = 0; // Four-character chunk ID | ||
40 | public int ckSize = 0; // Length of data in chunk | ||
41 | public RiffChunkHeader() | ||
42 | {} | ||
43 | } | ||
44 | |||
45 | |||
46 | // DDCRET | ||
47 | public static final int DDC_SUCCESS = 0; // The operation succeded | ||
48 | public static final int DDC_FAILURE = 1; // The operation failed for unspecified reasons | ||
49 | public static final int DDC_OUT_OF_MEMORY = 2; // Operation failed due to running out of memory | ||
50 | public static final int DDC_FILE_ERROR = 3; // Operation encountered file I/O error | ||
51 | public static final int DDC_INVALID_CALL = 4; // Operation was called with invalid parameters | ||
52 | public static final int DDC_USER_ABORT = 5; // Operation was aborted by the user | ||
53 | public static final int DDC_INVALID_FILE = 6; // File format does not match | ||
54 | |||
55 | // RiffFileMode | ||
56 | public static final int RFM_UNKNOWN = 0; // undefined type (can use to mean "N/A" or "not open") | ||
57 | public static final int RFM_WRITE = 1; // open for write | ||
58 | public static final int RFM_READ = 2; // open for read | ||
59 | |||
60 | private RiffChunkHeader riff_header; // header for whole file | ||
61 | protected int fmode; // current file I/O mode | ||
62 | protected RandomAccessFile file; // I/O stream to use | ||
63 | |||
64 | /** | ||
65 | * Dummy Constructor | ||
66 | */ | ||
67 | public RiffFile() | ||
68 | { | ||
69 | file = null; | ||
70 | fmode = RFM_UNKNOWN; | ||
71 | riff_header = new RiffChunkHeader(); | ||
72 | |||
73 | riff_header.ckID = FourCC("RIFF"); | ||
74 | riff_header.ckSize = 0; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Return File Mode. | ||
79 | */ | ||
80 | public int CurrentFileMode() | ||
81 | {return fmode;} | ||
82 | |||
83 | /** | ||
84 | * Open a RIFF file. | ||
85 | */ | ||
86 | public int Open(String Filename, int NewMode) | ||
87 | { | ||
88 | int retcode = DDC_SUCCESS; | ||
89 | |||
90 | if ( fmode != RFM_UNKNOWN ) | ||
91 | { | ||
92 | retcode = Close(); | ||
93 | } | ||
94 | |||
95 | if ( retcode == DDC_SUCCESS ) | ||
96 | { | ||
97 | switch ( NewMode ) | ||
98 | { | ||
99 | case RFM_WRITE: | ||
100 | try | ||
101 | { | ||
102 | file = new RandomAccessFile(Filename,"rw"); | ||
103 | |||
104 | try | ||
105 | { | ||
106 | // Write the RIFF header... | ||
107 | // We will have to come back later and patch it! | ||
108 | byte[] br = new byte[8]; | ||
109 | br[0] = (byte) ((riff_header.ckID >>> 24) & 0x000000FF); | ||
110 | br[1] = (byte) ((riff_header.ckID >>> 16) & 0x000000FF); | ||
111 | br[2] = (byte) ((riff_header.ckID >>> 8) & 0x000000FF); | ||
112 | br[3] = (byte) (riff_header.ckID & 0x000000FF); | ||
113 | |||
114 | byte br4 = (byte) ((riff_header.ckSize >>> 24)& 0x000000FF); | ||
115 | byte br5 = (byte) ((riff_header.ckSize >>> 16)& 0x000000FF); | ||
116 | byte br6 = (byte) ((riff_header.ckSize >>> 8)& 0x000000FF); | ||
117 | byte br7 = (byte) (riff_header.ckSize & 0x000000FF); | ||
118 | |||
119 | br[4] = br7; | ||
120 | br[5] = br6; | ||
121 | br[6] = br5; | ||
122 | br[7] = br4; | ||
123 | |||
124 | file.write(br,0,8); | ||
125 | fmode = RFM_WRITE; | ||
126 | } catch (IOException ioe) | ||
127 | { | ||
128 | file.close(); | ||
129 | fmode = RFM_UNKNOWN; | ||
130 | } | ||
131 | } catch (IOException ioe) | ||
132 | { | ||
133 | fmode = RFM_UNKNOWN; | ||
134 | retcode = DDC_FILE_ERROR; | ||
135 | } | ||
136 | break; | ||
137 | |||
138 | case RFM_READ: | ||
139 | try | ||
140 | { | ||
141 | file = new RandomAccessFile(Filename,"r"); | ||
142 | try | ||
143 | { | ||
144 | // Try to read the RIFF header... | ||
145 | byte[] br = new byte[8]; | ||
146 | file.read(br,0,8); | ||
147 | fmode = RFM_READ; | ||
148 | riff_header.ckID = ((br[0]<<24)& 0xFF000000) | ((br[1]<<16)&0x00FF0000) | ((br[2]<<8)&0x0000FF00) | (br[3]&0x000000FF); | ||
149 | riff_header.ckSize = ((br[4]<<24)& 0xFF000000) | ((br[5]<<16)&0x00FF0000) | ((br[6]<<8)&0x0000FF00) | (br[7]&0x000000FF); | ||
150 | } catch (IOException ioe) | ||
151 | { | ||
152 | file.close(); | ||
153 | fmode = RFM_UNKNOWN; | ||
154 | } | ||
155 | } catch (IOException ioe) | ||
156 | { | ||
157 | fmode = RFM_UNKNOWN; | ||
158 | retcode = DDC_FILE_ERROR; | ||
159 | } | ||
160 | break; | ||
161 | default: | ||
162 | retcode = DDC_INVALID_CALL; | ||
163 | } | ||
164 | } | ||
165 | return retcode; | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * Write NumBytes data. | ||
170 | */ | ||
171 | public int Write(byte[] Data, int NumBytes ) | ||
172 | { | ||
173 | if ( fmode != RFM_WRITE ) | ||
174 | { | ||
175 | return DDC_INVALID_CALL; | ||
176 | } | ||
177 | try | ||
178 | { | ||
179 | file.write(Data,0,NumBytes); | ||
180 | fmode = RFM_WRITE; | ||
181 | } | ||
182 | catch (IOException ioe) | ||
183 | { | ||
184 | return DDC_FILE_ERROR; | ||
185 | } | ||
186 | riff_header.ckSize += NumBytes; | ||
187 | return DDC_SUCCESS; | ||
188 | } | ||
189 | |||
190 | |||
191 | |||
192 | /** | ||
193 | * Write NumBytes data. | ||
194 | */ | ||
195 | public int Write(short[] Data, int NumBytes ) | ||
196 | { | ||
197 | byte[] theData = new byte[NumBytes]; | ||
198 | int yc = 0; | ||
199 | for (int y = 0;y<NumBytes;y=y+2) | ||
200 | { | ||
201 | theData[y] = (byte) (Data[yc] & 0x00FF); | ||
202 | theData[y+1] =(byte) ((Data[yc++] >>> 8) & 0x00FF); | ||
203 | } | ||
204 | if ( fmode != RFM_WRITE ) | ||
205 | { | ||
206 | return DDC_INVALID_CALL; | ||
207 | } | ||
208 | try | ||
209 | { | ||
210 | file.write(theData,0,NumBytes); | ||
211 | fmode = RFM_WRITE; | ||
212 | } | ||
213 | catch (IOException ioe) | ||
214 | { | ||
215 | return DDC_FILE_ERROR; | ||
216 | } | ||
217 | riff_header.ckSize += NumBytes; | ||
218 | return DDC_SUCCESS; | ||
219 | } | ||
220 | |||
221 | /** | ||
222 | * Write NumBytes data. | ||
223 | */ | ||
224 | public int Write(RiffChunkHeader Triff_header, int NumBytes ) | ||
225 | { | ||
226 | byte[] br = new byte[8]; | ||
227 | br[0] = (byte) ((Triff_header.ckID >>> 24) & 0x000000FF); | ||
228 | br[1] = (byte) ((Triff_header.ckID >>> 16) & 0x000000FF); | ||
229 | br[2] = (byte) ((Triff_header.ckID >>> 8) & 0x000000FF); | ||
230 | br[3] = (byte) (Triff_header.ckID & 0x000000FF); | ||
231 | |||
232 | byte br4 = (byte) ((Triff_header.ckSize >>> 24)& 0x000000FF); | ||
233 | byte br5 = (byte) ((Triff_header.ckSize >>> 16)& 0x000000FF); | ||
234 | byte br6 = (byte) ((Triff_header.ckSize >>> 8)& 0x000000FF); | ||
235 | byte br7 = (byte) (Triff_header.ckSize & 0x000000FF); | ||
236 | |||
237 | br[4] = br7; | ||
238 | br[5] = br6; | ||
239 | br[6] = br5; | ||
240 | br[7] = br4; | ||
241 | |||
242 | if ( fmode != RFM_WRITE ) | ||
243 | { | ||
244 | return DDC_INVALID_CALL; | ||
245 | } | ||
246 | try | ||
247 | { | ||
248 | file.write(br,0,NumBytes); | ||
249 | fmode = RFM_WRITE; | ||
250 | } catch (IOException ioe) | ||
251 | { | ||
252 | return DDC_FILE_ERROR; | ||
253 | } | ||
254 | riff_header.ckSize += NumBytes; | ||
255 | return DDC_SUCCESS; | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * Write NumBytes data. | ||
260 | */ | ||
261 | public int Write(short Data, int NumBytes ) | ||
262 | { | ||
263 | short theData = (short) ( ((Data>>>8)&0x00FF) | ((Data<<8)&0xFF00) ); | ||
264 | if ( fmode != RFM_WRITE ) | ||
265 | { | ||
266 | return DDC_INVALID_CALL; | ||
267 | } | ||
268 | try | ||
269 | { | ||
270 | file.writeShort(theData); | ||
271 | fmode = RFM_WRITE; | ||
272 | } catch (IOException ioe) | ||
273 | { | ||
274 | return DDC_FILE_ERROR; | ||
275 | } | ||
276 | riff_header.ckSize += NumBytes; | ||
277 | return DDC_SUCCESS; | ||
278 | } | ||
279 | /** | ||
280 | * Write NumBytes data. | ||
281 | */ | ||
282 | public int Write(int Data, int NumBytes ) | ||
283 | { | ||
284 | short theDataL = (short) ((Data>>>16)&0x0000FFFF); | ||
285 | short theDataR = (short) (Data&0x0000FFFF); | ||
286 | short theDataLI = (short) ( ((theDataL>>>8)&0x00FF) | ((theDataL<<8)&0xFF00) ); | ||
287 | short theDataRI = (short) ( ((theDataR>>>8)&0x00FF) | ((theDataR<<8)&0xFF00) ); | ||
288 | int theData = ((theDataRI<<16)&0xFFFF0000) | (theDataLI&0x0000FFFF); | ||
289 | if ( fmode != RFM_WRITE ) | ||
290 | { | ||
291 | return DDC_INVALID_CALL; | ||
292 | } | ||
293 | try | ||
294 | { | ||
295 | file.writeInt(theData); | ||
296 | fmode = RFM_WRITE; | ||
297 | } catch (IOException ioe) | ||
298 | { | ||
299 | return DDC_FILE_ERROR; | ||
300 | } | ||
301 | riff_header.ckSize += NumBytes; | ||
302 | return DDC_SUCCESS; | ||
303 | } | ||
304 | |||
305 | |||
306 | |||
307 | /** | ||
308 | * Read NumBytes data. | ||
309 | */ | ||
310 | public int Read (byte[] Data, int NumBytes) | ||
311 | { | ||
312 | int retcode = DDC_SUCCESS; | ||
313 | try | ||
314 | { | ||
315 | file.read(Data,0,NumBytes); | ||
316 | } catch (IOException ioe) | ||
317 | { | ||
318 | retcode = DDC_FILE_ERROR; | ||
319 | } | ||
320 | return retcode; | ||
321 | } | ||
322 | |||
323 | /** | ||
324 | * Expect NumBytes data. | ||
325 | */ | ||
326 | public int Expect(String Data, int NumBytes ) | ||
327 | { | ||
328 | byte target = 0; | ||
329 | int cnt = 0; | ||
330 | try | ||
331 | { | ||
332 | while ((NumBytes--) != 0) | ||
333 | { | ||
334 | target = file.readByte(); | ||
335 | if (target != Data.charAt(cnt++)) return DDC_FILE_ERROR; | ||
336 | } | ||
337 | } catch (IOException ioe) | ||
338 | { | ||
339 | return DDC_FILE_ERROR; | ||
340 | } | ||
341 | return DDC_SUCCESS; | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * Close Riff File. | ||
346 | * Length is written too. | ||
347 | */ | ||
348 | public int Close() | ||
349 | { | ||
350 | int retcode = DDC_SUCCESS; | ||
351 | |||
352 | switch ( fmode ) | ||
353 | { | ||
354 | case RFM_WRITE: | ||
355 | try | ||
356 | { | ||
357 | file.seek(0); | ||
358 | try | ||
359 | { | ||
360 | byte[] br = new byte[8]; | ||
361 | br[0] = (byte) ((riff_header.ckID >>> 24) & 0x000000FF); | ||
362 | br[1] = (byte) ((riff_header.ckID >>> 16) & 0x000000FF); | ||
363 | br[2] = (byte) ((riff_header.ckID >>> 8) & 0x000000FF); | ||
364 | br[3] = (byte) (riff_header.ckID & 0x000000FF); | ||
365 | |||
366 | br[7] = (byte) ((riff_header.ckSize >>> 24)& 0x000000FF); | ||
367 | br[6] = (byte) ((riff_header.ckSize >>> 16)& 0x000000FF); | ||
368 | br[5] = (byte) ((riff_header.ckSize >>> 8)& 0x000000FF); | ||
369 | br[4] = (byte) (riff_header.ckSize & 0x000000FF); | ||
370 | file.write(br,0,8); | ||
371 | file.close(); | ||
372 | } catch (IOException ioe) | ||
373 | { | ||
374 | retcode = DDC_FILE_ERROR; | ||
375 | } | ||
376 | } catch (IOException ioe) | ||
377 | { | ||
378 | retcode = DDC_FILE_ERROR; | ||
379 | } | ||
380 | break; | ||
381 | |||
382 | case RFM_READ: | ||
383 | try | ||
384 | { | ||
385 | file.close(); | ||
386 | } catch (IOException ioe) | ||
387 | { | ||
388 | retcode = DDC_FILE_ERROR; | ||
389 | } | ||
390 | break; | ||
391 | } | ||
392 | file = null; | ||
393 | fmode = RFM_UNKNOWN; | ||
394 | return retcode; | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * Return File Position. | ||
399 | */ | ||
400 | public long CurrentFilePosition() | ||
401 | { | ||
402 | long position; | ||
403 | try | ||
404 | { | ||
405 | position = file.getFilePointer(); | ||
406 | } catch (IOException ioe) | ||
407 | { | ||
408 | position = -1; | ||
409 | } | ||
410 | return position; | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * Write Data to specified offset. | ||
415 | */ | ||
416 | public int Backpatch (long FileOffset, RiffChunkHeader Data, int NumBytes ) | ||
417 | { | ||
418 | if (file == null) | ||
419 | { | ||
420 | return DDC_INVALID_CALL; | ||
421 | } | ||
422 | try | ||
423 | { | ||
424 | file.seek(FileOffset); | ||
425 | } catch (IOException ioe) | ||
426 | { | ||
427 | return DDC_FILE_ERROR; | ||
428 | } | ||
429 | return Write ( Data, NumBytes ); | ||
430 | } | ||
431 | |||
432 | public int Backpatch (long FileOffset, byte[] Data, int NumBytes ) | ||
433 | { | ||
434 | if (file == null) | ||
435 | { | ||
436 | return DDC_INVALID_CALL; | ||
437 | } | ||
438 | try | ||
439 | { | ||
440 | file.seek(FileOffset); | ||
441 | } catch (IOException ioe) | ||
442 | { | ||
443 | return DDC_FILE_ERROR; | ||
444 | } | ||
445 | return Write ( Data, NumBytes ); | ||
446 | } | ||
447 | |||
448 | |||
449 | /** | ||
450 | * Seek in the File. | ||
451 | */ | ||
452 | protected int Seek(long offset) | ||
453 | { | ||
454 | int rc; | ||
455 | try | ||
456 | { | ||
457 | file.seek(offset); | ||
458 | rc = DDC_SUCCESS; | ||
459 | } catch (IOException ioe) | ||
460 | { | ||
461 | rc = DDC_FILE_ERROR; | ||
462 | } | ||
463 | return rc; | ||
464 | } | ||
465 | |||
466 | /** | ||
467 | * Error Messages. | ||
468 | */ | ||
469 | private String DDCRET_String(int retcode) | ||
470 | { | ||
471 | switch ( retcode ) | ||
472 | { | ||
473 | case DDC_SUCCESS: return "DDC_SUCCESS"; | ||
474 | case DDC_FAILURE: return "DDC_FAILURE"; | ||
475 | case DDC_OUT_OF_MEMORY: return "DDC_OUT_OF_MEMORY"; | ||
476 | case DDC_FILE_ERROR: return "DDC_FILE_ERROR"; | ||
477 | case DDC_INVALID_CALL: return "DDC_INVALID_CALL"; | ||
478 | case DDC_USER_ABORT: return "DDC_USER_ABORT"; | ||
479 | case DDC_INVALID_FILE: return "DDC_INVALID_FILE"; | ||
480 | } | ||
481 | return "Unknown Error"; | ||
482 | } | ||
483 | |||
484 | /** | ||
485 | * Fill the header. | ||
486 | */ | ||
487 | public static int FourCC(String ChunkName) | ||
488 | { | ||
489 | byte[] p = {0x20,0x20,0x20,0x20}; | ||
490 | ChunkName.getBytes(0,4,p,0); | ||
491 | int ret = (((p[0] << 24)& 0xFF000000) | ((p[1] << 16)&0x00FF0000) | ((p[2] << 8)&0x0000FF00) | (p[3]&0x000000FF)); | ||
492 | return ret; | ||
493 | } | ||
494 | |||
495 | } | ||
diff --git a/songdbj/javazoom/jl/converter/WaveFile.java b/songdbj/javazoom/jl/converter/WaveFile.java new file mode 100644 index 0000000000..f158d7a39a --- /dev/null +++ b/songdbj/javazoom/jl/converter/WaveFile.java | |||
@@ -0,0 +1,522 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 02/23/99 JavaConversion by E.B | ||
4 | * Don Cross, April 1993. | ||
5 | * RIFF file format classes. | ||
6 | * See Chapter 8 of "Multimedia Programmer's Reference" in | ||
7 | * the Microsoft Windows SDK. | ||
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.jl.converter; | ||
27 | |||
28 | /** | ||
29 | * Class allowing WaveFormat Access | ||
30 | */ | ||
31 | public class WaveFile extends RiffFile | ||
32 | { | ||
33 | public static final int MAX_WAVE_CHANNELS = 2; | ||
34 | |||
35 | class WaveFormat_ChunkData | ||
36 | { | ||
37 | public short wFormatTag = 0; // Format category (PCM=1) | ||
38 | public short nChannels = 0; // Number of channels (mono=1, stereo=2) | ||
39 | public int nSamplesPerSec = 0; // Sampling rate [Hz] | ||
40 | public int nAvgBytesPerSec = 0; | ||
41 | public short nBlockAlign = 0; | ||
42 | public short nBitsPerSample = 0; | ||
43 | |||
44 | public WaveFormat_ChunkData() | ||
45 | { | ||
46 | wFormatTag = 1; // PCM | ||
47 | Config(44100,(short)16,(short)1); | ||
48 | } | ||
49 | |||
50 | public void Config (int NewSamplingRate, short NewBitsPerSample, short NewNumChannels) | ||
51 | { | ||
52 | nSamplesPerSec = NewSamplingRate; | ||
53 | nChannels = NewNumChannels; | ||
54 | nBitsPerSample = NewBitsPerSample; | ||
55 | nAvgBytesPerSec = (nChannels * nSamplesPerSec * nBitsPerSample) / 8; | ||
56 | nBlockAlign = (short) ((nChannels * nBitsPerSample) / 8); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | |||
61 | class WaveFormat_Chunk | ||
62 | { | ||
63 | public RiffChunkHeader header; | ||
64 | public WaveFormat_ChunkData data; | ||
65 | |||
66 | public WaveFormat_Chunk() | ||
67 | { | ||
68 | header = new RiffChunkHeader(); | ||
69 | data = new WaveFormat_ChunkData(); | ||
70 | header.ckID = FourCC("fmt "); | ||
71 | header.ckSize = 16; | ||
72 | } | ||
73 | |||
74 | public int VerifyValidity() | ||
75 | { | ||
76 | boolean ret = header.ckID == FourCC("fmt ") && | ||
77 | |||
78 | (data.nChannels == 1 || data.nChannels == 2) && | ||
79 | |||
80 | data.nAvgBytesPerSec == ( data.nChannels * | ||
81 | data.nSamplesPerSec * | ||
82 | data.nBitsPerSample ) / 8 && | ||
83 | |||
84 | data.nBlockAlign == ( data.nChannels * | ||
85 | data.nBitsPerSample ) / 8; | ||
86 | if (ret == true) return 1; | ||
87 | else return 0; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | public class WaveFileSample | ||
92 | { | ||
93 | public short[] chan; | ||
94 | |||
95 | public WaveFileSample() | ||
96 | {chan = new short[WaveFile.MAX_WAVE_CHANNELS];} | ||
97 | } | ||
98 | |||
99 | private WaveFormat_Chunk wave_format; | ||
100 | private RiffChunkHeader pcm_data; | ||
101 | private long pcm_data_offset = 0; // offset of 'pcm_data' in output file | ||
102 | private int num_samples = 0; | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Constructs a new WaveFile instance. | ||
107 | */ | ||
108 | public WaveFile() | ||
109 | { | ||
110 | pcm_data = new RiffChunkHeader(); | ||
111 | wave_format = new WaveFormat_Chunk(); | ||
112 | pcm_data.ckID = FourCC("data"); | ||
113 | pcm_data.ckSize = 0; | ||
114 | num_samples = 0; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * | ||
119 | * | ||
120 | public int OpenForRead (String Filename) | ||
121 | { | ||
122 | // Verify filename parameter as best we can... | ||
123 | if (Filename == null) | ||
124 | { | ||
125 | return DDC_INVALID_CALL; | ||
126 | } | ||
127 | int retcode = Open ( Filename, RFM_READ ); | ||
128 | |||
129 | if ( retcode == DDC_SUCCESS ) | ||
130 | { | ||
131 | retcode = Expect ( "WAVE", 4 ); | ||
132 | |||
133 | if ( retcode == DDC_SUCCESS ) | ||
134 | { | ||
135 | retcode = Read(wave_format,24); | ||
136 | |||
137 | if ( retcode == DDC_SUCCESS && !wave_format.VerifyValidity() ) | ||
138 | { | ||
139 | // This isn't standard PCM, so we don't know what it is! | ||
140 | retcode = DDC_FILE_ERROR; | ||
141 | } | ||
142 | |||
143 | if ( retcode == DDC_SUCCESS ) | ||
144 | { | ||
145 | pcm_data_offset = CurrentFilePosition(); | ||
146 | |||
147 | // Figure out number of samples from | ||
148 | // file size, current file position, and | ||
149 | // WAVE header. | ||
150 | retcode = Read (pcm_data, 8 ); | ||
151 | num_samples = filelength(fileno(file)) - CurrentFilePosition(); | ||
152 | num_samples /= NumChannels(); | ||
153 | num_samples /= (BitsPerSample() / 8); | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | return retcode; | ||
158 | }*/ | ||
159 | |||
160 | /** | ||
161 | * | ||
162 | */ | ||
163 | public int OpenForWrite (String Filename, int SamplingRate, short BitsPerSample, short NumChannels) | ||
164 | { | ||
165 | // Verify parameters... | ||
166 | if ( (Filename==null) || | ||
167 | (BitsPerSample != 8 && BitsPerSample != 16) || | ||
168 | NumChannels < 1 || NumChannels > 2 ) | ||
169 | { | ||
170 | return DDC_INVALID_CALL; | ||
171 | } | ||
172 | |||
173 | wave_format.data.Config ( SamplingRate, BitsPerSample, NumChannels ); | ||
174 | |||
175 | int retcode = Open ( Filename, RFM_WRITE ); | ||
176 | |||
177 | if ( retcode == DDC_SUCCESS ) | ||
178 | { | ||
179 | byte [] theWave = {(byte)'W',(byte)'A',(byte)'V',(byte)'E'}; | ||
180 | retcode = Write ( theWave, 4 ); | ||
181 | |||
182 | if ( retcode == DDC_SUCCESS ) | ||
183 | { | ||
184 | // Ecriture de wave_format | ||
185 | retcode = Write (wave_format.header, 8); | ||
186 | retcode = Write (wave_format.data.wFormatTag, 2); | ||
187 | retcode = Write (wave_format.data.nChannels, 2); | ||
188 | retcode = Write (wave_format.data.nSamplesPerSec, 4); | ||
189 | retcode = Write (wave_format.data.nAvgBytesPerSec, 4); | ||
190 | retcode = Write (wave_format.data.nBlockAlign, 2); | ||
191 | retcode = Write (wave_format.data.nBitsPerSample, 2); | ||
192 | /* byte[] br = new byte[16]; | ||
193 | br[0] = (byte) ((wave_format.data.wFormatTag >> 8) & 0x00FF); | ||
194 | br[1] = (byte) (wave_format.data.wFormatTag & 0x00FF); | ||
195 | |||
196 | br[2] = (byte) ((wave_format.data.nChannels >> 8) & 0x00FF); | ||
197 | br[3] = (byte) (wave_format.data.nChannels & 0x00FF); | ||
198 | |||
199 | br[4] = (byte) ((wave_format.data.nSamplesPerSec >> 24)& 0x000000FF); | ||
200 | br[5] = (byte) ((wave_format.data.nSamplesPerSec >> 16)& 0x000000FF); | ||
201 | br[6] = (byte) ((wave_format.data.nSamplesPerSec >> 8)& 0x000000FF); | ||
202 | br[7] = (byte) (wave_format.data.nSamplesPerSec & 0x000000FF); | ||
203 | |||
204 | br[8] = (byte) ((wave_format.data.nAvgBytesPerSec>> 24)& 0x000000FF); | ||
205 | br[9] = (byte) ((wave_format.data.nAvgBytesPerSec >> 16)& 0x000000FF); | ||
206 | br[10] = (byte) ((wave_format.data.nAvgBytesPerSec >> 8)& 0x000000FF); | ||
207 | br[11] = (byte) (wave_format.data.nAvgBytesPerSec & 0x000000FF); | ||
208 | |||
209 | br[12] = (byte) ((wave_format.data.nBlockAlign >> 8) & 0x00FF); | ||
210 | br[13] = (byte) (wave_format.data.nBlockAlign & 0x00FF); | ||
211 | |||
212 | br[14] = (byte) ((wave_format.data.nBitsPerSample >> 8) & 0x00FF); | ||
213 | br[15] = (byte) (wave_format.data.nBitsPerSample & 0x00FF); | ||
214 | retcode = Write (br, 16); */ | ||
215 | |||
216 | |||
217 | if ( retcode == DDC_SUCCESS ) | ||
218 | { | ||
219 | pcm_data_offset = CurrentFilePosition(); | ||
220 | retcode = Write ( pcm_data, 8 ); | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | |||
225 | return retcode; | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * | ||
230 | * | ||
231 | public int ReadSample ( short[] Sample ) | ||
232 | { | ||
233 | |||
234 | }*/ | ||
235 | |||
236 | /** | ||
237 | * | ||
238 | * | ||
239 | public int WriteSample( short[] Sample ) | ||
240 | { | ||
241 | int retcode = DDC_SUCCESS; | ||
242 | switch ( wave_format.data.nChannels ) | ||
243 | { | ||
244 | case 1: | ||
245 | switch ( wave_format.data.nBitsPerSample ) | ||
246 | { | ||
247 | case 8: | ||
248 | pcm_data.ckSize += 1; | ||
249 | retcode = Write ( Sample, 1 ); | ||
250 | break; | ||
251 | |||
252 | case 16: | ||
253 | pcm_data.ckSize += 2; | ||
254 | retcode = Write ( Sample, 2 ); | ||
255 | break; | ||
256 | |||
257 | default: | ||
258 | retcode = DDC_INVALID_CALL; | ||
259 | } | ||
260 | break; | ||
261 | |||
262 | case 2: | ||
263 | switch ( wave_format.data.nBitsPerSample ) | ||
264 | { | ||
265 | case 8: | ||
266 | retcode = Write ( Sample, 1 ); | ||
267 | if ( retcode == DDC_SUCCESS ) | ||
268 | { | ||
269 | // &Sample[1] | ||
270 | retcode = Write (Sample, 1 ); | ||
271 | if ( retcode == DDC_SUCCESS ) | ||
272 | { | ||
273 | pcm_data.ckSize += 2; | ||
274 | } | ||
275 | } | ||
276 | break; | ||
277 | |||
278 | case 16: | ||
279 | retcode = Write ( Sample, 2 ); | ||
280 | if ( retcode == DDC_SUCCESS ) | ||
281 | { | ||
282 | // &Sample[1] | ||
283 | retcode = Write (Sample, 2 ); | ||
284 | if ( retcode == DDC_SUCCESS ) | ||
285 | { | ||
286 | pcm_data.ckSize += 4; | ||
287 | } | ||
288 | } | ||
289 | break; | ||
290 | |||
291 | default: | ||
292 | retcode = DDC_INVALID_CALL; | ||
293 | } | ||
294 | break; | ||
295 | |||
296 | default: | ||
297 | retcode = DDC_INVALID_CALL; | ||
298 | } | ||
299 | |||
300 | return retcode; | ||
301 | }*/ | ||
302 | |||
303 | /** | ||
304 | * | ||
305 | * | ||
306 | public int SeekToSample ( long SampleIndex ) | ||
307 | { | ||
308 | if ( SampleIndex >= NumSamples() ) | ||
309 | { | ||
310 | return DDC_INVALID_CALL; | ||
311 | } | ||
312 | int SampleSize = (BitsPerSample() + 7) / 8; | ||
313 | int rc = Seek ( pcm_data_offset + 8 + | ||
314 | SampleSize * NumChannels() * SampleIndex ); | ||
315 | return rc; | ||
316 | }*/ | ||
317 | |||
318 | /** | ||
319 | * Write 16-bit audio | ||
320 | */ | ||
321 | public int WriteData ( short[] data, int numData ) | ||
322 | { | ||
323 | int extraBytes = numData * 2; | ||
324 | pcm_data.ckSize += extraBytes; | ||
325 | return super.Write ( data, extraBytes ); | ||
326 | } | ||
327 | |||
328 | /** | ||
329 | * Read 16-bit audio. | ||
330 | * | ||
331 | public int ReadData (short[] data, int numData) | ||
332 | {return super.Read ( data, numData * 2);} */ | ||
333 | |||
334 | /** | ||
335 | * Write 8-bit audio. | ||
336 | * | ||
337 | public int WriteData ( byte[] data, int numData ) | ||
338 | { | ||
339 | pcm_data.ckSize += numData; | ||
340 | return super.Write ( data, numData ); | ||
341 | }*/ | ||
342 | |||
343 | /** | ||
344 | * Read 8-bit audio. | ||
345 | * | ||
346 | public int ReadData ( byte[] data, int numData ) | ||
347 | {return super.Read ( data, numData );} */ | ||
348 | |||
349 | |||
350 | /** | ||
351 | * | ||
352 | * | ||
353 | public int ReadSamples (int num, int [] WaveFileSample) | ||
354 | { | ||
355 | |||
356 | }*/ | ||
357 | |||
358 | /** | ||
359 | * | ||
360 | * | ||
361 | public int WriteMonoSample ( short[] SampleData ) | ||
362 | { | ||
363 | switch ( wave_format.data.nBitsPerSample ) | ||
364 | { | ||
365 | case 8: | ||
366 | pcm_data.ckSize += 1; | ||
367 | return Write ( SampleData, 1 ); | ||
368 | |||
369 | case 16: | ||
370 | pcm_data.ckSize += 2; | ||
371 | return Write ( SampleData, 2 ); | ||
372 | } | ||
373 | return DDC_INVALID_CALL; | ||
374 | }*/ | ||
375 | |||
376 | /** | ||
377 | * | ||
378 | * | ||
379 | public int WriteStereoSample ( short[] LeftSample, short[] RightSample ) | ||
380 | { | ||
381 | int retcode = DDC_SUCCESS; | ||
382 | switch ( wave_format.data.nBitsPerSample ) | ||
383 | { | ||
384 | case 8: | ||
385 | retcode = Write ( LeftSample, 1 ); | ||
386 | if ( retcode == DDC_SUCCESS ) | ||
387 | { | ||
388 | retcode = Write ( RightSample, 1 ); | ||
389 | if ( retcode == DDC_SUCCESS ) | ||
390 | { | ||
391 | pcm_data.ckSize += 2; | ||
392 | } | ||
393 | } | ||
394 | break; | ||
395 | |||
396 | case 16: | ||
397 | retcode = Write ( LeftSample, 2 ); | ||
398 | if ( retcode == DDC_SUCCESS ) | ||
399 | { | ||
400 | retcode = Write ( RightSample, 2 ); | ||
401 | if ( retcode == DDC_SUCCESS ) | ||
402 | { | ||
403 | pcm_data.ckSize += 4; | ||
404 | } | ||
405 | } | ||
406 | break; | ||
407 | |||
408 | default: | ||
409 | retcode = DDC_INVALID_CALL; | ||
410 | } | ||
411 | return retcode; | ||
412 | }*/ | ||
413 | |||
414 | /** | ||
415 | * | ||
416 | * | ||
417 | public int ReadMonoSample ( short[] Sample ) | ||
418 | { | ||
419 | int retcode = DDC_SUCCESS; | ||
420 | switch ( wave_format.data.nBitsPerSample ) | ||
421 | { | ||
422 | case 8: | ||
423 | byte[] x = {0}; | ||
424 | retcode = Read ( x, 1 ); | ||
425 | Sample[0] = (short)(x[0]); | ||
426 | break; | ||
427 | |||
428 | case 16: | ||
429 | retcode = Read ( Sample, 2 ); | ||
430 | break; | ||
431 | |||
432 | default: | ||
433 | retcode = DDC_INVALID_CALL; | ||
434 | } | ||
435 | return retcode; | ||
436 | }*/ | ||
437 | |||
438 | /** | ||
439 | * | ||
440 | * | ||
441 | public int ReadStereoSample ( short[] LeftSampleData, short[] RightSampleData ) | ||
442 | { | ||
443 | int retcode = DDC_SUCCESS; | ||
444 | byte[] x = new byte[2]; | ||
445 | short[] y = new short[2]; | ||
446 | switch ( wave_format.data.nBitsPerSample ) | ||
447 | { | ||
448 | case 8: | ||
449 | retcode = Read ( x, 2 ); | ||
450 | L[0] = (short) ( x[0] ); | ||
451 | R[0] = (short) ( x[1] ); | ||
452 | break; | ||
453 | |||
454 | case 16: | ||
455 | retcode = Read ( y, 4 ); | ||
456 | L[0] = (short) ( y[0] ); | ||
457 | R[0] = (short) ( y[1] ); | ||
458 | break; | ||
459 | |||
460 | default: | ||
461 | retcode = DDC_INVALID_CALL; | ||
462 | } | ||
463 | return retcode; | ||
464 | }*/ | ||
465 | |||
466 | |||
467 | /** | ||
468 | * | ||
469 | */ | ||
470 | public int Close() | ||
471 | { | ||
472 | int rc = DDC_SUCCESS; | ||
473 | |||
474 | if ( fmode == RFM_WRITE ) | ||
475 | rc = Backpatch ( pcm_data_offset, pcm_data, 8 ); | ||
476 | if ( rc == DDC_SUCCESS ) | ||
477 | rc = super.Close(); | ||
478 | return rc; | ||
479 | } | ||
480 | |||
481 | // [Hz] | ||
482 | public int SamplingRate() | ||
483 | {return wave_format.data.nSamplesPerSec;} | ||
484 | |||
485 | public short BitsPerSample() | ||
486 | {return wave_format.data.nBitsPerSample;} | ||
487 | |||
488 | public short NumChannels() | ||
489 | {return wave_format.data.nChannels;} | ||
490 | |||
491 | public int NumSamples() | ||
492 | {return num_samples;} | ||
493 | |||
494 | |||
495 | /** | ||
496 | * Open for write using another wave file's parameters... | ||
497 | */ | ||
498 | public int OpenForWrite (String Filename, WaveFile OtherWave ) | ||
499 | { | ||
500 | return OpenForWrite ( Filename, | ||
501 | OtherWave.SamplingRate(), | ||
502 | OtherWave.BitsPerSample(), | ||
503 | OtherWave.NumChannels() ); | ||
504 | } | ||
505 | |||
506 | /** | ||
507 | * | ||
508 | */ | ||
509 | public long CurrentFilePosition() | ||
510 | { | ||
511 | return super.CurrentFilePosition(); | ||
512 | } | ||
513 | |||
514 | /* public int FourCC(String ChunkName) | ||
515 | { | ||
516 | byte[] p = {0x20,0x20,0x20,0x20}; | ||
517 | ChunkName.getBytes(0,4,p,0); | ||
518 | int ret = (((p[0] << 24)& 0xFF000000) | ((p[1] << 16)&0x00FF0000) | ((p[2] << 8)&0x0000FF00) | (p[3]&0x000000FF)); | ||
519 | return ret; | ||
520 | }*/ | ||
521 | |||
522 | } \ No newline at end of file | ||
diff --git a/songdbj/javazoom/jl/converter/WaveFileObuffer.java b/songdbj/javazoom/jl/converter/WaveFileObuffer.java new file mode 100644 index 0000000000..eaa1dd46d4 --- /dev/null +++ b/songdbj/javazoom/jl/converter/WaveFileObuffer.java | |||
@@ -0,0 +1,141 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 12/12/99 0.0.7 Renamed class, additional constructor arguments | ||
5 | * and larger write buffers. mdm@techie.com. | ||
6 | * | ||
7 | * 15/02/99 Java Conversion by E.B ,javalayer@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.jl.converter; | ||
27 | |||
28 | import javazoom.jl.decoder.Obuffer; | ||
29 | |||
30 | /** | ||
31 | * Implements an Obuffer by writing the data to | ||
32 | * a file in RIFF WAVE format. | ||
33 | * | ||
34 | * @since 0.0 | ||
35 | */ | ||
36 | |||
37 | |||
38 | public class WaveFileObuffer extends Obuffer | ||
39 | { | ||
40 | private short[] buffer; | ||
41 | private short[] bufferp; | ||
42 | private int channels; | ||
43 | private WaveFile outWave; | ||
44 | |||
45 | /** | ||
46 | * Creates a new WareFileObuffer instance. | ||
47 | * | ||
48 | * @param number_of_channels | ||
49 | * The number of channels of audio data | ||
50 | * this buffer will receive. | ||
51 | * | ||
52 | * @param freq The sample frequency of the samples in the buffer. | ||
53 | * | ||
54 | * @param fileName The filename to write the data to. | ||
55 | */ | ||
56 | public WaveFileObuffer(int number_of_channels, int freq, String FileName) | ||
57 | { | ||
58 | if (FileName==null) | ||
59 | throw new NullPointerException("FileName"); | ||
60 | |||
61 | buffer = new short[OBUFFERSIZE]; | ||
62 | bufferp = new short[MAXCHANNELS]; | ||
63 | channels = number_of_channels; | ||
64 | |||
65 | for (int i = 0; i < number_of_channels; ++i) | ||
66 | bufferp[i] = (short)i; | ||
67 | |||
68 | outWave = new WaveFile(); | ||
69 | |||
70 | int rc = outWave.OpenForWrite (FileName,freq,(short)16,(short)channels); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Takes a 16 Bit PCM sample. | ||
75 | */ | ||
76 | public void append(int channel, short value) | ||
77 | { | ||
78 | buffer[bufferp[channel]] = value; | ||
79 | bufferp[channel] += channels; | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * Write the samples to the file (Random Acces). | ||
84 | */ | ||
85 | short[] myBuffer = new short[2]; | ||
86 | public void write_buffer(int val) | ||
87 | { | ||
88 | |||
89 | int k = 0; | ||
90 | int rc = 0; | ||
91 | |||
92 | rc = outWave.WriteData(buffer, bufferp[0]); | ||
93 | // REVIEW: handle RiffFile errors. | ||
94 | /* | ||
95 | for (int j=0;j<bufferp[0];j=j+2) | ||
96 | { | ||
97 | |||
98 | //myBuffer[0] = (short)(((buffer[j]>>8)&0x000000FF) | ((buffer[j]<<8)&0x0000FF00)); | ||
99 | //myBuffer[1] = (short) (((buffer[j+1]>>8)&0x000000FF) | ((buffer[j+1]<<8)&0x0000FF00)); | ||
100 | myBuffer[0] = buffer[j]; | ||
101 | myBuffer[1] = buffer[j+1]; | ||
102 | rc = outWave.WriteData (myBuffer,2); | ||
103 | } | ||
104 | */ | ||
105 | for (int i = 0; i < channels; ++i) bufferp[i] = (short)i; | ||
106 | } | ||
107 | |||
108 | public void close() | ||
109 | { | ||
110 | outWave.Close(); | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * | ||
115 | */ | ||
116 | public void clear_buffer() | ||
117 | {} | ||
118 | |||
119 | /** | ||
120 | * | ||
121 | */ | ||
122 | public void set_stop_flag() | ||
123 | {} | ||
124 | |||
125 | /* | ||
126 | * Create STDOUT buffer | ||
127 | * | ||
128 | * | ||
129 | public static Obuffer create_stdout_obuffer(MPEG_Args maplay_args) | ||
130 | { | ||
131 | Obuffer thebuffer = null; | ||
132 | int mode = maplay_args.MPEGheader.mode(); | ||
133 | int which_channels = maplay_args.which_c; | ||
134 | if (mode == Header.single_channel || which_channels != MPEG_Args.both) | ||
135 | thebuffer = new FileObuffer(1,maplay_args.output_filename); | ||
136 | else | ||
137 | thebuffer = new FileObuffer(2,maplay_args.output_filename); | ||
138 | return(thebuffer); | ||
139 | } | ||
140 | */ | ||
141 | } | ||
diff --git a/songdbj/javazoom/jl/converter/jlc.java b/songdbj/javazoom/jl/converter/jlc.java new file mode 100644 index 0000000000..57c84eba4a --- /dev/null +++ b/songdbj/javazoom/jl/converter/jlc.java | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 29/01/00 Initial version. mdm@techie.com | ||
5 | * | ||
6 | * 12/12/99 JavaLayer 0.0.7 mdm@techie.com | ||
7 | * | ||
8 | * 14/02/99 MPEG_Args Based Class - E.B | ||
9 | * Adapted from javalayer and MPEG_Args. | ||
10 | * Doc'ed and integerated with JL converter. Removed | ||
11 | * Win32 specifics from original Maplay code. | ||
12 | *----------------------------------------------------------------------- | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU Library General Public License as published | ||
15 | * by the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU Library General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU Library General Public | ||
24 | * License along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | *---------------------------------------------------------------------- | ||
27 | */ | ||
28 | |||
29 | package javazoom.jl.converter; | ||
30 | |||
31 | import java.io.PrintWriter; | ||
32 | |||
33 | import javazoom.jl.decoder.Crc16; | ||
34 | import javazoom.jl.decoder.JavaLayerException; | ||
35 | import javazoom.jl.decoder.OutputChannels; | ||
36 | |||
37 | /** | ||
38 | * The <code>jlc</code> class presents the JavaLayer | ||
39 | * Conversion functionality as a command-line program. | ||
40 | * | ||
41 | * @since 0.0.7 | ||
42 | */ | ||
43 | public class jlc | ||
44 | { | ||
45 | |||
46 | static public void main(String args[]) | ||
47 | { | ||
48 | String[] argv; | ||
49 | long start = System.currentTimeMillis(); | ||
50 | int argc = args.length + 1; | ||
51 | argv = new String[argc]; | ||
52 | argv[0] = "jlc"; | ||
53 | for(int i=0;i<args.length;i++) | ||
54 | argv[i+1] = args[i]; | ||
55 | |||
56 | jlcArgs ma = new jlcArgs(); | ||
57 | if (!ma.processArgs(argv)) | ||
58 | System.exit(1); | ||
59 | |||
60 | Converter conv = new Converter(); | ||
61 | |||
62 | int detail = (ma.verbose_mode ? | ||
63 | ma.verbose_level : | ||
64 | Converter.PrintWriterProgressListener.NO_DETAIL); | ||
65 | |||
66 | Converter.ProgressListener listener = | ||
67 | new Converter.PrintWriterProgressListener( | ||
68 | new PrintWriter(System.out, true), detail); | ||
69 | |||
70 | try | ||
71 | { | ||
72 | conv.convert(ma.filename, ma.output_filename, listener); | ||
73 | } | ||
74 | catch (JavaLayerException ex) | ||
75 | { | ||
76 | System.err.println("Convertion failure: "+ex); | ||
77 | } | ||
78 | |||
79 | System.exit(0); | ||
80 | } | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Class to contain arguments for maplay. | ||
85 | */ | ||
86 | static class jlcArgs | ||
87 | { | ||
88 | // channel constants moved into OutputChannels class. | ||
89 | //public static final int both = 0; | ||
90 | //public static final int left = 1; | ||
91 | //public static final int right = 2; | ||
92 | //public static final int downmix = 3; | ||
93 | |||
94 | public int which_c; | ||
95 | public int output_mode; | ||
96 | public boolean use_own_scalefactor; | ||
97 | public float scalefactor; | ||
98 | public String output_filename; | ||
99 | public String filename; | ||
100 | //public boolean stdout_mode; | ||
101 | public boolean verbose_mode; | ||
102 | public int verbose_level = 3; | ||
103 | |||
104 | public jlcArgs() | ||
105 | { | ||
106 | which_c = OutputChannels.BOTH_CHANNELS; | ||
107 | use_own_scalefactor = false; | ||
108 | scalefactor = (float) 32768.0; | ||
109 | //stdout_mode = false; | ||
110 | verbose_mode = false; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * Process user arguments. | ||
115 | * | ||
116 | * Returns true if successful. | ||
117 | */ | ||
118 | public boolean processArgs(String[] argv) | ||
119 | { | ||
120 | filename = null; | ||
121 | Crc16[] crc; | ||
122 | crc = new Crc16[1]; | ||
123 | int i; | ||
124 | int argc = argv.length; | ||
125 | |||
126 | //stdout_mode = false; | ||
127 | verbose_mode = false; | ||
128 | output_mode = OutputChannels.BOTH_CHANNELS; | ||
129 | output_filename = ""; | ||
130 | if (argc < 2 || argv[1].equals("-h")) | ||
131 | return Usage(); | ||
132 | |||
133 | i = 1; | ||
134 | while (i < argc) | ||
135 | { | ||
136 | /* System.out.println("Option = "+argv[i]);*/ | ||
137 | if (argv[i].charAt(0) == '-') | ||
138 | { | ||
139 | if (argv[i].startsWith("-v")) | ||
140 | { | ||
141 | verbose_mode = true; | ||
142 | if (argv[i].length()>2) | ||
143 | { | ||
144 | try | ||
145 | { | ||
146 | String level = argv[i].substring(2); | ||
147 | verbose_level = Integer.parseInt(level); | ||
148 | } | ||
149 | catch (NumberFormatException ex) | ||
150 | { | ||
151 | System.err.println("Invalid verbose level. Using default."); | ||
152 | } | ||
153 | } | ||
154 | System.out.println("Verbose Activated (level "+verbose_level+")"); | ||
155 | } | ||
156 | /* else if (argv[i].equals("-s")) | ||
157 | ma.stdout_mode = true; */ | ||
158 | else if (argv[i].equals("-p")) | ||
159 | { | ||
160 | if (++i == argc) | ||
161 | { | ||
162 | System.out.println("Please specify an output filename after the -p option!"); | ||
163 | System.exit (1); | ||
164 | } | ||
165 | //output_mode = O_WAVEFILE; | ||
166 | output_filename = argv[i]; | ||
167 | } | ||
168 | /*else if (argv[i].equals("-f")) | ||
169 | { | ||
170 | if (++i == argc) | ||
171 | { | ||
172 | System.out.println("Please specify a new scalefactor after the -f option!"); | ||
173 | System.exit(1); | ||
174 | } | ||
175 | ma.use_own_scalefactor = true; | ||
176 | // ma.scalefactor = argv[i]; | ||
177 | }*/ | ||
178 | else return Usage(); | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | filename = argv[i]; | ||
183 | System.out.println("FileName = "+argv[i]); | ||
184 | if (filename == null) return Usage(); | ||
185 | } | ||
186 | i++; | ||
187 | } | ||
188 | if (filename == null) | ||
189 | return Usage(); | ||
190 | |||
191 | return true; | ||
192 | } | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Usage of JavaLayer. | ||
197 | */ | ||
198 | public boolean Usage() | ||
199 | { | ||
200 | System.out.println("JavaLayer Converter :"); | ||
201 | System.out.println(" -v[x] verbose mode. "); | ||
202 | System.out.println(" default = 2"); | ||
203 | /* System.out.println(" -s write u-law samples at 8 kHz rate to stdout"); | ||
204 | System.out.println(" -l decode only the left channel"); | ||
205 | System.out.println(" -r decode only the right channel"); | ||
206 | System.out.println(" -d downmix mode (layer III only)"); | ||
207 | System.out.println(" -s write pcm samples to stdout"); | ||
208 | System.out.println(" -d downmix mode (layer III only)");*/ | ||
209 | System.out.println(" -p name output as a PCM wave file"); | ||
210 | System.out.println(""); | ||
211 | System.out.println(" More info on http://www.javazoom.net"); | ||
212 | /* System.out.println(" -f ushort use this scalefactor instead of the default value 32768");*/ | ||
213 | return false; | ||
214 | } | ||
215 | }; | ||
216 | }; \ No newline at end of file | ||
diff --git a/songdbj/javazoom/jl/decoder/BitReserve.java b/songdbj/javazoom/jl/decoder/BitReserve.java new file mode 100644 index 0000000000..a5d3056d61 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/BitReserve.java | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 12/12/99 0.0.7 Implementation stores single bits | ||
5 | * as ints for better performance. mdm@techie.com. | ||
6 | * | ||
7 | * 02/28/99 0.0 Java Conversion by E.B, javalayer@javazoom.net | ||
8 | * | ||
9 | * Adapted from the public c code by Jeff Tsay. | ||
10 | * | ||
11 | *----------------------------------------------------------------------- | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU Library General Public License as published | ||
14 | * by the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU Library General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU Library General Public | ||
23 | * License along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | *---------------------------------------------------------------------- | ||
26 | */ | ||
27 | |||
28 | package javazoom.jl.decoder; | ||
29 | |||
30 | /** | ||
31 | * Implementation of Bit Reservoir for Layer III. | ||
32 | * <p> | ||
33 | * The implementation stores single bits as a word in the buffer. If | ||
34 | * a bit is set, the corresponding word in the buffer will be non-zero. | ||
35 | * If a bit is clear, the corresponding word is zero. Although this | ||
36 | * may seem waseful, this can be a factor of two quicker than | ||
37 | * packing 8 bits to a byte and extracting. | ||
38 | * <p> | ||
39 | */ | ||
40 | |||
41 | // REVIEW: there is no range checking, so buffer underflow or overflow | ||
42 | // can silently occur. | ||
43 | final class BitReserve | ||
44 | { | ||
45 | /** | ||
46 | * Size of the internal buffer to store the reserved bits. | ||
47 | * Must be a power of 2. And x8, as each bit is stored as a single | ||
48 | * entry. | ||
49 | */ | ||
50 | private static final int BUFSIZE = 4096*8; | ||
51 | |||
52 | /** | ||
53 | * Mask that can be used to quickly implement the | ||
54 | * modulus operation on BUFSIZE. | ||
55 | */ | ||
56 | private static final int BUFSIZE_MASK = BUFSIZE-1; | ||
57 | |||
58 | private int offset, totbit, buf_byte_idx; | ||
59 | private final int[] buf = new int[BUFSIZE]; | ||
60 | private int buf_bit_idx; | ||
61 | |||
62 | BitReserve() | ||
63 | { | ||
64 | |||
65 | offset = 0; | ||
66 | totbit = 0; | ||
67 | buf_byte_idx = 0; | ||
68 | } | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Return totbit Field. | ||
73 | */ | ||
74 | public int hsstell() | ||
75 | { | ||
76 | return(totbit); | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * Read a number bits from the bit stream. | ||
81 | * @param N the number of | ||
82 | */ | ||
83 | public int hgetbits(int N) | ||
84 | { | ||
85 | totbit += N; | ||
86 | |||
87 | int val = 0; | ||
88 | |||
89 | int pos = buf_byte_idx; | ||
90 | if (pos+N < BUFSIZE) | ||
91 | { | ||
92 | while (N-- > 0) | ||
93 | { | ||
94 | val <<= 1; | ||
95 | val |= ((buf[pos++]!=0) ? 1 : 0); | ||
96 | } | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | while (N-- > 0) | ||
101 | { | ||
102 | val <<= 1; | ||
103 | val |= ((buf[pos]!=0) ? 1 : 0); | ||
104 | pos = (pos+1) & BUFSIZE_MASK; | ||
105 | } | ||
106 | } | ||
107 | buf_byte_idx = pos; | ||
108 | return val; | ||
109 | } | ||
110 | |||
111 | |||
112 | |||
113 | /** | ||
114 | * Read 1 bit from the bit stream. | ||
115 | */ | ||
116 | /* | ||
117 | public int hget1bit_old() | ||
118 | { | ||
119 | int val; | ||
120 | totbit++; | ||
121 | if (buf_bit_idx == 0) | ||
122 | { | ||
123 | buf_bit_idx = 8; | ||
124 | buf_byte_idx++; | ||
125 | } | ||
126 | // BUFSIZE = 4096 = 2^12, so | ||
127 | // buf_byte_idx%BUFSIZE == buf_byte_idx & 0xfff | ||
128 | val = buf[buf_byte_idx & BUFSIZE_MASK] & putmask[buf_bit_idx]; | ||
129 | buf_bit_idx--; | ||
130 | val = val >>> buf_bit_idx; | ||
131 | return val; | ||
132 | } | ||
133 | */ | ||
134 | /** | ||
135 | * Returns next bit from reserve. | ||
136 | * @returns 0 if next bit is reset, or 1 if next bit is set. | ||
137 | */ | ||
138 | public int hget1bit() | ||
139 | { | ||
140 | totbit++; | ||
141 | int val = buf[buf_byte_idx]; | ||
142 | buf_byte_idx = (buf_byte_idx+1) & BUFSIZE_MASK; | ||
143 | return val; | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * Retrieves bits from the reserve. | ||
148 | */ | ||
149 | /* | ||
150 | public int readBits(int[] out, int len) | ||
151 | { | ||
152 | if (buf_bit_idx == 0) | ||
153 | { | ||
154 | buf_bit_idx = 8; | ||
155 | buf_byte_idx++; | ||
156 | current = buf[buf_byte_idx & BUFSIZE_MASK]; | ||
157 | } | ||
158 | |||
159 | |||
160 | |||
161 | // save total number of bits returned | ||
162 | len = buf_bit_idx; | ||
163 | buf_bit_idx = 0; | ||
164 | |||
165 | int b = current; | ||
166 | int count = len-1; | ||
167 | |||
168 | while (count >= 0) | ||
169 | { | ||
170 | out[count--] = (b & 0x1); | ||
171 | b >>>= 1; | ||
172 | } | ||
173 | |||
174 | totbit += len; | ||
175 | return len; | ||
176 | } | ||
177 | */ | ||
178 | |||
179 | /** | ||
180 | * Write 8 bits into the bit stream. | ||
181 | */ | ||
182 | public void hputbuf(int val) | ||
183 | { | ||
184 | int ofs = offset; | ||
185 | buf[ofs++] = val & 0x80; | ||
186 | buf[ofs++] = val & 0x40; | ||
187 | buf[ofs++] = val & 0x20; | ||
188 | buf[ofs++] = val & 0x10; | ||
189 | buf[ofs++] = val & 0x08; | ||
190 | buf[ofs++] = val & 0x04; | ||
191 | buf[ofs++] = val & 0x02; | ||
192 | buf[ofs++] = val & 0x01; | ||
193 | |||
194 | if (ofs==BUFSIZE) | ||
195 | offset = 0; | ||
196 | else | ||
197 | offset = ofs; | ||
198 | |||
199 | } | ||
200 | |||
201 | /** | ||
202 | * Rewind N bits in Stream. | ||
203 | */ | ||
204 | public void rewindNbits(int N) | ||
205 | { | ||
206 | totbit -= N; | ||
207 | buf_byte_idx -= N; | ||
208 | if (buf_byte_idx<0) | ||
209 | buf_byte_idx += BUFSIZE; | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * Rewind N bytes in Stream. | ||
214 | */ | ||
215 | public void rewindNbytes(int N) | ||
216 | { | ||
217 | int bits = (N << 3); | ||
218 | totbit -= bits; | ||
219 | buf_byte_idx -= bits; | ||
220 | if (buf_byte_idx<0) | ||
221 | buf_byte_idx += BUFSIZE; | ||
222 | } | ||
223 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/Bitstream.java b/songdbj/javazoom/jl/decoder/Bitstream.java new file mode 100644 index 0000000000..cebbd5b03b --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Bitstream.java | |||
@@ -0,0 +1,655 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 11/17/04 Uncomplete frames discarded. E.B, javalayer@javazoom.net | ||
5 | * | ||
6 | * 12/05/03 ID3v2 tag returned. E.B, javalayer@javazoom.net | ||
7 | * | ||
8 | * 12/12/99 Based on Ibitstream. Exceptions thrown on errors, | ||
9 | * Temporary removed seek functionality. mdm@techie.com | ||
10 | * | ||
11 | * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net | ||
12 | * | ||
13 | * 04/14/97 : Added function prototypes for new syncing and seeking | ||
14 | * mechanisms. Also made this file portable. Changes made by Jeff Tsay | ||
15 | * | ||
16 | * @(#) ibitstream.h 1.5, last edit: 6/15/94 16:55:34 | ||
17 | * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de) | ||
18 | * @(#) Berlin University of Technology | ||
19 | *----------------------------------------------------------------------- | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU Library General Public License as published | ||
22 | * by the Free Software Foundation; either version 2 of the License, or | ||
23 | * (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU Library General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU Library General Public | ||
31 | * License along with this program; if not, write to the Free Software | ||
32 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | *---------------------------------------------------------------------- | ||
34 | */ | ||
35 | |||
36 | package javazoom.jl.decoder; | ||
37 | |||
38 | import java.io.BufferedInputStream; | ||
39 | import java.io.ByteArrayInputStream; | ||
40 | import java.io.IOException; | ||
41 | import java.io.InputStream; | ||
42 | import java.io.PushbackInputStream; | ||
43 | |||
44 | |||
45 | /** | ||
46 | * The <code>Bistream</code> class is responsible for parsing | ||
47 | * an MPEG audio bitstream. | ||
48 | * | ||
49 | * <b>REVIEW:</b> much of the parsing currently occurs in the | ||
50 | * various decoders. This should be moved into this class and associated | ||
51 | * inner classes. | ||
52 | */ | ||
53 | public final class Bitstream implements BitstreamErrors | ||
54 | { | ||
55 | /** | ||
56 | * Synchronization control constant for the initial | ||
57 | * synchronization to the start of a frame. | ||
58 | */ | ||
59 | static byte INITIAL_SYNC = 0; | ||
60 | |||
61 | /** | ||
62 | * Synchronization control constant for non-initial frame | ||
63 | * synchronizations. | ||
64 | */ | ||
65 | static byte STRICT_SYNC = 1; | ||
66 | |||
67 | // max. 1730 bytes per frame: 144 * 384kbit/s / 32000 Hz + 2 Bytes CRC | ||
68 | /** | ||
69 | * Maximum size of the frame buffer. | ||
70 | */ | ||
71 | private static final int BUFFER_INT_SIZE = 433; | ||
72 | |||
73 | /** | ||
74 | * The frame buffer that holds the data for the current frame. | ||
75 | */ | ||
76 | private final int[] framebuffer = new int[BUFFER_INT_SIZE]; | ||
77 | |||
78 | /** | ||
79 | * Number of valid bytes in the frame buffer. | ||
80 | */ | ||
81 | private int framesize; | ||
82 | |||
83 | /** | ||
84 | * The bytes read from the stream. | ||
85 | */ | ||
86 | private byte[] frame_bytes = new byte[BUFFER_INT_SIZE*4]; | ||
87 | |||
88 | /** | ||
89 | * Index into <code>framebuffer</code> where the next bits are | ||
90 | * retrieved. | ||
91 | */ | ||
92 | private int wordpointer; | ||
93 | |||
94 | /** | ||
95 | * Number (0-31, from MSB to LSB) of next bit for get_bits() | ||
96 | */ | ||
97 | private int bitindex; | ||
98 | |||
99 | /** | ||
100 | * The current specified syncword | ||
101 | */ | ||
102 | private int syncword; | ||
103 | |||
104 | /** | ||
105 | * Audio header position in stream. | ||
106 | */ | ||
107 | private int header_pos = 0; | ||
108 | |||
109 | /** | ||
110 | * | ||
111 | */ | ||
112 | private boolean single_ch_mode; | ||
113 | //private int current_frame_number; | ||
114 | //private int last_frame_number; | ||
115 | |||
116 | private final int bitmask[] = {0, // dummy | ||
117 | 0x00000001, 0x00000003, 0x00000007, 0x0000000F, | ||
118 | 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, | ||
119 | 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, | ||
120 | 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, | ||
121 | 0x0001FFFF }; | ||
122 | |||
123 | private final PushbackInputStream source; | ||
124 | |||
125 | private final Header header = new Header(); | ||
126 | |||
127 | private final byte syncbuf[] = new byte[4]; | ||
128 | |||
129 | private Crc16[] crc = new Crc16[1]; | ||
130 | |||
131 | private byte[] rawid3v2 = null; | ||
132 | |||
133 | private boolean firstframe = true; | ||
134 | |||
135 | |||
136 | /** | ||
137 | * Construct a IBitstream that reads data from a | ||
138 | * given InputStream. | ||
139 | * | ||
140 | * @param in The InputStream to read from. | ||
141 | */ | ||
142 | public Bitstream(InputStream in) | ||
143 | { | ||
144 | if (in==null) throw new NullPointerException("in"); | ||
145 | in = new BufferedInputStream(in); | ||
146 | loadID3v2(in); | ||
147 | firstframe = true; | ||
148 | //source = new PushbackInputStream(in, 1024); | ||
149 | source = new PushbackInputStream(in, BUFFER_INT_SIZE*4); | ||
150 | |||
151 | closeFrame(); | ||
152 | //current_frame_number = -1; | ||
153 | //last_frame_number = -1; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * Return position of the first audio header. | ||
158 | * @return size of ID3v2 tag frames. | ||
159 | */ | ||
160 | public int header_pos() | ||
161 | { | ||
162 | return header_pos; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * Load ID3v2 frames. | ||
167 | * @param in MP3 InputStream. | ||
168 | * @author JavaZOOM | ||
169 | */ | ||
170 | private void loadID3v2(InputStream in) | ||
171 | { | ||
172 | int size = -1; | ||
173 | try | ||
174 | { | ||
175 | // Read ID3v2 header (10 bytes). | ||
176 | in.mark(10); | ||
177 | size = readID3v2Header(in); | ||
178 | header_pos = size; | ||
179 | } | ||
180 | catch (IOException e) | ||
181 | {} | ||
182 | finally | ||
183 | { | ||
184 | try | ||
185 | { | ||
186 | // Unread ID3v2 header (10 bytes). | ||
187 | in.reset(); | ||
188 | } | ||
189 | catch (IOException e) | ||
190 | {} | ||
191 | } | ||
192 | // Load ID3v2 tags. | ||
193 | try | ||
194 | { | ||
195 | if (size > 0) | ||
196 | { | ||
197 | rawid3v2 = new byte[size]; | ||
198 | in.read(rawid3v2,0,rawid3v2.length); | ||
199 | } | ||
200 | } | ||
201 | catch (IOException e) | ||
202 | {} | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * Parse ID3v2 tag header to find out size of ID3v2 frames. | ||
207 | * @param in MP3 InputStream | ||
208 | * @return size of ID3v2 frames + header | ||
209 | * @throws IOException | ||
210 | * @author JavaZOOM | ||
211 | */ | ||
212 | private int readID3v2Header(InputStream in) throws IOException | ||
213 | { | ||
214 | byte[] id3header = new byte[4]; | ||
215 | int size = -10; | ||
216 | in.read(id3header,0,3); | ||
217 | // Look for ID3v2 | ||
218 | if ( (id3header[0]=='I') && (id3header[1]=='D') && (id3header[2]=='3')) | ||
219 | { | ||
220 | in.read(id3header,0,3); | ||
221 | int majorVersion = id3header[0]; | ||
222 | int revision = id3header[1]; | ||
223 | in.read(id3header,0,4); | ||
224 | size = (int) (id3header[0] << 21) + (id3header[1] << 14) + (id3header[2] << 7) + (id3header[3]); | ||
225 | } | ||
226 | return (size+10); | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * Return raw ID3v2 frames + header. | ||
231 | * @return ID3v2 InputStream or null if ID3v2 frames are not available. | ||
232 | */ | ||
233 | public InputStream getRawID3v2() | ||
234 | { | ||
235 | if (rawid3v2 == null) return null; | ||
236 | else | ||
237 | { | ||
238 | ByteArrayInputStream bain = new ByteArrayInputStream(rawid3v2); | ||
239 | return bain; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * Close the Bitstream. | ||
245 | * @throws BitstreamException | ||
246 | */ | ||
247 | public void close() throws BitstreamException | ||
248 | { | ||
249 | try | ||
250 | { | ||
251 | source.close(); | ||
252 | } | ||
253 | catch (IOException ex) | ||
254 | { | ||
255 | throw newBitstreamException(STREAM_ERROR, ex); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | /** | ||
260 | * Reads and parses the next frame from the input source. | ||
261 | * @return the Header describing details of the frame read, | ||
262 | * or null if the end of the stream has been reached. | ||
263 | */ | ||
264 | public Header readFrame() throws BitstreamException | ||
265 | { | ||
266 | Header result = null; | ||
267 | try | ||
268 | { | ||
269 | result = readNextFrame(); | ||
270 | // E.B, Parse VBR (if any) first frame. | ||
271 | if (firstframe == true) | ||
272 | { | ||
273 | result.parseVBR(frame_bytes); | ||
274 | firstframe = false; | ||
275 | } | ||
276 | } | ||
277 | catch (BitstreamException ex) | ||
278 | { | ||
279 | if ((ex.getErrorCode()==INVALIDFRAME)) | ||
280 | { | ||
281 | // Try to skip this frame. | ||
282 | //System.out.println("INVALIDFRAME"); | ||
283 | try | ||
284 | { | ||
285 | closeFrame(); | ||
286 | result = readNextFrame(); | ||
287 | } | ||
288 | catch (BitstreamException e) | ||
289 | { | ||
290 | if ((e.getErrorCode()!=STREAM_EOF)) | ||
291 | { | ||
292 | // wrap original exception so stack trace is maintained. | ||
293 | throw newBitstreamException(e.getErrorCode(), e); | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | else if ((ex.getErrorCode()!=STREAM_EOF)) | ||
298 | { | ||
299 | // wrap original exception so stack trace is maintained. | ||
300 | throw newBitstreamException(ex.getErrorCode(), ex); | ||
301 | } | ||
302 | } | ||
303 | return result; | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * Read next MP3 frame. | ||
308 | * @return MP3 frame header. | ||
309 | * @throws BitstreamException | ||
310 | */ | ||
311 | private Header readNextFrame() throws BitstreamException | ||
312 | { | ||
313 | if (framesize == -1) | ||
314 | { | ||
315 | nextFrame(); | ||
316 | } | ||
317 | return header; | ||
318 | } | ||
319 | |||
320 | |||
321 | /** | ||
322 | * Read next MP3 frame. | ||
323 | * @throws BitstreamException | ||
324 | */ | ||
325 | private void nextFrame() throws BitstreamException | ||
326 | { | ||
327 | // entire frame is read by the header class. | ||
328 | header.read_header(this, crc); | ||
329 | } | ||
330 | |||
331 | /** | ||
332 | * Unreads the bytes read from the frame. | ||
333 | * @throws BitstreamException | ||
334 | */ | ||
335 | // REVIEW: add new error codes for this. | ||
336 | public void unreadFrame() throws BitstreamException | ||
337 | { | ||
338 | if (wordpointer==-1 && bitindex==-1 && (framesize>0)) | ||
339 | { | ||
340 | try | ||
341 | { | ||
342 | source.unread(frame_bytes, 0, framesize); | ||
343 | } | ||
344 | catch (IOException ex) | ||
345 | { | ||
346 | throw newBitstreamException(STREAM_ERROR); | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * Close MP3 frame. | ||
353 | */ | ||
354 | public void closeFrame() | ||
355 | { | ||
356 | framesize = -1; | ||
357 | wordpointer = -1; | ||
358 | bitindex = -1; | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * Determines if the next 4 bytes of the stream represent a | ||
363 | * frame header. | ||
364 | */ | ||
365 | public boolean isSyncCurrentPosition(int syncmode) throws BitstreamException | ||
366 | { | ||
367 | int read = readBytes(syncbuf, 0, 4); | ||
368 | int headerstring = ((syncbuf[0] << 24) & 0xFF000000) | ((syncbuf[1] << 16) & 0x00FF0000) | ((syncbuf[2] << 8) & 0x0000FF00) | ((syncbuf[3] << 0) & 0x000000FF); | ||
369 | |||
370 | try | ||
371 | { | ||
372 | source.unread(syncbuf, 0, read); | ||
373 | } | ||
374 | catch (IOException ex) | ||
375 | { | ||
376 | } | ||
377 | |||
378 | boolean sync = false; | ||
379 | switch (read) | ||
380 | { | ||
381 | case 0: | ||
382 | sync = true; | ||
383 | break; | ||
384 | case 4: | ||
385 | sync = isSyncMark(headerstring, syncmode, syncword); | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | return sync; | ||
390 | } | ||
391 | |||
392 | |||
393 | // REVIEW: this class should provide inner classes to | ||
394 | // parse the frame contents. Eventually, readBits will | ||
395 | // be removed. | ||
396 | public int readBits(int n) | ||
397 | { | ||
398 | return get_bits(n); | ||
399 | } | ||
400 | |||
401 | public int readCheckedBits(int n) | ||
402 | { | ||
403 | // REVIEW: implement CRC check. | ||
404 | return get_bits(n); | ||
405 | } | ||
406 | |||
407 | protected BitstreamException newBitstreamException(int errorcode) | ||
408 | { | ||
409 | return new BitstreamException(errorcode, null); | ||
410 | } | ||
411 | protected BitstreamException newBitstreamException(int errorcode, Throwable throwable) | ||
412 | { | ||
413 | return new BitstreamException(errorcode, throwable); | ||
414 | } | ||
415 | |||
416 | /** | ||
417 | * Get next 32 bits from bitstream. | ||
418 | * They are stored in the headerstring. | ||
419 | * syncmod allows Synchro flag ID | ||
420 | * The returned value is False at the end of stream. | ||
421 | */ | ||
422 | |||
423 | int syncHeader(byte syncmode) throws BitstreamException | ||
424 | { | ||
425 | boolean sync; | ||
426 | int headerstring; | ||
427 | // read additional 2 bytes | ||
428 | int bytesRead = readBytes(syncbuf, 0, 3); | ||
429 | |||
430 | if (bytesRead!=3) throw newBitstreamException(STREAM_EOF, null); | ||
431 | |||
432 | headerstring = ((syncbuf[0] << 16) & 0x00FF0000) | ((syncbuf[1] << 8) & 0x0000FF00) | ((syncbuf[2] << 0) & 0x000000FF); | ||
433 | |||
434 | do | ||
435 | { | ||
436 | headerstring <<= 8; | ||
437 | |||
438 | if (readBytes(syncbuf, 3, 1)!=1) | ||
439 | throw newBitstreamException(STREAM_EOF, null); | ||
440 | |||
441 | headerstring |= (syncbuf[3] & 0x000000FF); | ||
442 | |||
443 | sync = isSyncMark(headerstring, syncmode, syncword); | ||
444 | } | ||
445 | while (!sync); | ||
446 | |||
447 | //current_frame_number++; | ||
448 | //if (last_frame_number < current_frame_number) last_frame_number = current_frame_number; | ||
449 | |||
450 | return headerstring; | ||
451 | } | ||
452 | |||
453 | public boolean isSyncMark(int headerstring, int syncmode, int word) | ||
454 | { | ||
455 | boolean sync = false; | ||
456 | |||
457 | if (syncmode == INITIAL_SYNC) | ||
458 | { | ||
459 | //sync = ((headerstring & 0xFFF00000) == 0xFFF00000); | ||
460 | sync = ((headerstring & 0xFFE00000) == 0xFFE00000); // SZD: MPEG 2.5 | ||
461 | } | ||
462 | else | ||
463 | { | ||
464 | sync = ((headerstring & 0xFFF80C00) == word) && | ||
465 | (((headerstring & 0x000000C0) == 0x000000C0) == single_ch_mode); | ||
466 | } | ||
467 | |||
468 | // filter out invalid sample rate | ||
469 | if (sync) | ||
470 | sync = (((headerstring >>> 10) & 3)!=3); | ||
471 | // filter out invalid layer | ||
472 | if (sync) | ||
473 | sync = (((headerstring >>> 17) & 3)!=0); | ||
474 | // filter out invalid version | ||
475 | if (sync) | ||
476 | sync = (((headerstring >>> 19) & 3)!=1); | ||
477 | |||
478 | return sync; | ||
479 | } | ||
480 | |||
481 | /** | ||
482 | * Reads the data for the next frame. The frame is not parsed | ||
483 | * until parse frame is called. | ||
484 | */ | ||
485 | int read_frame_data(int bytesize) throws BitstreamException | ||
486 | { | ||
487 | int numread = 0; | ||
488 | numread = readFully(frame_bytes, 0, bytesize); | ||
489 | framesize = bytesize; | ||
490 | wordpointer = -1; | ||
491 | bitindex = -1; | ||
492 | return numread; | ||
493 | } | ||
494 | |||
495 | /** | ||
496 | * Parses the data previously read with read_frame_data(). | ||
497 | */ | ||
498 | void parse_frame() throws BitstreamException | ||
499 | { | ||
500 | // Convert Bytes read to int | ||
501 | int b=0; | ||
502 | byte[] byteread = frame_bytes; | ||
503 | int bytesize = framesize; | ||
504 | |||
505 | // Check ID3v1 TAG (True only if last frame). | ||
506 | //for (int t=0;t<(byteread.length)-2;t++) | ||
507 | //{ | ||
508 | // if ((byteread[t]=='T') && (byteread[t+1]=='A') && (byteread[t+2]=='G')) | ||
509 | // { | ||
510 | // System.out.println("ID3v1 detected at offset "+t); | ||
511 | // throw newBitstreamException(INVALIDFRAME, null); | ||
512 | // } | ||
513 | //} | ||
514 | |||
515 | for (int k=0;k<bytesize;k=k+4) | ||
516 | { | ||
517 | int convert = 0; | ||
518 | byte b0 = 0; | ||
519 | byte b1 = 0; | ||
520 | byte b2 = 0; | ||
521 | byte b3 = 0; | ||
522 | b0 = byteread[k]; | ||
523 | if (k+1<bytesize) b1 = byteread[k+1]; | ||
524 | if (k+2<bytesize) b2 = byteread[k+2]; | ||
525 | if (k+3<bytesize) b3 = byteread[k+3]; | ||
526 | framebuffer[b++] = ((b0 << 24) &0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF); | ||
527 | } | ||
528 | wordpointer = 0; | ||
529 | bitindex = 0; | ||
530 | } | ||
531 | |||
532 | /** | ||
533 | * Read bits from buffer into the lower bits of an unsigned int. | ||
534 | * The LSB contains the latest read bit of the stream. | ||
535 | * (1 <= number_of_bits <= 16) | ||
536 | */ | ||
537 | public int get_bits(int number_of_bits) | ||
538 | { | ||
539 | int returnvalue = 0; | ||
540 | int sum = bitindex + number_of_bits; | ||
541 | |||
542 | // E.B | ||
543 | // There is a problem here, wordpointer could be -1 ?! | ||
544 | if (wordpointer < 0) wordpointer = 0; | ||
545 | // E.B : End. | ||
546 | |||
547 | if (sum <= 32) | ||
548 | { | ||
549 | // all bits contained in *wordpointer | ||
550 | returnvalue = (framebuffer[wordpointer] >>> (32 - sum)) & bitmask[number_of_bits]; | ||
551 | // returnvalue = (wordpointer[0] >> (32 - sum)) & bitmask[number_of_bits]; | ||
552 | if ((bitindex += number_of_bits) == 32) | ||
553 | { | ||
554 | bitindex = 0; | ||
555 | wordpointer++; // added by me! | ||
556 | } | ||
557 | return returnvalue; | ||
558 | } | ||
559 | |||
560 | // E.B : Check that ? | ||
561 | //((short[])&returnvalue)[0] = ((short[])wordpointer + 1)[0]; | ||
562 | //wordpointer++; // Added by me! | ||
563 | //((short[])&returnvalue + 1)[0] = ((short[])wordpointer)[0]; | ||
564 | int Right = (framebuffer[wordpointer] & 0x0000FFFF); | ||
565 | wordpointer++; | ||
566 | int Left = (framebuffer[wordpointer] & 0xFFFF0000); | ||
567 | returnvalue = ((Right << 16) & 0xFFFF0000) | ((Left >>> 16)& 0x0000FFFF); | ||
568 | |||
569 | returnvalue >>>= 48 - sum; // returnvalue >>= 16 - (number_of_bits - (32 - bitindex)) | ||
570 | returnvalue &= bitmask[number_of_bits]; | ||
571 | bitindex = sum - 32; | ||
572 | return returnvalue; | ||
573 | } | ||
574 | |||
575 | /** | ||
576 | * Set the word we want to sync the header to. | ||
577 | * In Big-Endian byte order | ||
578 | */ | ||
579 | void set_syncword(int syncword0) | ||
580 | { | ||
581 | syncword = syncword0 & 0xFFFFFF3F; | ||
582 | single_ch_mode = ((syncword0 & 0x000000C0) == 0x000000C0); | ||
583 | } | ||
584 | /** | ||
585 | * Reads the exact number of bytes from the source | ||
586 | * input stream into a byte array. | ||
587 | * | ||
588 | * @param b The byte array to read the specified number | ||
589 | * of bytes into. | ||
590 | * @param offs The index in the array where the first byte | ||
591 | * read should be stored. | ||
592 | * @param len the number of bytes to read. | ||
593 | * | ||
594 | * @exception BitstreamException is thrown if the specified | ||
595 | * number of bytes could not be read from the stream. | ||
596 | */ | ||
597 | private int readFully(byte[] b, int offs, int len) | ||
598 | throws BitstreamException | ||
599 | { | ||
600 | int nRead = 0; | ||
601 | try | ||
602 | { | ||
603 | while (len > 0) | ||
604 | { | ||
605 | int bytesread = source.read(b, offs, len); | ||
606 | if (bytesread == -1) | ||
607 | { | ||
608 | while (len-->0) | ||
609 | { | ||
610 | b[offs++] = 0; | ||
611 | } | ||
612 | break; | ||
613 | //throw newBitstreamException(UNEXPECTED_EOF, new EOFException()); | ||
614 | } | ||
615 | nRead = nRead + bytesread; | ||
616 | offs += bytesread; | ||
617 | len -= bytesread; | ||
618 | } | ||
619 | } | ||
620 | catch (IOException ex) | ||
621 | { | ||
622 | throw newBitstreamException(STREAM_ERROR, ex); | ||
623 | } | ||
624 | return nRead; | ||
625 | } | ||
626 | |||
627 | /** | ||
628 | * Simlar to readFully, but doesn't throw exception when | ||
629 | * EOF is reached. | ||
630 | */ | ||
631 | private int readBytes(byte[] b, int offs, int len) | ||
632 | throws BitstreamException | ||
633 | { | ||
634 | int totalBytesRead = 0; | ||
635 | try | ||
636 | { | ||
637 | while (len > 0) | ||
638 | { | ||
639 | int bytesread = source.read(b, offs, len); | ||
640 | if (bytesread == -1) | ||
641 | { | ||
642 | break; | ||
643 | } | ||
644 | totalBytesRead += bytesread; | ||
645 | offs += bytesread; | ||
646 | len -= bytesread; | ||
647 | } | ||
648 | } | ||
649 | catch (IOException ex) | ||
650 | { | ||
651 | throw newBitstreamException(STREAM_ERROR, ex); | ||
652 | } | ||
653 | return totalBytesRead; | ||
654 | } | ||
655 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/BitstreamErrors.java b/songdbj/javazoom/jl/decoder/BitstreamErrors.java new file mode 100644 index 0000000000..2bdee6d797 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/BitstreamErrors.java | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 11/17/04 INVALIDFRAME code added. javalayer@javazoom.net | ||
4 | * 12/12/99 Initial version. mdm@techie.com | ||
5 | *----------------------------------------------------------------------- | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU Library General Public License as published | ||
8 | * by the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU Library General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Library General Public | ||
17 | * License along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | *---------------------------------------------------------------------- | ||
20 | */ | ||
21 | |||
22 | package javazoom.jl.decoder; | ||
23 | |||
24 | /** | ||
25 | * This interface describes all error codes that can be thrown | ||
26 | * in <code>BistreamException</code>s. | ||
27 | * | ||
28 | * @see BitstreamException | ||
29 | * | ||
30 | * @author MDM 12/12/99 | ||
31 | * @since 0.0.6 | ||
32 | */ | ||
33 | |||
34 | public interface BitstreamErrors extends JavaLayerErrors | ||
35 | { | ||
36 | |||
37 | /** | ||
38 | * An undeterminable error occurred. | ||
39 | */ | ||
40 | static public final int UNKNOWN_ERROR = BITSTREAM_ERROR + 0; | ||
41 | |||
42 | /** | ||
43 | * The header describes an unknown sample rate. | ||
44 | */ | ||
45 | static public final int UNKNOWN_SAMPLE_RATE = BITSTREAM_ERROR + 1; | ||
46 | |||
47 | /** | ||
48 | * A problem occurred reading from the stream. | ||
49 | */ | ||
50 | static public final int STREAM_ERROR = BITSTREAM_ERROR + 2; | ||
51 | |||
52 | /** | ||
53 | * The end of the stream was reached prematurely. | ||
54 | */ | ||
55 | static public final int UNEXPECTED_EOF = BITSTREAM_ERROR + 3; | ||
56 | |||
57 | /** | ||
58 | * The end of the stream was reached. | ||
59 | */ | ||
60 | static public final int STREAM_EOF = BITSTREAM_ERROR + 4; | ||
61 | |||
62 | /** | ||
63 | * Frame data are missing. | ||
64 | */ | ||
65 | static public final int INVALIDFRAME = BITSTREAM_ERROR + 5; | ||
66 | |||
67 | /** | ||
68 | * | ||
69 | */ | ||
70 | static public final int BITSTREAM_LAST = 0x1ff; | ||
71 | |||
72 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/BitstreamException.java b/songdbj/javazoom/jl/decoder/BitstreamException.java new file mode 100644 index 0000000000..99faa8962d --- /dev/null +++ b/songdbj/javazoom/jl/decoder/BitstreamException.java | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | /** | ||
24 | * Instances of <code>BitstreamException</code> are thrown | ||
25 | * when operations on a <code>Bitstream</code> fail. | ||
26 | * <p> | ||
27 | * The exception provides details of the exception condition | ||
28 | * in two ways: | ||
29 | * <ol><li> | ||
30 | * as an error-code describing the nature of the error | ||
31 | * </li><br></br><li> | ||
32 | * as the <code>Throwable</code> instance, if any, that was thrown | ||
33 | * indicating that an exceptional condition has occurred. | ||
34 | * </li></ol></p> | ||
35 | * | ||
36 | * @since 0.0.6 | ||
37 | * @author MDM 12/12/99 | ||
38 | */ | ||
39 | |||
40 | public class BitstreamException extends JavaLayerException | ||
41 | implements BitstreamErrors | ||
42 | { | ||
43 | private int errorcode = UNKNOWN_ERROR; | ||
44 | |||
45 | public BitstreamException(String msg, Throwable t) | ||
46 | { | ||
47 | super(msg, t); | ||
48 | } | ||
49 | |||
50 | public BitstreamException(int errorcode, Throwable t) | ||
51 | { | ||
52 | this(getErrorString(errorcode), t); | ||
53 | this.errorcode = errorcode; | ||
54 | } | ||
55 | |||
56 | public int getErrorCode() | ||
57 | { | ||
58 | return errorcode; | ||
59 | } | ||
60 | |||
61 | |||
62 | static public String getErrorString(int errorcode) | ||
63 | { | ||
64 | // REVIEW: use resource bundle to map error codes | ||
65 | // to locale-sensitive strings. | ||
66 | |||
67 | return "Bitstream errorcode "+Integer.toHexString(errorcode); | ||
68 | } | ||
69 | |||
70 | |||
71 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/Control.java b/songdbj/javazoom/jl/decoder/Control.java new file mode 100644 index 0000000000..080ed5215e --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Control.java | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | *----------------------------------------------------------------------- | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Library General Public License as published | ||
6 | * by the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library General Public | ||
15 | * License along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | *---------------------------------------------------------------------- | ||
18 | */ | ||
19 | |||
20 | package javazoom.jl.decoder; | ||
21 | |||
22 | /** | ||
23 | * Work in progress. | ||
24 | */ | ||
25 | |||
26 | public interface Control | ||
27 | { | ||
28 | |||
29 | /** | ||
30 | * Starts playback of the media presented by this control. | ||
31 | */ | ||
32 | public void start(); | ||
33 | |||
34 | /** | ||
35 | * Stops playback of the media presented by this control. | ||
36 | */ | ||
37 | public void stop(); | ||
38 | |||
39 | public boolean isPlaying(); | ||
40 | |||
41 | public void pause(); | ||
42 | |||
43 | |||
44 | public boolean isRandomAccess(); | ||
45 | |||
46 | /** | ||
47 | * Retrieves the current position. | ||
48 | */ | ||
49 | public double getPosition(); | ||
50 | |||
51 | /** | ||
52 | * | ||
53 | */ | ||
54 | public void setPosition(double d); | ||
55 | |||
56 | |||
57 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/Crc16.java b/songdbj/javazoom/jl/decoder/Crc16.java new file mode 100644 index 0000000000..c35cc19341 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Crc16.java | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * 11/19/04 : 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 02/12/99 : Java Conversion by E.B , javalayer@javazoom.net | ||
5 | * | ||
6 | * @(#) crc.h 1.5, last edit: 6/15/94 16:55:32 | ||
7 | * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de) | ||
8 | * @(#) Berlin University of Technology | ||
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 | package javazoom.jl.decoder; | ||
26 | |||
27 | /** | ||
28 | * 16-Bit CRC checksum | ||
29 | */ | ||
30 | public final class Crc16 | ||
31 | { | ||
32 | private static short polynomial=(short)0x8005; | ||
33 | private short crc; | ||
34 | |||
35 | /** | ||
36 | * Dummy Constructor | ||
37 | */ | ||
38 | public Crc16() | ||
39 | { | ||
40 | crc = (short) 0xFFFF; | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Feed a bitstring to the crc calculation (0 < length <= 32). | ||
45 | */ | ||
46 | public void add_bits (int bitstring, int length) | ||
47 | { | ||
48 | int bitmask = 1 << (length - 1); | ||
49 | do | ||
50 | if (((crc & 0x8000) == 0) ^ ((bitstring & bitmask) == 0 )) | ||
51 | { | ||
52 | crc <<= 1; | ||
53 | crc ^= polynomial; | ||
54 | } | ||
55 | else | ||
56 | crc <<= 1; | ||
57 | while ((bitmask >>>= 1) != 0); | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * Return the calculated checksum. | ||
62 | * Erase it for next calls to add_bits(). | ||
63 | */ | ||
64 | public short checksum() | ||
65 | { | ||
66 | short sum = crc; | ||
67 | crc = (short) 0xFFFF; | ||
68 | return sum; | ||
69 | } | ||
70 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/Decoder.java b/songdbj/javazoom/jl/decoder/Decoder.java new file mode 100644 index 0000000000..076f9dea27 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Decoder.java | |||
@@ -0,0 +1,357 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 01/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | /** | ||
24 | * The <code>Decoder</code> class encapsulates the details of | ||
25 | * decoding an MPEG audio frame. | ||
26 | * | ||
27 | * @author MDM | ||
28 | * @version 0.0.7 12/12/99 | ||
29 | * @since 0.0.5 | ||
30 | */ | ||
31 | public class Decoder implements DecoderErrors | ||
32 | { | ||
33 | static private final Params DEFAULT_PARAMS = new Params(); | ||
34 | |||
35 | /** | ||
36 | * The Bistream from which the MPEG audio frames are read. | ||
37 | */ | ||
38 | //private Bitstream stream; | ||
39 | |||
40 | /** | ||
41 | * The Obuffer instance that will receive the decoded | ||
42 | * PCM samples. | ||
43 | */ | ||
44 | private Obuffer output; | ||
45 | |||
46 | /** | ||
47 | * Synthesis filter for the left channel. | ||
48 | */ | ||
49 | private SynthesisFilter filter1; | ||
50 | |||
51 | /** | ||
52 | * Sythesis filter for the right channel. | ||
53 | */ | ||
54 | private SynthesisFilter filter2; | ||
55 | |||
56 | /** | ||
57 | * The decoder used to decode layer III frames. | ||
58 | */ | ||
59 | private LayerIIIDecoder l3decoder; | ||
60 | private LayerIIDecoder l2decoder; | ||
61 | private LayerIDecoder l1decoder; | ||
62 | |||
63 | private int outputFrequency; | ||
64 | private int outputChannels; | ||
65 | |||
66 | private Equalizer equalizer = new Equalizer(); | ||
67 | |||
68 | private Params params; | ||
69 | |||
70 | private boolean initialized; | ||
71 | |||
72 | |||
73 | /** | ||
74 | * Creates a new <code>Decoder</code> instance with default | ||
75 | * parameters. | ||
76 | */ | ||
77 | |||
78 | public Decoder() | ||
79 | { | ||
80 | this(null); | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * Creates a new <code>Decoder</code> instance with default | ||
85 | * parameters. | ||
86 | * | ||
87 | * @param params The <code>Params</code> instance that describes | ||
88 | * the customizable aspects of the decoder. | ||
89 | */ | ||
90 | public Decoder(Params params0) | ||
91 | { | ||
92 | if (params0==null) | ||
93 | params0 = DEFAULT_PARAMS; | ||
94 | |||
95 | params = params0; | ||
96 | |||
97 | Equalizer eq = params.getInitialEqualizerSettings(); | ||
98 | if (eq!=null) | ||
99 | { | ||
100 | equalizer.setFrom(eq); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static public Params getDefaultParams() | ||
105 | { | ||
106 | return (Params)DEFAULT_PARAMS.clone(); | ||
107 | } | ||
108 | |||
109 | public void setEqualizer(Equalizer eq) | ||
110 | { | ||
111 | if (eq==null) | ||
112 | eq = Equalizer.PASS_THRU_EQ; | ||
113 | |||
114 | equalizer.setFrom(eq); | ||
115 | |||
116 | float[] factors = equalizer.getBandFactors(); | ||
117 | |||
118 | if (filter1!=null) | ||
119 | filter1.setEQ(factors); | ||
120 | |||
121 | if (filter2!=null) | ||
122 | filter2.setEQ(factors); | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * Decodes one frame from an MPEG audio bitstream. | ||
127 | * | ||
128 | * @param header The header describing the frame to decode. | ||
129 | * @param bitstream The bistream that provides the bits for te body of the frame. | ||
130 | * | ||
131 | * @return A SampleBuffer containing the decoded samples. | ||
132 | */ | ||
133 | public Obuffer decodeFrame(Header header, Bitstream stream) | ||
134 | throws DecoderException | ||
135 | { | ||
136 | if (!initialized) | ||
137 | { | ||
138 | initialize(header); | ||
139 | } | ||
140 | |||
141 | int layer = header.layer(); | ||
142 | |||
143 | output.clear_buffer(); | ||
144 | |||
145 | FrameDecoder decoder = retrieveDecoder(header, stream, layer); | ||
146 | |||
147 | decoder.decodeFrame(); | ||
148 | |||
149 | output.write_buffer(1); | ||
150 | |||
151 | return output; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * Changes the output buffer. This will take effect the next time | ||
156 | * decodeFrame() is called. | ||
157 | */ | ||
158 | public void setOutputBuffer(Obuffer out) | ||
159 | { | ||
160 | output = out; | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * Retrieves the sample frequency of the PCM samples output | ||
165 | * by this decoder. This typically corresponds to the sample | ||
166 | * rate encoded in the MPEG audio stream. | ||
167 | * | ||
168 | * @param the sample rate (in Hz) of the samples written to the | ||
169 | * output buffer when decoding. | ||
170 | */ | ||
171 | public int getOutputFrequency() | ||
172 | { | ||
173 | return outputFrequency; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * Retrieves the number of channels of PCM samples output by | ||
178 | * this decoder. This usually corresponds to the number of | ||
179 | * channels in the MPEG audio stream, although it may differ. | ||
180 | * | ||
181 | * @return The number of output channels in the decoded samples: 1 | ||
182 | * for mono, or 2 for stereo. | ||
183 | * | ||
184 | */ | ||
185 | public int getOutputChannels() | ||
186 | { | ||
187 | return outputChannels; | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * Retrieves the maximum number of samples that will be written to | ||
192 | * the output buffer when one frame is decoded. This can be used to | ||
193 | * help calculate the size of other buffers whose size is based upon | ||
194 | * the number of samples written to the output buffer. NB: this is | ||
195 | * an upper bound and fewer samples may actually be written, depending | ||
196 | * upon the sample rate and number of channels. | ||
197 | * | ||
198 | * @return The maximum number of samples that are written to the | ||
199 | * output buffer when decoding a single frame of MPEG audio. | ||
200 | */ | ||
201 | public int getOutputBlockSize() | ||
202 | { | ||
203 | return Obuffer.OBUFFERSIZE; | ||
204 | } | ||
205 | |||
206 | |||
207 | protected DecoderException newDecoderException(int errorcode) | ||
208 | { | ||
209 | return new DecoderException(errorcode, null); | ||
210 | } | ||
211 | |||
212 | protected DecoderException newDecoderException(int errorcode, Throwable throwable) | ||
213 | { | ||
214 | return new DecoderException(errorcode, throwable); | ||
215 | } | ||
216 | |||
217 | protected FrameDecoder retrieveDecoder(Header header, Bitstream stream, int layer) | ||
218 | throws DecoderException | ||
219 | { | ||
220 | FrameDecoder decoder = null; | ||
221 | |||
222 | // REVIEW: allow channel output selection type | ||
223 | // (LEFT, RIGHT, BOTH, DOWNMIX) | ||
224 | switch (layer) | ||
225 | { | ||
226 | case 3: | ||
227 | if (l3decoder==null) | ||
228 | { | ||
229 | l3decoder = new LayerIIIDecoder(stream, | ||
230 | header, filter1, filter2, | ||
231 | output, OutputChannels.BOTH_CHANNELS); | ||
232 | } | ||
233 | |||
234 | decoder = l3decoder; | ||
235 | break; | ||
236 | case 2: | ||
237 | if (l2decoder==null) | ||
238 | { | ||
239 | l2decoder = new LayerIIDecoder(); | ||
240 | l2decoder.create(stream, | ||
241 | header, filter1, filter2, | ||
242 | output, OutputChannels.BOTH_CHANNELS); | ||
243 | } | ||
244 | decoder = l2decoder; | ||
245 | break; | ||
246 | case 1: | ||
247 | if (l1decoder==null) | ||
248 | { | ||
249 | l1decoder = new LayerIDecoder(); | ||
250 | l1decoder.create(stream, | ||
251 | header, filter1, filter2, | ||
252 | output, OutputChannels.BOTH_CHANNELS); | ||
253 | } | ||
254 | decoder = l1decoder; | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | if (decoder==null) | ||
259 | { | ||
260 | throw newDecoderException(UNSUPPORTED_LAYER, null); | ||
261 | } | ||
262 | |||
263 | return decoder; | ||
264 | } | ||
265 | |||
266 | private void initialize(Header header) | ||
267 | throws DecoderException | ||
268 | { | ||
269 | |||
270 | // REVIEW: allow customizable scale factor | ||
271 | float scalefactor = 32700.0f; | ||
272 | |||
273 | int mode = header.mode(); | ||
274 | int layer = header.layer(); | ||
275 | int channels = mode==Header.SINGLE_CHANNEL ? 1 : 2; | ||
276 | |||
277 | |||
278 | // set up output buffer if not set up by client. | ||
279 | if (output==null) | ||
280 | output = new SampleBuffer(header.frequency(), channels); | ||
281 | |||
282 | float[] factors = equalizer.getBandFactors(); | ||
283 | filter1 = new SynthesisFilter(0, scalefactor, factors); | ||
284 | |||
285 | // REVIEW: allow mono output for stereo | ||
286 | if (channels==2) | ||
287 | filter2 = new SynthesisFilter(1, scalefactor, factors); | ||
288 | |||
289 | outputChannels = channels; | ||
290 | outputFrequency = header.frequency(); | ||
291 | |||
292 | initialized = true; | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * The <code>Params</code> class presents the customizable | ||
297 | * aspects of the decoder. | ||
298 | * <p> | ||
299 | * Instances of this class are not thread safe. | ||
300 | */ | ||
301 | public static class Params implements Cloneable | ||
302 | { | ||
303 | private OutputChannels outputChannels = OutputChannels.BOTH; | ||
304 | |||
305 | private Equalizer equalizer = new Equalizer(); | ||
306 | |||
307 | public Params() | ||
308 | { | ||
309 | } | ||
310 | |||
311 | public Object clone() | ||
312 | { | ||
313 | try | ||
314 | { | ||
315 | return super.clone(); | ||
316 | } | ||
317 | catch (CloneNotSupportedException ex) | ||
318 | { | ||
319 | throw new InternalError(this+": "+ex); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | public void setOutputChannels(OutputChannels out) | ||
324 | { | ||
325 | if (out==null) | ||
326 | throw new NullPointerException("out"); | ||
327 | |||
328 | outputChannels = out; | ||
329 | } | ||
330 | |||
331 | public OutputChannels getOutputChannels() | ||
332 | { | ||
333 | return outputChannels; | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * Retrieves the equalizer settings that the decoder's equalizer | ||
338 | * will be initialized from. | ||
339 | * <p> | ||
340 | * The <code>Equalizer</code> instance returned | ||
341 | * cannot be changed in real time to affect the | ||
342 | * decoder output as it is used only to initialize the decoders | ||
343 | * EQ settings. To affect the decoder's output in realtime, | ||
344 | * use the Equalizer returned from the getEqualizer() method on | ||
345 | * the decoder. | ||
346 | * | ||
347 | * @return The <code>Equalizer</code> used to initialize the | ||
348 | * EQ settings of the decoder. | ||
349 | */ | ||
350 | public Equalizer getInitialEqualizerSettings() | ||
351 | { | ||
352 | return equalizer; | ||
353 | } | ||
354 | |||
355 | }; | ||
356 | } | ||
357 | |||
diff --git a/songdbj/javazoom/jl/decoder/DecoderErrors.java b/songdbj/javazoom/jl/decoder/DecoderErrors.java new file mode 100644 index 0000000000..66c1935051 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/DecoderErrors.java | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 01/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | /** | ||
24 | * This interface provides constants describing the error | ||
25 | * codes used by the Decoder to indicate errors. | ||
26 | * | ||
27 | * @author MDM | ||
28 | */ | ||
29 | public interface DecoderErrors extends JavaLayerErrors | ||
30 | { | ||
31 | |||
32 | static public final int UNKNOWN_ERROR = DECODER_ERROR + 0; | ||
33 | |||
34 | /** | ||
35 | * Layer not supported by the decoder. | ||
36 | */ | ||
37 | static public final int UNSUPPORTED_LAYER = DECODER_ERROR + 1; | ||
38 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/DecoderException.java b/songdbj/javazoom/jl/decoder/DecoderException.java new file mode 100644 index 0000000000..b75710870f --- /dev/null +++ b/songdbj/javazoom/jl/decoder/DecoderException.java | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 01/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | /** | ||
24 | * The <code>DecoderException</code> represents the class of | ||
25 | * errors that can occur when decoding MPEG audio. | ||
26 | * | ||
27 | * @author MDM | ||
28 | */ | ||
29 | public class DecoderException extends JavaLayerException | ||
30 | implements DecoderErrors | ||
31 | { | ||
32 | private int errorcode = UNKNOWN_ERROR; | ||
33 | |||
34 | public DecoderException(String msg, Throwable t) | ||
35 | { | ||
36 | super(msg, t); | ||
37 | } | ||
38 | |||
39 | public DecoderException(int errorcode, Throwable t) | ||
40 | { | ||
41 | this(getErrorString(errorcode), t); | ||
42 | this.errorcode = errorcode; | ||
43 | } | ||
44 | |||
45 | public int getErrorCode() | ||
46 | { | ||
47 | return errorcode; | ||
48 | } | ||
49 | |||
50 | |||
51 | static public String getErrorString(int errorcode) | ||
52 | { | ||
53 | // REVIEW: use resource file to map error codes | ||
54 | // to locale-sensitive strings. | ||
55 | |||
56 | return "Decoder errorcode "+Integer.toHexString(errorcode); | ||
57 | } | ||
58 | |||
59 | |||
60 | } | ||
61 | |||
diff --git a/songdbj/javazoom/jl/decoder/Equalizer.java b/songdbj/javazoom/jl/decoder/Equalizer.java new file mode 100644 index 0000000000..57545a939d --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Equalizer.java | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | |||
22 | package javazoom.jl.decoder; | ||
23 | |||
24 | /** | ||
25 | * The <code>Equalizer</code> class can be used to specify | ||
26 | * equalization settings for the MPEG audio decoder. | ||
27 | * <p> | ||
28 | * The equalizer consists of 32 band-pass filters. | ||
29 | * Each band of the equalizer can take on a fractional value between | ||
30 | * -1.0 and +1.0. | ||
31 | * At -1.0, the input signal is attenuated by 6dB, at +1.0 the signal is | ||
32 | * amplified by 6dB. | ||
33 | * | ||
34 | * @see Decoder | ||
35 | * | ||
36 | * @author MDM | ||
37 | */ | ||
38 | public final class Equalizer | ||
39 | { | ||
40 | /** | ||
41 | * Equalizer setting to denote that a given band will not be | ||
42 | * present in the output signal. | ||
43 | */ | ||
44 | static public final float BAND_NOT_PRESENT = Float.NEGATIVE_INFINITY; | ||
45 | |||
46 | static public final Equalizer PASS_THRU_EQ = new Equalizer(); | ||
47 | |||
48 | private static final int BANDS = 32; | ||
49 | |||
50 | private final float[] settings = new float[BANDS]; | ||
51 | |||
52 | /** | ||
53 | * Creates a new <code>Equalizer</code> instance. | ||
54 | */ | ||
55 | public Equalizer() | ||
56 | { | ||
57 | } | ||
58 | |||
59 | // private Equalizer(float b1, float b2, float b3, float b4, float b5, | ||
60 | // float b6, float b7, float b8, float b9, float b10, float b11, | ||
61 | // float b12, float b13, float b14, float b15, float b16, | ||
62 | // float b17, float b18, float b19, float b20); | ||
63 | |||
64 | public Equalizer(float[] settings) | ||
65 | { | ||
66 | setFrom(settings); | ||
67 | } | ||
68 | |||
69 | public Equalizer(EQFunction eq) | ||
70 | { | ||
71 | setFrom(eq); | ||
72 | } | ||
73 | |||
74 | public void setFrom(float[] eq) | ||
75 | { | ||
76 | reset(); | ||
77 | int max = (eq.length > BANDS) ? BANDS : eq.length; | ||
78 | |||
79 | for (int i=0; i<max; i++) | ||
80 | { | ||
81 | settings[i] = limit(eq[i]); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | public void setFrom(EQFunction eq) | ||
86 | { | ||
87 | reset(); | ||
88 | int max = BANDS; | ||
89 | |||
90 | for (int i=0; i<max; i++) | ||
91 | { | ||
92 | settings[i] = limit(eq.getBand(i)); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * Sets the bands of this equalizer to the value the bands of | ||
98 | * another equalizer. Bands that are not present in both equalizers are ignored. | ||
99 | */ | ||
100 | public void setFrom(Equalizer eq) | ||
101 | { | ||
102 | if (eq!=this) | ||
103 | { | ||
104 | setFrom(eq.settings); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | |||
109 | |||
110 | |||
111 | /** | ||
112 | * Sets all bands to 0.0 | ||
113 | */ | ||
114 | public void reset() | ||
115 | { | ||
116 | for (int i=0; i<BANDS; i++) | ||
117 | { | ||
118 | settings[i] = 0.0f; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | |||
123 | /** | ||
124 | * Retrieves the number of bands present in this equalizer. | ||
125 | */ | ||
126 | public int getBandCount() | ||
127 | { | ||
128 | return settings.length; | ||
129 | } | ||
130 | |||
131 | public float setBand(int band, float neweq) | ||
132 | { | ||
133 | float eq = 0.0f; | ||
134 | |||
135 | if ((band>=0) && (band<BANDS)) | ||
136 | { | ||
137 | eq = settings[band]; | ||
138 | settings[band] = limit(neweq); | ||
139 | } | ||
140 | |||
141 | return eq; | ||
142 | } | ||
143 | |||
144 | |||
145 | |||
146 | /** | ||
147 | * Retrieves the eq setting for a given band. | ||
148 | */ | ||
149 | public float getBand(int band) | ||
150 | { | ||
151 | float eq = 0.0f; | ||
152 | |||
153 | if ((band>=0) && (band<BANDS)) | ||
154 | { | ||
155 | eq = settings[band]; | ||
156 | } | ||
157 | |||
158 | return eq; | ||
159 | } | ||
160 | |||
161 | private float limit(float eq) | ||
162 | { | ||
163 | if (eq==BAND_NOT_PRESENT) | ||
164 | return eq; | ||
165 | if (eq > 1.0f) | ||
166 | return 1.0f; | ||
167 | if (eq < -1.0f) | ||
168 | return -1.0f; | ||
169 | |||
170 | return eq; | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * Retrieves an array of floats whose values represent a | ||
175 | * scaling factor that can be applied to linear samples | ||
176 | * in each band to provide the equalization represented by | ||
177 | * this instance. | ||
178 | * | ||
179 | * @return an array of factors that can be applied to the | ||
180 | * subbands. | ||
181 | */ | ||
182 | float[] getBandFactors() | ||
183 | { | ||
184 | float[] factors = new float[BANDS]; | ||
185 | for (int i=0, maxCount=BANDS; i<maxCount; i++) | ||
186 | { | ||
187 | factors[i] = getBandFactor(settings[i]); | ||
188 | } | ||
189 | |||
190 | return factors; | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * Converts an equalizer band setting to a sample factor. | ||
195 | * The factor is determined by the function f = 2^n where | ||
196 | * n is the equalizer band setting in the range [-1.0,1.0]. | ||
197 | * | ||
198 | */ | ||
199 | float getBandFactor(float eq) | ||
200 | { | ||
201 | if (eq==BAND_NOT_PRESENT) | ||
202 | return 0.0f; | ||
203 | |||
204 | float f = (float)Math.pow(2.0, eq); | ||
205 | return f; | ||
206 | } | ||
207 | |||
208 | |||
209 | static abstract public class EQFunction | ||
210 | { | ||
211 | /** | ||
212 | * Returns the setting of a band in the equalizer. | ||
213 | * | ||
214 | * @param band The index of the band to retrieve the setting | ||
215 | * for. | ||
216 | * | ||
217 | * @return the setting of the specified band. This is a value between | ||
218 | * -1 and +1. | ||
219 | */ | ||
220 | public float getBand(int band) | ||
221 | { | ||
222 | return 0.0f; | ||
223 | } | ||
224 | |||
225 | } | ||
226 | |||
227 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/FrameDecoder.java b/songdbj/javazoom/jl/decoder/FrameDecoder.java new file mode 100644 index 0000000000..eec6ac6a22 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/FrameDecoder.java | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | /** | ||
24 | * Implementations of FrameDecoder are responsible for decoding | ||
25 | * an MPEG audio frame. | ||
26 | * | ||
27 | */ | ||
28 | //REVIEW: the interface currently is too thin. There should be | ||
29 | // methods to specify the output buffer, the synthesis filters and | ||
30 | // possibly other objects used by the decoder. | ||
31 | public interface FrameDecoder | ||
32 | { | ||
33 | /** | ||
34 | * Decodes one frame of MPEG audio. | ||
35 | */ | ||
36 | public void decodeFrame(); | ||
37 | |||
38 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/Header.java b/songdbj/javazoom/jl/decoder/Header.java new file mode 100644 index 0000000000..e85fe19f64 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Header.java | |||
@@ -0,0 +1,762 @@ | |||
1 | /* | ||
2 | * 11/19/04 : 1.0 moved to LGPL. | ||
3 | * VBRI header support added, E.B javalayer@javazoom.net | ||
4 | * | ||
5 | * 12/04/03 : VBR (XING) header support added, E.B javalayer@javazoom.net | ||
6 | * | ||
7 | * 02/13/99 : Java Conversion by JavaZOOM , E.B javalayer@javazoom.net | ||
8 | * | ||
9 | * Declarations for MPEG header class | ||
10 | * A few layer III, MPEG-2 LSF, and seeking modifications made by Jeff Tsay. | ||
11 | * Last modified : 04/19/97 | ||
12 | * | ||
13 | * @(#) header.h 1.7, last edit: 6/15/94 16:55:33 | ||
14 | * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de) | ||
15 | * @(#) Berlin University of Technology | ||
16 | *----------------------------------------------------------------------- | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU Library General Public License as published | ||
19 | * by the Free Software Foundation; either version 2 of the License, or | ||
20 | * (at your option) any later version. | ||
21 | * | ||
22 | * This program is distributed in the hope that it will be useful, | ||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | * GNU Library General Public License for more details. | ||
26 | * | ||
27 | * You should have received a copy of the GNU Library General Public | ||
28 | * License along with this program; if not, write to the Free Software | ||
29 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
30 | *---------------------------------------------------------------------- | ||
31 | */ | ||
32 | package javazoom.jl.decoder; | ||
33 | |||
34 | /** | ||
35 | * Class for extracting information from a frame header. | ||
36 | */ | ||
37 | public final class Header | ||
38 | { | ||
39 | public static final int[][] frequencies = | ||
40 | {{22050, 24000, 16000, 1}, | ||
41 | {44100, 48000, 32000, 1}, | ||
42 | {11025, 12000, 8000, 1}}; // SZD: MPEG25 | ||
43 | |||
44 | /** | ||
45 | * Constant for MPEG-2 LSF version | ||
46 | */ | ||
47 | public static final int MPEG2_LSF = 0; | ||
48 | public static final int MPEG25_LSF = 2; // SZD | ||
49 | |||
50 | /** | ||
51 | * Constant for MPEG-1 version | ||
52 | */ | ||
53 | public static final int MPEG1 = 1; | ||
54 | |||
55 | public static final int STEREO = 0; | ||
56 | public static final int JOINT_STEREO = 1; | ||
57 | public static final int DUAL_CHANNEL = 2; | ||
58 | public static final int SINGLE_CHANNEL = 3; | ||
59 | public static final int FOURTYFOUR_POINT_ONE = 0; | ||
60 | public static final int FOURTYEIGHT=1; | ||
61 | public static final int THIRTYTWO=2; | ||
62 | |||
63 | private int h_layer, h_protection_bit, h_bitrate_index, | ||
64 | h_padding_bit, h_mode_extension; | ||
65 | private int h_version; | ||
66 | private int h_mode; | ||
67 | private int h_sample_frequency; | ||
68 | private int h_number_of_subbands, h_intensity_stereo_bound; | ||
69 | private boolean h_copyright, h_original; | ||
70 | // VBR support added by E.B | ||
71 | private double[] h_vbr_time_per_frame = {-1, 384, 1152, 1152}; | ||
72 | private boolean h_vbr; | ||
73 | private int h_vbr_frames; | ||
74 | private int h_vbr_scale; | ||
75 | private int h_vbr_bytes; | ||
76 | private byte[] h_vbr_toc; | ||
77 | |||
78 | private byte syncmode = Bitstream.INITIAL_SYNC; | ||
79 | private Crc16 crc; | ||
80 | |||
81 | public short checksum; | ||
82 | public int framesize; | ||
83 | public int nSlots; | ||
84 | |||
85 | private int _headerstring = -1; // E.B | ||
86 | |||
87 | Header() | ||
88 | { | ||
89 | } | ||
90 | public String toString() | ||
91 | { | ||
92 | StringBuffer buffer = new StringBuffer(200); | ||
93 | buffer.append("Layer "); | ||
94 | buffer.append(layer_string()); | ||
95 | buffer.append(" frame "); | ||
96 | buffer.append(mode_string()); | ||
97 | buffer.append(' '); | ||
98 | buffer.append(version_string()); | ||
99 | if (!checksums()) | ||
100 | buffer.append(" no"); | ||
101 | buffer.append(" checksums"); | ||
102 | buffer.append(' '); | ||
103 | buffer.append(sample_frequency_string()); | ||
104 | buffer.append(','); | ||
105 | buffer.append(' '); | ||
106 | buffer.append(bitrate_string()); | ||
107 | |||
108 | String s = buffer.toString(); | ||
109 | return s; | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * Read a 32-bit header from the bitstream. | ||
114 | */ | ||
115 | void read_header(Bitstream stream, Crc16[] crcp) throws BitstreamException | ||
116 | { | ||
117 | int headerstring; | ||
118 | int channel_bitrate; | ||
119 | boolean sync = false; | ||
120 | do | ||
121 | { | ||
122 | headerstring = stream.syncHeader(syncmode); | ||
123 | _headerstring = headerstring; // E.B | ||
124 | if (syncmode == Bitstream.INITIAL_SYNC) | ||
125 | { | ||
126 | h_version = ((headerstring >>> 19) & 1); | ||
127 | if (((headerstring >>> 20) & 1) == 0) // SZD: MPEG2.5 detection | ||
128 | if (h_version == MPEG2_LSF) | ||
129 | h_version = MPEG25_LSF; | ||
130 | else | ||
131 | throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR); | ||
132 | if ((h_sample_frequency = ((headerstring >>> 10) & 3)) == 3) | ||
133 | { | ||
134 | throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR); | ||
135 | } | ||
136 | } | ||
137 | h_layer = 4 - (headerstring >>> 17) & 3; | ||
138 | h_protection_bit = (headerstring >>> 16) & 1; | ||
139 | h_bitrate_index = (headerstring >>> 12) & 0xF; | ||
140 | h_padding_bit = (headerstring >>> 9) & 1; | ||
141 | h_mode = ((headerstring >>> 6) & 3); | ||
142 | h_mode_extension = (headerstring >>> 4) & 3; | ||
143 | if (h_mode == JOINT_STEREO) | ||
144 | h_intensity_stereo_bound = (h_mode_extension << 2) + 4; | ||
145 | else | ||
146 | h_intensity_stereo_bound = 0; // should never be used | ||
147 | if (((headerstring >>> 3) & 1) == 1) | ||
148 | h_copyright = true; | ||
149 | if (((headerstring >>> 2) & 1) == 1) | ||
150 | h_original = true; | ||
151 | // calculate number of subbands: | ||
152 | if (h_layer == 1) | ||
153 | h_number_of_subbands = 32; | ||
154 | else | ||
155 | { | ||
156 | channel_bitrate = h_bitrate_index; | ||
157 | // calculate bitrate per channel: | ||
158 | if (h_mode != SINGLE_CHANNEL) | ||
159 | if (channel_bitrate == 4) | ||
160 | channel_bitrate = 1; | ||
161 | else | ||
162 | channel_bitrate -= 4; | ||
163 | if ((channel_bitrate == 1) || (channel_bitrate == 2)) | ||
164 | if (h_sample_frequency == THIRTYTWO) | ||
165 | h_number_of_subbands = 12; | ||
166 | else | ||
167 | h_number_of_subbands = 8; | ||
168 | else if ((h_sample_frequency == FOURTYEIGHT) || ((channel_bitrate >= 3) && (channel_bitrate <= 5))) | ||
169 | h_number_of_subbands = 27; | ||
170 | else | ||
171 | h_number_of_subbands = 30; | ||
172 | } | ||
173 | if (h_intensity_stereo_bound > h_number_of_subbands) | ||
174 | h_intensity_stereo_bound = h_number_of_subbands; | ||
175 | // calculate framesize and nSlots | ||
176 | calculate_framesize(); | ||
177 | // read framedata: | ||
178 | int framesizeloaded = stream.read_frame_data(framesize); | ||
179 | if ((framesize >=0) && (framesizeloaded != framesize)) | ||
180 | { | ||
181 | // Data loaded does not match to expected framesize, | ||
182 | // it might be an ID3v1 TAG. (Fix 11/17/04). | ||
183 | throw stream.newBitstreamException(Bitstream.INVALIDFRAME); | ||
184 | } | ||
185 | if (stream.isSyncCurrentPosition(syncmode)) | ||
186 | { | ||
187 | if (syncmode == Bitstream.INITIAL_SYNC) | ||
188 | { | ||
189 | syncmode = Bitstream.STRICT_SYNC; | ||
190 | stream.set_syncword(headerstring & 0xFFF80CC0); | ||
191 | } | ||
192 | sync = true; | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | stream.unreadFrame(); | ||
197 | } | ||
198 | } | ||
199 | while (!sync); | ||
200 | stream.parse_frame(); | ||
201 | if (h_protection_bit == 0) | ||
202 | { | ||
203 | // frame contains a crc checksum | ||
204 | checksum = (short) stream.get_bits(16); | ||
205 | if (crc == null) | ||
206 | crc = new Crc16(); | ||
207 | crc.add_bits(headerstring, 16); | ||
208 | crcp[0] = crc; | ||
209 | } | ||
210 | else | ||
211 | crcp[0] = null; | ||
212 | if (h_sample_frequency == FOURTYFOUR_POINT_ONE) | ||
213 | { | ||
214 | /* | ||
215 | if (offset == null) | ||
216 | { | ||
217 | int max = max_number_of_frames(stream); | ||
218 | offset = new int[max]; | ||
219 | for(int i=0; i<max; i++) offset[i] = 0; | ||
220 | } | ||
221 | // E.B : Investigate more | ||
222 | int cf = stream.current_frame(); | ||
223 | int lf = stream.last_frame(); | ||
224 | if ((cf > 0) && (cf == lf)) | ||
225 | { | ||
226 | offset[cf] = offset[cf-1] + h_padding_bit; | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | offset[0] = h_padding_bit; | ||
231 | } | ||
232 | */ | ||
233 | } | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * Parse frame to extract optionnal VBR frame. | ||
238 | * @param firstframe | ||
239 | * @author E.B (javalayer@javazoom.net) | ||
240 | */ | ||
241 | void parseVBR(byte[] firstframe) throws BitstreamException | ||
242 | { | ||
243 | // Trying Xing header. | ||
244 | String xing = "Xing"; | ||
245 | byte tmp[] = new byte[4]; | ||
246 | int offset = 0; | ||
247 | // Compute "Xing" offset depending on MPEG version and channels. | ||
248 | if (h_version == MPEG1) | ||
249 | { | ||
250 | if (h_mode == SINGLE_CHANNEL) offset=21-4; | ||
251 | else offset=36-4; | ||
252 | } | ||
253 | else | ||
254 | { | ||
255 | if (h_mode == SINGLE_CHANNEL) offset=13-4; | ||
256 | else offset = 21-4; | ||
257 | } | ||
258 | try | ||
259 | { | ||
260 | System.arraycopy(firstframe, offset, tmp, 0, 4); | ||
261 | // Is "Xing" ? | ||
262 | if (xing.equals(new String(tmp))) | ||
263 | { | ||
264 | //Yes. | ||
265 | h_vbr = true; | ||
266 | h_vbr_frames = -1; | ||
267 | h_vbr_bytes = -1; | ||
268 | h_vbr_scale = -1; | ||
269 | h_vbr_toc = new byte[100]; | ||
270 | |||
271 | int length = 4; | ||
272 | // Read flags. | ||
273 | byte flags[] = new byte[4]; | ||
274 | System.arraycopy(firstframe, offset + length, flags, 0, flags.length); | ||
275 | length += flags.length; | ||
276 | // Read number of frames (if available). | ||
277 | if ((flags[3] & (byte) (1 << 0)) != 0) | ||
278 | { | ||
279 | System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); | ||
280 | h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; | ||
281 | length += 4; | ||
282 | } | ||
283 | // Read size (if available). | ||
284 | if ((flags[3] & (byte) (1 << 1)) != 0) | ||
285 | { | ||
286 | System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); | ||
287 | h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; | ||
288 | length += 4; | ||
289 | } | ||
290 | // Read TOC (if available). | ||
291 | if ((flags[3] & (byte) (1 << 2)) != 0) | ||
292 | { | ||
293 | System.arraycopy(firstframe, offset + length, h_vbr_toc, 0, h_vbr_toc.length); | ||
294 | length += h_vbr_toc.length; | ||
295 | } | ||
296 | // Read scale (if available). | ||
297 | if ((flags[3] & (byte) (1 << 3)) != 0) | ||
298 | { | ||
299 | System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); | ||
300 | h_vbr_scale = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; | ||
301 | length += 4; | ||
302 | } | ||
303 | //System.out.println("VBR:"+xing+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes); | ||
304 | } | ||
305 | } | ||
306 | catch (ArrayIndexOutOfBoundsException e) | ||
307 | { | ||
308 | throw new BitstreamException("XingVBRHeader Corrupted",e); | ||
309 | } | ||
310 | |||
311 | // Trying VBRI header. | ||
312 | String vbri = "VBRI"; | ||
313 | offset = 36-4; | ||
314 | try | ||
315 | { | ||
316 | System.arraycopy(firstframe, offset, tmp, 0, 4); | ||
317 | // Is "VBRI" ? | ||
318 | if (vbri.equals(new String(tmp))) | ||
319 | { | ||
320 | //Yes. | ||
321 | h_vbr = true; | ||
322 | h_vbr_frames = -1; | ||
323 | h_vbr_bytes = -1; | ||
324 | h_vbr_scale = -1; | ||
325 | h_vbr_toc = new byte[100]; | ||
326 | // Bytes. | ||
327 | int length = 4 + 6; | ||
328 | System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); | ||
329 | h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; | ||
330 | length += 4; | ||
331 | // Frames. | ||
332 | System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length); | ||
333 | h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF; | ||
334 | length += 4; | ||
335 | //System.out.println("VBR:"+vbri+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes); | ||
336 | // TOC | ||
337 | // TODO | ||
338 | } | ||
339 | } | ||
340 | catch (ArrayIndexOutOfBoundsException e) | ||
341 | { | ||
342 | throw new BitstreamException("VBRIVBRHeader Corrupted",e); | ||
343 | } | ||
344 | } | ||
345 | |||
346 | // Functions to query header contents: | ||
347 | /** | ||
348 | * Returns version. | ||
349 | */ | ||
350 | public int version() { return h_version; } | ||
351 | |||
352 | /** | ||
353 | * Returns Layer ID. | ||
354 | */ | ||
355 | public int layer() { return h_layer; } | ||
356 | |||
357 | /** | ||
358 | * Returns bitrate index. | ||
359 | */ | ||
360 | public int bitrate_index() { return h_bitrate_index; } | ||
361 | |||
362 | /** | ||
363 | * Returns Sample Frequency. | ||
364 | */ | ||
365 | public int sample_frequency() { return h_sample_frequency; } | ||
366 | |||
367 | /** | ||
368 | * Returns Frequency. | ||
369 | */ | ||
370 | public int frequency() {return frequencies[h_version][h_sample_frequency];} | ||
371 | |||
372 | /** | ||
373 | * Returns Mode. | ||
374 | */ | ||
375 | public int mode() { return h_mode; } | ||
376 | |||
377 | /** | ||
378 | * Returns Protection bit. | ||
379 | */ | ||
380 | public boolean checksums() | ||
381 | { | ||
382 | if (h_protection_bit == 0) return true; | ||
383 | else return false; | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * Returns Copyright. | ||
388 | */ | ||
389 | public boolean copyright() { return h_copyright; } | ||
390 | |||
391 | /** | ||
392 | * Returns Original. | ||
393 | */ | ||
394 | public boolean original() { return h_original; } | ||
395 | |||
396 | /** | ||
397 | * Return VBR. | ||
398 | * @return true if VBR header is found | ||
399 | */ | ||
400 | public boolean vbr() { return h_vbr; } | ||
401 | |||
402 | /** | ||
403 | * Return VBR scale. | ||
404 | * @return scale of -1 if not available | ||
405 | */ | ||
406 | public int vbr_scale() { return h_vbr_scale; } | ||
407 | |||
408 | /** | ||
409 | * Return VBR TOC. | ||
410 | * @return vbr toc ot null if not available | ||
411 | */ | ||
412 | public byte[] vbr_toc() { return h_vbr_toc; } | ||
413 | |||
414 | /** | ||
415 | * Returns Checksum flag. | ||
416 | * Compares computed checksum with stream checksum. | ||
417 | */ | ||
418 | public boolean checksum_ok () { return (checksum == crc.checksum()); } | ||
419 | |||
420 | // Seeking and layer III stuff | ||
421 | /** | ||
422 | * Returns Layer III Padding bit. | ||
423 | */ | ||
424 | public boolean padding() | ||
425 | { | ||
426 | if (h_padding_bit == 0) return false; | ||
427 | else return true; | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * Returns Slots. | ||
432 | */ | ||
433 | public int slots() { return nSlots; } | ||
434 | |||
435 | /** | ||
436 | * Returns Mode Extension. | ||
437 | */ | ||
438 | public int mode_extension() { return h_mode_extension; } | ||
439 | |||
440 | // E.B -> private to public | ||
441 | public static final int bitrates[][][] = { | ||
442 | {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000, | ||
443 | 112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0}, | ||
444 | {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000, | ||
445 | 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}, | ||
446 | {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000, | ||
447 | 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}}, | ||
448 | |||
449 | {{0 /*free format*/, 32000, 64000, 96000, 128000, 160000, 192000, | ||
450 | 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0}, | ||
451 | {0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000, | ||
452 | 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0}, | ||
453 | {0 /*free format*/, 32000, 40000, 48000, 56000, 64000, 80000, | ||
454 | 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}}, | ||
455 | // SZD: MPEG2.5 | ||
456 | {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000, | ||
457 | 112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0}, | ||
458 | {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000, | ||
459 | 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}, | ||
460 | {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000, | ||
461 | 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}}, | ||
462 | |||
463 | }; | ||
464 | |||
465 | // E.B -> private to public | ||
466 | /** | ||
467 | * Calculate Frame size. | ||
468 | * Calculates framesize in bytes excluding header size. | ||
469 | */ | ||
470 | public int calculate_framesize() | ||
471 | { | ||
472 | |||
473 | if (h_layer == 1) | ||
474 | { | ||
475 | framesize = (12 * bitrates[h_version][0][h_bitrate_index]) / | ||
476 | frequencies[h_version][h_sample_frequency]; | ||
477 | if (h_padding_bit != 0 ) framesize++; | ||
478 | framesize <<= 2; // one slot is 4 bytes long | ||
479 | nSlots = 0; | ||
480 | } | ||
481 | else | ||
482 | { | ||
483 | framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index]) / | ||
484 | frequencies[h_version][h_sample_frequency]; | ||
485 | if (h_version == MPEG2_LSF || h_version == MPEG25_LSF) framesize >>= 1; // SZD | ||
486 | if (h_padding_bit != 0) framesize++; | ||
487 | // Layer III slots | ||
488 | if (h_layer == 3) | ||
489 | { | ||
490 | if (h_version == MPEG1) | ||
491 | { | ||
492 | nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 17 : 32) // side info size | ||
493 | - ((h_protection_bit!=0) ? 0 : 2) // CRC size | ||
494 | - 4; // header size | ||
495 | } | ||
496 | else | ||
497 | { // MPEG-2 LSF, SZD: MPEG-2.5 LSF | ||
498 | nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 9 : 17) // side info size | ||
499 | - ((h_protection_bit!=0) ? 0 : 2) // CRC size | ||
500 | - 4; // header size | ||
501 | } | ||
502 | } | ||
503 | else | ||
504 | { | ||
505 | nSlots = 0; | ||
506 | } | ||
507 | } | ||
508 | framesize -= 4; // subtract header size | ||
509 | return framesize; | ||
510 | } | ||
511 | |||
512 | /** | ||
513 | * Returns the maximum number of frames in the stream. | ||
514 | * @param streamsize | ||
515 | * @return number of frames | ||
516 | */ | ||
517 | public int max_number_of_frames(int streamsize) // E.B | ||
518 | { | ||
519 | if (h_vbr == true) return h_vbr_frames; | ||
520 | else | ||
521 | { | ||
522 | if ((framesize + 4 - h_padding_bit) == 0) return 0; | ||
523 | else return(streamsize / (framesize + 4 - h_padding_bit)); | ||
524 | } | ||
525 | } | ||
526 | |||
527 | /** | ||
528 | * Returns the maximum number of frames in the stream. | ||
529 | * @param streamsize | ||
530 | * @return number of frames | ||
531 | */ | ||
532 | public int min_number_of_frames(int streamsize) // E.B | ||
533 | { | ||
534 | if (h_vbr == true) return h_vbr_frames; | ||
535 | else | ||
536 | { | ||
537 | if ((framesize + 5 - h_padding_bit) == 0) return 0; | ||
538 | else return(streamsize / (framesize + 5 - h_padding_bit)); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | |||
543 | /** | ||
544 | * Returns ms/frame. | ||
545 | * @return milliseconds per frame | ||
546 | */ | ||
547 | public float ms_per_frame() // E.B | ||
548 | { | ||
549 | if (h_vbr == true) | ||
550 | { | ||
551 | double tpf = h_vbr_time_per_frame[layer()] / frequency(); | ||
552 | if ((h_version == MPEG2_LSF) || (h_version == MPEG25_LSF)) tpf /= 2; | ||
553 | return ((float) (tpf * 1000)); | ||
554 | } | ||
555 | else | ||
556 | { | ||
557 | float ms_per_frame_array[][] = {{8.707483f, 8.0f, 12.0f}, | ||
558 | {26.12245f, 24.0f, 36.0f}, | ||
559 | {26.12245f, 24.0f, 36.0f}}; | ||
560 | return(ms_per_frame_array[h_layer-1][h_sample_frequency]); | ||
561 | } | ||
562 | } | ||
563 | |||
564 | /** | ||
565 | * Returns total ms. | ||
566 | * @param streamsize | ||
567 | * @return total milliseconds | ||
568 | */ | ||
569 | public float total_ms(int streamsize) // E.B | ||
570 | { | ||
571 | return(max_number_of_frames(streamsize) * ms_per_frame()); | ||
572 | } | ||
573 | |||
574 | /** | ||
575 | * Returns synchronized header. | ||
576 | */ | ||
577 | public int getSyncHeader() // E.B | ||
578 | { | ||
579 | return _headerstring; | ||
580 | } | ||
581 | |||
582 | // functions which return header informations as strings: | ||
583 | /** | ||
584 | * Return Layer version. | ||
585 | */ | ||
586 | public String layer_string() | ||
587 | { | ||
588 | switch (h_layer) | ||
589 | { | ||
590 | case 1: | ||
591 | return "I"; | ||
592 | case 2: | ||
593 | return "II"; | ||
594 | case 3: | ||
595 | return "III"; | ||
596 | } | ||
597 | return null; | ||
598 | } | ||
599 | |||
600 | // E.B -> private to public | ||
601 | public static final String bitrate_str[][][] = { | ||
602 | {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", | ||
603 | "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", | ||
604 | "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", | ||
605 | "forbidden"}, | ||
606 | {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", | ||
607 | "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", | ||
608 | "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", | ||
609 | "forbidden"}, | ||
610 | {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", | ||
611 | "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", | ||
612 | "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", | ||
613 | "forbidden"}}, | ||
614 | |||
615 | {{"free format", "32 kbit/s", "64 kbit/s", "96 kbit/s", "128 kbit/s", | ||
616 | "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "288 kbit/s", | ||
617 | "320 kbit/s", "352 kbit/s", "384 kbit/s", "416 kbit/s", "448 kbit/s", | ||
618 | "forbidden"}, | ||
619 | {"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", | ||
620 | "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s", | ||
621 | "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", "384 kbit/s", | ||
622 | "forbidden"}, | ||
623 | {"free format", "32 kbit/s", "40 kbit/s", "48 kbit/s", "56 kbit/s", | ||
624 | "64 kbit/s", "80 kbit/s" , "96 kbit/s", "112 kbit/s", "128 kbit/s", | ||
625 | "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", | ||
626 | "forbidden"}}, | ||
627 | // SZD: MPEG2.5 | ||
628 | {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", | ||
629 | "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", | ||
630 | "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", | ||
631 | "forbidden"}, | ||
632 | {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", | ||
633 | "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", | ||
634 | "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", | ||
635 | "forbidden"}, | ||
636 | {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", | ||
637 | "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", | ||
638 | "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", | ||
639 | "forbidden"}}, | ||
640 | }; | ||
641 | |||
642 | /** | ||
643 | * Return Bitrate. | ||
644 | * @return bitrate in bps | ||
645 | */ | ||
646 | public String bitrate_string() | ||
647 | { | ||
648 | if (h_vbr == true) | ||
649 | { | ||
650 | return Integer.toString(bitrate()/1000)+" kb/s"; | ||
651 | } | ||
652 | else return bitrate_str[h_version][h_layer - 1][h_bitrate_index]; | ||
653 | } | ||
654 | |||
655 | /** | ||
656 | * Return Bitrate. | ||
657 | * @return bitrate in bps and average bitrate for VBR header | ||
658 | */ | ||
659 | public int bitrate() | ||
660 | { | ||
661 | if (h_vbr == true) | ||
662 | { | ||
663 | return ((int) ((h_vbr_bytes * 8) / (ms_per_frame() * h_vbr_frames)))*1000; | ||
664 | } | ||
665 | else return bitrates[h_version][h_layer - 1][h_bitrate_index]; | ||
666 | } | ||
667 | |||
668 | /** | ||
669 | * Return Instant Bitrate. | ||
670 | * Bitrate for VBR is not constant. | ||
671 | * @return bitrate in bps | ||
672 | */ | ||
673 | public int bitrate_instant() | ||
674 | { | ||
675 | return bitrates[h_version][h_layer - 1][h_bitrate_index]; | ||
676 | } | ||
677 | |||
678 | /** | ||
679 | * Returns Frequency | ||
680 | * @return frequency string in kHz | ||
681 | */ | ||
682 | public String sample_frequency_string() | ||
683 | { | ||
684 | switch (h_sample_frequency) | ||
685 | { | ||
686 | case THIRTYTWO: | ||
687 | if (h_version == MPEG1) | ||
688 | return "32 kHz"; | ||
689 | else if (h_version == MPEG2_LSF) | ||
690 | return "16 kHz"; | ||
691 | else // SZD | ||
692 | return "8 kHz"; | ||
693 | case FOURTYFOUR_POINT_ONE: | ||
694 | if (h_version == MPEG1) | ||
695 | return "44.1 kHz"; | ||
696 | else if (h_version == MPEG2_LSF) | ||
697 | return "22.05 kHz"; | ||
698 | else // SZD | ||
699 | return "11.025 kHz"; | ||
700 | case FOURTYEIGHT: | ||
701 | if (h_version == MPEG1) | ||
702 | return "48 kHz"; | ||
703 | else if (h_version == MPEG2_LSF) | ||
704 | return "24 kHz"; | ||
705 | else // SZD | ||
706 | return "12 kHz"; | ||
707 | } | ||
708 | return(null); | ||
709 | } | ||
710 | |||
711 | /** | ||
712 | * Returns Mode. | ||
713 | */ | ||
714 | public String mode_string() | ||
715 | { | ||
716 | switch (h_mode) | ||
717 | { | ||
718 | case STEREO: | ||
719 | return "Stereo"; | ||
720 | case JOINT_STEREO: | ||
721 | return "Joint stereo"; | ||
722 | case DUAL_CHANNEL: | ||
723 | return "Dual channel"; | ||
724 | case SINGLE_CHANNEL: | ||
725 | return "Single channel"; | ||
726 | } | ||
727 | return null; | ||
728 | } | ||
729 | |||
730 | /** | ||
731 | * Returns Version. | ||
732 | * @return MPEG-1 or MPEG-2 LSF or MPEG-2.5 LSF | ||
733 | */ | ||
734 | public String version_string() | ||
735 | { | ||
736 | switch (h_version) | ||
737 | { | ||
738 | case MPEG1: | ||
739 | return "MPEG-1"; | ||
740 | case MPEG2_LSF: | ||
741 | return "MPEG-2 LSF"; | ||
742 | case MPEG25_LSF: // SZD | ||
743 | return "MPEG-2.5 LSF"; | ||
744 | } | ||
745 | return(null); | ||
746 | } | ||
747 | |||
748 | /** | ||
749 | * Returns the number of subbands in the current frame. | ||
750 | * @return number of subbands | ||
751 | */ | ||
752 | public int number_of_subbands() {return h_number_of_subbands;} | ||
753 | |||
754 | /** | ||
755 | * Returns Intensity Stereo. | ||
756 | * (Layer II joint stereo only). | ||
757 | * Returns the number of subbands which are in stereo mode, | ||
758 | * subbands above that limit are in intensity stereo mode. | ||
759 | * @return intensity | ||
760 | */ | ||
761 | public int intensity_stereo_bound() {return h_intensity_stereo_bound;} | ||
762 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/InputStreamSource.java b/songdbj/javazoom/jl/decoder/InputStreamSource.java new file mode 100644 index 0000000000..5c62947049 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/InputStreamSource.java | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | import java.io.IOException; | ||
24 | import java.io.InputStream; | ||
25 | |||
26 | /** | ||
27 | * <i>Work In Progress.</i> | ||
28 | * | ||
29 | * An instance of <code>InputStreamSource</code> implements a | ||
30 | * <code>Source</code> that provides data from an <code>InputStream | ||
31 | * </code>. Seeking functionality is not supported. | ||
32 | * | ||
33 | * @author MDM | ||
34 | */ | ||
35 | public class InputStreamSource implements Source | ||
36 | { | ||
37 | private final InputStream in; | ||
38 | |||
39 | public InputStreamSource(InputStream in) | ||
40 | { | ||
41 | if (in==null) | ||
42 | throw new NullPointerException("in"); | ||
43 | |||
44 | this.in = in; | ||
45 | } | ||
46 | |||
47 | public int read(byte[] b, int offs, int len) | ||
48 | throws IOException | ||
49 | { | ||
50 | int read = in.read(b, offs, len); | ||
51 | return read; | ||
52 | } | ||
53 | |||
54 | public boolean willReadBlock() | ||
55 | { | ||
56 | return true; | ||
57 | //boolean block = (in.available()==0); | ||
58 | //return block; | ||
59 | } | ||
60 | |||
61 | public boolean isSeekable() | ||
62 | { | ||
63 | return false; | ||
64 | } | ||
65 | |||
66 | public long tell() | ||
67 | { | ||
68 | return -1; | ||
69 | } | ||
70 | |||
71 | public long seek(long to) | ||
72 | { | ||
73 | return -1; | ||
74 | } | ||
75 | |||
76 | public long length() | ||
77 | { | ||
78 | return -1; | ||
79 | } | ||
80 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/JavaLayerError.java b/songdbj/javazoom/jl/decoder/JavaLayerError.java new file mode 100644 index 0000000000..d9910bcc71 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/JavaLayerError.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | /** | ||
24 | * Work in progress. | ||
25 | * | ||
26 | * API usage errors may be handled by throwing an instance of this | ||
27 | * class, as per JMF 2.0. | ||
28 | */ | ||
29 | public class JavaLayerError extends Error | ||
30 | { | ||
31 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/JavaLayerErrors.java b/songdbj/javazoom/jl/decoder/JavaLayerErrors.java new file mode 100644 index 0000000000..3b9c2ff9d7 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/JavaLayerErrors.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | /** | ||
24 | * Exception erorr codes for components of the JavaLayer API. | ||
25 | */ | ||
26 | public interface JavaLayerErrors | ||
27 | { | ||
28 | /** | ||
29 | * The first bitstream error code. See the {@link DecoderErrors DecoderErrors} | ||
30 | * interface for other bitstream error codes. | ||
31 | */ | ||
32 | static public final int BITSTREAM_ERROR = 0x100; | ||
33 | |||
34 | /** | ||
35 | * The first decoder error code. See the {@link DecoderErrors DecoderErrors} | ||
36 | * interface for other decoder error codes. | ||
37 | */ | ||
38 | static public final int DECODER_ERROR = 0x200; | ||
39 | |||
40 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/JavaLayerException.java b/songdbj/javazoom/jl/decoder/JavaLayerException.java new file mode 100644 index 0000000000..e7a50a8340 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/JavaLayerException.java | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | import java.io.PrintStream; | ||
24 | |||
25 | |||
26 | /** | ||
27 | * The JavaLayerException is the base class for all API-level | ||
28 | * exceptions thrown by JavaLayer. To facilitate conversion and | ||
29 | * common handling of exceptions from other domains, the class | ||
30 | * can delegate some functionality to a contained Throwable instance. | ||
31 | * <p> | ||
32 | * | ||
33 | * @author MDM | ||
34 | */ | ||
35 | public class JavaLayerException extends Exception | ||
36 | { | ||
37 | |||
38 | private Throwable exception; | ||
39 | |||
40 | |||
41 | public JavaLayerException() | ||
42 | { | ||
43 | } | ||
44 | |||
45 | public JavaLayerException(String msg) | ||
46 | { | ||
47 | super(msg); | ||
48 | } | ||
49 | |||
50 | public JavaLayerException(String msg, Throwable t) | ||
51 | { | ||
52 | super(msg); | ||
53 | exception = t; | ||
54 | } | ||
55 | |||
56 | public Throwable getException() | ||
57 | { | ||
58 | return exception; | ||
59 | } | ||
60 | |||
61 | |||
62 | public void printStackTrace() | ||
63 | { | ||
64 | printStackTrace(System.err); | ||
65 | } | ||
66 | |||
67 | public void printStackTrace(PrintStream ps) | ||
68 | { | ||
69 | if (this.exception==null) | ||
70 | { | ||
71 | super.printStackTrace(ps); | ||
72 | } | ||
73 | else | ||
74 | { | ||
75 | exception.printStackTrace(); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | |||
80 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/JavaLayerHook.java b/songdbj/javazoom/jl/decoder/JavaLayerHook.java new file mode 100644 index 0000000000..352059433d --- /dev/null +++ b/songdbj/javazoom/jl/decoder/JavaLayerHook.java | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | *----------------------------------------------------------------------- | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Library General Public License as published | ||
6 | * by the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library General Public | ||
15 | * License along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | *---------------------------------------------------------------------- | ||
18 | */ | ||
19 | |||
20 | package javazoom.jl.decoder; | ||
21 | |||
22 | import java.io.InputStream; | ||
23 | |||
24 | /** | ||
25 | * The <code>JavaLayerHooks</code> class allows developers to change | ||
26 | * the way the JavaLayer library uses Resources. | ||
27 | */ | ||
28 | |||
29 | public interface JavaLayerHook | ||
30 | { | ||
31 | /** | ||
32 | * Retrieves the named resource. This allows resources to be | ||
33 | * obtained without specifying how they are retrieved. | ||
34 | */ | ||
35 | public InputStream getResourceAsStream(String name); | ||
36 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/JavaLayerUtils.java b/songdbj/javazoom/jl/decoder/JavaLayerUtils.java new file mode 100644 index 0000000000..c9ce3838e5 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/JavaLayerUtils.java | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | import java.io.IOException; | ||
24 | import java.io.InputStream; | ||
25 | import java.io.InvalidClassException; | ||
26 | import java.io.InvalidObjectException; | ||
27 | import java.io.ObjectInputStream; | ||
28 | import java.io.ObjectOutputStream; | ||
29 | import java.io.OutputStream; | ||
30 | import java.lang.reflect.Array; | ||
31 | |||
32 | /** | ||
33 | * The JavaLayerUtils class is not strictly part of the JavaLayer API. | ||
34 | * It serves to provide useful methods and system-wide hooks. | ||
35 | * | ||
36 | * @author MDM | ||
37 | */ | ||
38 | public class JavaLayerUtils | ||
39 | { | ||
40 | static private JavaLayerHook hook = null; | ||
41 | |||
42 | /** | ||
43 | * Deserializes the object contained in the given input stream. | ||
44 | * @param in The input stream to deserialize an object from. | ||
45 | * @param cls The expected class of the deserialized object. | ||
46 | */ | ||
47 | static public Object deserialize(InputStream in, Class cls) | ||
48 | throws IOException | ||
49 | { | ||
50 | if (cls==null) | ||
51 | throw new NullPointerException("cls"); | ||
52 | |||
53 | Object obj = deserialize(in, cls); | ||
54 | if (!cls.isInstance(obj)) | ||
55 | { | ||
56 | throw new InvalidObjectException("type of deserialized instance not of required class."); | ||
57 | } | ||
58 | |||
59 | return obj; | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Deserializes an object from the given <code>InputStream</code>. | ||
64 | * The deserialization is delegated to an <code> | ||
65 | * ObjectInputStream</code> instance. | ||
66 | * | ||
67 | * @param in The <code>InputStream</code> to deserialize an object | ||
68 | * from. | ||
69 | * | ||
70 | * @return The object deserialized from the stream. | ||
71 | * @exception IOException is thrown if there was a problem reading | ||
72 | * the underlying stream, or an object could not be deserialized | ||
73 | * from the stream. | ||
74 | * | ||
75 | * @see java.io.ObjectInputStream | ||
76 | */ | ||
77 | static public Object deserialize(InputStream in) | ||
78 | throws IOException | ||
79 | { | ||
80 | if (in==null) | ||
81 | throw new NullPointerException("in"); | ||
82 | |||
83 | ObjectInputStream objIn = new ObjectInputStream(in); | ||
84 | |||
85 | Object obj; | ||
86 | |||
87 | try | ||
88 | { | ||
89 | obj = objIn.readObject(); | ||
90 | } | ||
91 | catch (ClassNotFoundException ex) | ||
92 | { | ||
93 | throw new InvalidClassException(ex.toString()); | ||
94 | } | ||
95 | |||
96 | return obj; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Deserializes an array from a given <code>InputStream</code>. | ||
101 | * | ||
102 | * @param in The <code>InputStream</code> to | ||
103 | * deserialize an object from. | ||
104 | * | ||
105 | * @param elemType The class denoting the type of the array | ||
106 | * elements. | ||
107 | * @param length The expected length of the array, or -1 if | ||
108 | * any length is expected. | ||
109 | */ | ||
110 | static public Object deserializeArray(InputStream in, Class elemType, int length) | ||
111 | throws IOException | ||
112 | { | ||
113 | if (elemType==null) | ||
114 | throw new NullPointerException("elemType"); | ||
115 | |||
116 | if (length<-1) | ||
117 | throw new IllegalArgumentException("length"); | ||
118 | |||
119 | Object obj = deserialize(in); | ||
120 | |||
121 | Class cls = obj.getClass(); | ||
122 | |||
123 | |||
124 | if (!cls.isArray()) | ||
125 | throw new InvalidObjectException("object is not an array"); | ||
126 | |||
127 | Class arrayElemType = cls.getComponentType(); | ||
128 | if (arrayElemType!=elemType) | ||
129 | throw new InvalidObjectException("unexpected array component type"); | ||
130 | |||
131 | if (length != -1) | ||
132 | { | ||
133 | int arrayLength = Array.getLength(obj); | ||
134 | if (arrayLength!=length) | ||
135 | throw new InvalidObjectException("array length mismatch"); | ||
136 | } | ||
137 | |||
138 | return obj; | ||
139 | } | ||
140 | |||
141 | static public Object deserializeArrayResource(String name, Class elemType, int length) | ||
142 | throws IOException | ||
143 | { | ||
144 | InputStream str = getResourceAsStream(name); | ||
145 | if (str==null) | ||
146 | throw new IOException("unable to load resource '"+name+"'"); | ||
147 | |||
148 | Object obj = deserializeArray(str, elemType, length); | ||
149 | |||
150 | return obj; | ||
151 | } | ||
152 | |||
153 | static public void serialize(OutputStream out, Object obj) | ||
154 | throws IOException | ||
155 | { | ||
156 | if (out==null) | ||
157 | throw new NullPointerException("out"); | ||
158 | |||
159 | if (obj==null) | ||
160 | throw new NullPointerException("obj"); | ||
161 | |||
162 | ObjectOutputStream objOut = new ObjectOutputStream(out); | ||
163 | objOut.writeObject(obj); | ||
164 | |||
165 | } | ||
166 | |||
167 | /** | ||
168 | * Sets the system-wide JavaLayer hook. | ||
169 | */ | ||
170 | static synchronized public void setHook(JavaLayerHook hook0) | ||
171 | { | ||
172 | hook = hook0; | ||
173 | } | ||
174 | |||
175 | static synchronized public JavaLayerHook getHook() | ||
176 | { | ||
177 | return hook; | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * Retrieves an InputStream for a named resource. | ||
182 | * | ||
183 | * @param name The name of the resource. This must be a simple | ||
184 | * name, and not a qualified package name. | ||
185 | * | ||
186 | * @return The InputStream for the named resource, or null if | ||
187 | * the resource has not been found. If a hook has been | ||
188 | * provided, its getResourceAsStream() method is called | ||
189 | * to retrieve the resource. | ||
190 | */ | ||
191 | static synchronized public InputStream getResourceAsStream(String name) | ||
192 | { | ||
193 | InputStream is = null; | ||
194 | |||
195 | if (hook!=null) | ||
196 | { | ||
197 | is = hook.getResourceAsStream(name); | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | Class cls = JavaLayerUtils.class; | ||
202 | is = cls.getResourceAsStream(name); | ||
203 | } | ||
204 | |||
205 | return is; | ||
206 | } | ||
207 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/LayerIDecoder.java b/songdbj/javazoom/jl/decoder/LayerIDecoder.java new file mode 100644 index 0000000000..b633dd2403 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/LayerIDecoder.java | |||
@@ -0,0 +1,444 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 12/12/99 Initial version. Adapted from javalayer.java | ||
5 | * and Subband*.java. mdm@techie.com | ||
6 | * | ||
7 | * 02/28/99 Initial version : javalayer.java by E.B | ||
8 | *----------------------------------------------------------------------- | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Library General Public License as published | ||
11 | * by the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU Library General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Library General Public | ||
20 | * License along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | *---------------------------------------------------------------------- | ||
23 | */ | ||
24 | |||
25 | package javazoom.jl.decoder; | ||
26 | |||
27 | /** | ||
28 | * Implements decoding of MPEG Audio Layer I frames. | ||
29 | */ | ||
30 | class LayerIDecoder implements FrameDecoder | ||
31 | { | ||
32 | protected Bitstream stream; | ||
33 | protected Header header; | ||
34 | protected SynthesisFilter filter1, filter2; | ||
35 | protected Obuffer buffer; | ||
36 | protected int which_channels; | ||
37 | protected int mode; | ||
38 | |||
39 | protected int num_subbands; | ||
40 | protected Subband[] subbands; | ||
41 | protected Crc16 crc = null; // new Crc16[1] to enable CRC checking. | ||
42 | |||
43 | public LayerIDecoder() | ||
44 | { | ||
45 | crc = new Crc16(); | ||
46 | } | ||
47 | |||
48 | public void create(Bitstream stream0, Header header0, | ||
49 | SynthesisFilter filtera, SynthesisFilter filterb, | ||
50 | Obuffer buffer0, int which_ch0) | ||
51 | { | ||
52 | stream = stream0; | ||
53 | header = header0; | ||
54 | filter1 = filtera; | ||
55 | filter2 = filterb; | ||
56 | buffer = buffer0; | ||
57 | which_channels = which_ch0; | ||
58 | |||
59 | } | ||
60 | |||
61 | |||
62 | |||
63 | public void decodeFrame() | ||
64 | { | ||
65 | |||
66 | num_subbands = header.number_of_subbands(); | ||
67 | subbands = new Subband[32]; | ||
68 | mode = header.mode(); | ||
69 | |||
70 | createSubbands(); | ||
71 | |||
72 | readAllocation(); | ||
73 | readScaleFactorSelection(); | ||
74 | |||
75 | if ((crc != null) || header.checksum_ok()) | ||
76 | { | ||
77 | readScaleFactors(); | ||
78 | |||
79 | readSampleData(); | ||
80 | } | ||
81 | |||
82 | } | ||
83 | |||
84 | protected void createSubbands() | ||
85 | { | ||
86 | int i; | ||
87 | if (mode == Header.SINGLE_CHANNEL) | ||
88 | for (i = 0; i < num_subbands; ++i) | ||
89 | subbands[i] = new SubbandLayer1(i); | ||
90 | else if (mode == Header.JOINT_STEREO) | ||
91 | { | ||
92 | for (i = 0; i < header.intensity_stereo_bound(); ++i) | ||
93 | subbands[i] = new SubbandLayer1Stereo(i); | ||
94 | for (; i < num_subbands; ++i) | ||
95 | subbands[i] = new SubbandLayer1IntensityStereo(i); | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | for (i = 0; i < num_subbands; ++i) | ||
100 | subbands[i] = new SubbandLayer1Stereo(i); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | protected void readAllocation() | ||
105 | { | ||
106 | // start to read audio data: | ||
107 | for (int i = 0; i < num_subbands; ++i) | ||
108 | subbands[i].read_allocation(stream, header, crc); | ||
109 | |||
110 | } | ||
111 | |||
112 | protected void readScaleFactorSelection() | ||
113 | { | ||
114 | // scale factor selection not present for layer I. | ||
115 | } | ||
116 | |||
117 | protected void readScaleFactors() | ||
118 | { | ||
119 | for (int i = 0; i < num_subbands; ++i) | ||
120 | subbands[i].read_scalefactor(stream, header); | ||
121 | } | ||
122 | |||
123 | protected void readSampleData() | ||
124 | { | ||
125 | boolean read_ready = false; | ||
126 | boolean write_ready = false; | ||
127 | int mode = header.mode(); | ||
128 | int i; | ||
129 | do | ||
130 | { | ||
131 | for (i = 0; i < num_subbands; ++i) | ||
132 | read_ready = subbands[i].read_sampledata(stream); | ||
133 | do | ||
134 | { | ||
135 | for (i = 0; i < num_subbands; ++i) | ||
136 | write_ready = subbands[i].put_next_sample(which_channels,filter1, filter2); | ||
137 | |||
138 | filter1.calculate_pcm_samples(buffer); | ||
139 | if ((which_channels == OutputChannels.BOTH_CHANNELS) && (mode != Header.SINGLE_CHANNEL)) | ||
140 | filter2.calculate_pcm_samples(buffer); | ||
141 | } while (!write_ready); | ||
142 | } while (!read_ready); | ||
143 | |||
144 | } | ||
145 | |||
146 | /** | ||
147 | * Abstract base class for subband classes of layer I and II | ||
148 | */ | ||
149 | static abstract class Subband | ||
150 | { | ||
151 | /* | ||
152 | * Changes from version 1.1 to 1.2: | ||
153 | * - array size increased by one, although a scalefactor with index 63 | ||
154 | * is illegal (to prevent segmentation faults) | ||
155 | */ | ||
156 | // Scalefactors for layer I and II, Annex 3-B.1 in ISO/IEC DIS 11172: | ||
157 | public static final float scalefactors[] = | ||
158 | { | ||
159 | 2.00000000000000f, 1.58740105196820f, 1.25992104989487f, 1.00000000000000f, | ||
160 | 0.79370052598410f, 0.62996052494744f, 0.50000000000000f, 0.39685026299205f, | ||
161 | 0.31498026247372f, 0.25000000000000f, 0.19842513149602f, 0.15749013123686f, | ||
162 | 0.12500000000000f, 0.09921256574801f, 0.07874506561843f, 0.06250000000000f, | ||
163 | 0.04960628287401f, 0.03937253280921f, 0.03125000000000f, 0.02480314143700f, | ||
164 | 0.01968626640461f, 0.01562500000000f, 0.01240157071850f, 0.00984313320230f, | ||
165 | 0.00781250000000f, 0.00620078535925f, 0.00492156660115f, 0.00390625000000f, | ||
166 | 0.00310039267963f, 0.00246078330058f, 0.00195312500000f, 0.00155019633981f, | ||
167 | 0.00123039165029f, 0.00097656250000f, 0.00077509816991f, 0.00061519582514f, | ||
168 | 0.00048828125000f, 0.00038754908495f, 0.00030759791257f, 0.00024414062500f, | ||
169 | 0.00019377454248f, 0.00015379895629f, 0.00012207031250f, 0.00009688727124f, | ||
170 | 0.00007689947814f, 0.00006103515625f, 0.00004844363562f, 0.00003844973907f, | ||
171 | 0.00003051757813f, 0.00002422181781f, 0.00001922486954f, 0.00001525878906f, | ||
172 | 0.00001211090890f, 0.00000961243477f, 0.00000762939453f, 0.00000605545445f, | ||
173 | 0.00000480621738f, 0.00000381469727f, 0.00000302772723f, 0.00000240310869f, | ||
174 | 0.00000190734863f, 0.00000151386361f, 0.00000120155435f, 0.00000000000000f /* illegal scalefactor */ | ||
175 | }; | ||
176 | |||
177 | public abstract void read_allocation (Bitstream stream, Header header, Crc16 crc); | ||
178 | public abstract void read_scalefactor (Bitstream stream, Header header); | ||
179 | public abstract boolean read_sampledata (Bitstream stream); | ||
180 | public abstract boolean put_next_sample (int channels, SynthesisFilter filter1, SynthesisFilter filter2); | ||
181 | }; | ||
182 | |||
183 | /** | ||
184 | * Class for layer I subbands in single channel mode. | ||
185 | * Used for single channel mode | ||
186 | * and in derived class for intensity stereo mode | ||
187 | */ | ||
188 | static class SubbandLayer1 extends Subband | ||
189 | { | ||
190 | |||
191 | // Factors and offsets for sample requantization | ||
192 | public static final float table_factor[] = { | ||
193 | 0.0f, (1.0f/2.0f) * (4.0f/3.0f), (1.0f/4.0f) * (8.0f/7.0f), (1.0f/8.0f) * (16.0f/15.0f), | ||
194 | (1.0f/16.0f) * (32.0f/31.0f), (1.0f/32.0f) * (64.0f/63.0f), (1.0f/64.0f) * (128.0f/127.0f), | ||
195 | (1.0f/128.0f) * (256.0f/255.0f), (1.0f/256.0f) * (512.0f/511.0f), | ||
196 | (1.0f/512.0f) * (1024.0f/1023.0f), (1.0f/1024.0f) * (2048.0f/2047.0f), | ||
197 | (1.0f/2048.0f) * (4096.0f/4095.0f), (1.0f/4096.0f) * (8192.0f/8191.0f), | ||
198 | (1.0f/8192.0f) * (16384.0f/16383.0f), (1.0f/16384.0f) * (32768.0f/32767.0f) | ||
199 | }; | ||
200 | |||
201 | public static final float table_offset[] = { | ||
202 | 0.0f, ((1.0f/2.0f)-1.0f) * (4.0f/3.0f), ((1.0f/4.0f)-1.0f) * (8.0f/7.0f), ((1.0f/8.0f)-1.0f) * (16.0f/15.0f), | ||
203 | ((1.0f/16.0f)-1.0f) * (32.0f/31.0f), ((1.0f/32.0f)-1.0f) * (64.0f/63.0f), ((1.0f/64.0f)-1.0f) * (128.0f/127.0f), | ||
204 | ((1.0f/128.0f)-1.0f) * (256.0f/255.0f), ((1.0f/256.0f)-1.0f) * (512.0f/511.0f), | ||
205 | ((1.0f/512.0f)-1.0f) * (1024.0f/1023.0f), ((1.0f/1024.0f)-1.0f) * (2048.0f/2047.0f), | ||
206 | ((1.0f/2048.0f)-1.0f) * (4096.0f/4095.0f), ((1.0f/4096.0f)-1.0f) * (8192.0f/8191.0f), | ||
207 | ((1.0f/8192.0f)-1.0f) * (16384.0f/16383.0f), ((1.0f/16384.0f)-1.0f) * (32768.0f/32767.0f) | ||
208 | }; | ||
209 | |||
210 | protected int subbandnumber; | ||
211 | protected int samplenumber; | ||
212 | protected int allocation; | ||
213 | protected float scalefactor; | ||
214 | protected int samplelength; | ||
215 | protected float sample; | ||
216 | protected float factor, offset; | ||
217 | |||
218 | /** | ||
219 | * Construtor. | ||
220 | */ | ||
221 | public SubbandLayer1(int subbandnumber) | ||
222 | { | ||
223 | this.subbandnumber = subbandnumber; | ||
224 | samplenumber = 0; | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * | ||
229 | */ | ||
230 | public void read_allocation(Bitstream stream, Header header, Crc16 crc) | ||
231 | { | ||
232 | if ((allocation = stream.get_bits (4)) == 15) ; | ||
233 | // cerr << "WARNING: stream contains an illegal allocation!\n"; | ||
234 | // MPEG-stream is corrupted! | ||
235 | if (crc != null) | ||
236 | crc.add_bits (allocation, 4); | ||
237 | if (allocation != 0) | ||
238 | { | ||
239 | samplelength = allocation + 1; | ||
240 | factor = table_factor[allocation]; | ||
241 | offset = table_offset[allocation]; | ||
242 | } | ||
243 | } | ||
244 | |||
245 | /** | ||
246 | * | ||
247 | */ | ||
248 | public void read_scalefactor(Bitstream stream, Header header) | ||
249 | { | ||
250 | if (allocation != 0) scalefactor = scalefactors[stream.get_bits(6)]; | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * | ||
255 | */ | ||
256 | public boolean read_sampledata(Bitstream stream) | ||
257 | { | ||
258 | if (allocation != 0) | ||
259 | { | ||
260 | sample = (float) (stream.get_bits(samplelength)); | ||
261 | } | ||
262 | if (++samplenumber == 12) | ||
263 | { | ||
264 | samplenumber = 0; | ||
265 | return true; | ||
266 | } | ||
267 | return false; | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * | ||
272 | */ | ||
273 | public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2) | ||
274 | { | ||
275 | if ((allocation !=0) && (channels != OutputChannels.RIGHT_CHANNEL)) | ||
276 | { | ||
277 | float scaled_sample = (sample * factor + offset) * scalefactor; | ||
278 | filter1.input_sample (scaled_sample, subbandnumber); | ||
279 | } | ||
280 | return true; | ||
281 | } | ||
282 | }; | ||
283 | |||
284 | /** | ||
285 | * Class for layer I subbands in joint stereo mode. | ||
286 | */ | ||
287 | static class SubbandLayer1IntensityStereo extends SubbandLayer1 | ||
288 | { | ||
289 | protected float channel2_scalefactor; | ||
290 | |||
291 | /** | ||
292 | * Constructor | ||
293 | */ | ||
294 | public SubbandLayer1IntensityStereo(int subbandnumber) | ||
295 | { | ||
296 | super(subbandnumber); | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * | ||
301 | */ | ||
302 | public void read_allocation(Bitstream stream, Header header, Crc16 crc) | ||
303 | { | ||
304 | super.read_allocation (stream, header, crc); | ||
305 | } | ||
306 | |||
307 | /** | ||
308 | * | ||
309 | */ | ||
310 | public void read_scalefactor (Bitstream stream, Header header) | ||
311 | { | ||
312 | if (allocation != 0) | ||
313 | { | ||
314 | scalefactor = scalefactors[stream.get_bits(6)]; | ||
315 | channel2_scalefactor = scalefactors[stream.get_bits(6)]; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * | ||
321 | */ | ||
322 | public boolean read_sampledata(Bitstream stream) | ||
323 | { | ||
324 | return super.read_sampledata (stream); | ||
325 | } | ||
326 | |||
327 | /** | ||
328 | * | ||
329 | */ | ||
330 | public boolean put_next_sample (int channels, SynthesisFilter filter1, SynthesisFilter filter2) | ||
331 | { | ||
332 | if (allocation !=0 ) | ||
333 | { | ||
334 | sample = sample * factor + offset; // requantization | ||
335 | if (channels == OutputChannels.BOTH_CHANNELS) | ||
336 | { | ||
337 | float sample1 = sample * scalefactor, | ||
338 | sample2 = sample * channel2_scalefactor; | ||
339 | filter1.input_sample(sample1, subbandnumber); | ||
340 | filter2.input_sample(sample2, subbandnumber); | ||
341 | } | ||
342 | else if (channels == OutputChannels.LEFT_CHANNEL) | ||
343 | { | ||
344 | float sample1 = sample * scalefactor; | ||
345 | filter1.input_sample(sample1, subbandnumber); | ||
346 | } | ||
347 | else | ||
348 | { | ||
349 | float sample2 = sample * channel2_scalefactor; | ||
350 | filter1.input_sample(sample2, subbandnumber); | ||
351 | } | ||
352 | } | ||
353 | return true; | ||
354 | } | ||
355 | }; | ||
356 | |||
357 | /** | ||
358 | * Class for layer I subbands in stereo mode. | ||
359 | */ | ||
360 | static class SubbandLayer1Stereo extends SubbandLayer1 | ||
361 | { | ||
362 | protected int channel2_allocation; | ||
363 | protected float channel2_scalefactor; | ||
364 | protected int channel2_samplelength; | ||
365 | protected float channel2_sample; | ||
366 | protected float channel2_factor, channel2_offset; | ||
367 | |||
368 | |||
369 | /** | ||
370 | * Constructor | ||
371 | */ | ||
372 | public SubbandLayer1Stereo(int subbandnumber) | ||
373 | { | ||
374 | super(subbandnumber); | ||
375 | } | ||
376 | |||
377 | /** | ||
378 | * | ||
379 | */ | ||
380 | public void read_allocation (Bitstream stream, Header header, Crc16 crc) | ||
381 | { | ||
382 | allocation = stream.get_bits(4); | ||
383 | channel2_allocation = stream.get_bits(4); | ||
384 | if (crc != null) | ||
385 | { | ||
386 | crc.add_bits (allocation, 4); | ||
387 | crc.add_bits (channel2_allocation, 4); | ||
388 | } | ||
389 | if (allocation != 0) | ||
390 | { | ||
391 | samplelength = allocation + 1; | ||
392 | factor = table_factor[allocation]; | ||
393 | offset = table_offset[allocation]; | ||
394 | } | ||
395 | if (channel2_allocation != 0) | ||
396 | { | ||
397 | channel2_samplelength = channel2_allocation + 1; | ||
398 | channel2_factor = table_factor[channel2_allocation]; | ||
399 | channel2_offset = table_offset[channel2_allocation]; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | /** | ||
404 | * | ||
405 | */ | ||
406 | public void read_scalefactor(Bitstream stream, Header header) | ||
407 | { | ||
408 | if (allocation != 0) scalefactor = scalefactors[stream.get_bits(6)]; | ||
409 | if (channel2_allocation != 0) channel2_scalefactor = scalefactors[stream.get_bits(6)]; | ||
410 | } | ||
411 | |||
412 | /** | ||
413 | * | ||
414 | */ | ||
415 | public boolean read_sampledata (Bitstream stream) | ||
416 | { | ||
417 | boolean returnvalue = super.read_sampledata(stream); | ||
418 | if (channel2_allocation != 0) | ||
419 | { | ||
420 | channel2_sample = (float) (stream.get_bits(channel2_samplelength)); | ||
421 | } | ||
422 | return(returnvalue); | ||
423 | } | ||
424 | |||
425 | /** | ||
426 | * | ||
427 | */ | ||
428 | public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2) | ||
429 | { | ||
430 | super.put_next_sample (channels, filter1, filter2); | ||
431 | if ((channel2_allocation != 0) && (channels != OutputChannels.LEFT_CHANNEL)) | ||
432 | { | ||
433 | float sample2 = (channel2_sample * channel2_factor + channel2_offset) * | ||
434 | channel2_scalefactor; | ||
435 | if (channels == OutputChannels.BOTH_CHANNELS) | ||
436 | filter2.input_sample (sample2, subbandnumber); | ||
437 | else | ||
438 | filter1.input_sample (sample2, subbandnumber); | ||
439 | } | ||
440 | return true; | ||
441 | } | ||
442 | }; | ||
443 | |||
444 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/LayerIIDecoder.java b/songdbj/javazoom/jl/decoder/LayerIIDecoder.java new file mode 100644 index 0000000000..7265b1f8fa --- /dev/null +++ b/songdbj/javazoom/jl/decoder/LayerIIDecoder.java | |||
@@ -0,0 +1,1064 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 29/05/01 Michael Scheerer, Fixed some C++ to Java porting bugs. | ||
5 | * | ||
6 | * 16/07/01 Michael Scheerer, Catched a bug in method | ||
7 | * read_sampledata, which causes an outOfIndexException. | ||
8 | * | ||
9 | * 12/12/99 Initial version. Adapted from javalayer.java | ||
10 | * and Subband*.java. mdm@techie.com | ||
11 | * | ||
12 | * 02/28/99 Initial version : javalayer.java by E.B | ||
13 | *----------------------------------------------------------------------- | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU Library General Public License as published | ||
16 | * by the Free Software Foundation; either version 2 of the License, or | ||
17 | * (at your option) any later version. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU Library General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU Library General Public | ||
25 | * License along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
27 | *---------------------------------------------------------------------- | ||
28 | */ | ||
29 | |||
30 | package javazoom.jl.decoder; | ||
31 | |||
32 | /** | ||
33 | * Implements decoding of MPEG Audio Layer II frames. | ||
34 | */ | ||
35 | class LayerIIDecoder extends LayerIDecoder implements FrameDecoder | ||
36 | { | ||
37 | |||
38 | public LayerIIDecoder() | ||
39 | { | ||
40 | } | ||
41 | |||
42 | |||
43 | protected void createSubbands() | ||
44 | { | ||
45 | int i; | ||
46 | if (mode == Header.SINGLE_CHANNEL) | ||
47 | for (i = 0; i < num_subbands; ++i) | ||
48 | subbands[i] = new SubbandLayer2(i); | ||
49 | else if (mode == Header.JOINT_STEREO) | ||
50 | { | ||
51 | for (i = 0; i < header.intensity_stereo_bound(); ++i) | ||
52 | subbands[i] = new SubbandLayer2Stereo(i); | ||
53 | for (; i < num_subbands; ++i) | ||
54 | subbands[i] = new SubbandLayer2IntensityStereo(i); | ||
55 | } | ||
56 | else | ||
57 | { | ||
58 | for (i = 0; i < num_subbands; ++i) | ||
59 | subbands[i] = new SubbandLayer2Stereo(i); | ||
60 | } | ||
61 | |||
62 | } | ||
63 | |||
64 | protected void readScaleFactorSelection() | ||
65 | { | ||
66 | for (int i = 0; i < num_subbands; ++i) | ||
67 | ((SubbandLayer2)subbands[i]).read_scalefactor_selection(stream, crc); | ||
68 | } | ||
69 | |||
70 | |||
71 | |||
72 | /** | ||
73 | * Class for layer II subbands in single channel mode. | ||
74 | */ | ||
75 | static class SubbandLayer2 extends Subband | ||
76 | { | ||
77 | // this table contains 3 requantized samples for each legal codeword | ||
78 | // when grouped in 5 bits, i.e. 3 quantizationsteps per sample | ||
79 | public static final float grouping_5bits[] = new float[] | ||
80 | { | ||
81 | -2.0f/3.0f, -2.0f/3.0f, -2.0f/3.0f, | ||
82 | 0.0f, -2.0f/3.0f, -2.0f/3.0f, | ||
83 | 2.0f/3.0f, -2.0f/3.0f, -2.0f/3.0f, | ||
84 | -2.0f/3.0f, 0.0f, -2.0f/3.0f, | ||
85 | 0.0f, 0.0f, -2.0f/3.0f, | ||
86 | 2.0f/3.0f, 0.0f, -2.0f/3.0f, | ||
87 | -2.0f/3.0f, 2.0f/3.0f, -2.0f/3.0f, | ||
88 | 0.0f, 2.0f/3.0f, -2.0f/3.0f, | ||
89 | 2.0f/3.0f, 2.0f/3.0f, -2.0f/3.0f, | ||
90 | -2.0f/3.0f, -2.0f/3.0f, 0.0f, | ||
91 | 0.0f, -2.0f/3.0f, 0.0f, | ||
92 | 2.0f/3.0f, -2.0f/3.0f, 0.0f, | ||
93 | -2.0f/3.0f, 0.0f, 0.0f, | ||
94 | 0.0f, 0.0f, 0.0f, | ||
95 | 2.0f/3.0f, 0.0f, 0.0f, | ||
96 | -2.0f/3.0f, 2.0f/3.0f, 0.0f, | ||
97 | 0.0f, 2.0f/3.0f, 0.0f, | ||
98 | 2.0f/3.0f, 2.0f/3.0f, 0.0f, | ||
99 | -2.0f/3.0f, -2.0f/3.0f, 2.0f/3.0f, | ||
100 | 0.0f, -2.0f/3.0f, 2.0f/3.0f, | ||
101 | 2.0f/3.0f, -2.0f/3.0f, 2.0f/3.0f, | ||
102 | -2.0f/3.0f, 0.0f, 2.0f/3.0f, | ||
103 | 0.0f, 0.0f, 2.0f/3.0f, | ||
104 | 2.0f/3.0f, 0.0f, 2.0f/3.0f, | ||
105 | -2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, | ||
106 | 0.0f, 2.0f/3.0f, 2.0f/3.0f, | ||
107 | 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f | ||
108 | }; | ||
109 | |||
110 | // this table contains 3 requantized samples for each legal codeword | ||
111 | // when grouped in 7 bits, i.e. 5 quantizationsteps per sample | ||
112 | public static final float grouping_7bits[] = new float[] | ||
113 | { | ||
114 | -0.8f, -0.8f, -0.8f, -0.4f, -0.8f, -0.8f, 0.0f, -0.8f, -0.8f, 0.4f, -0.8f, -0.8f, 0.8f, -0.8f, -0.8f, | ||
115 | -0.8f, -0.4f, -0.8f, -0.4f, -0.4f, -0.8f, 0.0f, -0.4f, -0.8f, 0.4f, -0.4f, -0.8f, 0.8f, -0.4f, -0.8f, | ||
116 | -0.8f, 0.0f, -0.8f, -0.4f, 0.0f, -0.8f, 0.0f, 0.0f, -0.8f, 0.4f, 0.0f, -0.8f, 0.8f, 0.0f, -0.8f, | ||
117 | -0.8f, 0.4f, -0.8f, -0.4f, 0.4f, -0.8f, 0.0f, 0.4f, -0.8f, 0.4f, 0.4f, -0.8f, 0.8f, 0.4f, -0.8f, | ||
118 | -0.8f, 0.8f, -0.8f, -0.4f, 0.8f, -0.8f, 0.0f, 0.8f, -0.8f, 0.4f, 0.8f, -0.8f, 0.8f, 0.8f, -0.8f, | ||
119 | -0.8f, -0.8f, -0.4f, -0.4f, -0.8f, -0.4f, 0.0f, -0.8f, -0.4f, 0.4f, -0.8f, -0.4f, 0.8f, -0.8f, -0.4f, | ||
120 | -0.8f, -0.4f, -0.4f, -0.4f, -0.4f, -0.4f, 0.0f, -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.8f, -0.4f, -0.4f, | ||
121 | -0.8f, 0.0f, -0.4f, -0.4f, 0.0f, -0.4f, 0.0f, 0.0f, -0.4f, 0.4f, 0.0f, -0.4f, 0.8f, 0.0f, -0.4f, | ||
122 | -0.8f, 0.4f, -0.4f, -0.4f, 0.4f, -0.4f, 0.0f, 0.4f, -0.4f, 0.4f, 0.4f, -0.4f, 0.8f, 0.4f, -0.4f, | ||
123 | -0.8f, 0.8f, -0.4f, -0.4f, 0.8f, -0.4f, 0.0f, 0.8f, -0.4f, 0.4f, 0.8f, -0.4f, 0.8f, 0.8f, -0.4f, | ||
124 | -0.8f, -0.8f, 0.0f, -0.4f, -0.8f, 0.0f, 0.0f, -0.8f, 0.0f, 0.4f, -0.8f, 0.0f, 0.8f, -0.8f, 0.0f, | ||
125 | -0.8f, -0.4f, 0.0f, -0.4f, -0.4f, 0.0f, 0.0f, -0.4f, 0.0f, 0.4f, -0.4f, 0.0f, 0.8f, -0.4f, 0.0f, | ||
126 | -0.8f, 0.0f, 0.0f, -0.4f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.0f, 0.0f, 0.8f, 0.0f, 0.0f, | ||
127 | -0.8f, 0.4f, 0.0f, -0.4f, 0.4f, 0.0f, 0.0f, 0.4f, 0.0f, 0.4f, 0.4f, 0.0f, 0.8f, 0.4f, 0.0f, | ||
128 | -0.8f, 0.8f, 0.0f, -0.4f, 0.8f, 0.0f, 0.0f, 0.8f, 0.0f, 0.4f, 0.8f, 0.0f, 0.8f, 0.8f, 0.0f, | ||
129 | -0.8f, -0.8f, 0.4f, -0.4f, -0.8f, 0.4f, 0.0f, -0.8f, 0.4f, 0.4f, -0.8f, 0.4f, 0.8f, -0.8f, 0.4f, | ||
130 | -0.8f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.0f, -0.4f, 0.4f, 0.4f, -0.4f, 0.4f, 0.8f, -0.4f, 0.4f, | ||
131 | -0.8f, 0.0f, 0.4f, -0.4f, 0.0f, 0.4f, 0.0f, 0.0f, 0.4f, 0.4f, 0.0f, 0.4f, 0.8f, 0.0f, 0.4f, | ||
132 | -0.8f, 0.4f, 0.4f, -0.4f, 0.4f, 0.4f, 0.0f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.8f, 0.4f, 0.4f, | ||
133 | -0.8f, 0.8f, 0.4f, -0.4f, 0.8f, 0.4f, 0.0f, 0.8f, 0.4f, 0.4f, 0.8f, 0.4f, 0.8f, 0.8f, 0.4f, | ||
134 | -0.8f, -0.8f, 0.8f, -0.4f, -0.8f, 0.8f, 0.0f, -0.8f, 0.8f, 0.4f, -0.8f, 0.8f, 0.8f, -0.8f, 0.8f, | ||
135 | -0.8f, -0.4f, 0.8f, -0.4f, -0.4f, 0.8f, 0.0f, -0.4f, 0.8f, 0.4f, -0.4f, 0.8f, 0.8f, -0.4f, 0.8f, | ||
136 | -0.8f, 0.0f, 0.8f, -0.4f, 0.0f, 0.8f, 0.0f, 0.0f, 0.8f, 0.4f, 0.0f, 0.8f, 0.8f, 0.0f, 0.8f, | ||
137 | -0.8f, 0.4f, 0.8f, -0.4f, 0.4f, 0.8f, 0.0f, 0.4f, 0.8f, 0.4f, 0.4f, 0.8f, 0.8f, 0.4f, 0.8f, | ||
138 | -0.8f, 0.8f, 0.8f, -0.4f, 0.8f, 0.8f, 0.0f, 0.8f, 0.8f, 0.4f, 0.8f, 0.8f, 0.8f, 0.8f, 0.8f | ||
139 | }; | ||
140 | |||
141 | // this table contains 3 requantized samples for each legal codeword | ||
142 | // when grouped in 10 bits, i.e. 9 quantizationsteps per sample | ||
143 | public static final float grouping_10bits[] = | ||
144 | { | ||
145 | -8.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, | ||
146 | -2.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, 0.0f, -8.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, | ||
147 | 4.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -8.0f/9.0f, | ||
148 | -8.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, | ||
149 | -2.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 0.0f, -6.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, | ||
150 | 4.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, | ||
151 | -8.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, | ||
152 | -2.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 0.0f, -4.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, | ||
153 | 4.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, | ||
154 | -8.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, | ||
155 | -2.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, 0.0f, -2.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, | ||
156 | 4.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -8.0f/9.0f, | ||
157 | -8.0f/9.0f, 0.0f, -8.0f/9.0f, -6.0f/9.0f, 0.0f, -8.0f/9.0f, -4.0f/9.0f, 0.0f, -8.0f/9.0f, | ||
158 | -2.0f/9.0f, 0.0f, -8.0f/9.0f, 0.0f, 0.0f, -8.0f/9.0f, 2.0f/9.0f, 0.0f, -8.0f/9.0f, | ||
159 | 4.0f/9.0f, 0.0f, -8.0f/9.0f, 6.0f/9.0f, 0.0f, -8.0f/9.0f, 8.0f/9.0f, 0.0f, -8.0f/9.0f, | ||
160 | -8.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, | ||
161 | -2.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 0.0f, 2.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, | ||
162 | 4.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, | ||
163 | -8.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, | ||
164 | -2.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, 0.0f, 4.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, | ||
165 | 4.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -8.0f/9.0f, | ||
166 | -8.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, | ||
167 | -2.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 0.0f, 6.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, | ||
168 | 4.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, | ||
169 | -8.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, | ||
170 | -2.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 0.0f, 8.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, | ||
171 | 4.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, | ||
172 | -8.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, | ||
173 | -2.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 0.0f, -8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, | ||
174 | 4.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -6.0f/9.0f, | ||
175 | -8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, | ||
176 | -2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 0.0f, -6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, | ||
177 | 4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, | ||
178 | -8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, | ||
179 | -2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 0.0f, -4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, | ||
180 | 4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, | ||
181 | -8.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, | ||
182 | -2.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 0.0f, -2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, | ||
183 | 4.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, | ||
184 | -8.0f/9.0f, 0.0f, -6.0f/9.0f, -6.0f/9.0f, 0.0f, -6.0f/9.0f, -4.0f/9.0f, 0.0f, -6.0f/9.0f, | ||
185 | -2.0f/9.0f, 0.0f, -6.0f/9.0f, 0.0f, 0.0f, -6.0f/9.0f, 2.0f/9.0f, 0.0f, -6.0f/9.0f, | ||
186 | 4.0f/9.0f, 0.0f, -6.0f/9.0f, 6.0f/9.0f, 0.0f, -6.0f/9.0f, 8.0f/9.0f, 0.0f, -6.0f/9.0f, | ||
187 | -8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, | ||
188 | -2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 0.0f, 2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, | ||
189 | 4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, | ||
190 | -8.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, | ||
191 | -2.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 0.0f, 4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, | ||
192 | 4.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, | ||
193 | -8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, | ||
194 | -2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 0.0f, 6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, | ||
195 | 4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, | ||
196 | -8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, | ||
197 | -2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 0.0f, 8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, | ||
198 | 4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, | ||
199 | -8.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, | ||
200 | -2.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 0.0f, -8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, | ||
201 | 4.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -4.0f/9.0f, | ||
202 | -8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, | ||
203 | -2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 0.0f, -6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, | ||
204 | 4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, | ||
205 | -8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, | ||
206 | -2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 0.0f, -4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, | ||
207 | 4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, | ||
208 | -8.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, | ||
209 | -2.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 0.0f, -2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, | ||
210 | 4.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, | ||
211 | -8.0f/9.0f, 0.0f, -4.0f/9.0f, -6.0f/9.0f, 0.0f, -4.0f/9.0f, -4.0f/9.0f, 0.0f, -4.0f/9.0f, | ||
212 | -2.0f/9.0f, 0.0f, -4.0f/9.0f, 0.0f, 0.0f, -4.0f/9.0f, 2.0f/9.0f, 0.0f, -4.0f/9.0f, | ||
213 | 4.0f/9.0f, 0.0f, -4.0f/9.0f, 6.0f/9.0f, 0.0f, -4.0f/9.0f, 8.0f/9.0f, 0.0f, -4.0f/9.0f, | ||
214 | -8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, | ||
215 | -2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 0.0f, 2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, | ||
216 | 4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, | ||
217 | -8.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, | ||
218 | -2.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 0.0f, 4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, | ||
219 | 4.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, | ||
220 | -8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, | ||
221 | -2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 0.0f, 6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, | ||
222 | 4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, | ||
223 | -8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, | ||
224 | -2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 0.0f, 8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, | ||
225 | 4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, | ||
226 | -8.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, | ||
227 | -2.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, 0.0f, -8.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, | ||
228 | 4.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, -2.0f/9.0f, | ||
229 | -8.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, | ||
230 | -2.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 0.0f, -6.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, | ||
231 | 4.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, | ||
232 | -8.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, | ||
233 | -2.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 0.0f, -4.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, | ||
234 | 4.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, | ||
235 | -8.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, | ||
236 | -2.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, 0.0f, -2.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, | ||
237 | 4.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -2.0f/9.0f, | ||
238 | -8.0f/9.0f, 0.0f, -2.0f/9.0f, -6.0f/9.0f, 0.0f, -2.0f/9.0f, -4.0f/9.0f, 0.0f, -2.0f/9.0f, | ||
239 | -2.0f/9.0f, 0.0f, -2.0f/9.0f, 0.0f, 0.0f, -2.0f/9.0f, 2.0f/9.0f, 0.0f, -2.0f/9.0f, | ||
240 | 4.0f/9.0f, 0.0f, -2.0f/9.0f, 6.0f/9.0f, 0.0f, -2.0f/9.0f, 8.0f/9.0f, 0.0f, -2.0f/9.0f, | ||
241 | -8.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, | ||
242 | -2.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 0.0f, 2.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, | ||
243 | 4.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, | ||
244 | -8.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, | ||
245 | -2.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, 0.0f, 4.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, | ||
246 | 4.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -2.0f/9.0f, | ||
247 | -8.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, | ||
248 | -2.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 0.0f, 6.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, | ||
249 | 4.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, | ||
250 | -8.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, | ||
251 | -2.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 0.0f, 8.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, | ||
252 | 4.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, | ||
253 | -8.0f/9.0f, -8.0f/9.0f, 0.0f, -6.0f/9.0f, -8.0f/9.0f, 0.0f, -4.0f/9.0f, -8.0f/9.0f, 0.0f, | ||
254 | -2.0f/9.0f, -8.0f/9.0f, 0.0f, 0.0f, -8.0f/9.0f, 0.0f, 2.0f/9.0f, -8.0f/9.0f, 0.0f, | ||
255 | 4.0f/9.0f, -8.0f/9.0f, 0.0f, 6.0f/9.0f, -8.0f/9.0f, 0.0f, 8.0f/9.0f, -8.0f/9.0f, 0.0f, | ||
256 | -8.0f/9.0f, -6.0f/9.0f, 0.0f, -6.0f/9.0f, -6.0f/9.0f, 0.0f, -4.0f/9.0f, -6.0f/9.0f, 0.0f, | ||
257 | -2.0f/9.0f, -6.0f/9.0f, 0.0f, 0.0f, -6.0f/9.0f, 0.0f, 2.0f/9.0f, -6.0f/9.0f, 0.0f, | ||
258 | 4.0f/9.0f, -6.0f/9.0f, 0.0f, 6.0f/9.0f, -6.0f/9.0f, 0.0f, 8.0f/9.0f, -6.0f/9.0f, 0.0f, | ||
259 | -8.0f/9.0f, -4.0f/9.0f, 0.0f, -6.0f/9.0f, -4.0f/9.0f, 0.0f, -4.0f/9.0f, -4.0f/9.0f, 0.0f, | ||
260 | -2.0f/9.0f, -4.0f/9.0f, 0.0f, 0.0f, -4.0f/9.0f, 0.0f, 2.0f/9.0f, -4.0f/9.0f, 0.0f, | ||
261 | 4.0f/9.0f, -4.0f/9.0f, 0.0f, 6.0f/9.0f, -4.0f/9.0f, 0.0f, 8.0f/9.0f, -4.0f/9.0f, 0.0f, | ||
262 | -8.0f/9.0f, -2.0f/9.0f, 0.0f, -6.0f/9.0f, -2.0f/9.0f, 0.0f, -4.0f/9.0f, -2.0f/9.0f, 0.0f, | ||
263 | -2.0f/9.0f, -2.0f/9.0f, 0.0f, 0.0f, -2.0f/9.0f, 0.0f, 2.0f/9.0f, -2.0f/9.0f, 0.0f, | ||
264 | 4.0f/9.0f, -2.0f/9.0f, 0.0f, 6.0f/9.0f, -2.0f/9.0f, 0.0f, 8.0f/9.0f, -2.0f/9.0f, 0.0f, | ||
265 | -8.0f/9.0f, 0.0f, 0.0f, -6.0f/9.0f, 0.0f, 0.0f, -4.0f/9.0f, 0.0f, 0.0f, | ||
266 | -2.0f/9.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f/9.0f, 0.0f, 0.0f, | ||
267 | 4.0f/9.0f, 0.0f, 0.0f, 6.0f/9.0f, 0.0f, 0.0f, 8.0f/9.0f, 0.0f, 0.0f, | ||
268 | -8.0f/9.0f, 2.0f/9.0f, 0.0f, -6.0f/9.0f, 2.0f/9.0f, 0.0f, -4.0f/9.0f, 2.0f/9.0f, 0.0f, | ||
269 | -2.0f/9.0f, 2.0f/9.0f, 0.0f, 0.0f, 2.0f/9.0f, 0.0f, 2.0f/9.0f, 2.0f/9.0f, 0.0f, | ||
270 | 4.0f/9.0f, 2.0f/9.0f, 0.0f, 6.0f/9.0f, 2.0f/9.0f, 0.0f, 8.0f/9.0f, 2.0f/9.0f, 0.0f, | ||
271 | -8.0f/9.0f, 4.0f/9.0f, 0.0f, -6.0f/9.0f, 4.0f/9.0f, 0.0f, -4.0f/9.0f, 4.0f/9.0f, 0.0f, | ||
272 | -2.0f/9.0f, 4.0f/9.0f, 0.0f, 0.0f, 4.0f/9.0f, 0.0f, 2.0f/9.0f, 4.0f/9.0f, 0.0f, | ||
273 | 4.0f/9.0f, 4.0f/9.0f, 0.0f, 6.0f/9.0f, 4.0f/9.0f, 0.0f, 8.0f/9.0f, 4.0f/9.0f, 0.0f, | ||
274 | -8.0f/9.0f, 6.0f/9.0f, 0.0f, -6.0f/9.0f, 6.0f/9.0f, 0.0f, -4.0f/9.0f, 6.0f/9.0f, 0.0f, | ||
275 | -2.0f/9.0f, 6.0f/9.0f, 0.0f, 0.0f, 6.0f/9.0f, 0.0f, 2.0f/9.0f, 6.0f/9.0f, 0.0f, | ||
276 | 4.0f/9.0f, 6.0f/9.0f, 0.0f, 6.0f/9.0f, 6.0f/9.0f, 0.0f, 8.0f/9.0f, 6.0f/9.0f, 0.0f, | ||
277 | -8.0f/9.0f, 8.0f/9.0f, 0.0f, -6.0f/9.0f, 8.0f/9.0f, 0.0f, -4.0f/9.0f, 8.0f/9.0f, 0.0f, | ||
278 | -2.0f/9.0f, 8.0f/9.0f, 0.0f, 0.0f, 8.0f/9.0f, 0.0f, 2.0f/9.0f, 8.0f/9.0f, 0.0f, | ||
279 | 4.0f/9.0f, 8.0f/9.0f, 0.0f, 6.0f/9.0f, 8.0f/9.0f, 0.0f, 8.0f/9.0f, 8.0f/9.0f, 0.0f, | ||
280 | -8.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, | ||
281 | -2.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 0.0f, -8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, | ||
282 | 4.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 2.0f/9.0f, | ||
283 | -8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, | ||
284 | -2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 0.0f, -6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, | ||
285 | 4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, | ||
286 | -8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, | ||
287 | -2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 0.0f, -4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, | ||
288 | 4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, | ||
289 | -8.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, | ||
290 | -2.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 0.0f, -2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, | ||
291 | 4.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 2.0f/9.0f, | ||
292 | -8.0f/9.0f, 0.0f, 2.0f/9.0f, -6.0f/9.0f, 0.0f, 2.0f/9.0f, -4.0f/9.0f, 0.0f, 2.0f/9.0f, | ||
293 | -2.0f/9.0f, 0.0f, 2.0f/9.0f, 0.0f, 0.0f, 2.0f/9.0f, 2.0f/9.0f, 0.0f, 2.0f/9.0f, | ||
294 | 4.0f/9.0f, 0.0f, 2.0f/9.0f, 6.0f/9.0f, 0.0f, 2.0f/9.0f, 8.0f/9.0f, 0.0f, 2.0f/9.0f, | ||
295 | -8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, | ||
296 | -2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 0.0f, 2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, | ||
297 | 4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, | ||
298 | -8.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, | ||
299 | -2.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 0.0f, 4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, | ||
300 | 4.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, | ||
301 | -8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, | ||
302 | -2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 0.0f, 6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, | ||
303 | 4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, | ||
304 | -8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, | ||
305 | -2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 0.0f, 8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, | ||
306 | 4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, | ||
307 | -8.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, | ||
308 | -2.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, 0.0f, -8.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, | ||
309 | 4.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 4.0f/9.0f, | ||
310 | -8.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, | ||
311 | -2.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 0.0f, -6.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, | ||
312 | 4.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, | ||
313 | -8.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, | ||
314 | -2.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 0.0f, -4.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, | ||
315 | 4.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, | ||
316 | -8.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, | ||
317 | -2.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, 0.0f, -2.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, | ||
318 | 4.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 4.0f/9.0f, | ||
319 | -8.0f/9.0f, 0.0f, 4.0f/9.0f, -6.0f/9.0f, 0.0f, 4.0f/9.0f, -4.0f/9.0f, 0.0f, 4.0f/9.0f, | ||
320 | -2.0f/9.0f, 0.0f, 4.0f/9.0f, 0.0f, 0.0f, 4.0f/9.0f, 2.0f/9.0f, 0.0f, 4.0f/9.0f, | ||
321 | 4.0f/9.0f, 0.0f, 4.0f/9.0f, 6.0f/9.0f, 0.0f, 4.0f/9.0f, 8.0f/9.0f, 0.0f, 4.0f/9.0f, | ||
322 | -8.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, | ||
323 | -2.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 0.0f, 2.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, | ||
324 | 4.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, | ||
325 | -8.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, | ||
326 | -2.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, 0.0f, 4.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, | ||
327 | 4.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 4.0f/9.0f, | ||
328 | -8.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, | ||
329 | -2.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 0.0f, 6.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, | ||
330 | 4.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, | ||
331 | -8.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, | ||
332 | -2.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 0.0f, 8.0f/9.0f, 4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, | ||
333 | 4.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, | ||
334 | -8.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, | ||
335 | -2.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 0.0f, -8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, | ||
336 | 4.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 6.0f/9.0f, | ||
337 | -8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, | ||
338 | -2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 0.0f, -6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, | ||
339 | 4.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, | ||
340 | -8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, | ||
341 | -2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 0.0f, -4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, | ||
342 | 4.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, | ||
343 | -8.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, | ||
344 | -2.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 0.0f, -2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, | ||
345 | 4.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 6.0f/9.0f, | ||
346 | -8.0f/9.0f, 0.0f, 6.0f/9.0f, -6.0f/9.0f, 0.0f, 6.0f/9.0f, -4.0f/9.0f, 0.0f, 6.0f/9.0f, | ||
347 | -2.0f/9.0f, 0.0f, 6.0f/9.0f, 0.0f, 0.0f, 6.0f/9.0f, 2.0f/9.0f, 0.0f, 6.0f/9.0f, | ||
348 | 4.0f/9.0f, 0.0f, 6.0f/9.0f, 6.0f/9.0f, 0.0f, 6.0f/9.0f, 8.0f/9.0f, 0.0f, 6.0f/9.0f, | ||
349 | -8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, | ||
350 | -2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 0.0f, 2.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, | ||
351 | 4.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, | ||
352 | -8.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, | ||
353 | -2.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 0.0f, 4.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, | ||
354 | 4.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 6.0f/9.0f, | ||
355 | -8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, | ||
356 | -2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 0.0f, 6.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, | ||
357 | 4.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, | ||
358 | -8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, | ||
359 | -2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 0.0f, 8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, | ||
360 | 4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, | ||
361 | -8.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, | ||
362 | -2.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 0.0f, -8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, | ||
363 | 4.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -8.0f/9.0f, 8.0f/9.0f, | ||
364 | -8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, | ||
365 | -2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 0.0f, -6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, | ||
366 | 4.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, | ||
367 | -8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, | ||
368 | -2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 0.0f, -4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, | ||
369 | 4.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, | ||
370 | -8.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, | ||
371 | -2.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 0.0f, -2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, | ||
372 | 4.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -2.0f/9.0f, 8.0f/9.0f, | ||
373 | -8.0f/9.0f, 0.0f, 8.0f/9.0f, -6.0f/9.0f, 0.0f, 8.0f/9.0f, -4.0f/9.0f, 0.0f, 8.0f/9.0f, | ||
374 | -2.0f/9.0f, 0.0f, 8.0f/9.0f, 0.0f, 0.0f, 8.0f/9.0f, 2.0f/9.0f, 0.0f, 8.0f/9.0f, | ||
375 | 4.0f/9.0f, 0.0f, 8.0f/9.0f, 6.0f/9.0f, 0.0f, 8.0f/9.0f, 8.0f/9.0f, 0.0f, 8.0f/9.0f, | ||
376 | -8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, | ||
377 | -2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 0.0f, 2.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, | ||
378 | 4.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, | ||
379 | -8.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, | ||
380 | -2.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 0.0f, 4.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, | ||
381 | 4.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 4.0f/9.0f, 8.0f/9.0f, | ||
382 | -8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, | ||
383 | -2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 0.0f, 6.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, | ||
384 | 4.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, | ||
385 | -8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, -4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, | ||
386 | -2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 0.0f, 8.0f/9.0f, 8.0f/9.0f, 2.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, | ||
387 | 4.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 6.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f, 8.0f/9.0f | ||
388 | }; | ||
389 | |||
390 | // data taken from ISO/IEC DIS 11172, Annexes 3-B.2[abcd] and 3-B.4: | ||
391 | |||
392 | // subbands 0-2 in tables 3-B.2a and 2b: (index is allocation) | ||
393 | public static final int table_ab1_codelength[] = | ||
394 | // bits per codeword | ||
395 | { 0, 5, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; | ||
396 | |||
397 | public static final float table_ab1_groupingtables[][] = | ||
398 | // pointer to sample grouping table, or NULL-pointer if ungrouped | ||
399 | { null, grouping_5bits, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; | ||
400 | |||
401 | public static final float table_ab1_factor[] = | ||
402 | // factor for requantization: (real)sample * factor - 1.0 gives requantized sample | ||
403 | { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/8.0f, 1.0f/16.0f, 1.0f/32.0f, 1.0f/64.0f, | ||
404 | 1.0f/128.0f, 1.0f/256.0f, 1.0f/512.0f, 1.0f/1024.0f, 1.0f/2048.0f, | ||
405 | 1.0f/4096.0f, 1.0f/8192.0f, 1.0f/16384.0f, 1.0f/32768.0f }; | ||
406 | |||
407 | public static final float table_ab1_c[] = | ||
408 | // factor c for requantization from table 3-B.4 | ||
409 | { 0.0f, 1.33333333333f, 1.14285714286f, 1.06666666666f, 1.03225806452f, | ||
410 | 1.01587301587f, 1.00787401575f, 1.00392156863f, 1.00195694716f, 1.00097751711f, | ||
411 | 1.00048851979f, 1.00024420024f, 1.00012208522f, 1.00006103888f, 1.00003051851f, | ||
412 | 1.00001525902f }; | ||
413 | |||
414 | public static final float table_ab1_d[] = | ||
415 | // addend d for requantization from table 3-B.4 | ||
416 | { 0.0f, 0.50000000000f, 0.25000000000f, 0.12500000000f, 0.06250000000f, | ||
417 | 0.03125000000f, 0.01562500000f, 0.00781250000f, 0.00390625000f, 0.00195312500f, | ||
418 | 0.00097656250f, 0.00048828125f, 0.00024414063f, 0.00012207031f, 0.00006103516f, | ||
419 | 0.00003051758f }; | ||
420 | |||
421 | // subbands 3-... tables 3-B.2a and 2b: | ||
422 | public static final float[] table_ab234_groupingtables[] = | ||
423 | { null, grouping_5bits, grouping_7bits, null, grouping_10bits, null, null, null, null, null, null, null, null, null, null, null }; | ||
424 | |||
425 | // subbands 3-10 in tables 3-B.2a and 2b: | ||
426 | public static final int table_ab2_codelength[] = | ||
427 | { 0, 5, 7, 3, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 }; | ||
428 | public static final float table_ab2_factor[] = | ||
429 | { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/4.0f, 1.0f/8.0f, 1.0f/8.0f, 1.0f/16.0f, | ||
430 | 1.0f/32.0f, 1.0f/64.0f, 1.0f/128.0f, 1.0f/256.0f, 1.0f/512.0f, | ||
431 | 1.0f/1024.0f, 1.0f/2048.0f, 1.0f/4096.0f, 1.0f/32768.0f }; | ||
432 | public static final float table_ab2_c[] = | ||
433 | { 0.0f, 1.33333333333f, 1.60000000000f, 1.14285714286f, 1.77777777777f, | ||
434 | 1.06666666666f, 1.03225806452f, 1.01587301587f, 1.00787401575f, 1.00392156863f, | ||
435 | 1.00195694716f, 1.00097751711f, 1.00048851979f, 1.00024420024f, 1.00012208522f, | ||
436 | 1.00001525902f }; | ||
437 | public static final float table_ab2_d[] = | ||
438 | { 0.0f, 0.50000000000f, 0.50000000000f, 0.25000000000f, 0.50000000000f, | ||
439 | 0.12500000000f, 0.06250000000f, 0.03125000000f, 0.01562500000f, 0.00781250000f, | ||
440 | 0.00390625000f, 0.00195312500f, 0.00097656250f, 0.00048828125f, 0.00024414063f, | ||
441 | 0.00003051758f }; | ||
442 | |||
443 | // subbands 11-22 in tables 3-B.2a and 2b: | ||
444 | public static final int table_ab3_codelength[] = { 0, 5, 7, 3, 10, 4, 5, 16 }; | ||
445 | public static final float table_ab3_factor[] = | ||
446 | { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/4.0f, 1.0f/8.0f, 1.0f/8.0f, 1.0f/16.0f, 1.0f/32768.0f }; | ||
447 | public static final float table_ab3_c[] = | ||
448 | { 0.0f, 1.33333333333f, 1.60000000000f, 1.14285714286f, 1.77777777777f, | ||
449 | 1.06666666666f, 1.03225806452f, 1.00001525902f }; | ||
450 | public static final float table_ab3_d[] = | ||
451 | { 0.0f, 0.50000000000f, 0.50000000000f, 0.25000000000f, 0.50000000000f, | ||
452 | 0.12500000000f, 0.06250000000f, 0.00003051758f }; | ||
453 | |||
454 | // subbands 23-... in tables 3-B.2a and 2b: | ||
455 | public static final int table_ab4_codelength[] = { 0, 5, 7, 16 }; | ||
456 | public static final float table_ab4_factor[] = { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/32768.0f }; | ||
457 | public static final float table_ab4_c[] = { 0.0f, 1.33333333333f, 1.60000000000f, 1.00001525902f }; | ||
458 | public static final float table_ab4_d[] = { 0.0f, 0.50000000000f, 0.50000000000f, 0.00003051758f }; | ||
459 | |||
460 | // subbands in tables 3-B.2c and 2d: | ||
461 | public static final int table_cd_codelength[] = | ||
462 | { 0, 5, 7, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; | ||
463 | public static final float table_cd_groupingtables[][] = | ||
464 | { null, grouping_5bits, grouping_7bits, grouping_10bits, null, null, null, null, null, null, null, null, null, null, null, null }; | ||
465 | public static final float table_cd_factor[] = | ||
466 | { 0.0f, 1.0f/2.0f, 1.0f/4.0f, 1.0f/8.0f, 1.0f/8.0f, 1.0f/16.0f, 1.0f/32.0f, 1.0f/64.0f, | ||
467 | 1.0f/128.0f, 1.0f/256.0f, 1.0f/512.0f, 1.0f/1024.0f, 1.0f/2048.0f, 1.0f/4096.0f, | ||
468 | 1.0f/8192.0f, 1.0f/16384.0f }; | ||
469 | public static final float table_cd_c[] = | ||
470 | { 0.0f, 1.33333333333f, 1.60000000000f, 1.77777777777f, 1.06666666666f, | ||
471 | 1.03225806452f, 1.01587301587f, 1.00787401575f, 1.00392156863f, 1.00195694716f, | ||
472 | 1.00097751711f, 1.00048851979f, 1.00024420024f, 1.00012208522f, 1.00006103888f, | ||
473 | 1.00003051851f }; | ||
474 | public static final float table_cd_d[] = | ||
475 | { 0.0f, 0.50000000000f, 0.50000000000f, 0.50000000000f, 0.12500000000f, | ||
476 | 0.06250000000f, 0.03125000000f, 0.01562500000f, 0.00781250000f, 0.00390625000f, | ||
477 | 0.00195312500f, 0.00097656250f, 0.00048828125f, 0.00024414063f, 0.00012207031f, | ||
478 | 0.00006103516f }; | ||
479 | |||
480 | |||
481 | |||
482 | protected int subbandnumber; | ||
483 | protected int allocation; | ||
484 | protected int scfsi; | ||
485 | protected float scalefactor1, scalefactor2, scalefactor3; | ||
486 | protected int[] codelength = {0}; | ||
487 | protected float groupingtable[][] = new float[2][]; | ||
488 | //protected float[][] groupingtable = {{0},{0}} ; | ||
489 | protected float[] factor = {0.0f}; | ||
490 | protected int groupnumber; | ||
491 | protected int samplenumber; | ||
492 | protected float[] samples = new float[3]; | ||
493 | protected float[] c = {0}; | ||
494 | protected float[] d = {0}; | ||
495 | /** | ||
496 | * Constructor | ||
497 | */ | ||
498 | public SubbandLayer2(int subbandnumber) | ||
499 | { | ||
500 | this.subbandnumber = subbandnumber; | ||
501 | groupnumber = samplenumber = 0; | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
506 | * | ||
507 | */ | ||
508 | protected int get_allocationlength (Header header) | ||
509 | { | ||
510 | if (header.version() == Header.MPEG1) | ||
511 | { | ||
512 | int channel_bitrate = header.bitrate_index(); | ||
513 | |||
514 | // calculate bitrate per channel: | ||
515 | if (header.mode() != Header.SINGLE_CHANNEL) | ||
516 | if (channel_bitrate == 4) | ||
517 | channel_bitrate = 1; | ||
518 | else | ||
519 | channel_bitrate -= 4; | ||
520 | |||
521 | if (channel_bitrate == 1 || channel_bitrate == 2) | ||
522 | // table 3-B.2c or 3-B.2d | ||
523 | if (subbandnumber <= 1) | ||
524 | return 4; | ||
525 | else | ||
526 | return 3; | ||
527 | else | ||
528 | // tables 3-B.2a or 3-B.2b | ||
529 | if (subbandnumber <= 10) | ||
530 | return 4; | ||
531 | else if (subbandnumber <= 22) | ||
532 | return 3; | ||
533 | else | ||
534 | return 2; | ||
535 | } | ||
536 | else | ||
537 | { // MPEG-2 LSF -- Jeff | ||
538 | |||
539 | // table B.1 of ISO/IEC 13818-3 | ||
540 | if (subbandnumber <= 3) | ||
541 | return 4; | ||
542 | else if (subbandnumber <= 10) | ||
543 | return 3; | ||
544 | else | ||
545 | return 2; | ||
546 | } | ||
547 | } | ||
548 | |||
549 | /** | ||
550 | * | ||
551 | */ | ||
552 | protected void prepare_sample_reading(Header header, int allocation, | ||
553 | //float[][] groupingtable, | ||
554 | int channel, | ||
555 | float[] factor, int[] codelength, | ||
556 | float[] c, float[] d) | ||
557 | { | ||
558 | int channel_bitrate = header.bitrate_index(); | ||
559 | // calculate bitrate per channel: | ||
560 | if (header.mode() != Header.SINGLE_CHANNEL) | ||
561 | if (channel_bitrate == 4) | ||
562 | channel_bitrate = 1; | ||
563 | else | ||
564 | channel_bitrate -= 4; | ||
565 | |||
566 | if (channel_bitrate == 1 || channel_bitrate == 2) | ||
567 | { | ||
568 | // table 3-B.2c or 3-B.2d | ||
569 | groupingtable[channel] = table_cd_groupingtables[allocation]; | ||
570 | factor[0] = table_cd_factor[allocation]; | ||
571 | codelength[0] = table_cd_codelength[allocation]; | ||
572 | c[0] = table_cd_c[allocation]; | ||
573 | d[0] = table_cd_d[allocation]; | ||
574 | } | ||
575 | else | ||
576 | { | ||
577 | // tables 3-B.2a or 3-B.2b | ||
578 | if (subbandnumber <= 2) | ||
579 | { | ||
580 | groupingtable[channel] = table_ab1_groupingtables[allocation]; | ||
581 | factor[0] = table_ab1_factor[allocation]; | ||
582 | codelength[0] = table_ab1_codelength[allocation]; | ||
583 | c[0] = table_ab1_c[allocation]; | ||
584 | d[0] = table_ab1_d[allocation]; | ||
585 | } | ||
586 | else | ||
587 | { | ||
588 | groupingtable[channel] = table_ab234_groupingtables[allocation]; | ||
589 | if (subbandnumber <= 10) | ||
590 | { | ||
591 | factor[0] = table_ab2_factor[allocation]; | ||
592 | codelength[0] = table_ab2_codelength[allocation]; | ||
593 | c[0] = table_ab2_c[allocation]; | ||
594 | d[0] = table_ab2_d[allocation]; | ||
595 | } | ||
596 | else if (subbandnumber <= 22) | ||
597 | { | ||
598 | factor[0] = table_ab3_factor[allocation]; | ||
599 | codelength[0] = table_ab3_codelength[allocation]; | ||
600 | c[0] = table_ab3_c[allocation]; | ||
601 | d[0] = table_ab3_d[allocation]; | ||
602 | } | ||
603 | else | ||
604 | { | ||
605 | factor[0] = table_ab4_factor[allocation]; | ||
606 | codelength[0] = table_ab4_codelength[allocation]; | ||
607 | c[0] = table_ab4_c[allocation]; | ||
608 | d[0] = table_ab4_d[allocation]; | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | |||
615 | /** | ||
616 | * | ||
617 | */ | ||
618 | public void read_allocation(Bitstream stream, Header header, Crc16 crc) | ||
619 | { | ||
620 | int length = get_allocationlength(header); | ||
621 | allocation = stream.get_bits(length); | ||
622 | if (crc != null) | ||
623 | crc.add_bits(allocation, length); | ||
624 | } | ||
625 | |||
626 | /** | ||
627 | * | ||
628 | */ | ||
629 | public void read_scalefactor_selection (Bitstream stream, Crc16 crc) | ||
630 | { | ||
631 | if (allocation != 0) | ||
632 | { | ||
633 | scfsi = stream.get_bits(2); | ||
634 | if (crc != null) crc.add_bits(scfsi, 2); | ||
635 | } | ||
636 | } | ||
637 | |||
638 | /** | ||
639 | * | ||
640 | */ | ||
641 | public void read_scalefactor (Bitstream stream, Header header) | ||
642 | { | ||
643 | if (allocation != 0) | ||
644 | { | ||
645 | switch (scfsi) | ||
646 | { | ||
647 | case 0: | ||
648 | scalefactor1 = scalefactors[stream.get_bits(6)]; | ||
649 | scalefactor2 = scalefactors[stream.get_bits(6)]; | ||
650 | scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
651 | break; | ||
652 | case 1: | ||
653 | scalefactor1 = scalefactor2 = scalefactors[stream.get_bits(6)]; | ||
654 | scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
655 | break; | ||
656 | case 2: | ||
657 | scalefactor1 = scalefactor2 = scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
658 | break; | ||
659 | case 3: | ||
660 | scalefactor1 = scalefactors[stream.get_bits(6)]; | ||
661 | scalefactor2 = scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
662 | break; | ||
663 | } | ||
664 | prepare_sample_reading(header, allocation, 0, | ||
665 | factor, codelength, c, d); | ||
666 | } | ||
667 | } | ||
668 | |||
669 | /** | ||
670 | * | ||
671 | */ | ||
672 | public boolean read_sampledata (Bitstream stream) | ||
673 | { | ||
674 | if (allocation != 0) | ||
675 | if (groupingtable[0] != null) | ||
676 | { | ||
677 | int samplecode = stream.get_bits(codelength[0]); | ||
678 | // create requantized samples: | ||
679 | samplecode += samplecode << 1; | ||
680 | float[] target = samples; | ||
681 | float[] source = groupingtable[0]; | ||
682 | /* | ||
683 | int tmp = 0; | ||
684 | int temp = 0; | ||
685 | target[tmp++] = source[samplecode + temp]; | ||
686 | temp++; | ||
687 | target[tmp++] = source[samplecode + temp]; | ||
688 | temp++; | ||
689 | target[tmp] = source[samplecode + temp]; | ||
690 | */ | ||
691 | //Bugfix: | ||
692 | int tmp = 0; | ||
693 | int temp = samplecode; | ||
694 | |||
695 | if(temp > source.length - 3) temp = source.length - 3; | ||
696 | |||
697 | target[tmp] = source[temp]; | ||
698 | temp++;tmp++; | ||
699 | target[tmp] = source[temp]; | ||
700 | temp++;tmp++; | ||
701 | target[tmp] = source[temp]; | ||
702 | |||
703 | // memcpy (samples, groupingtable + samplecode, 3 * sizeof (real)); | ||
704 | } | ||
705 | else | ||
706 | { | ||
707 | samples[0] = (float) ((stream.get_bits(codelength[0])) * factor[0] - 1.0); | ||
708 | samples[1] = (float) ((stream.get_bits(codelength[0])) * factor[0] - 1.0); | ||
709 | samples[2] = (float) ((stream.get_bits(codelength[0])) * factor[0] - 1.0); | ||
710 | } | ||
711 | |||
712 | samplenumber = 0; | ||
713 | if (++groupnumber == 12) | ||
714 | return true; | ||
715 | else | ||
716 | return false; | ||
717 | } | ||
718 | |||
719 | /** | ||
720 | * | ||
721 | */ | ||
722 | public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2) | ||
723 | { | ||
724 | if ((allocation != 0) && (channels != OutputChannels.RIGHT_CHANNEL)) | ||
725 | { | ||
726 | float sample = samples[samplenumber]; | ||
727 | |||
728 | if (groupingtable[0] == null) | ||
729 | sample = (sample + d[0]) * c[0]; | ||
730 | if (groupnumber <= 4) | ||
731 | sample *= scalefactor1; | ||
732 | else if (groupnumber <= 8) | ||
733 | sample *= scalefactor2; | ||
734 | else | ||
735 | sample *= scalefactor3; | ||
736 | filter1.input_sample(sample, subbandnumber); | ||
737 | } | ||
738 | |||
739 | if (++samplenumber == 3) | ||
740 | return true; | ||
741 | else | ||
742 | return false; | ||
743 | } | ||
744 | }; | ||
745 | |||
746 | /** | ||
747 | * Class for layer II subbands in joint stereo mode. | ||
748 | */ | ||
749 | static class SubbandLayer2IntensityStereo extends SubbandLayer2 | ||
750 | { | ||
751 | protected int channel2_scfsi; | ||
752 | protected float channel2_scalefactor1, channel2_scalefactor2, channel2_scalefactor3; | ||
753 | |||
754 | /** | ||
755 | * Constructor | ||
756 | */ | ||
757 | public SubbandLayer2IntensityStereo (int subbandnumber) | ||
758 | { | ||
759 | super(subbandnumber); | ||
760 | } | ||
761 | |||
762 | /** | ||
763 | * | ||
764 | */ | ||
765 | public void read_allocation(Bitstream stream, Header header, Crc16 crc) | ||
766 | { | ||
767 | super.read_allocation (stream, header, crc); | ||
768 | } | ||
769 | |||
770 | /** | ||
771 | * | ||
772 | */ | ||
773 | public void read_scalefactor_selection(Bitstream stream, Crc16 crc) | ||
774 | { | ||
775 | if (allocation != 0) | ||
776 | { | ||
777 | scfsi = stream.get_bits(2); | ||
778 | channel2_scfsi = stream.get_bits(2); | ||
779 | if (crc != null) | ||
780 | { | ||
781 | crc.add_bits(scfsi, 2); | ||
782 | crc.add_bits(channel2_scfsi, 2); | ||
783 | } | ||
784 | } | ||
785 | } | ||
786 | |||
787 | /** | ||
788 | * | ||
789 | */ | ||
790 | public void read_scalefactor(Bitstream stream, Header header) | ||
791 | { | ||
792 | if (allocation != 0) | ||
793 | { | ||
794 | super.read_scalefactor(stream, header); | ||
795 | switch (channel2_scfsi) | ||
796 | { | ||
797 | case 0: | ||
798 | channel2_scalefactor1 = scalefactors[stream.get_bits(6)]; | ||
799 | channel2_scalefactor2 = scalefactors[stream.get_bits(6)]; | ||
800 | channel2_scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
801 | break; | ||
802 | |||
803 | case 1: | ||
804 | channel2_scalefactor1 = channel2_scalefactor2 = scalefactors[stream.get_bits (6)]; | ||
805 | channel2_scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
806 | break; | ||
807 | |||
808 | case 2: | ||
809 | channel2_scalefactor1 = channel2_scalefactor2 = | ||
810 | channel2_scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
811 | break; | ||
812 | |||
813 | case 3: | ||
814 | channel2_scalefactor1 = scalefactors[stream.get_bits(6)]; | ||
815 | channel2_scalefactor2 = channel2_scalefactor3 = scalefactors[stream.get_bits (6)]; | ||
816 | break; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | } | ||
821 | |||
822 | /** | ||
823 | * | ||
824 | */ | ||
825 | public boolean read_sampledata(Bitstream stream) | ||
826 | { | ||
827 | return super.read_sampledata (stream); | ||
828 | } | ||
829 | |||
830 | /** | ||
831 | * | ||
832 | */ | ||
833 | public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2) | ||
834 | { | ||
835 | if (allocation != 0) | ||
836 | { | ||
837 | float sample = samples[samplenumber]; | ||
838 | |||
839 | if (groupingtable[0] == null) | ||
840 | sample = (sample + d[0]) * c[0]; | ||
841 | if (channels == OutputChannels.BOTH_CHANNELS) | ||
842 | { | ||
843 | float sample2 = sample; | ||
844 | if (groupnumber <= 4) | ||
845 | { | ||
846 | sample *= scalefactor1; | ||
847 | sample2 *= channel2_scalefactor1; | ||
848 | } | ||
849 | else if (groupnumber <= 8) | ||
850 | { | ||
851 | sample *= scalefactor2; | ||
852 | sample2 *= channel2_scalefactor2; | ||
853 | } | ||
854 | else | ||
855 | { | ||
856 | sample *= scalefactor3; | ||
857 | sample2 *= channel2_scalefactor3; | ||
858 | } | ||
859 | filter1.input_sample(sample, subbandnumber); | ||
860 | filter2.input_sample(sample2, subbandnumber); | ||
861 | } | ||
862 | else if (channels == OutputChannels.LEFT_CHANNEL) | ||
863 | { | ||
864 | if (groupnumber <= 4) | ||
865 | sample *= scalefactor1; | ||
866 | else if (groupnumber <= 8) | ||
867 | sample *= scalefactor2; | ||
868 | else | ||
869 | sample *= scalefactor3; | ||
870 | filter1.input_sample(sample, subbandnumber); | ||
871 | } | ||
872 | else | ||
873 | { | ||
874 | if (groupnumber <= 4) | ||
875 | sample *= channel2_scalefactor1; | ||
876 | else if (groupnumber <= 8) | ||
877 | sample *= channel2_scalefactor2; | ||
878 | else | ||
879 | sample *= channel2_scalefactor3; | ||
880 | filter1.input_sample(sample, subbandnumber); | ||
881 | } | ||
882 | } | ||
883 | |||
884 | if (++samplenumber == 3) | ||
885 | return true; | ||
886 | else | ||
887 | return false; | ||
888 | } | ||
889 | }; | ||
890 | |||
891 | /** | ||
892 | * Class for layer II subbands in stereo mode. | ||
893 | */ | ||
894 | static class SubbandLayer2Stereo extends SubbandLayer2 | ||
895 | { | ||
896 | protected int channel2_allocation; | ||
897 | protected int channel2_scfsi; | ||
898 | protected float channel2_scalefactor1, channel2_scalefactor2, channel2_scalefactor3; | ||
899 | //protected boolean channel2_grouping; ???? Never used! | ||
900 | protected int[] channel2_codelength = {0}; | ||
901 | //protected float[][] channel2_groupingtable = {{0},{0}}; | ||
902 | protected float[] channel2_factor = {0}; | ||
903 | protected float[] channel2_samples; | ||
904 | protected float[] channel2_c = {0}; | ||
905 | protected float[] channel2_d = {0}; | ||
906 | |||
907 | /** | ||
908 | * Constructor | ||
909 | */ | ||
910 | public SubbandLayer2Stereo(int subbandnumber) | ||
911 | { | ||
912 | super(subbandnumber); | ||
913 | channel2_samples = new float[3]; | ||
914 | } | ||
915 | |||
916 | /** | ||
917 | * | ||
918 | */ | ||
919 | public void read_allocation (Bitstream stream, Header header, Crc16 crc) | ||
920 | { | ||
921 | int length = get_allocationlength(header); | ||
922 | allocation = stream.get_bits(length); | ||
923 | channel2_allocation = stream.get_bits(length); | ||
924 | if (crc != null) | ||
925 | { | ||
926 | crc.add_bits(allocation, length); | ||
927 | crc.add_bits(channel2_allocation, length); | ||
928 | } | ||
929 | } | ||
930 | |||
931 | /** | ||
932 | * | ||
933 | */ | ||
934 | public void read_scalefactor_selection(Bitstream stream, Crc16 crc) | ||
935 | { | ||
936 | if (allocation != 0) | ||
937 | { | ||
938 | scfsi = stream.get_bits(2); | ||
939 | if (crc != null) | ||
940 | crc.add_bits(scfsi, 2); | ||
941 | } | ||
942 | if (channel2_allocation != 0) | ||
943 | { | ||
944 | channel2_scfsi = stream.get_bits(2); | ||
945 | if (crc != null) | ||
946 | crc.add_bits(channel2_scfsi, 2); | ||
947 | } | ||
948 | } | ||
949 | |||
950 | /** | ||
951 | * | ||
952 | */ | ||
953 | public void read_scalefactor(Bitstream stream, Header header) | ||
954 | { | ||
955 | super.read_scalefactor(stream, header); | ||
956 | if (channel2_allocation != 0) | ||
957 | { | ||
958 | switch (channel2_scfsi) | ||
959 | { | ||
960 | case 0: | ||
961 | channel2_scalefactor1 = scalefactors[stream.get_bits(6)]; | ||
962 | channel2_scalefactor2 = scalefactors[stream.get_bits(6)]; | ||
963 | channel2_scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
964 | break; | ||
965 | |||
966 | case 1: | ||
967 | channel2_scalefactor1 = channel2_scalefactor2 = | ||
968 | scalefactors[stream.get_bits(6)]; | ||
969 | channel2_scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
970 | break; | ||
971 | |||
972 | case 2: | ||
973 | channel2_scalefactor1 = channel2_scalefactor2 = | ||
974 | channel2_scalefactor3 = scalefactors[stream.get_bits(6)]; | ||
975 | break; | ||
976 | |||
977 | case 3: | ||
978 | channel2_scalefactor1 = scalefactors[stream.get_bits(6)]; | ||
979 | channel2_scalefactor2 = channel2_scalefactor3 = | ||
980 | scalefactors[stream.get_bits(6)]; | ||
981 | break; | ||
982 | } | ||
983 | prepare_sample_reading(header, channel2_allocation, 1, | ||
984 | channel2_factor, channel2_codelength, channel2_c, | ||
985 | channel2_d); | ||
986 | } | ||
987 | } | ||
988 | |||
989 | /** | ||
990 | * | ||
991 | */ | ||
992 | public boolean read_sampledata (Bitstream stream) | ||
993 | { | ||
994 | boolean returnvalue = super.read_sampledata(stream); | ||
995 | |||
996 | if (channel2_allocation != 0) | ||
997 | if (groupingtable[1] != null) | ||
998 | { | ||
999 | int samplecode = stream.get_bits(channel2_codelength[0]); | ||
1000 | // create requantized samples: | ||
1001 | samplecode += samplecode << 1; | ||
1002 | /* | ||
1003 | float[] target = channel2_samples; | ||
1004 | float[] source = channel2_groupingtable[0]; | ||
1005 | int tmp = 0; | ||
1006 | int temp = 0; | ||
1007 | target[tmp++] = source[samplecode + temp]; | ||
1008 | temp++; | ||
1009 | target[tmp++] = source[samplecode + temp]; | ||
1010 | temp++; | ||
1011 | target[tmp] = source[samplecode + temp]; | ||
1012 | // memcpy (channel2_samples, channel2_groupingtable + samplecode, 3 * sizeof (real)); | ||
1013 | */ | ||
1014 | float[] target = channel2_samples; | ||
1015 | float[] source = groupingtable[1]; | ||
1016 | int tmp = 0; | ||
1017 | int temp = samplecode; | ||
1018 | target[tmp] = source[temp]; | ||
1019 | temp++;tmp++; | ||
1020 | target[tmp] = source[temp]; | ||
1021 | temp++;tmp++; | ||
1022 | target[tmp] = source[temp]; | ||
1023 | |||
1024 | } | ||
1025 | else | ||
1026 | { | ||
1027 | channel2_samples[0] = (float) ((stream.get_bits(channel2_codelength[0])) * | ||
1028 | channel2_factor[0] - 1.0); | ||
1029 | channel2_samples[1] = (float) ((stream.get_bits(channel2_codelength[0])) * | ||
1030 | channel2_factor[0] - 1.0); | ||
1031 | channel2_samples[2] = (float) ((stream.get_bits(channel2_codelength[0])) * | ||
1032 | channel2_factor[0] - 1.0); | ||
1033 | } | ||
1034 | return returnvalue; | ||
1035 | } | ||
1036 | |||
1037 | /** | ||
1038 | * | ||
1039 | */ | ||
1040 | public boolean put_next_sample(int channels, SynthesisFilter filter1, SynthesisFilter filter2) | ||
1041 | { | ||
1042 | boolean returnvalue = super.put_next_sample(channels, filter1, filter2); | ||
1043 | if ((channel2_allocation != 0) && (channels != OutputChannels.LEFT_CHANNEL)) | ||
1044 | { | ||
1045 | float sample = channel2_samples[samplenumber - 1]; | ||
1046 | |||
1047 | if (groupingtable[1] == null) | ||
1048 | sample = (sample + channel2_d[0]) * channel2_c[0]; | ||
1049 | |||
1050 | if (groupnumber <= 4) | ||
1051 | sample *= channel2_scalefactor1; | ||
1052 | else if (groupnumber <= 8) | ||
1053 | sample *= channel2_scalefactor2; | ||
1054 | else | ||
1055 | sample *= channel2_scalefactor3; | ||
1056 | if (channels == OutputChannels.BOTH_CHANNELS) | ||
1057 | filter2.input_sample(sample, subbandnumber); | ||
1058 | else | ||
1059 | filter1.input_sample(sample, subbandnumber); | ||
1060 | } | ||
1061 | return returnvalue; | ||
1062 | } | ||
1063 | } | ||
1064 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/LayerIIIDecoder.java b/songdbj/javazoom/jl/decoder/LayerIIIDecoder.java new file mode 100644 index 0000000000..602badf0f2 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/LayerIIIDecoder.java | |||
@@ -0,0 +1,2439 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 18/06/01 Michael Scheerer, Fixed bugs which causes | ||
5 | * negative indexes in method huffmann_decode and in method | ||
6 | * dequanisize_sample. | ||
7 | * | ||
8 | * 16/07/01 Michael Scheerer, Catched a bug in method | ||
9 | * huffmann_decode, which causes an outOfIndexException. | ||
10 | * Cause : Indexnumber of 24 at SfBandIndex, | ||
11 | * which has only a length of 22. I have simply and dirty | ||
12 | * fixed the index to <= 22, because I'm not really be able | ||
13 | * to fix the bug. The Indexnumber is taken from the MP3 | ||
14 | * file and the origin Ma-Player with the same code works | ||
15 | * well. | ||
16 | * | ||
17 | * 02/19/99 Java Conversion by E.B, javalayer@javazoom.net | ||
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.jl.decoder; | ||
36 | |||
37 | /** | ||
38 | * Class Implementing Layer 3 Decoder. | ||
39 | * | ||
40 | * @since 0.0 | ||
41 | */ | ||
42 | final class LayerIIIDecoder implements FrameDecoder | ||
43 | { | ||
44 | final double d43 = (4.0/3.0); | ||
45 | |||
46 | public int[] scalefac_buffer; | ||
47 | |||
48 | // MDM: removed, as this wasn't being used. | ||
49 | //private float CheckSumOut1d = 0.0f; | ||
50 | private int CheckSumHuff = 0; | ||
51 | private int[] is_1d; | ||
52 | private float[][][] ro; | ||
53 | private float[][][] lr; | ||
54 | private float[] out_1d; | ||
55 | private float[][] prevblck; | ||
56 | private float[][] k; | ||
57 | private int[] nonzero; | ||
58 | private Bitstream stream; | ||
59 | private Header header; | ||
60 | private SynthesisFilter filter1, filter2; | ||
61 | private Obuffer buffer; | ||
62 | private int which_channels; | ||
63 | private BitReserve br; | ||
64 | private III_side_info_t si; | ||
65 | |||
66 | private temporaire2[] III_scalefac_t; | ||
67 | private temporaire2[] scalefac; | ||
68 | // private III_scalefac_t scalefac; | ||
69 | |||
70 | private int max_gr; | ||
71 | private int frame_start; | ||
72 | private int part2_start; | ||
73 | private int channels; | ||
74 | private int first_channel; | ||
75 | private int last_channel; | ||
76 | private int sfreq; | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Constructor. | ||
81 | */ | ||
82 | // REVIEW: these constructor arguments should be moved to the | ||
83 | // decodeFrame() method, where possible, so that one | ||
84 | public LayerIIIDecoder(Bitstream stream0, Header header0, | ||
85 | SynthesisFilter filtera, SynthesisFilter filterb, | ||
86 | Obuffer buffer0, int which_ch0) | ||
87 | { | ||
88 | huffcodetab.inithuff(); | ||
89 | is_1d = new int[SBLIMIT*SSLIMIT+4]; | ||
90 | ro = new float[2][SBLIMIT][SSLIMIT]; | ||
91 | lr = new float[2][SBLIMIT][SSLIMIT]; | ||
92 | out_1d = new float[SBLIMIT*SSLIMIT]; | ||
93 | prevblck = new float[2][SBLIMIT*SSLIMIT]; | ||
94 | k = new float[2][SBLIMIT*SSLIMIT]; | ||
95 | nonzero = new int[2]; | ||
96 | |||
97 | //III_scalefact_t | ||
98 | III_scalefac_t = new temporaire2[2]; | ||
99 | III_scalefac_t[0] = new temporaire2(); | ||
100 | III_scalefac_t[1] = new temporaire2(); | ||
101 | scalefac = III_scalefac_t; | ||
102 | // L3TABLE INIT | ||
103 | |||
104 | sfBandIndex = new SBI[9]; // SZD: MPEG2.5 +3 indices | ||
105 | int[] l0 = {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}; | ||
106 | int[] s0 = {0,4,8,12,18,24,32,42,56,74,100,132,174,192}; | ||
107 | int[] l1 = {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278,330,394,464,540,576}; | ||
108 | int[] s1 = {0,4,8,12,18,26,36,48,62,80,104,136,180,192}; | ||
109 | int[] l2 = {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}; | ||
110 | int[] s2 = {0,4,8,12,18,26,36,48,62,80,104,134,174,192}; | ||
111 | |||
112 | int[] l3 = {0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576}; | ||
113 | int[] s3 = {0,4,8,12,16,22,30,40,52,66,84,106,136,192}; | ||
114 | int[] l4 = {0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576}; | ||
115 | int[] s4 = {0,4,8,12,16,22,28,38,50,64,80,100,126,192}; | ||
116 | int[] l5 = {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576}; | ||
117 | int[] s5 = {0,4,8,12,16,22,30,42,58,78,104,138,180,192}; | ||
118 | // SZD: MPEG2.5 | ||
119 | int[] l6 = {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}; | ||
120 | int[] s6 = {0,4,8,12,18,26,36,48,62,80,104,134,174,192}; | ||
121 | int[] l7 = {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}; | ||
122 | int[] s7 = {0,4,8,12,18,26,36,48,62,80,104,134,174,192}; | ||
123 | int[] l8 = {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}; | ||
124 | int[] s8 = {0,8,16,24,36,52,72,96,124,160,162,164,166,192}; | ||
125 | |||
126 | sfBandIndex[0]= new SBI(l0,s0); | ||
127 | sfBandIndex[1]= new SBI(l1,s1); | ||
128 | sfBandIndex[2]= new SBI(l2,s2); | ||
129 | |||
130 | sfBandIndex[3]= new SBI(l3,s3); | ||
131 | sfBandIndex[4]= new SBI(l4,s4); | ||
132 | sfBandIndex[5]= new SBI(l5,s5); | ||
133 | //SZD: MPEG2.5 | ||
134 | sfBandIndex[6]= new SBI(l6,s6); | ||
135 | sfBandIndex[7]= new SBI(l7,s7); | ||
136 | sfBandIndex[8]= new SBI(l8,s8); | ||
137 | // END OF L3TABLE INIT | ||
138 | |||
139 | if(reorder_table == null) { // SZD: generate LUT | ||
140 | reorder_table = new int[9][]; | ||
141 | for(int i = 0; i < 9; i++) | ||
142 | reorder_table[i] = reorder(sfBandIndex[i].s); | ||
143 | } | ||
144 | |||
145 | // Sftable | ||
146 | int[] ll0 = {0, 6, 11, 16, 21}; | ||
147 | int[] ss0 = {0, 6, 12}; | ||
148 | sftable = new Sftable(ll0,ss0); | ||
149 | // END OF Sftable | ||
150 | |||
151 | // scalefac_buffer | ||
152 | scalefac_buffer = new int[54]; | ||
153 | // END OF scalefac_buffer | ||
154 | |||
155 | stream = stream0; | ||
156 | header = header0; | ||
157 | filter1 = filtera; | ||
158 | filter2 = filterb; | ||
159 | buffer = buffer0; | ||
160 | which_channels = which_ch0; | ||
161 | |||
162 | frame_start = 0; | ||
163 | channels = (header.mode() == Header.SINGLE_CHANNEL) ? 1 : 2; | ||
164 | max_gr = (header.version() == Header.MPEG1) ? 2 : 1; | ||
165 | |||
166 | sfreq = header.sample_frequency() + | ||
167 | ((header.version() == Header.MPEG1) ? 3 : | ||
168 | (header.version() == Header.MPEG25_LSF) ? 6 : 0); // SZD | ||
169 | |||
170 | if (channels == 2) | ||
171 | { | ||
172 | switch (which_channels) | ||
173 | { | ||
174 | case OutputChannels.LEFT_CHANNEL: | ||
175 | case OutputChannels.DOWNMIX_CHANNELS: | ||
176 | first_channel = last_channel = 0; | ||
177 | break; | ||
178 | |||
179 | case OutputChannels.RIGHT_CHANNEL: | ||
180 | first_channel = last_channel = 1; | ||
181 | break; | ||
182 | |||
183 | case OutputChannels.BOTH_CHANNELS: | ||
184 | default: | ||
185 | first_channel = 0; | ||
186 | last_channel = 1; | ||
187 | break; | ||
188 | } | ||
189 | } | ||
190 | else | ||
191 | { | ||
192 | first_channel = last_channel = 0; | ||
193 | } | ||
194 | |||
195 | for(int ch=0;ch<2;ch++) | ||
196 | for (int j=0; j<576; j++) | ||
197 | prevblck[ch][j] = 0.0f; | ||
198 | |||
199 | nonzero[0] = nonzero[1] = 576; | ||
200 | |||
201 | br = new BitReserve(); | ||
202 | si = new III_side_info_t(); | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * Notify decoder that a seek is being made. | ||
207 | */ | ||
208 | public void seek_notify() | ||
209 | { | ||
210 | frame_start = 0; | ||
211 | for(int ch=0;ch<2;ch++) | ||
212 | for (int j=0; j<576; j++) | ||
213 | prevblck[ch][j] = 0.0f; | ||
214 | br = new BitReserve(); | ||
215 | } | ||
216 | |||
217 | public void decodeFrame() | ||
218 | { | ||
219 | decode(); | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * Decode one frame, filling the buffer with the output samples. | ||
224 | */ | ||
225 | |||
226 | // subband samples are buffered and passed to the | ||
227 | // SynthesisFilter in one go. | ||
228 | private float[] samples1 = new float[32]; | ||
229 | private float[] samples2 = new float[32]; | ||
230 | |||
231 | public void decode() | ||
232 | { | ||
233 | int nSlots = header.slots(); | ||
234 | int flush_main; | ||
235 | int gr, ch, ss, sb, sb18; | ||
236 | int main_data_end; | ||
237 | int bytes_to_discard; | ||
238 | int i; | ||
239 | |||
240 | get_side_info(); | ||
241 | |||
242 | for (i=0; i<nSlots; i++) | ||
243 | br.hputbuf(stream.get_bits(8)); | ||
244 | |||
245 | main_data_end = br.hsstell() >>> 3; // of previous frame | ||
246 | |||
247 | if ((flush_main = (br.hsstell() & 7)) != 0) { | ||
248 | br.hgetbits(8 - flush_main); | ||
249 | main_data_end++; | ||
250 | } | ||
251 | |||
252 | bytes_to_discard = frame_start - main_data_end | ||
253 | - si.main_data_begin; | ||
254 | |||
255 | frame_start += nSlots; | ||
256 | |||
257 | if (bytes_to_discard < 0) | ||
258 | return; | ||
259 | |||
260 | if (main_data_end > 4096) { | ||
261 | frame_start -= 4096; | ||
262 | br.rewindNbytes(4096); | ||
263 | } | ||
264 | |||
265 | for (; bytes_to_discard > 0; bytes_to_discard--) | ||
266 | br.hgetbits(8); | ||
267 | |||
268 | for (gr=0;gr<max_gr;gr++) { | ||
269 | |||
270 | for (ch=0; ch<channels; ch++) { | ||
271 | part2_start = br.hsstell(); | ||
272 | |||
273 | if (header.version() == Header.MPEG1) | ||
274 | get_scale_factors(ch, gr); | ||
275 | else // MPEG-2 LSF, SZD: MPEG-2.5 LSF | ||
276 | get_LSF_scale_factors(ch, gr); | ||
277 | |||
278 | huffman_decode(ch, gr); | ||
279 | // System.out.println("CheckSum HuffMan = " + CheckSumHuff); | ||
280 | dequantize_sample(ro[ch], ch, gr); | ||
281 | } | ||
282 | |||
283 | stereo(gr); | ||
284 | |||
285 | if ((which_channels == OutputChannels.DOWNMIX_CHANNELS) && (channels > 1)) | ||
286 | do_downmix(); | ||
287 | |||
288 | for (ch=first_channel; ch<=last_channel; ch++) { | ||
289 | |||
290 | reorder(lr[ch], ch, gr); | ||
291 | antialias(ch, gr); | ||
292 | //for (int hb = 0;hb<576;hb++) CheckSumOut1d = CheckSumOut1d + out_1d[hb]; | ||
293 | //System.out.println("CheckSumOut1d = "+CheckSumOut1d); | ||
294 | |||
295 | hybrid(ch, gr); | ||
296 | |||
297 | //for (int hb = 0;hb<576;hb++) CheckSumOut1d = CheckSumOut1d + out_1d[hb]; | ||
298 | //System.out.println("CheckSumOut1d = "+CheckSumOut1d); | ||
299 | |||
300 | for (sb18=18;sb18<576;sb18+=36) // Frequency inversion | ||
301 | for (ss=1;ss<SSLIMIT;ss+=2) | ||
302 | out_1d[sb18 + ss] = -out_1d[sb18 + ss]; | ||
303 | |||
304 | if ((ch == 0) || (which_channels == OutputChannels.RIGHT_CHANNEL)) { | ||
305 | for (ss=0;ss<SSLIMIT;ss++) { // Polyphase synthesis | ||
306 | sb = 0; | ||
307 | for (sb18=0; sb18<576; sb18+=18) { | ||
308 | samples1[sb] = out_1d[sb18+ss]; | ||
309 | //filter1.input_sample(out_1d[sb18+ss], sb); | ||
310 | sb++; | ||
311 | } | ||
312 | filter1.input_samples(samples1); | ||
313 | filter1.calculate_pcm_samples(buffer); | ||
314 | } | ||
315 | } else { | ||
316 | for (ss=0;ss<SSLIMIT;ss++) { // Polyphase synthesis | ||
317 | sb = 0; | ||
318 | for (sb18=0; sb18<576; sb18+=18) { | ||
319 | samples2[sb] = out_1d[sb18+ss]; | ||
320 | //filter2.input_sample(out_1d[sb18+ss], sb); | ||
321 | sb++; | ||
322 | } | ||
323 | filter2.input_samples(samples2); | ||
324 | filter2.calculate_pcm_samples(buffer); | ||
325 | } | ||
326 | |||
327 | } | ||
328 | } // channels | ||
329 | } // granule | ||
330 | |||
331 | |||
332 | // System.out.println("Counter = ................................."+counter); | ||
333 | //if (counter < 609) | ||
334 | //{ | ||
335 | counter++; | ||
336 | buffer.write_buffer(1); | ||
337 | //} | ||
338 | //else if (counter == 609) | ||
339 | //{ | ||
340 | // buffer.close(); | ||
341 | // counter++; | ||
342 | //} | ||
343 | //else | ||
344 | //{ | ||
345 | //} | ||
346 | |||
347 | } | ||
348 | |||
349 | /** | ||
350 | * Reads the side info from the stream, assuming the entire. | ||
351 | * frame has been read already. | ||
352 | * Mono : 136 bits (= 17 bytes) | ||
353 | * Stereo : 256 bits (= 32 bytes) | ||
354 | */ | ||
355 | private boolean get_side_info() | ||
356 | { | ||
357 | int ch, gr; | ||
358 | if (header.version() == Header.MPEG1) | ||
359 | { | ||
360 | |||
361 | si.main_data_begin = stream.get_bits(9); | ||
362 | if (channels == 1) | ||
363 | si.private_bits = stream.get_bits(5); | ||
364 | else si.private_bits = stream.get_bits(3); | ||
365 | |||
366 | for (ch=0; ch<channels; ch++) { | ||
367 | si.ch[ch].scfsi[0] = stream.get_bits(1); | ||
368 | si.ch[ch].scfsi[1] = stream.get_bits(1); | ||
369 | si.ch[ch].scfsi[2] = stream.get_bits(1); | ||
370 | si.ch[ch].scfsi[3] = stream.get_bits(1); | ||
371 | } | ||
372 | |||
373 | for (gr=0; gr<2; gr++) { | ||
374 | for (ch=0; ch<channels; ch++) { | ||
375 | si.ch[ch].gr[gr].part2_3_length = stream.get_bits(12); | ||
376 | si.ch[ch].gr[gr].big_values = stream.get_bits(9); | ||
377 | si.ch[ch].gr[gr].global_gain = stream.get_bits(8); | ||
378 | si.ch[ch].gr[gr].scalefac_compress = stream.get_bits(4); | ||
379 | si.ch[ch].gr[gr].window_switching_flag = stream.get_bits(1); | ||
380 | if ((si.ch[ch].gr[gr].window_switching_flag) != 0) { | ||
381 | si.ch[ch].gr[gr].block_type = stream.get_bits(2); | ||
382 | si.ch[ch].gr[gr].mixed_block_flag = stream.get_bits(1); | ||
383 | |||
384 | si.ch[ch].gr[gr].table_select[0] = stream.get_bits(5); | ||
385 | si.ch[ch].gr[gr].table_select[1] = stream.get_bits(5); | ||
386 | |||
387 | si.ch[ch].gr[gr].subblock_gain[0] = stream.get_bits(3); | ||
388 | si.ch[ch].gr[gr].subblock_gain[1] = stream.get_bits(3); | ||
389 | si.ch[ch].gr[gr].subblock_gain[2] = stream.get_bits(3); | ||
390 | |||
391 | // Set region_count parameters since they are implicit in this case. | ||
392 | |||
393 | if (si.ch[ch].gr[gr].block_type == 0) { | ||
394 | // Side info bad: block_type == 0 in split block | ||
395 | return false; | ||
396 | } else if (si.ch[ch].gr[gr].block_type == 2 | ||
397 | && si.ch[ch].gr[gr].mixed_block_flag == 0) { | ||
398 | si.ch[ch].gr[gr].region0_count = 8; | ||
399 | } else { | ||
400 | si.ch[ch].gr[gr].region0_count = 7; | ||
401 | } | ||
402 | si.ch[ch].gr[gr].region1_count = 20 - | ||
403 | si.ch[ch].gr[gr].region0_count; | ||
404 | } else { | ||
405 | si.ch[ch].gr[gr].table_select[0] = stream.get_bits(5); | ||
406 | si.ch[ch].gr[gr].table_select[1] = stream.get_bits(5); | ||
407 | si.ch[ch].gr[gr].table_select[2] = stream.get_bits(5); | ||
408 | si.ch[ch].gr[gr].region0_count = stream.get_bits(4); | ||
409 | si.ch[ch].gr[gr].region1_count = stream.get_bits(3); | ||
410 | si.ch[ch].gr[gr].block_type = 0; | ||
411 | } | ||
412 | si.ch[ch].gr[gr].preflag = stream.get_bits(1); | ||
413 | si.ch[ch].gr[gr].scalefac_scale = stream.get_bits(1); | ||
414 | si.ch[ch].gr[gr].count1table_select = stream.get_bits(1); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | } else { // MPEG-2 LSF, SZD: MPEG-2.5 LSF | ||
419 | |||
420 | si.main_data_begin = stream.get_bits(8); | ||
421 | if (channels == 1) | ||
422 | si.private_bits = stream.get_bits(1); | ||
423 | else si.private_bits = stream.get_bits(2); | ||
424 | |||
425 | for (ch=0; ch<channels; ch++) { | ||
426 | |||
427 | si.ch[ch].gr[0].part2_3_length = stream.get_bits(12); | ||
428 | si.ch[ch].gr[0].big_values = stream.get_bits(9); | ||
429 | si.ch[ch].gr[0].global_gain = stream.get_bits(8); | ||
430 | si.ch[ch].gr[0].scalefac_compress = stream.get_bits(9); | ||
431 | si.ch[ch].gr[0].window_switching_flag = stream.get_bits(1); | ||
432 | |||
433 | if ((si.ch[ch].gr[0].window_switching_flag) != 0) { | ||
434 | |||
435 | si.ch[ch].gr[0].block_type = stream.get_bits(2); | ||
436 | si.ch[ch].gr[0].mixed_block_flag = stream.get_bits(1); | ||
437 | si.ch[ch].gr[0].table_select[0] = stream.get_bits(5); | ||
438 | si.ch[ch].gr[0].table_select[1] = stream.get_bits(5); | ||
439 | |||
440 | si.ch[ch].gr[0].subblock_gain[0] = stream.get_bits(3); | ||
441 | si.ch[ch].gr[0].subblock_gain[1] = stream.get_bits(3); | ||
442 | si.ch[ch].gr[0].subblock_gain[2] = stream.get_bits(3); | ||
443 | |||
444 | // Set region_count parameters since they are implicit in this case. | ||
445 | |||
446 | if (si.ch[ch].gr[0].block_type == 0) { | ||
447 | // Side info bad: block_type == 0 in split block | ||
448 | return false; | ||
449 | } else if (si.ch[ch].gr[0].block_type == 2 | ||
450 | && si.ch[ch].gr[0].mixed_block_flag == 0) { | ||
451 | si.ch[ch].gr[0].region0_count = 8; | ||
452 | } else { | ||
453 | si.ch[ch].gr[0].region0_count = 7; | ||
454 | si.ch[ch].gr[0].region1_count = 20 - | ||
455 | si.ch[ch].gr[0].region0_count; | ||
456 | } | ||
457 | |||
458 | } else { | ||
459 | si.ch[ch].gr[0].table_select[0] = stream.get_bits(5); | ||
460 | si.ch[ch].gr[0].table_select[1] = stream.get_bits(5); | ||
461 | si.ch[ch].gr[0].table_select[2] = stream.get_bits(5); | ||
462 | si.ch[ch].gr[0].region0_count = stream.get_bits(4); | ||
463 | si.ch[ch].gr[0].region1_count = stream.get_bits(3); | ||
464 | si.ch[ch].gr[0].block_type = 0; | ||
465 | } | ||
466 | |||
467 | si.ch[ch].gr[0].scalefac_scale = stream.get_bits(1); | ||
468 | si.ch[ch].gr[0].count1table_select = stream.get_bits(1); | ||
469 | } // for(ch=0; ch<channels; ch++) | ||
470 | } // if (header.version() == MPEG1) | ||
471 | return true; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * | ||
476 | */ | ||
477 | private void get_scale_factors(int ch, int gr) | ||
478 | { | ||
479 | int sfb, window; | ||
480 | gr_info_s gr_info = (si.ch[ch].gr[gr]); | ||
481 | int scale_comp = gr_info.scalefac_compress; | ||
482 | int length0 = slen[0][scale_comp]; | ||
483 | int length1 = slen[1][scale_comp]; | ||
484 | |||
485 | if ((gr_info.window_switching_flag != 0) && (gr_info.block_type == 2)) { | ||
486 | if ((gr_info.mixed_block_flag) != 0) { // MIXED | ||
487 | for (sfb = 0; sfb < 8; sfb++) | ||
488 | scalefac[ch].l[sfb] = br.hgetbits( | ||
489 | slen[0][gr_info.scalefac_compress]); | ||
490 | for (sfb = 3; sfb < 6; sfb++) | ||
491 | for (window=0; window<3; window++) | ||
492 | scalefac[ch].s[window][sfb] = br.hgetbits( | ||
493 | slen[0][gr_info.scalefac_compress]); | ||
494 | for (sfb = 6; sfb < 12; sfb++) | ||
495 | for (window=0; window<3; window++) | ||
496 | scalefac[ch].s[window][sfb] = br.hgetbits( | ||
497 | slen[1][gr_info.scalefac_compress]); | ||
498 | for (sfb=12,window=0; window<3; window++) | ||
499 | scalefac[ch].s[window][sfb] = 0; | ||
500 | |||
501 | } else { // SHORT | ||
502 | |||
503 | scalefac[ch].s[0][0] = br.hgetbits(length0); | ||
504 | scalefac[ch].s[1][0] = br.hgetbits(length0); | ||
505 | scalefac[ch].s[2][0] = br.hgetbits(length0); | ||
506 | scalefac[ch].s[0][1] = br.hgetbits(length0); | ||
507 | scalefac[ch].s[1][1] = br.hgetbits(length0); | ||
508 | scalefac[ch].s[2][1] = br.hgetbits(length0); | ||
509 | scalefac[ch].s[0][2] = br.hgetbits(length0); | ||
510 | scalefac[ch].s[1][2] = br.hgetbits(length0); | ||
511 | scalefac[ch].s[2][2] = br.hgetbits(length0); | ||
512 | scalefac[ch].s[0][3] = br.hgetbits(length0); | ||
513 | scalefac[ch].s[1][3] = br.hgetbits(length0); | ||
514 | scalefac[ch].s[2][3] = br.hgetbits(length0); | ||
515 | scalefac[ch].s[0][4] = br.hgetbits(length0); | ||
516 | scalefac[ch].s[1][4] = br.hgetbits(length0); | ||
517 | scalefac[ch].s[2][4] = br.hgetbits(length0); | ||
518 | scalefac[ch].s[0][5] = br.hgetbits(length0); | ||
519 | scalefac[ch].s[1][5] = br.hgetbits(length0); | ||
520 | scalefac[ch].s[2][5] = br.hgetbits(length0); | ||
521 | scalefac[ch].s[0][6] = br.hgetbits(length1); | ||
522 | scalefac[ch].s[1][6] = br.hgetbits(length1); | ||
523 | scalefac[ch].s[2][6] = br.hgetbits(length1); | ||
524 | scalefac[ch].s[0][7] = br.hgetbits(length1); | ||
525 | scalefac[ch].s[1][7] = br.hgetbits(length1); | ||
526 | scalefac[ch].s[2][7] = br.hgetbits(length1); | ||
527 | scalefac[ch].s[0][8] = br.hgetbits(length1); | ||
528 | scalefac[ch].s[1][8] = br.hgetbits(length1); | ||
529 | scalefac[ch].s[2][8] = br.hgetbits(length1); | ||
530 | scalefac[ch].s[0][9] = br.hgetbits(length1); | ||
531 | scalefac[ch].s[1][9] = br.hgetbits(length1); | ||
532 | scalefac[ch].s[2][9] = br.hgetbits(length1); | ||
533 | scalefac[ch].s[0][10] = br.hgetbits(length1); | ||
534 | scalefac[ch].s[1][10] = br.hgetbits(length1); | ||
535 | scalefac[ch].s[2][10] = br.hgetbits(length1); | ||
536 | scalefac[ch].s[0][11] = br.hgetbits(length1); | ||
537 | scalefac[ch].s[1][11] = br.hgetbits(length1); | ||
538 | scalefac[ch].s[2][11] = br.hgetbits(length1); | ||
539 | scalefac[ch].s[0][12] = 0; | ||
540 | scalefac[ch].s[1][12] = 0; | ||
541 | scalefac[ch].s[2][12] = 0; | ||
542 | } // SHORT | ||
543 | |||
544 | } else { // LONG types 0,1,3 | ||
545 | |||
546 | if ((si.ch[ch].scfsi[0] == 0) || (gr == 0)) { | ||
547 | scalefac[ch].l[0] = br.hgetbits(length0); | ||
548 | scalefac[ch].l[1] = br.hgetbits(length0); | ||
549 | scalefac[ch].l[2] = br.hgetbits(length0); | ||
550 | scalefac[ch].l[3] = br.hgetbits(length0); | ||
551 | scalefac[ch].l[4] = br.hgetbits(length0); | ||
552 | scalefac[ch].l[5] = br.hgetbits(length0); | ||
553 | } | ||
554 | if ((si.ch[ch].scfsi[1] == 0) || (gr == 0)) { | ||
555 | scalefac[ch].l[6] = br.hgetbits(length0); | ||
556 | scalefac[ch].l[7] = br.hgetbits(length0); | ||
557 | scalefac[ch].l[8] = br.hgetbits(length0); | ||
558 | scalefac[ch].l[9] = br.hgetbits(length0); | ||
559 | scalefac[ch].l[10] = br.hgetbits(length0); | ||
560 | } | ||
561 | if ((si.ch[ch].scfsi[2] == 0) || (gr == 0)) { | ||
562 | scalefac[ch].l[11] = br.hgetbits(length1); | ||
563 | scalefac[ch].l[12] = br.hgetbits(length1); | ||
564 | scalefac[ch].l[13] = br.hgetbits(length1); | ||
565 | scalefac[ch].l[14] = br.hgetbits(length1); | ||
566 | scalefac[ch].l[15] = br.hgetbits(length1); | ||
567 | } | ||
568 | if ((si.ch[ch].scfsi[3] == 0) || (gr == 0)) { | ||
569 | scalefac[ch].l[16] = br.hgetbits(length1); | ||
570 | scalefac[ch].l[17] = br.hgetbits(length1); | ||
571 | scalefac[ch].l[18] = br.hgetbits(length1); | ||
572 | scalefac[ch].l[19] = br.hgetbits(length1); | ||
573 | scalefac[ch].l[20] = br.hgetbits(length1); | ||
574 | } | ||
575 | |||
576 | scalefac[ch].l[21] = 0; | ||
577 | scalefac[ch].l[22] = 0; | ||
578 | } | ||
579 | } | ||
580 | |||
581 | /** | ||
582 | * | ||
583 | */ | ||
584 | // MDM: new_slen is fully initialized before use, no need | ||
585 | // to reallocate array. | ||
586 | private final int[] new_slen = new int[4]; | ||
587 | |||
588 | private void get_LSF_scale_data(int ch, int gr) | ||
589 | { | ||
590 | |||
591 | int scalefac_comp, int_scalefac_comp; | ||
592 | int mode_ext = header.mode_extension(); | ||
593 | int m; | ||
594 | int blocktypenumber; | ||
595 | int blocknumber = 0; | ||
596 | |||
597 | gr_info_s gr_info = (si.ch[ch].gr[gr]); | ||
598 | |||
599 | scalefac_comp = gr_info.scalefac_compress; | ||
600 | |||
601 | if (gr_info.block_type == 2) { | ||
602 | if (gr_info.mixed_block_flag == 0) | ||
603 | blocktypenumber = 1; | ||
604 | else if (gr_info.mixed_block_flag == 1) | ||
605 | blocktypenumber = 2; | ||
606 | else | ||
607 | blocktypenumber = 0; | ||
608 | } else { | ||
609 | blocktypenumber = 0; | ||
610 | } | ||
611 | |||
612 | if(!(((mode_ext == 1) || (mode_ext == 3)) && (ch == 1))) { | ||
613 | |||
614 | if(scalefac_comp < 400) { | ||
615 | |||
616 | new_slen[0] = (scalefac_comp >>> 4) / 5 ; | ||
617 | new_slen[1] = (scalefac_comp >>> 4) % 5 ; | ||
618 | new_slen[2] = (scalefac_comp & 0xF) >>> 2 ; | ||
619 | new_slen[3] = (scalefac_comp & 3); | ||
620 | si.ch[ch].gr[gr].preflag = 0; | ||
621 | blocknumber = 0; | ||
622 | |||
623 | } else if (scalefac_comp < 500) { | ||
624 | |||
625 | new_slen[0] = ((scalefac_comp - 400) >>> 2) / 5 ; | ||
626 | new_slen[1] = ((scalefac_comp - 400) >>> 2) % 5 ; | ||
627 | new_slen[2] = (scalefac_comp - 400 ) & 3 ; | ||
628 | new_slen[3] = 0; | ||
629 | si.ch[ch].gr[gr].preflag = 0; | ||
630 | blocknumber = 1; | ||
631 | |||
632 | } else if (scalefac_comp < 512) { | ||
633 | |||
634 | new_slen[0] = (scalefac_comp - 500 ) / 3 ; | ||
635 | new_slen[1] = (scalefac_comp - 500) % 3 ; | ||
636 | new_slen[2] = 0; | ||
637 | new_slen[3] = 0; | ||
638 | si.ch[ch].gr[gr].preflag = 1; | ||
639 | blocknumber = 2; | ||
640 | } | ||
641 | } | ||
642 | |||
643 | if((((mode_ext == 1) || (mode_ext == 3)) && (ch == 1))) | ||
644 | { | ||
645 | int_scalefac_comp = scalefac_comp >>> 1; | ||
646 | |||
647 | if (int_scalefac_comp < 180) | ||
648 | { | ||
649 | new_slen[0] = int_scalefac_comp / 36 ; | ||
650 | new_slen[1] = (int_scalefac_comp % 36 ) / 6 ; | ||
651 | new_slen[2] = (int_scalefac_comp % 36) % 6; | ||
652 | new_slen[3] = 0; | ||
653 | si.ch[ch].gr[gr].preflag = 0; | ||
654 | blocknumber = 3; | ||
655 | } else if (int_scalefac_comp < 244) { | ||
656 | new_slen[0] = ((int_scalefac_comp - 180 ) & 0x3F) >>> 4 ; | ||
657 | new_slen[1] = ((int_scalefac_comp - 180) & 0xF) >>> 2 ; | ||
658 | new_slen[2] = (int_scalefac_comp - 180 ) & 3 ; | ||
659 | new_slen[3] = 0; | ||
660 | si.ch[ch].gr[gr].preflag = 0; | ||
661 | blocknumber = 4; | ||
662 | } else if (int_scalefac_comp < 255) { | ||
663 | new_slen[0] = (int_scalefac_comp - 244 ) / 3 ; | ||
664 | new_slen[1] = (int_scalefac_comp - 244 ) % 3 ; | ||
665 | new_slen[2] = 0 ; | ||
666 | new_slen[3] = 0; | ||
667 | si.ch[ch].gr[gr].preflag = 0; | ||
668 | blocknumber = 5; | ||
669 | } | ||
670 | } | ||
671 | |||
672 | for (int x=0; x<45; x++) // why 45, not 54? | ||
673 | scalefac_buffer[x] = 0; | ||
674 | |||
675 | m = 0; | ||
676 | for (int i=0; i<4;i++) { | ||
677 | for (int j = 0; j < nr_of_sfb_block[blocknumber][blocktypenumber][i]; | ||
678 | j++) | ||
679 | { | ||
680 | scalefac_buffer[m] = (new_slen[i] == 0) ? 0 : | ||
681 | br.hgetbits(new_slen[i]); | ||
682 | m++; | ||
683 | |||
684 | } // for (unint32 j ... | ||
685 | } // for (uint32 i ... | ||
686 | } | ||
687 | |||
688 | /** | ||
689 | * | ||
690 | */ | ||
691 | private void get_LSF_scale_factors(int ch, int gr) | ||
692 | { | ||
693 | int m = 0; | ||
694 | int sfb, window; | ||
695 | gr_info_s gr_info = (si.ch[ch].gr[gr]); | ||
696 | |||
697 | get_LSF_scale_data(ch, gr); | ||
698 | |||
699 | if ((gr_info.window_switching_flag != 0) && (gr_info.block_type == 2)) { | ||
700 | if (gr_info.mixed_block_flag != 0) { // MIXED | ||
701 | for (sfb = 0; sfb < 8; sfb++) | ||
702 | { | ||
703 | scalefac[ch].l[sfb] = scalefac_buffer[m]; | ||
704 | m++; | ||
705 | } | ||
706 | for (sfb = 3; sfb < 12; sfb++) { | ||
707 | for (window=0; window<3; window++) | ||
708 | { | ||
709 | scalefac[ch].s[window][sfb] = scalefac_buffer[m]; | ||
710 | m++; | ||
711 | } | ||
712 | } | ||
713 | for (window=0; window<3; window++) | ||
714 | scalefac[ch].s[window][12] = 0; | ||
715 | |||
716 | } else { // SHORT | ||
717 | |||
718 | for (sfb = 0; sfb < 12; sfb++) { | ||
719 | for (window=0; window<3; window++) | ||
720 | { | ||
721 | scalefac[ch].s[window][sfb] = scalefac_buffer[m]; | ||
722 | m++; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | for (window=0; window<3; window++) | ||
727 | scalefac[ch].s[window][12] = 0; | ||
728 | } | ||
729 | } else { // LONG types 0,1,3 | ||
730 | |||
731 | for (sfb = 0; sfb < 21; sfb++) { | ||
732 | scalefac[ch].l[sfb] = scalefac_buffer[m]; | ||
733 | m++; | ||
734 | } | ||
735 | scalefac[ch].l[21] = 0; // Jeff | ||
736 | scalefac[ch].l[22] = 0; | ||
737 | } | ||
738 | } | ||
739 | |||
740 | /** | ||
741 | * | ||
742 | */ | ||
743 | int[] x = {0}; | ||
744 | int[] y = {0}; | ||
745 | int[] v = {0}; | ||
746 | int[] w = {0}; | ||
747 | private void huffman_decode(int ch, int gr) | ||
748 | { | ||
749 | x[0] = 0; | ||
750 | y[0] = 0; | ||
751 | v[0] = 0; | ||
752 | w[0] = 0; | ||
753 | |||
754 | int part2_3_end = part2_start + si.ch[ch].gr[gr].part2_3_length; | ||
755 | int num_bits; | ||
756 | int region1Start; | ||
757 | int region2Start; | ||
758 | int index; | ||
759 | |||
760 | int buf, buf1; | ||
761 | |||
762 | huffcodetab h; | ||
763 | |||
764 | // Find region boundary for short block case | ||
765 | |||
766 | if ( ((si.ch[ch].gr[gr].window_switching_flag) != 0) && | ||
767 | (si.ch[ch].gr[gr].block_type == 2) ) { | ||
768 | |||
769 | // Region2. | ||
770 | //MS: Extrahandling for 8KHZ | ||
771 | region1Start = (sfreq == 8) ? 72 : 36; // sfb[9/3]*3=36 or in case 8KHZ = 72 | ||
772 | region2Start = 576; // No Region2 for short block case | ||
773 | |||
774 | } else { // Find region boundary for long block case | ||
775 | |||
776 | buf = si.ch[ch].gr[gr].region0_count + 1; | ||
777 | buf1 = buf + si.ch[ch].gr[gr].region1_count + 1; | ||
778 | |||
779 | if(buf1 > sfBandIndex[sfreq].l.length - 1) buf1 = sfBandIndex[sfreq].l.length - 1; | ||
780 | |||
781 | region1Start = sfBandIndex[sfreq].l[buf]; | ||
782 | region2Start = sfBandIndex[sfreq].l[buf1]; /* MI */ | ||
783 | } | ||
784 | |||
785 | index = 0; | ||
786 | // Read bigvalues area | ||
787 | for (int i=0; i<(si.ch[ch].gr[gr].big_values<<1); i+=2) { | ||
788 | if (i<region1Start) h = huffcodetab.ht[si.ch[ch].gr[gr].table_select[0]]; | ||
789 | else if (i<region2Start) h = huffcodetab.ht[si.ch[ch].gr[gr].table_select[1]]; | ||
790 | else h = huffcodetab.ht[si.ch[ch].gr[gr].table_select[2]]; | ||
791 | |||
792 | huffcodetab.huffman_decoder(h, x, y, v, w, br); | ||
793 | //if (index >= is_1d.length) System.out.println("i0="+i+"/"+(si.ch[ch].gr[gr].big_values<<1)+" Index="+index+" is_1d="+is_1d.length); | ||
794 | |||
795 | is_1d[index++] = x[0]; | ||
796 | is_1d[index++] = y[0]; | ||
797 | |||
798 | CheckSumHuff = CheckSumHuff + x[0] + y[0]; | ||
799 | // System.out.println("x = "+x[0]+" y = "+y[0]); | ||
800 | } | ||
801 | |||
802 | // Read count1 area | ||
803 | h = huffcodetab.ht[si.ch[ch].gr[gr].count1table_select+32]; | ||
804 | num_bits = br.hsstell(); | ||
805 | |||
806 | while ((num_bits < part2_3_end) && (index < 576)) { | ||
807 | |||
808 | huffcodetab.huffman_decoder(h, x, y, v, w, br); | ||
809 | |||
810 | is_1d[index++] = v[0]; | ||
811 | is_1d[index++] = w[0]; | ||
812 | is_1d[index++] = x[0]; | ||
813 | is_1d[index++] = y[0]; | ||
814 | CheckSumHuff = CheckSumHuff + v[0] + w[0] + x[0] + y[0]; | ||
815 | // System.out.println("v = "+v[0]+" w = "+w[0]); | ||
816 | // System.out.println("x = "+x[0]+" y = "+y[0]); | ||
817 | num_bits = br.hsstell(); | ||
818 | } | ||
819 | |||
820 | if (num_bits > part2_3_end) { | ||
821 | br.rewindNbits(num_bits - part2_3_end); | ||
822 | index-=4; | ||
823 | } | ||
824 | |||
825 | num_bits = br.hsstell(); | ||
826 | |||
827 | // Dismiss stuffing bits | ||
828 | if (num_bits < part2_3_end) | ||
829 | br.hgetbits(part2_3_end - num_bits); | ||
830 | |||
831 | // Zero out rest | ||
832 | |||
833 | if (index < 576) | ||
834 | nonzero[ch] = index; | ||
835 | else | ||
836 | nonzero[ch] = 576; | ||
837 | |||
838 | if (index < 0) index = 0; | ||
839 | |||
840 | // may not be necessary | ||
841 | for (; index<576; index++) | ||
842 | is_1d[index] = 0; | ||
843 | } | ||
844 | |||
845 | /** | ||
846 | * | ||
847 | */ | ||
848 | private void i_stereo_k_values(int is_pos, int io_type, int i) | ||
849 | { | ||
850 | if (is_pos == 0) { | ||
851 | k[0][i] = 1.0f; | ||
852 | k[1][i] = 1.0f; | ||
853 | } else if ((is_pos & 1) != 0) { | ||
854 | k[0][i] = io[io_type][(is_pos + 1) >>> 1]; | ||
855 | k[1][i] = 1.0f; | ||
856 | } else { | ||
857 | k[0][i] = 1.0f; | ||
858 | k[1][i] = io[io_type][is_pos >>> 1]; | ||
859 | } | ||
860 | } | ||
861 | |||
862 | /** | ||
863 | * | ||
864 | */ | ||
865 | private void dequantize_sample(float xr[][], int ch, int gr) | ||
866 | { | ||
867 | gr_info_s gr_info = (si.ch[ch].gr[gr]); | ||
868 | int cb=0; | ||
869 | int next_cb_boundary; | ||
870 | int cb_begin = 0; | ||
871 | int cb_width = 0; | ||
872 | int index=0, t_index, j; | ||
873 | float g_gain; | ||
874 | float[][] xr_1d = xr; | ||
875 | |||
876 | // choose correct scalefactor band per block type, initalize boundary | ||
877 | |||
878 | if ((gr_info.window_switching_flag !=0 ) && (gr_info.block_type == 2) ) { | ||
879 | if (gr_info.mixed_block_flag != 0) | ||
880 | next_cb_boundary=sfBandIndex[sfreq].l[1]; // LONG blocks: 0,1,3 | ||
881 | else { | ||
882 | cb_width = sfBandIndex[sfreq].s[1]; | ||
883 | next_cb_boundary = (cb_width << 2) - cb_width; | ||
884 | cb_begin = 0; | ||
885 | } | ||
886 | } else { | ||
887 | next_cb_boundary=sfBandIndex[sfreq].l[1]; // LONG blocks: 0,1,3 | ||
888 | } | ||
889 | |||
890 | // Compute overall (global) scaling. | ||
891 | |||
892 | g_gain = (float) Math.pow(2.0 , (0.25 * (gr_info.global_gain - 210.0))); | ||
893 | |||
894 | for (j=0; j<nonzero[ch]; j++) | ||
895 | { | ||
896 | // Modif E.B 02/22/99 | ||
897 | int reste = j % SSLIMIT; | ||
898 | int quotien = (int) ((j-reste)/SSLIMIT); | ||
899 | if (is_1d[j] == 0) xr_1d[quotien][reste] = 0.0f; | ||
900 | else | ||
901 | { | ||
902 | int abv = is_1d[j]; | ||
903 | // Pow Array fix (11/17/04) | ||
904 | if (abv < t_43.length) | ||
905 | { | ||
906 | if (is_1d[j] > 0) xr_1d[quotien][reste] = g_gain * t_43[abv]; | ||
907 | else | ||
908 | { | ||
909 | if (-abv < t_43.length) xr_1d[quotien][reste] = -g_gain * t_43[-abv]; | ||
910 | else xr_1d[quotien][reste] = -g_gain * (float)Math.pow(-abv, d43); | ||
911 | } | ||
912 | } | ||
913 | else | ||
914 | { | ||
915 | if (is_1d[j] > 0) xr_1d[quotien][reste] = g_gain * (float)Math.pow(abv, d43); | ||
916 | else xr_1d[quotien][reste] = -g_gain * (float)Math.pow(-abv, d43); | ||
917 | } | ||
918 | } | ||
919 | } | ||
920 | |||
921 | // apply formula per block type | ||
922 | for (j=0; j<nonzero[ch]; j++) | ||
923 | { | ||
924 | // Modif E.B 02/22/99 | ||
925 | int reste = j % SSLIMIT; | ||
926 | int quotien = (int) ((j-reste)/SSLIMIT); | ||
927 | |||
928 | if (index == next_cb_boundary) { /* Adjust critical band boundary */ | ||
929 | if ((gr_info.window_switching_flag != 0) && (gr_info.block_type == 2)) { | ||
930 | if (gr_info.mixed_block_flag != 0) { | ||
931 | |||
932 | if (index == sfBandIndex[sfreq].l[8]) { | ||
933 | next_cb_boundary = sfBandIndex[sfreq].s[4]; | ||
934 | next_cb_boundary = (next_cb_boundary << 2) - | ||
935 | next_cb_boundary; | ||
936 | cb = 3; | ||
937 | cb_width = sfBandIndex[sfreq].s[4] - | ||
938 | sfBandIndex[sfreq].s[3]; | ||
939 | |||
940 | cb_begin = sfBandIndex[sfreq].s[3]; | ||
941 | cb_begin = (cb_begin << 2) - cb_begin; | ||
942 | |||
943 | } else if (index < sfBandIndex[sfreq].l[8]) { | ||
944 | |||
945 | next_cb_boundary = sfBandIndex[sfreq].l[(++cb)+1]; | ||
946 | |||
947 | } else { | ||
948 | |||
949 | next_cb_boundary = sfBandIndex[sfreq].s[(++cb)+1]; | ||
950 | next_cb_boundary = (next_cb_boundary << 2) - | ||
951 | next_cb_boundary; | ||
952 | |||
953 | cb_begin = sfBandIndex[sfreq].s[cb]; | ||
954 | cb_width = sfBandIndex[sfreq].s[cb+1] - | ||
955 | cb_begin; | ||
956 | cb_begin = (cb_begin << 2) - cb_begin; | ||
957 | } | ||
958 | |||
959 | } else { | ||
960 | |||
961 | next_cb_boundary = sfBandIndex[sfreq].s[(++cb)+1]; | ||
962 | next_cb_boundary = (next_cb_boundary << 2) - | ||
963 | next_cb_boundary; | ||
964 | |||
965 | cb_begin = sfBandIndex[sfreq].s[cb]; | ||
966 | cb_width = sfBandIndex[sfreq].s[cb+1] - | ||
967 | cb_begin; | ||
968 | cb_begin = (cb_begin << 2) - cb_begin; | ||
969 | } | ||
970 | |||
971 | } else { // long blocks | ||
972 | |||
973 | next_cb_boundary = sfBandIndex[sfreq].l[(++cb)+1]; | ||
974 | |||
975 | } | ||
976 | } | ||
977 | |||
978 | // Do long/short dependent scaling operations | ||
979 | |||
980 | if ((gr_info.window_switching_flag !=0)&& | ||
981 | (((gr_info.block_type == 2) && (gr_info.mixed_block_flag == 0)) || | ||
982 | ((gr_info.block_type == 2) && (gr_info.mixed_block_flag!=0) && (j >= 36)) )) | ||
983 | { | ||
984 | |||
985 | t_index = (index - cb_begin) / cb_width; | ||
986 | /* xr[sb][ss] *= pow(2.0, ((-2.0 * gr_info.subblock_gain[t_index]) | ||
987 | -(0.5 * (1.0 + gr_info.scalefac_scale) | ||
988 | * scalefac[ch].s[t_index][cb]))); */ | ||
989 | int idx = scalefac[ch].s[t_index][cb] | ||
990 | << gr_info.scalefac_scale; | ||
991 | idx += (gr_info.subblock_gain[t_index] << 2); | ||
992 | |||
993 | xr_1d[quotien][reste] *= two_to_negative_half_pow[idx]; | ||
994 | |||
995 | } else { // LONG block types 0,1,3 & 1st 2 subbands of switched blocks | ||
996 | /* xr[sb][ss] *= pow(2.0, -0.5 * (1.0+gr_info.scalefac_scale) | ||
997 | * (scalefac[ch].l[cb] | ||
998 | + gr_info.preflag * pretab[cb])); */ | ||
999 | int idx = scalefac[ch].l[cb]; | ||
1000 | |||
1001 | if (gr_info.preflag != 0) | ||
1002 | idx += pretab[cb]; | ||
1003 | |||
1004 | idx = idx << gr_info.scalefac_scale; | ||
1005 | xr_1d[quotien][reste] *= two_to_negative_half_pow[idx]; | ||
1006 | } | ||
1007 | index++; | ||
1008 | } | ||
1009 | |||
1010 | for (j=nonzero[ch]; j<576; j++) | ||
1011 | { | ||
1012 | // Modif E.B 02/22/99 | ||
1013 | int reste = j % SSLIMIT; | ||
1014 | int quotien = (int) ((j-reste)/SSLIMIT); | ||
1015 | if(reste < 0) reste = 0; | ||
1016 | if(quotien < 0) quotien = 0; | ||
1017 | xr_1d[quotien][reste] = 0.0f; | ||
1018 | } | ||
1019 | |||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | /** | ||
1024 | * | ||
1025 | */ | ||
1026 | private void reorder(float xr[][], int ch, int gr) | ||
1027 | { | ||
1028 | gr_info_s gr_info = (si.ch[ch].gr[gr]); | ||
1029 | int freq, freq3; | ||
1030 | int index; | ||
1031 | int sfb, sfb_start, sfb_lines; | ||
1032 | int src_line, des_line; | ||
1033 | float[][] xr_1d = xr; | ||
1034 | |||
1035 | if ((gr_info.window_switching_flag !=0) && (gr_info.block_type == 2)) { | ||
1036 | |||
1037 | for(index=0; index<576; index++) | ||
1038 | out_1d[index] = 0.0f; | ||
1039 | |||
1040 | if (gr_info.mixed_block_flag !=0 ) { | ||
1041 | // NO REORDER FOR LOW 2 SUBBANDS | ||
1042 | for (index = 0; index < 36; index++) | ||
1043 | { | ||
1044 | // Modif E.B 02/22/99 | ||
1045 | int reste = index % SSLIMIT; | ||
1046 | int quotien = (int) ((index-reste)/SSLIMIT); | ||
1047 | out_1d[index] = xr_1d[quotien][reste]; | ||
1048 | } | ||
1049 | // REORDERING FOR REST SWITCHED SHORT | ||
1050 | /*for( sfb=3,sfb_start=sfBandIndex[sfreq].s[3], | ||
1051 | sfb_lines=sfBandIndex[sfreq].s[4] - sfb_start; | ||
1052 | sfb < 13; sfb++,sfb_start = sfBandIndex[sfreq].s[sfb], | ||
1053 | sfb_lines = sfBandIndex[sfreq].s[sfb+1] - sfb_start ) | ||
1054 | {*/ | ||
1055 | for( sfb=3; sfb < 13; sfb++) | ||
1056 | { | ||
1057 | //System.out.println("sfreq="+sfreq+" sfb="+sfb+" sfBandIndex="+sfBandIndex.length+" sfBandIndex[sfreq].s="+sfBandIndex[sfreq].s.length); | ||
1058 | sfb_start = sfBandIndex[sfreq].s[sfb]; | ||
1059 | sfb_lines = sfBandIndex[sfreq].s[sfb+1] - sfb_start; | ||
1060 | |||
1061 | int sfb_start3 = (sfb_start << 2) - sfb_start; | ||
1062 | |||
1063 | for(freq=0, freq3=0; freq<sfb_lines; | ||
1064 | freq++, freq3+=3) { | ||
1065 | |||
1066 | src_line = sfb_start3 + freq; | ||
1067 | des_line = sfb_start3 + freq3; | ||
1068 | // Modif E.B 02/22/99 | ||
1069 | int reste = src_line % SSLIMIT; | ||
1070 | int quotien = (int) ((src_line-reste)/SSLIMIT); | ||
1071 | |||
1072 | out_1d[des_line] = xr_1d[quotien][reste]; | ||
1073 | src_line += sfb_lines; | ||
1074 | des_line++; | ||
1075 | |||
1076 | reste = src_line % SSLIMIT; | ||
1077 | quotien = (int) ((src_line-reste)/SSLIMIT); | ||
1078 | |||
1079 | out_1d[des_line] = xr_1d[quotien][reste]; | ||
1080 | src_line += sfb_lines; | ||
1081 | des_line++; | ||
1082 | |||
1083 | reste = src_line % SSLIMIT; | ||
1084 | quotien = (int) ((src_line-reste)/SSLIMIT); | ||
1085 | |||
1086 | out_1d[des_line] = xr_1d[quotien][reste]; | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | } else { // pure short | ||
1091 | for(index=0;index<576;index++) | ||
1092 | { | ||
1093 | int j = reorder_table[sfreq][index]; | ||
1094 | int reste = j % SSLIMIT; | ||
1095 | int quotien = (int) ((j-reste)/SSLIMIT); | ||
1096 | out_1d[index] = xr_1d[quotien][reste]; | ||
1097 | } | ||
1098 | } | ||
1099 | } | ||
1100 | else { // long blocks | ||
1101 | for(index=0; index<576; index++) | ||
1102 | { | ||
1103 | // Modif E.B 02/22/99 | ||
1104 | int reste = index % SSLIMIT; | ||
1105 | int quotien = (int) ((index-reste)/SSLIMIT); | ||
1106 | out_1d[index] = xr_1d[quotien][reste]; | ||
1107 | } | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | /** | ||
1112 | * | ||
1113 | */ | ||
1114 | |||
1115 | int[] is_pos = new int[576]; | ||
1116 | float[] is_ratio = new float[576]; | ||
1117 | |||
1118 | private void stereo(int gr) | ||
1119 | { | ||
1120 | int sb, ss; | ||
1121 | |||
1122 | if (channels == 1) { // mono , bypass xr[0][][] to lr[0][][] | ||
1123 | |||
1124 | for(sb=0;sb<SBLIMIT;sb++) | ||
1125 | for(ss=0;ss<SSLIMIT;ss+=3) { | ||
1126 | lr[0][sb][ss] = ro[0][sb][ss]; | ||
1127 | lr[0][sb][ss+1] = ro[0][sb][ss+1]; | ||
1128 | lr[0][sb][ss+2] = ro[0][sb][ss+2]; | ||
1129 | } | ||
1130 | |||
1131 | } else { | ||
1132 | |||
1133 | gr_info_s gr_info = (si.ch[0].gr[gr]); | ||
1134 | int mode_ext = header.mode_extension(); | ||
1135 | int sfb; | ||
1136 | int i; | ||
1137 | int lines, temp, temp2; | ||
1138 | |||
1139 | boolean ms_stereo = ((header.mode() == Header.JOINT_STEREO) && ((mode_ext & 0x2)!=0)); | ||
1140 | boolean i_stereo = ((header.mode() == Header.JOINT_STEREO) && ((mode_ext & 0x1)!=0)); | ||
1141 | boolean lsf = ((header.version() == Header.MPEG2_LSF || header.version() == Header.MPEG25_LSF )); // SZD | ||
1142 | |||
1143 | int io_type = (gr_info.scalefac_compress & 1); | ||
1144 | |||
1145 | // initialization | ||
1146 | |||
1147 | for (i=0; i<576; i++) | ||
1148 | { | ||
1149 | is_pos[i] = 7; | ||
1150 | |||
1151 | is_ratio[i] = 0.0f; | ||
1152 | } | ||
1153 | |||
1154 | if (i_stereo) { | ||
1155 | if ((gr_info.window_switching_flag !=0 )&& (gr_info.block_type == 2)) { | ||
1156 | if (gr_info.mixed_block_flag != 0) { | ||
1157 | |||
1158 | int max_sfb = 0; | ||
1159 | |||
1160 | for (int j=0; j<3; j++) { | ||
1161 | int sfbcnt; | ||
1162 | sfbcnt = 2; | ||
1163 | for( sfb=12; sfb >=3; sfb-- ) { | ||
1164 | i = sfBandIndex[sfreq].s[sfb]; | ||
1165 | lines = sfBandIndex[sfreq].s[sfb+1] - i; | ||
1166 | i = (i << 2) - i + (j+1) * lines - 1; | ||
1167 | |||
1168 | while (lines > 0) { | ||
1169 | if (ro[1][i/18][i%18] != 0.0f) { | ||
1170 | // MDM: in java, array access is very slow. | ||
1171 | // Is quicker to compute div and mod values. | ||
1172 | //if (ro[1][ss_div[i]][ss_mod[i]] != 0.0f) { | ||
1173 | sfbcnt = sfb; | ||
1174 | sfb = -10; | ||
1175 | lines = -10; | ||
1176 | } | ||
1177 | |||
1178 | lines--; | ||
1179 | i--; | ||
1180 | |||
1181 | } // while (lines > 0) | ||
1182 | |||
1183 | } // for (sfb=12 ... | ||
1184 | sfb = sfbcnt + 1; | ||
1185 | |||
1186 | if (sfb > max_sfb) | ||
1187 | max_sfb = sfb; | ||
1188 | |||
1189 | while(sfb < 12) { | ||
1190 | temp = sfBandIndex[sfreq].s[sfb]; | ||
1191 | sb = sfBandIndex[sfreq].s[sfb+1] - temp; | ||
1192 | i = (temp << 2) - temp + j * sb; | ||
1193 | |||
1194 | for ( ; sb > 0; sb--) { | ||
1195 | is_pos[i] = scalefac[1].s[j][sfb]; | ||
1196 | if (is_pos[i] != 7) | ||
1197 | if (lsf) | ||
1198 | i_stereo_k_values(is_pos[i], io_type, i); | ||
1199 | else | ||
1200 | is_ratio[i] = TAN12[is_pos[i]]; | ||
1201 | |||
1202 | i++; | ||
1203 | } // for (; sb>0... | ||
1204 | sfb++; | ||
1205 | } // while (sfb < 12) | ||
1206 | sfb = sfBandIndex[sfreq].s[10]; | ||
1207 | sb = sfBandIndex[sfreq].s[11] - sfb; | ||
1208 | sfb = (sfb << 2) - sfb + j * sb; | ||
1209 | temp = sfBandIndex[sfreq].s[11]; | ||
1210 | sb = sfBandIndex[sfreq].s[12] - temp; | ||
1211 | i = (temp << 2) - temp + j * sb; | ||
1212 | |||
1213 | for (; sb > 0; sb--) { | ||
1214 | is_pos[i] = is_pos[sfb]; | ||
1215 | |||
1216 | if (lsf) { | ||
1217 | k[0][i] = k[0][sfb]; | ||
1218 | k[1][i] = k[1][sfb]; | ||
1219 | } else { | ||
1220 | is_ratio[i] = is_ratio[sfb]; | ||
1221 | } | ||
1222 | i++; | ||
1223 | } // for (; sb > 0 ... | ||
1224 | } | ||
1225 | if (max_sfb <= 3) { | ||
1226 | i = 2; | ||
1227 | ss = 17; | ||
1228 | sb = -1; | ||
1229 | while (i >= 0) { | ||
1230 | if (ro[1][i][ss] != 0.0f) { | ||
1231 | sb = (i<<4) + (i<<1) + ss; | ||
1232 | i = -1; | ||
1233 | } else { | ||
1234 | ss--; | ||
1235 | if (ss < 0) { | ||
1236 | i--; | ||
1237 | ss = 17; | ||
1238 | } | ||
1239 | } // if (ro ... | ||
1240 | } // while (i>=0) | ||
1241 | i = 0; | ||
1242 | while (sfBandIndex[sfreq].l[i] <= sb) | ||
1243 | i++; | ||
1244 | sfb = i; | ||
1245 | i = sfBandIndex[sfreq].l[i]; | ||
1246 | for (; sfb<8; sfb++) { | ||
1247 | sb = sfBandIndex[sfreq].l[sfb+1]-sfBandIndex[sfreq].l[sfb]; | ||
1248 | for (; sb>0; sb--) { | ||
1249 | is_pos[i] = scalefac[1].l[sfb]; | ||
1250 | if (is_pos[i] != 7) | ||
1251 | if (lsf) | ||
1252 | i_stereo_k_values(is_pos[i], io_type, i); | ||
1253 | else | ||
1254 | is_ratio[i] = TAN12[is_pos[i]]; | ||
1255 | i++; | ||
1256 | } // for (; sb>0 ... | ||
1257 | } // for (; sfb<8 ... | ||
1258 | } // for (j=0 ... | ||
1259 | } else { // if (gr_info.mixed_block_flag) | ||
1260 | for (int j=0; j<3; j++) { | ||
1261 | int sfbcnt; | ||
1262 | sfbcnt = -1; | ||
1263 | for( sfb=12; sfb >=0; sfb-- ) | ||
1264 | { | ||
1265 | temp = sfBandIndex[sfreq].s[sfb]; | ||
1266 | lines = sfBandIndex[sfreq].s[sfb+1] - temp; | ||
1267 | i = (temp << 2) - temp + (j+1) * lines - 1; | ||
1268 | |||
1269 | while (lines > 0) { | ||
1270 | if (ro[1][i/18][i%18] != 0.0f) { | ||
1271 | // MDM: in java, array access is very slow. | ||
1272 | // Is quicker to compute div and mod values. | ||
1273 | //if (ro[1][ss_div[i]][ss_mod[i]] != 0.0f) { | ||
1274 | sfbcnt = sfb; | ||
1275 | sfb = -10; | ||
1276 | lines = -10; | ||
1277 | } | ||
1278 | lines--; | ||
1279 | i--; | ||
1280 | } // while (lines > 0) */ | ||
1281 | |||
1282 | } // for (sfb=12 ... | ||
1283 | sfb = sfbcnt + 1; | ||
1284 | while(sfb<12) { | ||
1285 | temp = sfBandIndex[sfreq].s[sfb]; | ||
1286 | sb = sfBandIndex[sfreq].s[sfb+1] - temp; | ||
1287 | i = (temp << 2) - temp + j * sb; | ||
1288 | for ( ; sb > 0; sb--) { | ||
1289 | is_pos[i] = scalefac[1].s[j][sfb]; | ||
1290 | if (is_pos[i] != 7) | ||
1291 | if (lsf) | ||
1292 | i_stereo_k_values(is_pos[i], io_type, i); | ||
1293 | else | ||
1294 | is_ratio[i] = TAN12[is_pos[i]]; | ||
1295 | i++; | ||
1296 | } // for (; sb>0 ... | ||
1297 | sfb++; | ||
1298 | } // while (sfb<12) | ||
1299 | |||
1300 | temp = sfBandIndex[sfreq].s[10]; | ||
1301 | temp2= sfBandIndex[sfreq].s[11]; | ||
1302 | sb = temp2 - temp; | ||
1303 | sfb = (temp << 2) - temp + j * sb; | ||
1304 | sb = sfBandIndex[sfreq].s[12] - temp2; | ||
1305 | i = (temp2 << 2) - temp2 + j * sb; | ||
1306 | |||
1307 | for (; sb>0; sb--) { | ||
1308 | is_pos[i] = is_pos[sfb]; | ||
1309 | |||
1310 | if (lsf) { | ||
1311 | k[0][i] = k[0][sfb]; | ||
1312 | k[1][i] = k[1][sfb]; | ||
1313 | } else { | ||
1314 | is_ratio[i] = is_ratio[sfb]; | ||
1315 | } | ||
1316 | i++; | ||
1317 | } // for (; sb>0 ... | ||
1318 | } // for (sfb=12 | ||
1319 | } // for (j=0 ... | ||
1320 | } else { // if (gr_info.window_switching_flag ... | ||
1321 | i = 31; | ||
1322 | ss = 17; | ||
1323 | sb = 0; | ||
1324 | while (i >= 0) { | ||
1325 | if (ro[1][i][ss] != 0.0f) { | ||
1326 | sb = (i<<4) + (i<<1) + ss; | ||
1327 | i = -1; | ||
1328 | } else { | ||
1329 | ss--; | ||
1330 | if (ss < 0) { | ||
1331 | i--; | ||
1332 | ss = 17; | ||
1333 | } | ||
1334 | } | ||
1335 | } | ||
1336 | i = 0; | ||
1337 | while (sfBandIndex[sfreq].l[i] <= sb) | ||
1338 | i++; | ||
1339 | |||
1340 | sfb = i; | ||
1341 | i = sfBandIndex[sfreq].l[i]; | ||
1342 | for (; sfb<21; sfb++) { | ||
1343 | sb = sfBandIndex[sfreq].l[sfb+1] - sfBandIndex[sfreq].l[sfb]; | ||
1344 | for (; sb > 0; sb--) { | ||
1345 | is_pos[i] = scalefac[1].l[sfb]; | ||
1346 | if (is_pos[i] != 7) | ||
1347 | if (lsf) | ||
1348 | i_stereo_k_values(is_pos[i], io_type, i); | ||
1349 | else | ||
1350 | is_ratio[i] = TAN12[is_pos[i]]; | ||
1351 | i++; | ||
1352 | } | ||
1353 | } | ||
1354 | sfb = sfBandIndex[sfreq].l[20]; | ||
1355 | for (sb = 576 - sfBandIndex[sfreq].l[21]; (sb > 0) && (i<576); sb--) | ||
1356 | { | ||
1357 | is_pos[i] = is_pos[sfb]; // error here : i >=576 | ||
1358 | |||
1359 | if (lsf) { | ||
1360 | k[0][i] = k[0][sfb]; | ||
1361 | k[1][i] = k[1][sfb]; | ||
1362 | } else { | ||
1363 | is_ratio[i] = is_ratio[sfb]; | ||
1364 | } | ||
1365 | i++; | ||
1366 | } // if (gr_info.mixed_block_flag) | ||
1367 | } // if (gr_info.window_switching_flag ... | ||
1368 | } // if (i_stereo) | ||
1369 | |||
1370 | i = 0; | ||
1371 | for(sb=0;sb<SBLIMIT;sb++) | ||
1372 | for(ss=0;ss<SSLIMIT;ss++) { | ||
1373 | if (is_pos[i] == 7) { | ||
1374 | if (ms_stereo) { | ||
1375 | lr[0][sb][ss] = (ro[0][sb][ss]+ro[1][sb][ss]) * 0.707106781f; | ||
1376 | lr[1][sb][ss] = (ro[0][sb][ss]-ro[1][sb][ss]) * 0.707106781f; | ||
1377 | } else { | ||
1378 | lr[0][sb][ss] = ro[0][sb][ss]; | ||
1379 | lr[1][sb][ss] = ro[1][sb][ss]; | ||
1380 | } | ||
1381 | } | ||
1382 | else if (i_stereo) { | ||
1383 | |||
1384 | if (lsf) { | ||
1385 | lr[0][sb][ss] = ro[0][sb][ss] * k[0][i]; | ||
1386 | lr[1][sb][ss] = ro[0][sb][ss] * k[1][i]; | ||
1387 | } else { | ||
1388 | lr[1][sb][ss] = ro[0][sb][ss] / (float) (1 + is_ratio[i]); | ||
1389 | lr[0][sb][ss] = lr[1][sb][ss] * is_ratio[i]; | ||
1390 | } | ||
1391 | } | ||
1392 | /* else { | ||
1393 | System.out.println("Error in stereo processing\n"); | ||
1394 | } */ | ||
1395 | i++; | ||
1396 | } | ||
1397 | |||
1398 | } // channels == 2 | ||
1399 | |||
1400 | } | ||
1401 | |||
1402 | /** | ||
1403 | * | ||
1404 | */ | ||
1405 | private void antialias(int ch, int gr) | ||
1406 | { | ||
1407 | int sb18, ss, sb18lim; | ||
1408 | gr_info_s gr_info = (si.ch[ch].gr[gr]); | ||
1409 | // 31 alias-reduction operations between each pair of sub-bands | ||
1410 | // with 8 butterflies between each pair | ||
1411 | |||
1412 | if ((gr_info.window_switching_flag !=0) && (gr_info.block_type == 2) && | ||
1413 | !(gr_info.mixed_block_flag != 0) ) | ||
1414 | return; | ||
1415 | |||
1416 | if ((gr_info.window_switching_flag !=0) && (gr_info.mixed_block_flag != 0)&& | ||
1417 | (gr_info.block_type == 2)) { | ||
1418 | sb18lim = 18; | ||
1419 | } else { | ||
1420 | sb18lim = 558; | ||
1421 | } | ||
1422 | |||
1423 | for (sb18=0; sb18 < sb18lim; sb18+=18) { | ||
1424 | for (ss=0;ss<8;ss++) { | ||
1425 | int src_idx1 = sb18 + 17 - ss; | ||
1426 | int src_idx2 = sb18 + 18 + ss; | ||
1427 | float bu = out_1d[src_idx1]; | ||
1428 | float bd = out_1d[src_idx2]; | ||
1429 | out_1d[src_idx1] = (bu * cs[ss]) - (bd * ca[ss]); | ||
1430 | out_1d[src_idx2] = (bd * cs[ss]) + (bu * ca[ss]); | ||
1431 | } | ||
1432 | } | ||
1433 | } | ||
1434 | |||
1435 | /** | ||
1436 | * | ||
1437 | */ | ||
1438 | |||
1439 | // MDM: tsOutCopy and rawout do not need initializing, so the arrays | ||
1440 | // can be reused. | ||
1441 | float[] tsOutCopy = new float[18]; | ||
1442 | float[] rawout = new float[36]; | ||
1443 | |||
1444 | private void hybrid(int ch, int gr) | ||
1445 | { | ||
1446 | int bt; | ||
1447 | int sb18; | ||
1448 | gr_info_s gr_info = (si.ch[ch].gr[gr]); | ||
1449 | float[] tsOut; | ||
1450 | |||
1451 | float[][] prvblk; | ||
1452 | |||
1453 | for(sb18=0;sb18<576;sb18+=18) | ||
1454 | { | ||
1455 | bt = ((gr_info.window_switching_flag !=0 ) && (gr_info.mixed_block_flag !=0) && | ||
1456 | (sb18 < 36)) ? 0 : gr_info.block_type; | ||
1457 | |||
1458 | tsOut = out_1d; | ||
1459 | // Modif E.B 02/22/99 | ||
1460 | for (int cc = 0;cc<18;cc++) | ||
1461 | tsOutCopy[cc] = tsOut[cc+sb18]; | ||
1462 | |||
1463 | inv_mdct(tsOutCopy, rawout, bt); | ||
1464 | |||
1465 | |||
1466 | for (int cc = 0;cc<18;cc++) | ||
1467 | tsOut[cc+sb18] = tsOutCopy[cc]; | ||
1468 | // Fin Modif | ||
1469 | |||
1470 | // overlap addition | ||
1471 | prvblk = prevblck; | ||
1472 | |||
1473 | tsOut[0 + sb18] = rawout[0] + prvblk[ch][sb18 + 0]; | ||
1474 | prvblk[ch][sb18 + 0] = rawout[18]; | ||
1475 | tsOut[1 + sb18] = rawout[1] + prvblk[ch][sb18 + 1]; | ||
1476 | prvblk[ch][sb18 + 1] = rawout[19]; | ||
1477 | tsOut[2 + sb18] = rawout[2] + prvblk[ch][sb18 + 2]; | ||
1478 | prvblk[ch][sb18 + 2] = rawout[20]; | ||
1479 | tsOut[3 + sb18] = rawout[3] + prvblk[ch][sb18 + 3]; | ||
1480 | prvblk[ch][sb18 + 3] = rawout[21]; | ||
1481 | tsOut[4 + sb18] = rawout[4] + prvblk[ch][sb18 + 4]; | ||
1482 | prvblk[ch][sb18 + 4] = rawout[22]; | ||
1483 | tsOut[5 + sb18] = rawout[5] + prvblk[ch][sb18 + 5]; | ||
1484 | prvblk[ch][sb18 + 5] = rawout[23]; | ||
1485 | tsOut[6 + sb18] = rawout[6] + prvblk[ch][sb18 + 6]; | ||
1486 | prvblk[ch][sb18 + 6] = rawout[24]; | ||
1487 | tsOut[7 + sb18] = rawout[7] + prvblk[ch][sb18 + 7]; | ||
1488 | prvblk[ch][sb18 + 7] = rawout[25]; | ||
1489 | tsOut[8 + sb18] = rawout[8] + prvblk[ch][sb18 + 8]; | ||
1490 | prvblk[ch][sb18 + 8] = rawout[26]; | ||
1491 | tsOut[9 + sb18] = rawout[9] + prvblk[ch][sb18 + 9]; | ||
1492 | prvblk[ch][sb18 + 9] = rawout[27]; | ||
1493 | tsOut[10 + sb18] = rawout[10] + prvblk[ch][sb18 + 10]; | ||
1494 | prvblk[ch][sb18 + 10] = rawout[28]; | ||
1495 | tsOut[11 + sb18] = rawout[11] + prvblk[ch][sb18 + 11]; | ||
1496 | prvblk[ch][sb18 + 11] = rawout[29]; | ||
1497 | tsOut[12 + sb18] = rawout[12] + prvblk[ch][sb18 + 12]; | ||
1498 | prvblk[ch][sb18 + 12] = rawout[30]; | ||
1499 | tsOut[13 + sb18] = rawout[13] + prvblk[ch][sb18 + 13]; | ||
1500 | prvblk[ch][sb18 + 13] = rawout[31]; | ||
1501 | tsOut[14 + sb18] = rawout[14] + prvblk[ch][sb18 + 14]; | ||
1502 | prvblk[ch][sb18 + 14] = rawout[32]; | ||
1503 | tsOut[15 + sb18] = rawout[15] + prvblk[ch][sb18 + 15]; | ||
1504 | prvblk[ch][sb18 + 15] = rawout[33]; | ||
1505 | tsOut[16 + sb18] = rawout[16] + prvblk[ch][sb18 + 16]; | ||
1506 | prvblk[ch][sb18 + 16] = rawout[34]; | ||
1507 | tsOut[17 + sb18] = rawout[17] + prvblk[ch][sb18 + 17]; | ||
1508 | prvblk[ch][sb18 + 17] = rawout[35]; | ||
1509 | } | ||
1510 | } | ||
1511 | |||
1512 | /** | ||
1513 | * | ||
1514 | */ | ||
1515 | private void do_downmix() | ||
1516 | { | ||
1517 | for (int sb=0; sb<SSLIMIT; sb++) { | ||
1518 | for (int ss=0; ss<SSLIMIT; ss+=3) { | ||
1519 | lr[0][sb][ss] = (lr[0][sb][ss] + lr[1][sb][ss]) * 0.5f; | ||
1520 | lr[0][sb][ss+1] = (lr[0][sb][ss+1] + lr[1][sb][ss+1]) * 0.5f; | ||
1521 | lr[0][sb][ss+2] = (lr[0][sb][ss+2] + lr[1][sb][ss+2]) * 0.5f; | ||
1522 | } | ||
1523 | } | ||
1524 | } | ||
1525 | |||
1526 | /** | ||
1527 | * Fast INV_MDCT. | ||
1528 | */ | ||
1529 | |||
1530 | public void inv_mdct(float[] in, float[] out, int block_type) | ||
1531 | { | ||
1532 | float[] win_bt; | ||
1533 | int i; | ||
1534 | |||
1535 | float tmpf_0, tmpf_1, tmpf_2, tmpf_3, tmpf_4, tmpf_5, tmpf_6, tmpf_7, tmpf_8, tmpf_9; | ||
1536 | float tmpf_10, tmpf_11, tmpf_12, tmpf_13, tmpf_14, tmpf_15, tmpf_16, tmpf_17; | ||
1537 | |||
1538 | tmpf_0 = tmpf_1 = tmpf_2 = tmpf_3 = tmpf_4 = tmpf_5 = tmpf_6 = tmpf_7 = tmpf_8 = tmpf_9 = | ||
1539 | tmpf_10 = tmpf_11 = tmpf_12 = tmpf_13 = tmpf_14 = tmpf_15 = tmpf_16 = tmpf_17 = 0.0f; | ||
1540 | |||
1541 | |||
1542 | |||
1543 | if(block_type == 2) | ||
1544 | { | ||
1545 | |||
1546 | /* | ||
1547 | * | ||
1548 | * Under MicrosoftVM 2922, This causes a GPF, or | ||
1549 | * At best, an ArrayIndexOutOfBoundsExceptin. | ||
1550 | for(int p=0;p<36;p+=9) | ||
1551 | { | ||
1552 | out[p] = out[p+1] = out[p+2] = out[p+3] = | ||
1553 | out[p+4] = out[p+5] = out[p+6] = out[p+7] = | ||
1554 | out[p+8] = 0.0f; | ||
1555 | } | ||
1556 | */ | ||
1557 | out[0] = 0.0f; | ||
1558 | out[1] = 0.0f; | ||
1559 | out[2] = 0.0f; | ||
1560 | out[3] = 0.0f; | ||
1561 | out[4] = 0.0f; | ||
1562 | out[5] = 0.0f; | ||
1563 | out[6] = 0.0f; | ||
1564 | out[7] = 0.0f; | ||
1565 | out[8] = 0.0f; | ||
1566 | out[9] = 0.0f; | ||
1567 | out[10] = 0.0f; | ||
1568 | out[11] = 0.0f; | ||
1569 | out[12] = 0.0f; | ||
1570 | out[13] = 0.0f; | ||
1571 | out[14] = 0.0f; | ||
1572 | out[15] = 0.0f; | ||
1573 | out[16] = 0.0f; | ||
1574 | out[17] = 0.0f; | ||
1575 | out[18] = 0.0f; | ||
1576 | out[19] = 0.0f; | ||
1577 | out[20] = 0.0f; | ||
1578 | out[21] = 0.0f; | ||
1579 | out[22] = 0.0f; | ||
1580 | out[23] = 0.0f; | ||
1581 | out[24] = 0.0f; | ||
1582 | out[25] = 0.0f; | ||
1583 | out[26] = 0.0f; | ||
1584 | out[27] = 0.0f; | ||
1585 | out[28] = 0.0f; | ||
1586 | out[29] = 0.0f; | ||
1587 | out[30] = 0.0f; | ||
1588 | out[31] = 0.0f; | ||
1589 | out[32] = 0.0f; | ||
1590 | out[33] = 0.0f; | ||
1591 | out[34] = 0.0f; | ||
1592 | out[35] = 0.0f; | ||
1593 | |||
1594 | int six_i = 0; | ||
1595 | |||
1596 | for(i=0;i<3;i++) | ||
1597 | { | ||
1598 | // 12 point IMDCT | ||
1599 | // Begin 12 point IDCT | ||
1600 | // Input aliasing for 12 pt IDCT | ||
1601 | in[15+i] += in[12+i]; in[12+i] += in[9+i]; in[9+i] += in[6+i]; | ||
1602 | in[6+i] += in[3+i]; in[3+i] += in[0+i]; | ||
1603 | |||
1604 | // Input aliasing on odd indices (for 6 point IDCT) | ||
1605 | in[15+i] += in[9+i]; in[9+i] += in[3+i]; | ||
1606 | |||
1607 | // 3 point IDCT on even indices | ||
1608 | float pp1, pp2, sum; | ||
1609 | pp2 = in[12+i] * 0.500000000f; | ||
1610 | pp1 = in[ 6+i] * 0.866025403f; | ||
1611 | sum = in[0+i] + pp2; | ||
1612 | tmpf_1 = in[0+i] - in[12+i]; | ||
1613 | tmpf_0 = sum + pp1; | ||
1614 | tmpf_2 = sum - pp1; | ||
1615 | |||
1616 | // End 3 point IDCT on even indices | ||
1617 | // 3 point IDCT on odd indices (for 6 point IDCT) | ||
1618 | pp2 = in[15+i] * 0.500000000f; | ||
1619 | pp1 = in[ 9+i] * 0.866025403f; | ||
1620 | sum = in[ 3+i] + pp2; | ||
1621 | tmpf_4 = in[3+i] - in[15+i]; | ||
1622 | tmpf_5 = sum + pp1; | ||
1623 | tmpf_3 = sum - pp1; | ||
1624 | // End 3 point IDCT on odd indices | ||
1625 | // Twiddle factors on odd indices (for 6 point IDCT) | ||
1626 | |||
1627 | tmpf_3 *= 1.931851653f; | ||
1628 | tmpf_4 *= 0.707106781f; | ||
1629 | tmpf_5 *= 0.517638090f; | ||
1630 | |||
1631 | // Output butterflies on 2 3 point IDCT's (for 6 point IDCT) | ||
1632 | float save = tmpf_0; | ||
1633 | tmpf_0 += tmpf_5; | ||
1634 | tmpf_5 = save - tmpf_5; | ||
1635 | save = tmpf_1; | ||
1636 | tmpf_1 += tmpf_4; | ||
1637 | tmpf_4 = save - tmpf_4; | ||
1638 | save = tmpf_2; | ||
1639 | tmpf_2 += tmpf_3; | ||
1640 | tmpf_3 = save - tmpf_3; | ||
1641 | |||
1642 | // End 6 point IDCT | ||
1643 | // Twiddle factors on indices (for 12 point IDCT) | ||
1644 | |||
1645 | tmpf_0 *= 0.504314480f; | ||
1646 | tmpf_1 *= 0.541196100f; | ||
1647 | tmpf_2 *= 0.630236207f; | ||
1648 | tmpf_3 *= 0.821339815f; | ||
1649 | tmpf_4 *= 1.306562965f; | ||
1650 | tmpf_5 *= 3.830648788f; | ||
1651 | |||
1652 | // End 12 point IDCT | ||
1653 | |||
1654 | // Shift to 12 point modified IDCT, multiply by window type 2 | ||
1655 | tmpf_8 = -tmpf_0 * 0.793353340f; | ||
1656 | tmpf_9 = -tmpf_0 * 0.608761429f; | ||
1657 | tmpf_7 = -tmpf_1 * 0.923879532f; | ||
1658 | tmpf_10 = -tmpf_1 * 0.382683432f; | ||
1659 | tmpf_6 = -tmpf_2 * 0.991444861f; | ||
1660 | tmpf_11 = -tmpf_2 * 0.130526192f; | ||
1661 | |||
1662 | tmpf_0 = tmpf_3; | ||
1663 | tmpf_1 = tmpf_4 * 0.382683432f; | ||
1664 | tmpf_2 = tmpf_5 * 0.608761429f; | ||
1665 | |||
1666 | tmpf_3 = -tmpf_5 * 0.793353340f; | ||
1667 | tmpf_4 = -tmpf_4 * 0.923879532f; | ||
1668 | tmpf_5 = -tmpf_0 * 0.991444861f; | ||
1669 | |||
1670 | tmpf_0 *= 0.130526192f; | ||
1671 | |||
1672 | out[six_i + 6] += tmpf_0; | ||
1673 | out[six_i + 7] += tmpf_1; | ||
1674 | out[six_i + 8] += tmpf_2; | ||
1675 | out[six_i + 9] += tmpf_3; | ||
1676 | out[six_i + 10] += tmpf_4; | ||
1677 | out[six_i + 11] += tmpf_5; | ||
1678 | out[six_i + 12] += tmpf_6; | ||
1679 | out[six_i + 13] += tmpf_7; | ||
1680 | out[six_i + 14] += tmpf_8; | ||
1681 | out[six_i + 15] += tmpf_9; | ||
1682 | out[six_i + 16] += tmpf_10; | ||
1683 | out[six_i + 17] += tmpf_11; | ||
1684 | |||
1685 | six_i += 6; | ||
1686 | } | ||
1687 | } | ||
1688 | else | ||
1689 | { | ||
1690 | // 36 point IDCT | ||
1691 | // input aliasing for 36 point IDCT | ||
1692 | in[17]+=in[16]; in[16]+=in[15]; in[15]+=in[14]; in[14]+=in[13]; | ||
1693 | in[13]+=in[12]; in[12]+=in[11]; in[11]+=in[10]; in[10]+=in[9]; | ||
1694 | in[9] +=in[8]; in[8] +=in[7]; in[7] +=in[6]; in[6] +=in[5]; | ||
1695 | in[5] +=in[4]; in[4] +=in[3]; in[3] +=in[2]; in[2] +=in[1]; | ||
1696 | in[1] +=in[0]; | ||
1697 | |||
1698 | // 18 point IDCT for odd indices | ||
1699 | // input aliasing for 18 point IDCT | ||
1700 | in[17]+=in[15]; in[15]+=in[13]; in[13]+=in[11]; in[11]+=in[9]; | ||
1701 | in[9] +=in[7]; in[7] +=in[5]; in[5] +=in[3]; in[3] +=in[1]; | ||
1702 | |||
1703 | float tmp0,tmp1,tmp2,tmp3,tmp4,tmp0_,tmp1_,tmp2_,tmp3_; | ||
1704 | float tmp0o,tmp1o,tmp2o,tmp3o,tmp4o,tmp0_o,tmp1_o,tmp2_o,tmp3_o; | ||
1705 | |||
1706 | // Fast 9 Point Inverse Discrete Cosine Transform | ||
1707 | // | ||
1708 | // By Francois-Raymond Boyer | ||
1709 | // mailto:boyerf@iro.umontreal.ca | ||
1710 | // http://www.iro.umontreal.ca/~boyerf | ||
1711 | // | ||
1712 | // The code has been optimized for Intel processors | ||
1713 | // (takes a lot of time to convert float to and from iternal FPU representation) | ||
1714 | // | ||
1715 | // It is a simple "factorization" of the IDCT matrix. | ||
1716 | |||
1717 | // 9 point IDCT on even indices | ||
1718 | |||
1719 | // 5 points on odd indices (not realy an IDCT) | ||
1720 | float i00 = in[0]+in[0]; | ||
1721 | float iip12 = i00 + in[12]; | ||
1722 | |||
1723 | tmp0 = iip12 + in[4]*1.8793852415718f + in[8]*1.532088886238f + in[16]*0.34729635533386f; | ||
1724 | tmp1 = i00 + in[4] - in[8] - in[12] - in[12] - in[16]; | ||
1725 | tmp2 = iip12 - in[4]*0.34729635533386f - in[8]*1.8793852415718f + in[16]*1.532088886238f; | ||
1726 | tmp3 = iip12 - in[4]*1.532088886238f + in[8]*0.34729635533386f - in[16]*1.8793852415718f; | ||
1727 | tmp4 = in[0] - in[4] + in[8] - in[12] + in[16]; | ||
1728 | |||
1729 | // 4 points on even indices | ||
1730 | float i66_ = in[6]*1.732050808f; // Sqrt[3] | ||
1731 | |||
1732 | tmp0_ = in[2]*1.9696155060244f + i66_ + in[10]*1.2855752193731f + in[14]*0.68404028665134f; | ||
1733 | tmp1_ = (in[2] - in[10] - in[14])*1.732050808f; | ||
1734 | tmp2_ = in[2]*1.2855752193731f - i66_ - in[10]*0.68404028665134f + in[14]*1.9696155060244f; | ||
1735 | tmp3_ = in[2]*0.68404028665134f - i66_ + in[10]*1.9696155060244f - in[14]*1.2855752193731f; | ||
1736 | |||
1737 | // 9 point IDCT on odd indices | ||
1738 | // 5 points on odd indices (not realy an IDCT) | ||
1739 | float i0 = in[0+1]+in[0+1]; | ||
1740 | float i0p12 = i0 + in[12+1]; | ||
1741 | |||
1742 | tmp0o = i0p12 + in[4+1]*1.8793852415718f + in[8+1]*1.532088886238f + in[16+1]*0.34729635533386f; | ||
1743 | tmp1o = i0 + in[4+1] - in[8+1] - in[12+1] - in[12+1] - in[16+1]; | ||
1744 | tmp2o = i0p12 - in[4+1]*0.34729635533386f - in[8+1]*1.8793852415718f + in[16+1]*1.532088886238f; | ||
1745 | tmp3o = i0p12 - in[4+1]*1.532088886238f + in[8+1]*0.34729635533386f - in[16+1]*1.8793852415718f; | ||
1746 | tmp4o = (in[0+1] - in[4+1] + in[8+1] - in[12+1] + in[16+1])*0.707106781f; // Twiddled | ||
1747 | |||
1748 | // 4 points on even indices | ||
1749 | float i6_ = in[6+1]*1.732050808f; // Sqrt[3] | ||
1750 | |||
1751 | tmp0_o = in[2+1]*1.9696155060244f + i6_ + in[10+1]*1.2855752193731f + in[14+1]*0.68404028665134f; | ||
1752 | tmp1_o = (in[2+1] - in[10+1] - in[14+1])*1.732050808f; | ||
1753 | tmp2_o = in[2+1]*1.2855752193731f - i6_ - in[10+1]*0.68404028665134f + in[14+1]*1.9696155060244f; | ||
1754 | tmp3_o = in[2+1]*0.68404028665134f - i6_ + in[10+1]*1.9696155060244f - in[14+1]*1.2855752193731f; | ||
1755 | |||
1756 | // Twiddle factors on odd indices | ||
1757 | // and | ||
1758 | // Butterflies on 9 point IDCT's | ||
1759 | // and | ||
1760 | // twiddle factors for 36 point IDCT | ||
1761 | |||
1762 | float e, o; | ||
1763 | e = tmp0 + tmp0_; o = (tmp0o + tmp0_o)*0.501909918f; tmpf_0 = e + o; tmpf_17 = e - o; | ||
1764 | e = tmp1 + tmp1_; o = (tmp1o + tmp1_o)*0.517638090f; tmpf_1 = e + o; tmpf_16 = e - o; | ||
1765 | e = tmp2 + tmp2_; o = (tmp2o + tmp2_o)*0.551688959f; tmpf_2 = e + o; tmpf_15 = e - o; | ||
1766 | e = tmp3 + tmp3_; o = (tmp3o + tmp3_o)*0.610387294f; tmpf_3 = e + o; tmpf_14 = e - o; | ||
1767 | tmpf_4 = tmp4 + tmp4o; tmpf_13 = tmp4 - tmp4o; | ||
1768 | e = tmp3 - tmp3_; o = (tmp3o - tmp3_o)*0.871723397f; tmpf_5 = e + o; tmpf_12 = e - o; | ||
1769 | e = tmp2 - tmp2_; o = (tmp2o - tmp2_o)*1.183100792f; tmpf_6 = e + o; tmpf_11 = e - o; | ||
1770 | e = tmp1 - tmp1_; o = (tmp1o - tmp1_o)*1.931851653f; tmpf_7 = e + o; tmpf_10 = e - o; | ||
1771 | e = tmp0 - tmp0_; o = (tmp0o - tmp0_o)*5.736856623f; tmpf_8 = e + o; tmpf_9 = e - o; | ||
1772 | |||
1773 | // end 36 point IDCT */ | ||
1774 | // shift to modified IDCT | ||
1775 | win_bt = win[block_type]; | ||
1776 | |||
1777 | out[0] =-tmpf_9 * win_bt[0]; | ||
1778 | out[1] =-tmpf_10 * win_bt[1]; | ||
1779 | out[2] =-tmpf_11 * win_bt[2]; | ||
1780 | out[3] =-tmpf_12 * win_bt[3]; | ||
1781 | out[4] =-tmpf_13 * win_bt[4]; | ||
1782 | out[5] =-tmpf_14 * win_bt[5]; | ||
1783 | out[6] =-tmpf_15 * win_bt[6]; | ||
1784 | out[7] =-tmpf_16 * win_bt[7]; | ||
1785 | out[8] =-tmpf_17 * win_bt[8]; | ||
1786 | out[9] = tmpf_17 * win_bt[9]; | ||
1787 | out[10]= tmpf_16 * win_bt[10]; | ||
1788 | out[11]= tmpf_15 * win_bt[11]; | ||
1789 | out[12]= tmpf_14 * win_bt[12]; | ||
1790 | out[13]= tmpf_13 * win_bt[13]; | ||
1791 | out[14]= tmpf_12 * win_bt[14]; | ||
1792 | out[15]= tmpf_11 * win_bt[15]; | ||
1793 | out[16]= tmpf_10 * win_bt[16]; | ||
1794 | out[17]= tmpf_9 * win_bt[17]; | ||
1795 | out[18]= tmpf_8 * win_bt[18]; | ||
1796 | out[19]= tmpf_7 * win_bt[19]; | ||
1797 | out[20]= tmpf_6 * win_bt[20]; | ||
1798 | out[21]= tmpf_5 * win_bt[21]; | ||
1799 | out[22]= tmpf_4 * win_bt[22]; | ||
1800 | out[23]= tmpf_3 * win_bt[23]; | ||
1801 | out[24]= tmpf_2 * win_bt[24]; | ||
1802 | out[25]= tmpf_1 * win_bt[25]; | ||
1803 | out[26]= tmpf_0 * win_bt[26]; | ||
1804 | out[27]= tmpf_0 * win_bt[27]; | ||
1805 | out[28]= tmpf_1 * win_bt[28]; | ||
1806 | out[29]= tmpf_2 * win_bt[29]; | ||
1807 | out[30]= tmpf_3 * win_bt[30]; | ||
1808 | out[31]= tmpf_4 * win_bt[31]; | ||
1809 | out[32]= tmpf_5 * win_bt[32]; | ||
1810 | out[33]= tmpf_6 * win_bt[33]; | ||
1811 | out[34]= tmpf_7 * win_bt[34]; | ||
1812 | out[35]= tmpf_8 * win_bt[35]; | ||
1813 | } | ||
1814 | } | ||
1815 | |||
1816 | private int counter = 0; | ||
1817 | private static final int SSLIMIT=18; | ||
1818 | private static final int SBLIMIT=32; | ||
1819 | // Size of the table of whole numbers raised to 4/3 power. | ||
1820 | // This may be adjusted for performance without any problems. | ||
1821 | //public static final int POW_TABLE_LIMIT=512; | ||
1822 | |||
1823 | /************************************************************/ | ||
1824 | /* L3TABLE */ | ||
1825 | /************************************************************/ | ||
1826 | |||
1827 | static class SBI | ||
1828 | { | ||
1829 | public int[] l; | ||
1830 | public int[] s; | ||
1831 | |||
1832 | public SBI() | ||
1833 | { | ||
1834 | l = new int[23]; | ||
1835 | s = new int[14]; | ||
1836 | } | ||
1837 | public SBI(int[] thel, int[] thes) | ||
1838 | { | ||
1839 | l = thel; | ||
1840 | s = thes; | ||
1841 | } | ||
1842 | } | ||
1843 | |||
1844 | static class gr_info_s | ||
1845 | { | ||
1846 | public int part2_3_length = 0; | ||
1847 | public int big_values = 0; | ||
1848 | public int global_gain = 0; | ||
1849 | public int scalefac_compress = 0; | ||
1850 | public int window_switching_flag = 0; | ||
1851 | public int block_type = 0; | ||
1852 | public int mixed_block_flag = 0; | ||
1853 | public int[] table_select; | ||
1854 | public int[] subblock_gain; | ||
1855 | public int region0_count = 0; | ||
1856 | public int region1_count = 0; | ||
1857 | public int preflag = 0; | ||
1858 | public int scalefac_scale = 0; | ||
1859 | public int count1table_select = 0; | ||
1860 | |||
1861 | /** | ||
1862 | * Dummy Constructor | ||
1863 | */ | ||
1864 | public gr_info_s() | ||
1865 | { | ||
1866 | table_select = new int[3]; | ||
1867 | subblock_gain = new int[3]; | ||
1868 | } | ||
1869 | } | ||
1870 | |||
1871 | static class temporaire | ||
1872 | { | ||
1873 | public int[] scfsi; | ||
1874 | public gr_info_s[] gr; | ||
1875 | |||
1876 | /** | ||
1877 | * Dummy Constructor | ||
1878 | */ | ||
1879 | public temporaire() | ||
1880 | { | ||
1881 | scfsi = new int[4]; | ||
1882 | gr = new gr_info_s[2]; | ||
1883 | gr[0] = new gr_info_s(); | ||
1884 | gr[1] = new gr_info_s(); | ||
1885 | } | ||
1886 | } | ||
1887 | |||
1888 | static class III_side_info_t | ||
1889 | { | ||
1890 | |||
1891 | public int main_data_begin = 0; | ||
1892 | public int private_bits = 0; | ||
1893 | public temporaire[] ch; | ||
1894 | /** | ||
1895 | * Dummy Constructor | ||
1896 | */ | ||
1897 | public III_side_info_t() | ||
1898 | { | ||
1899 | ch = new temporaire[2]; | ||
1900 | ch[0] = new temporaire(); | ||
1901 | ch[1] = new temporaire(); | ||
1902 | } | ||
1903 | } | ||
1904 | |||
1905 | static class temporaire2 | ||
1906 | { | ||
1907 | public int[] l; /* [cb] */ | ||
1908 | public int[][] s; /* [window][cb] */ | ||
1909 | |||
1910 | /** | ||
1911 | * Dummy Constructor | ||
1912 | */ | ||
1913 | public temporaire2() | ||
1914 | { | ||
1915 | l = new int[23]; | ||
1916 | s = new int[3][13]; | ||
1917 | } | ||
1918 | } | ||
1919 | //class III_scalefac_t | ||
1920 | //{ | ||
1921 | // public temporaire2[] tab; | ||
1922 | // /** | ||
1923 | // * Dummy Constructor | ||
1924 | // */ | ||
1925 | // public III_scalefac_t() | ||
1926 | // { | ||
1927 | // tab = new temporaire2[2]; | ||
1928 | // } | ||
1929 | //} | ||
1930 | |||
1931 | private static final int slen[][] = | ||
1932 | { | ||
1933 | {0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4}, | ||
1934 | {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3} | ||
1935 | }; | ||
1936 | |||
1937 | public static final int pretab[] = | ||
1938 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0}; | ||
1939 | |||
1940 | private SBI[] sfBandIndex; // Init in the constructor. | ||
1941 | |||
1942 | public static final float two_to_negative_half_pow[] = | ||
1943 | { 1.0000000000E+00f, 7.0710678119E-01f, 5.0000000000E-01f, 3.5355339059E-01f, | ||
1944 | 2.5000000000E-01f, 1.7677669530E-01f, 1.2500000000E-01f, 8.8388347648E-02f, | ||
1945 | 6.2500000000E-02f, 4.4194173824E-02f, 3.1250000000E-02f, 2.2097086912E-02f, | ||
1946 | 1.5625000000E-02f, 1.1048543456E-02f, 7.8125000000E-03f, 5.5242717280E-03f, | ||
1947 | 3.9062500000E-03f, 2.7621358640E-03f, 1.9531250000E-03f, 1.3810679320E-03f, | ||
1948 | 9.7656250000E-04f, 6.9053396600E-04f, 4.8828125000E-04f, 3.4526698300E-04f, | ||
1949 | 2.4414062500E-04f, 1.7263349150E-04f, 1.2207031250E-04f, 8.6316745750E-05f, | ||
1950 | 6.1035156250E-05f, 4.3158372875E-05f, 3.0517578125E-05f, 2.1579186438E-05f, | ||
1951 | 1.5258789062E-05f, 1.0789593219E-05f, 7.6293945312E-06f, 5.3947966094E-06f, | ||
1952 | 3.8146972656E-06f, 2.6973983047E-06f, 1.9073486328E-06f, 1.3486991523E-06f, | ||
1953 | 9.5367431641E-07f, 6.7434957617E-07f, 4.7683715820E-07f, 3.3717478809E-07f, | ||
1954 | 2.3841857910E-07f, 1.6858739404E-07f, 1.1920928955E-07f, 8.4293697022E-08f, | ||
1955 | 5.9604644775E-08f, 4.2146848511E-08f, 2.9802322388E-08f, 2.1073424255E-08f, | ||
1956 | 1.4901161194E-08f, 1.0536712128E-08f, 7.4505805969E-09f, 5.2683560639E-09f, | ||
1957 | 3.7252902985E-09f, 2.6341780319E-09f, 1.8626451492E-09f, 1.3170890160E-09f, | ||
1958 | 9.3132257462E-10f, 6.5854450798E-10f, 4.6566128731E-10f, 3.2927225399E-10f | ||
1959 | }; | ||
1960 | |||
1961 | |||
1962 | public static final float t_43[] = create_t_43(); | ||
1963 | |||
1964 | static private float[] create_t_43() | ||
1965 | { | ||
1966 | float[] t43 = new float[8192]; | ||
1967 | final double d43 = (4.0/3.0); | ||
1968 | |||
1969 | for (int i=0; i<8192; i++) | ||
1970 | { | ||
1971 | t43[i] = (float)Math.pow(i, d43); | ||
1972 | } | ||
1973 | return t43; | ||
1974 | } | ||
1975 | |||
1976 | public static final float io[][] = | ||
1977 | { | ||
1978 | { 1.0000000000E+00f, 8.4089641526E-01f, 7.0710678119E-01f, 5.9460355751E-01f, | ||
1979 | 5.0000000001E-01f, 4.2044820763E-01f, 3.5355339060E-01f, 2.9730177876E-01f, | ||
1980 | 2.5000000001E-01f, 2.1022410382E-01f, 1.7677669530E-01f, 1.4865088938E-01f, | ||
1981 | 1.2500000000E-01f, 1.0511205191E-01f, 8.8388347652E-02f, 7.4325444691E-02f, | ||
1982 | 6.2500000003E-02f, 5.2556025956E-02f, 4.4194173826E-02f, 3.7162722346E-02f, | ||
1983 | 3.1250000002E-02f, 2.6278012978E-02f, 2.2097086913E-02f, 1.8581361173E-02f, | ||
1984 | 1.5625000001E-02f, 1.3139006489E-02f, 1.1048543457E-02f, 9.2906805866E-03f, | ||
1985 | 7.8125000006E-03f, 6.5695032447E-03f, 5.5242717285E-03f, 4.6453402934E-03f }, | ||
1986 | { 1.0000000000E+00f, 7.0710678119E-01f, 5.0000000000E-01f, 3.5355339060E-01f, | ||
1987 | 2.5000000000E-01f, 1.7677669530E-01f, 1.2500000000E-01f, 8.8388347650E-02f, | ||
1988 | 6.2500000001E-02f, 4.4194173825E-02f, 3.1250000001E-02f, 2.2097086913E-02f, | ||
1989 | 1.5625000000E-02f, 1.1048543456E-02f, 7.8125000002E-03f, 5.5242717282E-03f, | ||
1990 | 3.9062500001E-03f, 2.7621358641E-03f, 1.9531250001E-03f, 1.3810679321E-03f, | ||
1991 | 9.7656250004E-04f, 6.9053396603E-04f, 4.8828125002E-04f, 3.4526698302E-04f, | ||
1992 | 2.4414062501E-04f, 1.7263349151E-04f, 1.2207031251E-04f, 8.6316745755E-05f, | ||
1993 | 6.1035156254E-05f, 4.3158372878E-05f, 3.0517578127E-05f, 2.1579186439E-05f } | ||
1994 | }; | ||
1995 | |||
1996 | |||
1997 | |||
1998 | public static final float TAN12[] = | ||
1999 | { | ||
2000 | 0.0f, 0.26794919f, 0.57735027f, 1.0f, | ||
2001 | 1.73205081f, 3.73205081f, 9.9999999e10f, -3.73205081f, | ||
2002 | -1.73205081f, -1.0f, -0.57735027f, -0.26794919f, | ||
2003 | 0.0f, 0.26794919f, 0.57735027f, 1.0f | ||
2004 | }; | ||
2005 | |||
2006 | // REVIEW: in java, the array lookup may well be slower than | ||
2007 | // the actual calculation | ||
2008 | // 576 / 18 | ||
2009 | /* | ||
2010 | private static final int ss_div[] = | ||
2011 | { | ||
2012 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
2013 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | ||
2014 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | ||
2015 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | ||
2016 | 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, | ||
2017 | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, | ||
2018 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, | ||
2019 | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, | ||
2020 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, | ||
2021 | 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, | ||
2022 | 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, | ||
2023 | 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, | ||
2024 | 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, | ||
2025 | 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, | ||
2026 | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, | ||
2027 | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, | ||
2028 | 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, | ||
2029 | 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, | ||
2030 | 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, | ||
2031 | 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, | ||
2032 | 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, | ||
2033 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, | ||
2034 | 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, | ||
2035 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, | ||
2036 | 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, | ||
2037 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, | ||
2038 | 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, | ||
2039 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, | ||
2040 | 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, | ||
2041 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, | ||
2042 | 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, | ||
2043 | 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 | ||
2044 | }; | ||
2045 | |||
2046 | // 576 % 18 | ||
2047 | private static final int ss_mod[] = | ||
2048 | { | ||
2049 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2050 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2051 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2052 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2053 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2054 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2055 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2056 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2057 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2058 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2059 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2060 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2061 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2062 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2063 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2064 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2065 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2066 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2067 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2068 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2069 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2070 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2071 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2072 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2073 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2074 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2075 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2076 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2077 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2078 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2079 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, | ||
2080 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 | ||
2081 | }; | ||
2082 | */ | ||
2083 | private static /*final*/ int reorder_table[][]/* = loadReorderTable()*/; // SZD: will be generated on demand | ||
2084 | |||
2085 | /** | ||
2086 | * Loads the data for the reorder | ||
2087 | */ | ||
2088 | /*private static int[][] loadReorderTable() // SZD: table will be generated | ||
2089 | { | ||
2090 | try | ||
2091 | { | ||
2092 | Class elemType = int[][].class.getComponentType(); | ||
2093 | Object o = JavaLayerUtils.deserializeArrayResource("l3reorder.ser", elemType, 6); | ||
2094 | return (int[][])o; | ||
2095 | } | ||
2096 | catch (IOException ex) | ||
2097 | { | ||
2098 | throw new ExceptionInInitializerError(ex); | ||
2099 | } | ||
2100 | }*/ | ||
2101 | |||
2102 | static int[] reorder(int scalefac_band[]) { // SZD: converted from LAME | ||
2103 | int j = 0; | ||
2104 | int ix[] = new int[576]; | ||
2105 | for(int sfb = 0; sfb < 13; sfb++) { | ||
2106 | int start = scalefac_band[sfb]; | ||
2107 | int end = scalefac_band[sfb + 1]; | ||
2108 | for(int window = 0; window < 3; window++) | ||
2109 | for(int i = start; i < end; i++) | ||
2110 | ix[3 * i + window] = j++; | ||
2111 | } | ||
2112 | return ix; | ||
2113 | } | ||
2114 | |||
2115 | /*static final int reorder_table_data[][]; = | ||
2116 | { | ||
2117 | { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, 12, 16, 20, 13, | ||
2118 | 17, 21, 14, 18, 22, 15, 19, 23, 24, 28, 32, 25, 29, 33, 26, 30, | ||
2119 | 34, 27, 31, 35, 36, 42, 48, 37, 43, 49, 38, 44, 50, 39, 45, 51, | ||
2120 | 40, 46, 52, 41, 47, 53, 54, 60, 66, 55, 61, 67, 56, 62, 68, 57, | ||
2121 | 63, 69, 58, 64, 70, 59, 65, 71, 72, 80, 88, 73, 81, 89, 74, 82, | ||
2122 | 90, 75, 83, 91, 76, 84, 92, 77, 85, 93, 78, 86, 94, 79, 87, 95, | ||
2123 | 96,106,116, 97,107,117, 98,108,118, 99,109,119,100,110,120,101, | ||
2124 | 111,121,102,112,122,103,113,123,104,114,124,105,115,125,126,140, | ||
2125 | 154,127,141,155,128,142,156,129,143,157,130,144,158,131,145,159, | ||
2126 | 132,146,160,133,147,161,134,148,162,135,149,163,136,150,164,137, | ||
2127 | 151,165,138,152,166,139,153,167,168,186,204,169,187,205,170,188, | ||
2128 | 206,171,189,207,172,190,208,173,191,209,174,192,210,175,193,211, | ||
2129 | 176,194,212,177,195,213,178,196,214,179,197,215,180,198,216,181, | ||
2130 | 199,217,182,200,218,183,201,219,184,202,220,185,203,221,222,248, | ||
2131 | 274,223,249,275,224,250,276,225,251,277,226,252,278,227,253,279, | ||
2132 | 228,254,280,229,255,281,230,256,282,231,257,283,232,258,284,233, | ||
2133 | 259,285,234,260,286,235,261,287,236,262,288,237,263,289,238,264, | ||
2134 | 290,239,265,291,240,266,292,241,267,293,242,268,294,243,269,295, | ||
2135 | 244,270,296,245,271,297,246,272,298,247,273,299,300,332,364,301, | ||
2136 | 333,365,302,334,366,303,335,367,304,336,368,305,337,369,306,338, | ||
2137 | 370,307,339,371,308,340,372,309,341,373,310,342,374,311,343,375, | ||
2138 | 312,344,376,313,345,377,314,346,378,315,347,379,316,348,380,317, | ||
2139 | 349,381,318,350,382,319,351,383,320,352,384,321,353,385,322,354, | ||
2140 | 386,323,355,387,324,356,388,325,357,389,326,358,390,327,359,391, | ||
2141 | 328,360,392,329,361,393,330,362,394,331,363,395,396,438,480,397, | ||
2142 | 439,481,398,440,482,399,441,483,400,442,484,401,443,485,402,444, | ||
2143 | 486,403,445,487,404,446,488,405,447,489,406,448,490,407,449,491, | ||
2144 | 408,450,492,409,451,493,410,452,494,411,453,495,412,454,496,413, | ||
2145 | 455,497,414,456,498,415,457,499,416,458,500,417,459,501,418,460, | ||
2146 | 502,419,461,503,420,462,504,421,463,505,422,464,506,423,465,507, | ||
2147 | 424,466,508,425,467,509,426,468,510,427,469,511,428,470,512,429, | ||
2148 | 471,513,430,472,514,431,473,515,432,474,516,433,475,517,434,476, | ||
2149 | 518,435,477,519,436,478,520,437,479,521,522,540,558,523,541,559, | ||
2150 | 524,542,560,525,543,561,526,544,562,527,545,563,528,546,564,529, | ||
2151 | 547,565,530,548,566,531,549,567,532,550,568,533,551,569,534,552, | ||
2152 | 570,535,553,571,536,554,572,537,555,573,538,556,574,539,557,575}, | ||
2153 | { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, 12, 16, 20, 13, | ||
2154 | 17, 21, 14, 18, 22, 15, 19, 23, 24, 28, 32, 25, 29, 33, 26, 30, | ||
2155 | 34, 27, 31, 35, 36, 42, 48, 37, 43, 49, 38, 44, 50, 39, 45, 51, | ||
2156 | 40, 46, 52, 41, 47, 53, 54, 62, 70, 55, 63, 71, 56, 64, 72, 57, | ||
2157 | 65, 73, 58, 66, 74, 59, 67, 75, 60, 68, 76, 61, 69, 77, 78, 88, | ||
2158 | 98, 79, 89, 99, 80, 90,100, 81, 91,101, 82, 92,102, 83, 93,103, | ||
2159 | 84, 94,104, 85, 95,105, 86, 96,106, 87, 97,107,108,120,132,109, | ||
2160 | 121,133,110,122,134,111,123,135,112,124,136,113,125,137,114,126, | ||
2161 | 138,115,127,139,116,128,140,117,129,141,118,130,142,119,131,143, | ||
2162 | 144,158,172,145,159,173,146,160,174,147,161,175,148,162,176,149, | ||
2163 | 163,177,150,164,178,151,165,179,152,166,180,153,167,181,154,168, | ||
2164 | 182,155,169,183,156,170,184,157,171,185,186,204,222,187,205,223, | ||
2165 | 188,206,224,189,207,225,190,208,226,191,209,227,192,210,228,193, | ||
2166 | 211,229,194,212,230,195,213,231,196,214,232,197,215,233,198,216, | ||
2167 | 234,199,217,235,200,218,236,201,219,237,202,220,238,203,221,239, | ||
2168 | 240,264,288,241,265,289,242,266,290,243,267,291,244,268,292,245, | ||
2169 | 269,293,246,270,294,247,271,295,248,272,296,249,273,297,250,274, | ||
2170 | 298,251,275,299,252,276,300,253,277,301,254,278,302,255,279,303, | ||
2171 | 256,280,304,257,281,305,258,282,306,259,283,307,260,284,308,261, | ||
2172 | 285,309,262,286,310,263,287,311,312,344,376,313,345,377,314,346, | ||
2173 | 378,315,347,379,316,348,380,317,349,381,318,350,382,319,351,383, | ||
2174 | 320,352,384,321,353,385,322,354,386,323,355,387,324,356,388,325, | ||
2175 | 357,389,326,358,390,327,359,391,328,360,392,329,361,393,330,362, | ||
2176 | 394,331,363,395,332,364,396,333,365,397,334,366,398,335,367,399, | ||
2177 | 336,368,400,337,369,401,338,370,402,339,371,403,340,372,404,341, | ||
2178 | 373,405,342,374,406,343,375,407,408,452,496,409,453,497,410,454, | ||
2179 | 498,411,455,499,412,456,500,413,457,501,414,458,502,415,459,503, | ||
2180 | 416,460,504,417,461,505,418,462,506,419,463,507,420,464,508,421, | ||
2181 | 465,509,422,466,510,423,467,511,424,468,512,425,469,513,426,470, | ||
2182 | 514,427,471,515,428,472,516,429,473,517,430,474,518,431,475,519, | ||
2183 | 432,476,520,433,477,521,434,478,522,435,479,523,436,480,524,437, | ||
2184 | 481,525,438,482,526,439,483,527,440,484,528,441,485,529,442,486, | ||
2185 | 530,443,487,531,444,488,532,445,489,533,446,490,534,447,491,535, | ||
2186 | 448,492,536,449,493,537,450,494,538,451,495,539,540,552,564,541, | ||
2187 | 553,565,542,554,566,543,555,567,544,556,568,545,557,569,546,558, | ||
2188 | 570,547,559,571,548,560,572,549,561,573,550,562,574,551,563,575}, | ||
2189 | { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, 12, 16, 20, 13, | ||
2190 | 17, 21, 14, 18, 22, 15, 19, 23, 24, 28, 32, 25, 29, 33, 26, 30, | ||
2191 | 34, 27, 31, 35, 36, 42, 48, 37, 43, 49, 38, 44, 50, 39, 45, 51, | ||
2192 | 40, 46, 52, 41, 47, 53, 54, 62, 70, 55, 63, 71, 56, 64, 72, 57, | ||
2193 | 65, 73, 58, 66, 74, 59, 67, 75, 60, 68, 76, 61, 69, 77, 78, 88, | ||
2194 | 98, 79, 89, 99, 80, 90,100, 81, 91,101, 82, 92,102, 83, 93,103, | ||
2195 | 84, 94,104, 85, 95,105, 86, 96,106, 87, 97,107,108,120,132,109, | ||
2196 | 121,133,110,122,134,111,123,135,112,124,136,113,125,137,114,126, | ||
2197 | 138,115,127,139,116,128,140,117,129,141,118,130,142,119,131,143, | ||
2198 | 144,158,172,145,159,173,146,160,174,147,161,175,148,162,176,149, | ||
2199 | 163,177,150,164,178,151,165,179,152,166,180,153,167,181,154,168, | ||
2200 | 182,155,169,183,156,170,184,157,171,185,186,204,222,187,205,223, | ||
2201 | 188,206,224,189,207,225,190,208,226,191,209,227,192,210,228,193, | ||
2202 | 211,229,194,212,230,195,213,231,196,214,232,197,215,233,198,216, | ||
2203 | 234,199,217,235,200,218,236,201,219,237,202,220,238,203,221,239, | ||
2204 | 240,264,288,241,265,289,242,266,290,243,267,291,244,268,292,245, | ||
2205 | 269,293,246,270,294,247,271,295,248,272,296,249,273,297,250,274, | ||
2206 | 298,251,275,299,252,276,300,253,277,301,254,278,302,255,279,303, | ||
2207 | 256,280,304,257,281,305,258,282,306,259,283,307,260,284,308,261, | ||
2208 | 285,309,262,286,310,263,287,311,312,342,372,313,343,373,314,344, | ||
2209 | 374,315,345,375,316,346,376,317,347,377,318,348,378,319,349,379, | ||
2210 | 320,350,380,321,351,381,322,352,382,323,353,383,324,354,384,325, | ||
2211 | 355,385,326,356,386,327,357,387,328,358,388,329,359,389,330,360, | ||
2212 | 390,331,361,391,332,362,392,333,363,393,334,364,394,335,365,395, | ||
2213 | 336,366,396,337,367,397,338,368,398,339,369,399,340,370,400,341, | ||
2214 | 371,401,402,442,482,403,443,483,404,444,484,405,445,485,406,446, | ||
2215 | 486,407,447,487,408,448,488,409,449,489,410,450,490,411,451,491, | ||
2216 | 412,452,492,413,453,493,414,454,494,415,455,495,416,456,496,417, | ||
2217 | 457,497,418,458,498,419,459,499,420,460,500,421,461,501,422,462, | ||
2218 | 502,423,463,503,424,464,504,425,465,505,426,466,506,427,467,507, | ||
2219 | 428,468,508,429,469,509,430,470,510,431,471,511,432,472,512,433, | ||
2220 | 473,513,434,474,514,435,475,515,436,476,516,437,477,517,438,478, | ||
2221 | 518,439,479,519,440,480,520,441,481,521,522,540,558,523,541,559, | ||
2222 | 524,542,560,525,543,561,526,544,562,527,545,563,528,546,564,529, | ||
2223 | 547,565,530,548,566,531,549,567,532,550,568,533,551,569,534,552, | ||
2224 | 570,535,553,571,536,554,572,537,555,573,538,556,574,539,557,575}, | ||
2225 | { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, 12, 16, 20, 13, | ||
2226 | 17, 21, 14, 18, 22, 15, 19, 23, 24, 28, 32, 25, 29, 33, 26, 30, | ||
2227 | 34, 27, 31, 35, 36, 40, 44, 37, 41, 45, 38, 42, 46, 39, 43, 47, | ||
2228 | 48, 54, 60, 49, 55, 61, 50, 56, 62, 51, 57, 63, 52, 58, 64, 53, | ||
2229 | 59, 65, 66, 74, 82, 67, 75, 83, 68, 76, 84, 69, 77, 85, 70, 78, | ||
2230 | 86, 71, 79, 87, 72, 80, 88, 73, 81, 89, 90,100,110, 91,101,111, | ||
2231 | 92,102,112, 93,103,113, 94,104,114, 95,105,115, 96,106,116, 97, | ||
2232 | 107,117, 98,108,118, 99,109,119,120,132,144,121,133,145,122,134, | ||
2233 | 146,123,135,147,124,136,148,125,137,149,126,138,150,127,139,151, | ||
2234 | 128,140,152,129,141,153,130,142,154,131,143,155,156,170,184,157, | ||
2235 | 171,185,158,172,186,159,173,187,160,174,188,161,175,189,162,176, | ||
2236 | 190,163,177,191,164,178,192,165,179,193,166,180,194,167,181,195, | ||
2237 | 168,182,196,169,183,197,198,216,234,199,217,235,200,218,236,201, | ||
2238 | 219,237,202,220,238,203,221,239,204,222,240,205,223,241,206,224, | ||
2239 | 242,207,225,243,208,226,244,209,227,245,210,228,246,211,229,247, | ||
2240 | 212,230,248,213,231,249,214,232,250,215,233,251,252,274,296,253, | ||
2241 | 275,297,254,276,298,255,277,299,256,278,300,257,279,301,258,280, | ||
2242 | 302,259,281,303,260,282,304,261,283,305,262,284,306,263,285,307, | ||
2243 | 264,286,308,265,287,309,266,288,310,267,289,311,268,290,312,269, | ||
2244 | 291,313,270,292,314,271,293,315,272,294,316,273,295,317,318,348, | ||
2245 | 378,319,349,379,320,350,380,321,351,381,322,352,382,323,353,383, | ||
2246 | 324,354,384,325,355,385,326,356,386,327,357,387,328,358,388,329, | ||
2247 | 359,389,330,360,390,331,361,391,332,362,392,333,363,393,334,364, | ||
2248 | 394,335,365,395,336,366,396,337,367,397,338,368,398,339,369,399, | ||
2249 | 340,370,400,341,371,401,342,372,402,343,373,403,344,374,404,345, | ||
2250 | 375,405,346,376,406,347,377,407,408,464,520,409,465,521,410,466, | ||
2251 | 522,411,467,523,412,468,524,413,469,525,414,470,526,415,471,527, | ||
2252 | 416,472,528,417,473,529,418,474,530,419,475,531,420,476,532,421, | ||
2253 | 477,533,422,478,534,423,479,535,424,480,536,425,481,537,426,482, | ||
2254 | 538,427,483,539,428,484,540,429,485,541,430,486,542,431,487,543, | ||
2255 | 432,488,544,433,489,545,434,490,546,435,491,547,436,492,548,437, | ||
2256 | 493,549,438,494,550,439,495,551,440,496,552,441,497,553,442,498, | ||
2257 | 554,443,499,555,444,500,556,445,501,557,446,502,558,447,503,559, | ||
2258 | 448,504,560,449,505,561,450,506,562,451,507,563,452,508,564,453, | ||
2259 | 509,565,454,510,566,455,511,567,456,512,568,457,513,569,458,514, | ||
2260 | 570,459,515,571,460,516,572,461,517,573,462,518,574,463,519,575}, | ||
2261 | { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, 12, 16, 20, 13, | ||
2262 | 17, 21, 14, 18, 22, 15, 19, 23, 24, 28, 32, 25, 29, 33, 26, 30, | ||
2263 | 34, 27, 31, 35, 36, 40, 44, 37, 41, 45, 38, 42, 46, 39, 43, 47, | ||
2264 | 48, 54, 60, 49, 55, 61, 50, 56, 62, 51, 57, 63, 52, 58, 64, 53, | ||
2265 | 59, 65, 66, 72, 78, 67, 73, 79, 68, 74, 80, 69, 75, 81, 70, 76, | ||
2266 | 82, 71, 77, 83, 84, 94,104, 85, 95,105, 86, 96,106, 87, 97,107, | ||
2267 | 88, 98,108, 89, 99,109, 90,100,110, 91,101,111, 92,102,112, 93, | ||
2268 | 103,113,114,126,138,115,127,139,116,128,140,117,129,141,118,130, | ||
2269 | 142,119,131,143,120,132,144,121,133,145,122,134,146,123,135,147, | ||
2270 | 124,136,148,125,137,149,150,164,178,151,165,179,152,166,180,153, | ||
2271 | 167,181,154,168,182,155,169,183,156,170,184,157,171,185,158,172, | ||
2272 | 186,159,173,187,160,174,188,161,175,189,162,176,190,163,177,191, | ||
2273 | 192,208,224,193,209,225,194,210,226,195,211,227,196,212,228,197, | ||
2274 | 213,229,198,214,230,199,215,231,200,216,232,201,217,233,202,218, | ||
2275 | 234,203,219,235,204,220,236,205,221,237,206,222,238,207,223,239, | ||
2276 | 240,260,280,241,261,281,242,262,282,243,263,283,244,264,284,245, | ||
2277 | 265,285,246,266,286,247,267,287,248,268,288,249,269,289,250,270, | ||
2278 | 290,251,271,291,252,272,292,253,273,293,254,274,294,255,275,295, | ||
2279 | 256,276,296,257,277,297,258,278,298,259,279,299,300,326,352,301, | ||
2280 | 327,353,302,328,354,303,329,355,304,330,356,305,331,357,306,332, | ||
2281 | 358,307,333,359,308,334,360,309,335,361,310,336,362,311,337,363, | ||
2282 | 312,338,364,313,339,365,314,340,366,315,341,367,316,342,368,317, | ||
2283 | 343,369,318,344,370,319,345,371,320,346,372,321,347,373,322,348, | ||
2284 | 374,323,349,375,324,350,376,325,351,377,378,444,510,379,445,511, | ||
2285 | 380,446,512,381,447,513,382,448,514,383,449,515,384,450,516,385, | ||
2286 | 451,517,386,452,518,387,453,519,388,454,520,389,455,521,390,456, | ||
2287 | 522,391,457,523,392,458,524,393,459,525,394,460,526,395,461,527, | ||
2288 | 396,462,528,397,463,529,398,464,530,399,465,531,400,466,532,401, | ||
2289 | 467,533,402,468,534,403,469,535,404,470,536,405,471,537,406,472, | ||
2290 | 538,407,473,539,408,474,540,409,475,541,410,476,542,411,477,543, | ||
2291 | 412,478,544,413,479,545,414,480,546,415,481,547,416,482,548,417, | ||
2292 | 483,549,418,484,550,419,485,551,420,486,552,421,487,553,422,488, | ||
2293 | 554,423,489,555,424,490,556,425,491,557,426,492,558,427,493,559, | ||
2294 | 428,494,560,429,495,561,430,496,562,431,497,563,432,498,564,433, | ||
2295 | 499,565,434,500,566,435,501,567,436,502,568,437,503,569,438,504, | ||
2296 | 570,439,505,571,440,506,572,441,507,573,442,508,574,443,509,575}, | ||
2297 | { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11, 12, 16, 20, 13, | ||
2298 | 17, 21, 14, 18, 22, 15, 19, 23, 24, 28, 32, 25, 29, 33, 26, 30, | ||
2299 | 34, 27, 31, 35, 36, 40, 44, 37, 41, 45, 38, 42, 46, 39, 43, 47, | ||
2300 | 48, 54, 60, 49, 55, 61, 50, 56, 62, 51, 57, 63, 52, 58, 64, 53, | ||
2301 | 59, 65, 66, 74, 82, 67, 75, 83, 68, 76, 84, 69, 77, 85, 70, 78, | ||
2302 | 86, 71, 79, 87, 72, 80, 88, 73, 81, 89, 90,102,114, 91,103,115, | ||
2303 | 92,104,116, 93,105,117, 94,106,118, 95,107,119, 96,108,120, 97, | ||
2304 | 109,121, 98,110,122, 99,111,123,100,112,124,101,113,125,126,142, | ||
2305 | 158,127,143,159,128,144,160,129,145,161,130,146,162,131,147,163, | ||
2306 | 132,148,164,133,149,165,134,150,166,135,151,167,136,152,168,137, | ||
2307 | 153,169,138,154,170,139,155,171,140,156,172,141,157,173,174,194, | ||
2308 | 214,175,195,215,176,196,216,177,197,217,178,198,218,179,199,219, | ||
2309 | 180,200,220,181,201,221,182,202,222,183,203,223,184,204,224,185, | ||
2310 | 205,225,186,206,226,187,207,227,188,208,228,189,209,229,190,210, | ||
2311 | 230,191,211,231,192,212,232,193,213,233,234,260,286,235,261,287, | ||
2312 | 236,262,288,237,263,289,238,264,290,239,265,291,240,266,292,241, | ||
2313 | 267,293,242,268,294,243,269,295,244,270,296,245,271,297,246,272, | ||
2314 | 298,247,273,299,248,274,300,249,275,301,250,276,302,251,277,303, | ||
2315 | 252,278,304,253,279,305,254,280,306,255,281,307,256,282,308,257, | ||
2316 | 283,309,258,284,310,259,285,311,312,346,380,313,347,381,314,348, | ||
2317 | 382,315,349,383,316,350,384,317,351,385,318,352,386,319,353,387, | ||
2318 | 320,354,388,321,355,389,322,356,390,323,357,391,324,358,392,325, | ||
2319 | 359,393,326,360,394,327,361,395,328,362,396,329,363,397,330,364, | ||
2320 | 398,331,365,399,332,366,400,333,367,401,334,368,402,335,369,403, | ||
2321 | 336,370,404,337,371,405,338,372,406,339,373,407,340,374,408,341, | ||
2322 | 375,409,342,376,410,343,377,411,344,378,412,345,379,413,414,456, | ||
2323 | 498,415,457,499,416,458,500,417,459,501,418,460,502,419,461,503, | ||
2324 | 420,462,504,421,463,505,422,464,506,423,465,507,424,466,508,425, | ||
2325 | 467,509,426,468,510,427,469,511,428,470,512,429,471,513,430,472, | ||
2326 | 514,431,473,515,432,474,516,433,475,517,434,476,518,435,477,519, | ||
2327 | 436,478,520,437,479,521,438,480,522,439,481,523,440,482,524,441, | ||
2328 | 483,525,442,484,526,443,485,527,444,486,528,445,487,529,446,488, | ||
2329 | 530,447,489,531,448,490,532,449,491,533,450,492,534,451,493,535, | ||
2330 | 452,494,536,453,495,537,454,496,538,455,497,539,540,552,564,541, | ||
2331 | 553,565,542,554,566,543,555,567,544,556,568,545,557,569,546,558, | ||
2332 | 570,547,559,571,548,560,572,549,561,573,550,562,574,551,563,575} | ||
2333 | }; | ||
2334 | */ | ||
2335 | |||
2336 | private static final float cs[] = | ||
2337 | { | ||
2338 | 0.857492925712f, 0.881741997318f, 0.949628649103f, 0.983314592492f, | ||
2339 | 0.995517816065f, 0.999160558175f, 0.999899195243f, 0.999993155067f | ||
2340 | }; | ||
2341 | |||
2342 | private static final float ca[] = | ||
2343 | { | ||
2344 | -0.5144957554270f, -0.4717319685650f, -0.3133774542040f, -0.1819131996110f, | ||
2345 | -0.0945741925262f, -0.0409655828852f, -0.0141985685725f, -0.00369997467375f | ||
2346 | }; | ||
2347 | |||
2348 | /************************************************************/ | ||
2349 | /* END OF L3TABLE */ | ||
2350 | /************************************************************/ | ||
2351 | |||
2352 | /************************************************************/ | ||
2353 | /* L3TYPE */ | ||
2354 | /************************************************************/ | ||
2355 | |||
2356 | |||
2357 | /***************************************************************/ | ||
2358 | /* END OF L3TYPE */ | ||
2359 | /***************************************************************/ | ||
2360 | |||
2361 | /***************************************************************/ | ||
2362 | /* INV_MDCT */ | ||
2363 | /***************************************************************/ | ||
2364 | public static final float win[][] = | ||
2365 | { | ||
2366 | { -1.6141214951E-02f, -5.3603178919E-02f, -1.0070713296E-01f, -1.6280817573E-01f, | ||
2367 | -4.9999999679E-01f, -3.8388735032E-01f, -6.2061144372E-01f, -1.1659756083E+00f, | ||
2368 | -3.8720752656E+00f, -4.2256286556E+00f, -1.5195289984E+00f, -9.7416483388E-01f, | ||
2369 | -7.3744074053E-01f, -1.2071067773E+00f, -5.1636156596E-01f, -4.5426052317E-01f, | ||
2370 | -4.0715656898E-01f, -3.6969460527E-01f, -3.3876269197E-01f, -3.1242222492E-01f, | ||
2371 | -2.8939587111E-01f, -2.6880081906E-01f, -5.0000000266E-01f, -2.3251417468E-01f, | ||
2372 | -2.1596714708E-01f, -2.0004979098E-01f, -1.8449493497E-01f, -1.6905846094E-01f, | ||
2373 | -1.5350360518E-01f, -1.3758624925E-01f, -1.2103922149E-01f, -2.0710679058E-01f, | ||
2374 | -8.4752577594E-02f, -6.4157525656E-02f, -4.1131172614E-02f, -1.4790705759E-02f }, | ||
2375 | |||
2376 | { -1.6141214951E-02f, -5.3603178919E-02f, -1.0070713296E-01f, -1.6280817573E-01f, | ||
2377 | -4.9999999679E-01f, -3.8388735032E-01f, -6.2061144372E-01f, -1.1659756083E+00f, | ||
2378 | -3.8720752656E+00f, -4.2256286556E+00f, -1.5195289984E+00f, -9.7416483388E-01f, | ||
2379 | -7.3744074053E-01f, -1.2071067773E+00f, -5.1636156596E-01f, -4.5426052317E-01f, | ||
2380 | -4.0715656898E-01f, -3.6969460527E-01f, -3.3908542600E-01f, -3.1511810350E-01f, | ||
2381 | -2.9642226150E-01f, -2.8184548650E-01f, -5.4119610000E-01f, -2.6213228100E-01f, | ||
2382 | -2.5387916537E-01f, -2.3296291359E-01f, -1.9852728987E-01f, -1.5233534808E-01f, | ||
2383 | -9.6496400054E-02f, -3.3423828516E-02f, 0.0000000000E+00f, 0.0000000000E+00f, | ||
2384 | 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f }, | ||
2385 | |||
2386 | { -4.8300800645E-02f, -1.5715656932E-01f, -2.8325045177E-01f, -4.2953747763E-01f, | ||
2387 | -1.2071067795E+00f, -8.2426483178E-01f, -1.1451749106E+00f, -1.7695290101E+00f, | ||
2388 | -4.5470225061E+00f, -3.4890531002E+00f, -7.3296292804E-01f, -1.5076514758E-01f, | ||
2389 | 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, | ||
2390 | 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, | ||
2391 | 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, | ||
2392 | 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, | ||
2393 | 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, | ||
2394 | 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f }, | ||
2395 | |||
2396 | { 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, 0.0000000000E+00f, | ||
2397 | 0.0000000000E+00f, 0.0000000000E+00f, -1.5076513660E-01f, -7.3296291107E-01f, | ||
2398 | -3.4890530566E+00f, -4.5470224727E+00f, -1.7695290031E+00f, -1.1451749092E+00f, | ||
2399 | -8.3137738100E-01f, -1.3065629650E+00f, -5.4142014250E-01f, -4.6528974900E-01f, | ||
2400 | -4.1066990750E-01f, -3.7004680800E-01f, -3.3876269197E-01f, -3.1242222492E-01f, | ||
2401 | -2.8939587111E-01f, -2.6880081906E-01f, -5.0000000266E-01f, -2.3251417468E-01f, | ||
2402 | -2.1596714708E-01f, -2.0004979098E-01f, -1.8449493497E-01f, -1.6905846094E-01f, | ||
2403 | -1.5350360518E-01f, -1.3758624925E-01f, -1.2103922149E-01f, -2.0710679058E-01f, | ||
2404 | -8.4752577594E-02f, -6.4157525656E-02f, -4.1131172614E-02f, -1.4790705759E-02f } | ||
2405 | }; | ||
2406 | /***************************************************************/ | ||
2407 | /* END OF INV_MDCT */ | ||
2408 | /***************************************************************/ | ||
2409 | |||
2410 | class Sftable | ||
2411 | { | ||
2412 | public int[] l; | ||
2413 | public int[] s; | ||
2414 | |||
2415 | public Sftable() | ||
2416 | { | ||
2417 | l = new int[5]; | ||
2418 | s = new int[3]; | ||
2419 | } | ||
2420 | |||
2421 | public Sftable(int[] thel, int[] thes) | ||
2422 | { | ||
2423 | l = thel; | ||
2424 | s = thes; | ||
2425 | } | ||
2426 | } | ||
2427 | |||
2428 | public Sftable sftable; | ||
2429 | |||
2430 | public static final int nr_of_sfb_block[][][] = | ||
2431 | {{{ 6, 5, 5, 5} , { 9, 9, 9, 9} , { 6, 9, 9, 9}}, | ||
2432 | {{ 6, 5, 7, 3} , { 9, 9,12, 6} , { 6, 9,12, 6}}, | ||
2433 | {{11,10, 0, 0} , {18,18, 0, 0} , {15,18, 0, 0}}, | ||
2434 | {{ 7, 7, 7, 0} , {12,12,12, 0} , { 6,15,12, 0}}, | ||
2435 | {{ 6, 6, 6, 3} , {12, 9, 9, 6} , { 6,12, 9, 6}}, | ||
2436 | {{ 8, 8, 5, 0} , {15,12, 9, 0} , { 6,18, 9, 0}}}; | ||
2437 | |||
2438 | |||
2439 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/Manager.java b/songdbj/javazoom/jl/decoder/Manager.java new file mode 100644 index 0000000000..f566a232e7 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Manager.java | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | *----------------------------------------------------------------------- | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Library General Public License as published | ||
6 | * by the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library General Public | ||
15 | * License along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | *---------------------------------------------------------------------- | ||
18 | */ | ||
19 | |||
20 | package javazoom.jl.decoder; | ||
21 | |||
22 | /** | ||
23 | * Work in progress. | ||
24 | * | ||
25 | * Manages a number of controls. | ||
26 | */ | ||
27 | public class Manager //implements Control | ||
28 | { | ||
29 | public void addControl(Control c) | ||
30 | { | ||
31 | |||
32 | } | ||
33 | |||
34 | public void removeControl(Control c) | ||
35 | { | ||
36 | |||
37 | } | ||
38 | |||
39 | public void removeAll() | ||
40 | { | ||
41 | |||
42 | } | ||
43 | |||
44 | // control interface delegates to a managed control | ||
45 | |||
46 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/Obuffer.java b/songdbj/javazoom/jl/decoder/Obuffer.java new file mode 100644 index 0000000000..45a71a9baf --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Obuffer.java | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Added appendSamples() method for efficiency. MDM. | ||
4 | * 15/02/99 ,Java Conversion by E.B ,ebsp@iname.com, JavaLayer | ||
5 | * | ||
6 | * Declarations for output buffer, includes operating system | ||
7 | * implementation of the virtual Obuffer. Optional routines | ||
8 | * enabling seeks and stops added by Jeff Tsay. | ||
9 | * | ||
10 | * @(#) obuffer.h 1.8, last edit: 6/15/94 16:51:56 | ||
11 | * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de) | ||
12 | * @(#) Berlin University of Technology | ||
13 | * | ||
14 | * Idea and first implementation for u-law output with fast downsampling by | ||
15 | * Jim Boucher (jboucher@flash.bu.edu) | ||
16 | * | ||
17 | * LinuxObuffer class written by | ||
18 | * Louis P. Kruger (lpkruger@phoenix.princeton.edu) | ||
19 | *----------------------------------------------------------------------- | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU Library General Public License as published | ||
22 | * by the Free Software Foundation; either version 2 of the License, or | ||
23 | * (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU Library General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU Library General Public | ||
31 | * License along with this program; if not, write to the Free Software | ||
32 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
33 | *---------------------------------------------------------------------- | ||
34 | */ | ||
35 | package javazoom.jl.decoder; | ||
36 | |||
37 | /** | ||
38 | * Base Class for audio output. | ||
39 | */ | ||
40 | public abstract class Obuffer | ||
41 | { | ||
42 | public static final int OBUFFERSIZE = 2 * 1152; // max. 2 * 1152 samples per frame | ||
43 | public static final int MAXCHANNELS = 2; // max. number of channels | ||
44 | |||
45 | /** | ||
46 | * Takes a 16 Bit PCM sample. | ||
47 | */ | ||
48 | public abstract void append(int channel, short value); | ||
49 | |||
50 | /** | ||
51 | * Accepts 32 new PCM samples. | ||
52 | */ | ||
53 | public void appendSamples(int channel, float[] f) | ||
54 | { | ||
55 | short s; | ||
56 | for (int i=0; i<32;) | ||
57 | { | ||
58 | s = clip(f[i++]); | ||
59 | append(channel, s); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * Clip Sample to 16 Bits | ||
65 | */ | ||
66 | private final short clip(float sample) | ||
67 | { | ||
68 | return ((sample > 32767.0f) ? 32767 : | ||
69 | ((sample < -32768.0f) ? -32768 : | ||
70 | (short) sample)); | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Write the samples to the file or directly to the audio hardware. | ||
75 | */ | ||
76 | public abstract void write_buffer(int val); | ||
77 | public abstract void close(); | ||
78 | |||
79 | /** | ||
80 | * Clears all data in the buffer (for seeking). | ||
81 | */ | ||
82 | public abstract void clear_buffer(); | ||
83 | |||
84 | /** | ||
85 | * Notify the buffer that the user has stopped the stream. | ||
86 | */ | ||
87 | public abstract void set_stop_flag(); | ||
88 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/OutputChannels.java b/songdbj/javazoom/jl/decoder/OutputChannels.java new file mode 100644 index 0000000000..58c8310de7 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/OutputChannels.java | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 12/12/99 Initial implementation. mdm@techie.com. | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.decoder; | ||
22 | |||
23 | |||
24 | /** | ||
25 | * A Type-safe representation of the the supported output channel | ||
26 | * constants. | ||
27 | * | ||
28 | * This class is immutable and, hence, is thread safe. | ||
29 | * | ||
30 | * @author Mat McGowan 12/12/99 | ||
31 | * @since 0.0.7 | ||
32 | */ | ||
33 | public class OutputChannels | ||
34 | { | ||
35 | /** | ||
36 | * Flag to indicate output should include both channels. | ||
37 | */ | ||
38 | public static final int BOTH_CHANNELS = 0; | ||
39 | |||
40 | /** | ||
41 | * Flag to indicate output should include the left channel only. | ||
42 | */ | ||
43 | public static final int LEFT_CHANNEL = 1; | ||
44 | |||
45 | /** | ||
46 | * Flag to indicate output should include the right channel only. | ||
47 | */ | ||
48 | public static final int RIGHT_CHANNEL = 2; | ||
49 | |||
50 | /** | ||
51 | * Flag to indicate output is mono. | ||
52 | */ | ||
53 | public static final int DOWNMIX_CHANNELS = 3; | ||
54 | |||
55 | |||
56 | public static final OutputChannels LEFT = new OutputChannels(LEFT_CHANNEL); | ||
57 | public static final OutputChannels RIGHT = new OutputChannels(RIGHT_CHANNEL); | ||
58 | public static final OutputChannels BOTH = new OutputChannels(BOTH_CHANNELS); | ||
59 | public static final OutputChannels DOWNMIX = new OutputChannels(DOWNMIX_CHANNELS); | ||
60 | |||
61 | |||
62 | private /*final*/ int outputChannels; | ||
63 | |||
64 | /** | ||
65 | * Creates an <code>OutputChannels</code> instance | ||
66 | * corresponding to the given channel code. | ||
67 | * | ||
68 | * @param code one of the OutputChannels channel code constants. | ||
69 | * | ||
70 | * @throws IllegalArgumentException if code is not a valid | ||
71 | * channel code. | ||
72 | */ | ||
73 | static public OutputChannels fromInt(int code) | ||
74 | { | ||
75 | switch (code) | ||
76 | { | ||
77 | case LEFT_CHANNEL: | ||
78 | return LEFT; | ||
79 | case RIGHT_CHANNEL: | ||
80 | return RIGHT; | ||
81 | case BOTH_CHANNELS: | ||
82 | return BOTH; | ||
83 | case DOWNMIX_CHANNELS: | ||
84 | return DOWNMIX; | ||
85 | default: | ||
86 | throw new IllegalArgumentException("Invalid channel code: "+code); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | private OutputChannels(int channels) | ||
91 | { | ||
92 | outputChannels = channels; | ||
93 | |||
94 | if (channels<0 || channels>3) | ||
95 | throw new IllegalArgumentException("channels"); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * Retrieves the code representing the desired output channels. | ||
100 | * Will be one of LEFT_CHANNEL, RIGHT_CHANNEL, BOTH_CHANNELS | ||
101 | * or DOWNMIX_CHANNELS. | ||
102 | * | ||
103 | * @return the channel code represented by this instance. | ||
104 | */ | ||
105 | public int getChannelsOutputCode() | ||
106 | { | ||
107 | return outputChannels; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Retrieves the number of output channels represented | ||
112 | * by this channel output type. | ||
113 | * | ||
114 | * @return The number of output channels for this channel output | ||
115 | * type. This will be 2 for BOTH_CHANNELS only, and 1 | ||
116 | * for all other types. | ||
117 | */ | ||
118 | public int getChannelCount() | ||
119 | { | ||
120 | int count = (outputChannels==BOTH_CHANNELS) ? 2 : 1; | ||
121 | return count; | ||
122 | } | ||
123 | |||
124 | |||
125 | public boolean equals(Object o) | ||
126 | { | ||
127 | boolean equals = false; | ||
128 | |||
129 | if (o instanceof OutputChannels) | ||
130 | { | ||
131 | OutputChannels oc = (OutputChannels)o; | ||
132 | equals = (oc.outputChannels == outputChannels); | ||
133 | } | ||
134 | |||
135 | return equals; | ||
136 | } | ||
137 | |||
138 | public int hashCode() | ||
139 | { | ||
140 | return outputChannels; | ||
141 | } | ||
142 | |||
143 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/SampleBuffer.java b/songdbj/javazoom/jl/decoder/SampleBuffer.java new file mode 100644 index 0000000000..ba4bfa060f --- /dev/null +++ b/songdbj/javazoom/jl/decoder/SampleBuffer.java | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 12/12/99 Initial Version based on FileObuffer. mdm@techie.com. | ||
5 | * | ||
6 | * FileObuffer: | ||
7 | * 15/02/99 Java Conversion by E.B ,javalayer@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.jl.decoder; | ||
27 | |||
28 | /** | ||
29 | * The <code>SampleBuffer</code> class implements an output buffer | ||
30 | * that provides storage for a fixed size block of samples. | ||
31 | */ | ||
32 | public class SampleBuffer extends Obuffer | ||
33 | { | ||
34 | private short[] buffer; | ||
35 | private int[] bufferp; | ||
36 | private int channels; | ||
37 | private int frequency; | ||
38 | |||
39 | /** | ||
40 | * Constructor | ||
41 | */ | ||
42 | public SampleBuffer(int sample_frequency, int number_of_channels) | ||
43 | { | ||
44 | buffer = new short[OBUFFERSIZE]; | ||
45 | bufferp = new int[MAXCHANNELS]; | ||
46 | channels = number_of_channels; | ||
47 | frequency = sample_frequency; | ||
48 | |||
49 | for (int i = 0; i < number_of_channels; ++i) | ||
50 | bufferp[i] = (short)i; | ||
51 | |||
52 | } | ||
53 | |||
54 | public int getChannelCount() | ||
55 | { | ||
56 | return this.channels; | ||
57 | } | ||
58 | |||
59 | public int getSampleFrequency() | ||
60 | { | ||
61 | return this.frequency; | ||
62 | } | ||
63 | |||
64 | public short[] getBuffer() | ||
65 | { | ||
66 | return this.buffer; | ||
67 | } | ||
68 | |||
69 | public int getBufferLength() | ||
70 | { | ||
71 | return bufferp[0]; | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * Takes a 16 Bit PCM sample. | ||
76 | */ | ||
77 | public void append(int channel, short value) | ||
78 | { | ||
79 | buffer[bufferp[channel]] = value; | ||
80 | bufferp[channel] += channels; | ||
81 | } | ||
82 | |||
83 | public void appendSamples(int channel, float[] f) | ||
84 | { | ||
85 | int pos = bufferp[channel]; | ||
86 | |||
87 | short s; | ||
88 | float fs; | ||
89 | for (int i=0; i<32;) | ||
90 | { | ||
91 | fs = f[i++]; | ||
92 | fs = (fs>32767.0f ? 32767.0f | ||
93 | : (fs < -32767.0f ? -32767.0f : fs)); | ||
94 | |||
95 | s = (short)fs; | ||
96 | buffer[pos] = s; | ||
97 | pos += channels; | ||
98 | } | ||
99 | |||
100 | bufferp[channel] = pos; | ||
101 | } | ||
102 | |||
103 | |||
104 | /** | ||
105 | * Write the samples to the file (Random Acces). | ||
106 | */ | ||
107 | public void write_buffer(int val) | ||
108 | { | ||
109 | |||
110 | //for (int i = 0; i < channels; ++i) | ||
111 | // bufferp[i] = (short)i; | ||
112 | |||
113 | } | ||
114 | |||
115 | public void close() | ||
116 | {} | ||
117 | |||
118 | /** | ||
119 | * | ||
120 | */ | ||
121 | public void clear_buffer() | ||
122 | { | ||
123 | for (int i = 0; i < channels; ++i) | ||
124 | bufferp[i] = (short)i; | ||
125 | } | ||
126 | |||
127 | /** | ||
128 | * | ||
129 | */ | ||
130 | public void set_stop_flag() | ||
131 | {} | ||
132 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/Source.java b/songdbj/javazoom/jl/decoder/Source.java new file mode 100644 index 0000000000..9d6a5d732e --- /dev/null +++ b/songdbj/javazoom/jl/decoder/Source.java | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | *----------------------------------------------------------------------- | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Library General Public License as published | ||
6 | * by the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library General Public | ||
15 | * License along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | *---------------------------------------------------------------------- | ||
18 | */ | ||
19 | |||
20 | package javazoom.jl.decoder; | ||
21 | |||
22 | import java.io.IOException; | ||
23 | |||
24 | /** | ||
25 | * Work in progress. | ||
26 | * | ||
27 | * Class to describe a seekable data source. | ||
28 | * | ||
29 | */ | ||
30 | public interface Source | ||
31 | { | ||
32 | |||
33 | public static final long LENGTH_UNKNOWN = -1; | ||
34 | |||
35 | public int read(byte[] b, int offs, int len) | ||
36 | throws IOException; | ||
37 | |||
38 | |||
39 | public boolean willReadBlock(); | ||
40 | |||
41 | public boolean isSeekable(); | ||
42 | |||
43 | public long length(); | ||
44 | |||
45 | public long tell(); | ||
46 | |||
47 | public long seek(long pos); | ||
48 | |||
49 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/SynthesisFilter.java b/songdbj/javazoom/jl/decoder/SynthesisFilter.java new file mode 100644 index 0000000000..581ab03cc2 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/SynthesisFilter.java | |||
@@ -0,0 +1,1817 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 04/01/00 Fixes for running under build 23xx Microsoft JVM. mdm. | ||
5 | * | ||
6 | * 19/12/99 Performance improvements to compute_pcm_samples(). | ||
7 | * Mat McGowan. mdm@techie.com. | ||
8 | * | ||
9 | * 16/02/99 Java Conversion by E.B , javalayer@javazoom.net | ||
10 | * | ||
11 | * @(#) synthesis_filter.h 1.8, last edit: 6/15/94 16:52:00 | ||
12 | * @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de) | ||
13 | * @(#) Berlin University of Technology | ||
14 | * | ||
15 | *----------------------------------------------------------------------- | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU Library General Public License as published | ||
18 | * by the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU Library General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU Library General Public | ||
27 | * License along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | *---------------------------------------------------------------------- | ||
30 | */ | ||
31 | package javazoom.jl.decoder; | ||
32 | |||
33 | import java.io.IOException; | ||
34 | |||
35 | /** | ||
36 | * A class for the synthesis filter bank. | ||
37 | * This class does a fast downsampling from 32, 44.1 or 48 kHz to 8 kHz, if ULAW is defined. | ||
38 | * Frequencies above 4 kHz are removed by ignoring higher subbands. | ||
39 | */ | ||
40 | final class SynthesisFilter | ||
41 | { | ||
42 | private float[] v1; | ||
43 | private float[] v2; | ||
44 | private float[] actual_v; // v1 or v2 | ||
45 | private int actual_write_pos; // 0-15 | ||
46 | private float[] samples; // 32 new subband samples | ||
47 | private int channel; | ||
48 | private float scalefactor; | ||
49 | private float[] eq; | ||
50 | |||
51 | /** | ||
52 | * Quality value for controlling CPU usage/quality tradeoff. | ||
53 | */ | ||
54 | /* | ||
55 | private int quality; | ||
56 | |||
57 | private int v_inc; | ||
58 | |||
59 | |||
60 | |||
61 | public static final int HIGH_QUALITY = 1; | ||
62 | public static final int MEDIUM_QUALITY = 2; | ||
63 | public static final int LOW_QUALITY = 4; | ||
64 | */ | ||
65 | |||
66 | /** | ||
67 | * Contructor. | ||
68 | * The scalefactor scales the calculated float pcm samples to short values | ||
69 | * (raw pcm samples are in [-1.0, 1.0], if no violations occur). | ||
70 | */ | ||
71 | public SynthesisFilter(int channelnumber, float factor, float[] eq0) | ||
72 | { | ||
73 | if (d==null) | ||
74 | { | ||
75 | d = load_d(); | ||
76 | d16 = splitArray(d, 16); | ||
77 | } | ||
78 | |||
79 | v1 = new float[512]; | ||
80 | v2 = new float[512]; | ||
81 | samples = new float[32]; | ||
82 | channel = channelnumber; | ||
83 | scalefactor = factor; | ||
84 | setEQ(eq); | ||
85 | //setQuality(HIGH_QUALITY); | ||
86 | |||
87 | reset(); | ||
88 | } | ||
89 | |||
90 | public void setEQ(float[] eq0) | ||
91 | { | ||
92 | this.eq = eq0; | ||
93 | if (eq==null) | ||
94 | { | ||
95 | eq = new float[32]; | ||
96 | for (int i=0; i<32; i++) | ||
97 | eq[i] = 1.0f; | ||
98 | } | ||
99 | if (eq.length<32) | ||
100 | { | ||
101 | throw new IllegalArgumentException("eq0"); | ||
102 | } | ||
103 | |||
104 | } | ||
105 | |||
106 | /* | ||
107 | private void setQuality(int quality0) | ||
108 | { | ||
109 | switch (quality0) | ||
110 | { | ||
111 | case HIGH_QUALITY: | ||
112 | case MEDIUM_QUALITY: | ||
113 | case LOW_QUALITY: | ||
114 | v_inc = 16 * quality0; | ||
115 | quality = quality0; | ||
116 | break; | ||
117 | default : | ||
118 | throw new IllegalArgumentException("Unknown quality value"); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | public int getQuality() | ||
123 | { | ||
124 | return quality; | ||
125 | } | ||
126 | */ | ||
127 | |||
128 | /** | ||
129 | * Reset the synthesis filter. | ||
130 | */ | ||
131 | public void reset() | ||
132 | { | ||
133 | //float[] floatp; | ||
134 | // float[] floatp2; | ||
135 | |||
136 | // initialize v1[] and v2[]: | ||
137 | //for (floatp = v1 + 512, floatp2 = v2 + 512; floatp > v1; ) | ||
138 | // *--floatp = *--floatp2 = 0.0; | ||
139 | for (int p=0;p<512;p++) | ||
140 | v1[p] = v2[p] = 0.0f; | ||
141 | |||
142 | // initialize samples[]: | ||
143 | //for (floatp = samples + 32; floatp > samples; ) | ||
144 | // *--floatp = 0.0; | ||
145 | for (int p2=0;p2<32;p2++) | ||
146 | samples[p2] = 0.0f; | ||
147 | |||
148 | actual_v = v1; | ||
149 | actual_write_pos = 15; | ||
150 | } | ||
151 | |||
152 | |||
153 | /** | ||
154 | * Inject Sample. | ||
155 | */ | ||
156 | public void input_sample(float sample, int subbandnumber) | ||
157 | { | ||
158 | samples[subbandnumber] = eq[subbandnumber]*sample; | ||
159 | } | ||
160 | |||
161 | public void input_samples(float[] s) | ||
162 | { | ||
163 | for (int i=31; i>=0; i--) | ||
164 | { | ||
165 | samples[i] = s[i]*eq[i]; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Compute new values via a fast cosine transform. | ||
171 | */ | ||
172 | private void compute_new_v() | ||
173 | { | ||
174 | // p is fully initialized from x1 | ||
175 | //float[] p = _p; | ||
176 | // pp is fully initialized from p | ||
177 | //float[] pp = _pp; | ||
178 | |||
179 | //float[] new_v = _new_v; | ||
180 | |||
181 | //float[] new_v = new float[32]; // new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3 | ||
182 | //float[] p = new float[16]; | ||
183 | //float[] pp = new float[16]; | ||
184 | |||
185 | /* | ||
186 | for (int i=31; i>=0; i--) | ||
187 | { | ||
188 | new_v[i] = 0.0f; | ||
189 | } | ||
190 | */ | ||
191 | |||
192 | float new_v0, new_v1, new_v2, new_v3, new_v4, new_v5, new_v6, new_v7, new_v8, new_v9; | ||
193 | float new_v10, new_v11, new_v12, new_v13, new_v14, new_v15, new_v16, new_v17, new_v18, new_v19; | ||
194 | float new_v20, new_v21, new_v22, new_v23, new_v24, new_v25, new_v26, new_v27, new_v28, new_v29; | ||
195 | float new_v30, new_v31; | ||
196 | |||
197 | new_v0 = new_v1 = new_v2 = new_v3 = new_v4 = new_v5 = new_v6 = new_v7 = new_v8 = new_v9 = | ||
198 | new_v10 = new_v11 = new_v12 = new_v13 = new_v14 = new_v15 = new_v16 = new_v17 = new_v18 = new_v19 = | ||
199 | new_v20 = new_v21 = new_v22 = new_v23 = new_v24 = new_v25 = new_v26 = new_v27 = new_v28 = new_v29 = | ||
200 | new_v30 = new_v31 = 0.0f; | ||
201 | |||
202 | |||
203 | // float[] new_v = new float[32]; // new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3 | ||
204 | // float[] p = new float[16]; | ||
205 | // float[] pp = new float[16]; | ||
206 | |||
207 | float[] s = samples; | ||
208 | |||
209 | float s0 = s[0]; | ||
210 | float s1 = s[1]; | ||
211 | float s2 = s[2]; | ||
212 | float s3 = s[3]; | ||
213 | float s4 = s[4]; | ||
214 | float s5 = s[5]; | ||
215 | float s6 = s[6]; | ||
216 | float s7 = s[7]; | ||
217 | float s8 = s[8]; | ||
218 | float s9 = s[9]; | ||
219 | float s10 = s[10]; | ||
220 | float s11 = s[11]; | ||
221 | float s12 = s[12]; | ||
222 | float s13 = s[13]; | ||
223 | float s14 = s[14]; | ||
224 | float s15 = s[15]; | ||
225 | float s16 = s[16]; | ||
226 | float s17 = s[17]; | ||
227 | float s18 = s[18]; | ||
228 | float s19 = s[19]; | ||
229 | float s20 = s[20]; | ||
230 | float s21 = s[21]; | ||
231 | float s22 = s[22]; | ||
232 | float s23 = s[23]; | ||
233 | float s24 = s[24]; | ||
234 | float s25 = s[25]; | ||
235 | float s26 = s[26]; | ||
236 | float s27 = s[27]; | ||
237 | float s28 = s[28]; | ||
238 | float s29 = s[29]; | ||
239 | float s30 = s[30]; | ||
240 | float s31 = s[31]; | ||
241 | |||
242 | float p0 = s0 + s31; | ||
243 | float p1 = s1 + s30; | ||
244 | float p2 = s2 + s29; | ||
245 | float p3 = s3 + s28; | ||
246 | float p4 = s4 + s27; | ||
247 | float p5 = s5 + s26; | ||
248 | float p6 = s6 + s25; | ||
249 | float p7 = s7 + s24; | ||
250 | float p8 = s8 + s23; | ||
251 | float p9 = s9 + s22; | ||
252 | float p10 = s10 + s21; | ||
253 | float p11 = s11 + s20; | ||
254 | float p12 = s12 + s19; | ||
255 | float p13 = s13 + s18; | ||
256 | float p14 = s14 + s17; | ||
257 | float p15 = s15 + s16; | ||
258 | |||
259 | float pp0 = p0 + p15; | ||
260 | float pp1 = p1 + p14; | ||
261 | float pp2 = p2 + p13; | ||
262 | float pp3 = p3 + p12; | ||
263 | float pp4 = p4 + p11; | ||
264 | float pp5 = p5 + p10; | ||
265 | float pp6 = p6 + p9; | ||
266 | float pp7 = p7 + p8; | ||
267 | float pp8 = (p0 - p15) * cos1_32; | ||
268 | float pp9 = (p1 - p14) * cos3_32; | ||
269 | float pp10 = (p2 - p13) * cos5_32; | ||
270 | float pp11 = (p3 - p12) * cos7_32; | ||
271 | float pp12 = (p4 - p11) * cos9_32; | ||
272 | float pp13 = (p5 - p10) * cos11_32; | ||
273 | float pp14 = (p6 - p9) * cos13_32; | ||
274 | float pp15 = (p7 - p8) * cos15_32; | ||
275 | |||
276 | p0 = pp0 + pp7; | ||
277 | p1 = pp1 + pp6; | ||
278 | p2 = pp2 + pp5; | ||
279 | p3 = pp3 + pp4; | ||
280 | p4 = (pp0 - pp7) * cos1_16; | ||
281 | p5 = (pp1 - pp6) * cos3_16; | ||
282 | p6 = (pp2 - pp5) * cos5_16; | ||
283 | p7 = (pp3 - pp4) * cos7_16; | ||
284 | p8 = pp8 + pp15; | ||
285 | p9 = pp9 + pp14; | ||
286 | p10 = pp10 + pp13; | ||
287 | p11 = pp11 + pp12; | ||
288 | p12 = (pp8 - pp15) * cos1_16; | ||
289 | p13 = (pp9 - pp14) * cos3_16; | ||
290 | p14 = (pp10 - pp13) * cos5_16; | ||
291 | p15 = (pp11 - pp12) * cos7_16; | ||
292 | |||
293 | |||
294 | pp0 = p0 + p3; | ||
295 | pp1 = p1 + p2; | ||
296 | pp2 = (p0 - p3) * cos1_8; | ||
297 | pp3 = (p1 - p2) * cos3_8; | ||
298 | pp4 = p4 + p7; | ||
299 | pp5 = p5 + p6; | ||
300 | pp6 = (p4 - p7) * cos1_8; | ||
301 | pp7 = (p5 - p6) * cos3_8; | ||
302 | pp8 = p8 + p11; | ||
303 | pp9 = p9 + p10; | ||
304 | pp10 = (p8 - p11) * cos1_8; | ||
305 | pp11 = (p9 - p10) * cos3_8; | ||
306 | pp12 = p12 + p15; | ||
307 | pp13 = p13 + p14; | ||
308 | pp14 = (p12 - p15) * cos1_8; | ||
309 | pp15 = (p13 - p14) * cos3_8; | ||
310 | |||
311 | p0 = pp0 + pp1; | ||
312 | p1 = (pp0 - pp1) * cos1_4; | ||
313 | p2 = pp2 + pp3; | ||
314 | p3 = (pp2 - pp3) * cos1_4; | ||
315 | p4 = pp4 + pp5; | ||
316 | p5 = (pp4 - pp5) * cos1_4; | ||
317 | p6 = pp6 + pp7; | ||
318 | p7 = (pp6 - pp7) * cos1_4; | ||
319 | p8 = pp8 + pp9; | ||
320 | p9 = (pp8 - pp9) * cos1_4; | ||
321 | p10 = pp10 + pp11; | ||
322 | p11 = (pp10 - pp11) * cos1_4; | ||
323 | p12 = pp12 + pp13; | ||
324 | p13 = (pp12 - pp13) * cos1_4; | ||
325 | p14 = pp14 + pp15; | ||
326 | p15 = (pp14 - pp15) * cos1_4; | ||
327 | |||
328 | // this is pretty insane coding | ||
329 | float tmp1; | ||
330 | new_v19/*36-17*/ = -(new_v4 = (new_v12 = p7) + p5) - p6; | ||
331 | new_v27/*44-17*/ = -p6 - p7 - p4; | ||
332 | new_v6 = (new_v10 = (new_v14 = p15) + p11) + p13; | ||
333 | new_v17/*34-17*/ = -(new_v2 = p15 + p13 + p9) - p14; | ||
334 | new_v21/*38-17*/ = (tmp1 = -p14 - p15 - p10 - p11) - p13; | ||
335 | new_v29/*46-17*/ = -p14 - p15 - p12 - p8; | ||
336 | new_v25/*42-17*/ = tmp1 - p12; | ||
337 | new_v31/*48-17*/ = -p0; | ||
338 | new_v0 = p1; | ||
339 | new_v23/*40-17*/ = -(new_v8 = p3) - p2; | ||
340 | |||
341 | p0 = (s0 - s31) * cos1_64; | ||
342 | p1 = (s1 - s30) * cos3_64; | ||
343 | p2 = (s2 - s29) * cos5_64; | ||
344 | p3 = (s3 - s28) * cos7_64; | ||
345 | p4 = (s4 - s27) * cos9_64; | ||
346 | p5 = (s5 - s26) * cos11_64; | ||
347 | p6 = (s6 - s25) * cos13_64; | ||
348 | p7 = (s7 - s24) * cos15_64; | ||
349 | p8 = (s8 - s23) * cos17_64; | ||
350 | p9 = (s9 - s22) * cos19_64; | ||
351 | p10 = (s10 - s21) * cos21_64; | ||
352 | p11 = (s11 - s20) * cos23_64; | ||
353 | p12 = (s12 - s19) * cos25_64; | ||
354 | p13 = (s13 - s18) * cos27_64; | ||
355 | p14 = (s14 - s17) * cos29_64; | ||
356 | p15 = (s15 - s16) * cos31_64; | ||
357 | |||
358 | |||
359 | pp0 = p0 + p15; | ||
360 | pp1 = p1 + p14; | ||
361 | pp2 = p2 + p13; | ||
362 | pp3 = p3 + p12; | ||
363 | pp4 = p4 + p11; | ||
364 | pp5 = p5 + p10; | ||
365 | pp6 = p6 + p9; | ||
366 | pp7 = p7 + p8; | ||
367 | pp8 = (p0 - p15) * cos1_32; | ||
368 | pp9 = (p1 - p14) * cos3_32; | ||
369 | pp10 = (p2 - p13) * cos5_32; | ||
370 | pp11 = (p3 - p12) * cos7_32; | ||
371 | pp12 = (p4 - p11) * cos9_32; | ||
372 | pp13 = (p5 - p10) * cos11_32; | ||
373 | pp14 = (p6 - p9) * cos13_32; | ||
374 | pp15 = (p7 - p8) * cos15_32; | ||
375 | |||
376 | |||
377 | p0 = pp0 + pp7; | ||
378 | p1 = pp1 + pp6; | ||
379 | p2 = pp2 + pp5; | ||
380 | p3 = pp3 + pp4; | ||
381 | p4 = (pp0 - pp7) * cos1_16; | ||
382 | p5 = (pp1 - pp6) * cos3_16; | ||
383 | p6 = (pp2 - pp5) * cos5_16; | ||
384 | p7 = (pp3 - pp4) * cos7_16; | ||
385 | p8 = pp8 + pp15; | ||
386 | p9 = pp9 + pp14; | ||
387 | p10 = pp10 + pp13; | ||
388 | p11 = pp11 + pp12; | ||
389 | p12 = (pp8 - pp15) * cos1_16; | ||
390 | p13 = (pp9 - pp14) * cos3_16; | ||
391 | p14 = (pp10 - pp13) * cos5_16; | ||
392 | p15 = (pp11 - pp12) * cos7_16; | ||
393 | |||
394 | |||
395 | pp0 = p0 + p3; | ||
396 | pp1 = p1 + p2; | ||
397 | pp2 = (p0 - p3) * cos1_8; | ||
398 | pp3 = (p1 - p2) * cos3_8; | ||
399 | pp4 = p4 + p7; | ||
400 | pp5 = p5 + p6; | ||
401 | pp6 = (p4 - p7) * cos1_8; | ||
402 | pp7 = (p5 - p6) * cos3_8; | ||
403 | pp8 = p8 + p11; | ||
404 | pp9 = p9 + p10; | ||
405 | pp10 = (p8 - p11) * cos1_8; | ||
406 | pp11 = (p9 - p10) * cos3_8; | ||
407 | pp12 = p12 + p15; | ||
408 | pp13 = p13 + p14; | ||
409 | pp14 = (p12 - p15) * cos1_8; | ||
410 | pp15 = (p13 - p14) * cos3_8; | ||
411 | |||
412 | |||
413 | p0 = pp0 + pp1; | ||
414 | p1 = (pp0 - pp1) * cos1_4; | ||
415 | p2 = pp2 + pp3; | ||
416 | p3 = (pp2 - pp3) * cos1_4; | ||
417 | p4 = pp4 + pp5; | ||
418 | p5 = (pp4 - pp5) * cos1_4; | ||
419 | p6 = pp6 + pp7; | ||
420 | p7 = (pp6 - pp7) * cos1_4; | ||
421 | p8 = pp8 + pp9; | ||
422 | p9 = (pp8 - pp9) * cos1_4; | ||
423 | p10 = pp10 + pp11; | ||
424 | p11 = (pp10 - pp11) * cos1_4; | ||
425 | p12 = pp12 + pp13; | ||
426 | p13 = (pp12 - pp13) * cos1_4; | ||
427 | p14 = pp14 + pp15; | ||
428 | p15 = (pp14 - pp15) * cos1_4; | ||
429 | |||
430 | |||
431 | // manually doing something that a compiler should handle sucks | ||
432 | // coding like this is hard to read | ||
433 | float tmp2; | ||
434 | new_v5 = (new_v11 = (new_v13 = (new_v15 = p15) + p7) + p11) | ||
435 | + p5 + p13; | ||
436 | new_v7 = (new_v9 = p15 + p11 + p3) + p13; | ||
437 | new_v16/*33-17*/ = -(new_v1 = (tmp1 = p13 + p15 + p9) + p1) - p14; | ||
438 | new_v18/*35-17*/ = -(new_v3 = tmp1 + p5 + p7) - p6 - p14; | ||
439 | |||
440 | new_v22/*39-17*/ = (tmp1 = -p10 - p11 - p14 - p15) | ||
441 | - p13 - p2 - p3; | ||
442 | new_v20/*37-17*/ = tmp1 - p13 - p5 - p6 - p7; | ||
443 | new_v24/*41-17*/ = tmp1 - p12 - p2 - p3; | ||
444 | new_v26/*43-17*/ = tmp1 - p12 - (tmp2 = p4 + p6 + p7); | ||
445 | new_v30/*47-17*/ = (tmp1 = -p8 - p12 - p14 - p15) - p0; | ||
446 | new_v28/*45-17*/ = tmp1 - tmp2; | ||
447 | |||
448 | // insert V[0-15] (== new_v[0-15]) into actual v: | ||
449 | // float[] x2 = actual_v + actual_write_pos; | ||
450 | float dest[] = actual_v; | ||
451 | |||
452 | int pos = actual_write_pos; | ||
453 | |||
454 | dest[0 + pos] = new_v0; | ||
455 | dest[16 + pos] = new_v1; | ||
456 | dest[32 + pos] = new_v2; | ||
457 | dest[48 + pos] = new_v3; | ||
458 | dest[64 + pos] = new_v4; | ||
459 | dest[80 + pos] = new_v5; | ||
460 | dest[96 + pos] = new_v6; | ||
461 | dest[112 + pos] = new_v7; | ||
462 | dest[128 + pos] = new_v8; | ||
463 | dest[144 + pos] = new_v9; | ||
464 | dest[160 + pos] = new_v10; | ||
465 | dest[176 + pos] = new_v11; | ||
466 | dest[192 + pos] = new_v12; | ||
467 | dest[208 + pos] = new_v13; | ||
468 | dest[224 + pos] = new_v14; | ||
469 | dest[240 + pos] = new_v15; | ||
470 | |||
471 | // V[16] is always 0.0: | ||
472 | dest[256 + pos] = 0.0f; | ||
473 | |||
474 | // insert V[17-31] (== -new_v[15-1]) into actual v: | ||
475 | dest[272 + pos] = -new_v15; | ||
476 | dest[288 + pos] = -new_v14; | ||
477 | dest[304 + pos] = -new_v13; | ||
478 | dest[320 + pos] = -new_v12; | ||
479 | dest[336 + pos] = -new_v11; | ||
480 | dest[352 + pos] = -new_v10; | ||
481 | dest[368 + pos] = -new_v9; | ||
482 | dest[384 + pos] = -new_v8; | ||
483 | dest[400 + pos] = -new_v7; | ||
484 | dest[416 + pos] = -new_v6; | ||
485 | dest[432 + pos] = -new_v5; | ||
486 | dest[448 + pos] = -new_v4; | ||
487 | dest[464 + pos] = -new_v3; | ||
488 | dest[480 + pos] = -new_v2; | ||
489 | dest[496 + pos] = -new_v1; | ||
490 | |||
491 | // insert V[32] (== -new_v[0]) into other v: | ||
492 | dest = (actual_v==v1) ? v2 : v1; | ||
493 | |||
494 | dest[0 + pos] = -new_v0; | ||
495 | // insert V[33-48] (== new_v[16-31]) into other v: | ||
496 | dest[16 + pos] = new_v16; | ||
497 | dest[32 + pos] = new_v17; | ||
498 | dest[48 + pos] = new_v18; | ||
499 | dest[64 + pos] = new_v19; | ||
500 | dest[80 + pos] = new_v20; | ||
501 | dest[96 + pos] = new_v21; | ||
502 | dest[112 + pos] = new_v22; | ||
503 | dest[128 + pos] = new_v23; | ||
504 | dest[144 + pos] = new_v24; | ||
505 | dest[160 + pos] = new_v25; | ||
506 | dest[176 + pos] = new_v26; | ||
507 | dest[192 + pos] = new_v27; | ||
508 | dest[208 + pos] = new_v28; | ||
509 | dest[224 + pos] = new_v29; | ||
510 | dest[240 + pos] = new_v30; | ||
511 | dest[256 + pos] = new_v31; | ||
512 | |||
513 | // insert V[49-63] (== new_v[30-16]) into other v: | ||
514 | dest[272 + pos] = new_v30; | ||
515 | dest[288 + pos] = new_v29; | ||
516 | dest[304 + pos] = new_v28; | ||
517 | dest[320 + pos] = new_v27; | ||
518 | dest[336 + pos] = new_v26; | ||
519 | dest[352 + pos] = new_v25; | ||
520 | dest[368 + pos] = new_v24; | ||
521 | dest[384 + pos] = new_v23; | ||
522 | dest[400 + pos] = new_v22; | ||
523 | dest[416 + pos] = new_v21; | ||
524 | dest[432 + pos] = new_v20; | ||
525 | dest[448 + pos] = new_v19; | ||
526 | dest[464 + pos] = new_v18; | ||
527 | dest[480 + pos] = new_v17; | ||
528 | dest[496 + pos] = new_v16; | ||
529 | /* | ||
530 | } | ||
531 | else | ||
532 | { | ||
533 | v1[0 + actual_write_pos] = -new_v0; | ||
534 | // insert V[33-48] (== new_v[16-31]) into other v: | ||
535 | v1[16 + actual_write_pos] = new_v16; | ||
536 | v1[32 + actual_write_pos] = new_v17; | ||
537 | v1[48 + actual_write_pos] = new_v18; | ||
538 | v1[64 + actual_write_pos] = new_v19; | ||
539 | v1[80 + actual_write_pos] = new_v20; | ||
540 | v1[96 + actual_write_pos] = new_v21; | ||
541 | v1[112 + actual_write_pos] = new_v22; | ||
542 | v1[128 + actual_write_pos] = new_v23; | ||
543 | v1[144 + actual_write_pos] = new_v24; | ||
544 | v1[160 + actual_write_pos] = new_v25; | ||
545 | v1[176 + actual_write_pos] = new_v26; | ||
546 | v1[192 + actual_write_pos] = new_v27; | ||
547 | v1[208 + actual_write_pos] = new_v28; | ||
548 | v1[224 + actual_write_pos] = new_v29; | ||
549 | v1[240 + actual_write_pos] = new_v30; | ||
550 | v1[256 + actual_write_pos] = new_v31; | ||
551 | |||
552 | // insert V[49-63] (== new_v[30-16]) into other v: | ||
553 | v1[272 + actual_write_pos] = new_v30; | ||
554 | v1[288 + actual_write_pos] = new_v29; | ||
555 | v1[304 + actual_write_pos] = new_v28; | ||
556 | v1[320 + actual_write_pos] = new_v27; | ||
557 | v1[336 + actual_write_pos] = new_v26; | ||
558 | v1[352 + actual_write_pos] = new_v25; | ||
559 | v1[368 + actual_write_pos] = new_v24; | ||
560 | v1[384 + actual_write_pos] = new_v23; | ||
561 | v1[400 + actual_write_pos] = new_v22; | ||
562 | v1[416 + actual_write_pos] = new_v21; | ||
563 | v1[432 + actual_write_pos] = new_v20; | ||
564 | v1[448 + actual_write_pos] = new_v19; | ||
565 | v1[464 + actual_write_pos] = new_v18; | ||
566 | v1[480 + actual_write_pos] = new_v17; | ||
567 | v1[496 + actual_write_pos] = new_v16; | ||
568 | } | ||
569 | */ | ||
570 | } | ||
571 | |||
572 | /** | ||
573 | * Compute new values via a fast cosine transform. | ||
574 | */ | ||
575 | private void compute_new_v_old() | ||
576 | { | ||
577 | // p is fully initialized from x1 | ||
578 | //float[] p = _p; | ||
579 | // pp is fully initialized from p | ||
580 | //float[] pp = _pp; | ||
581 | |||
582 | //float[] new_v = _new_v; | ||
583 | |||
584 | float[] new_v = new float[32]; // new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3 | ||
585 | float[] p = new float[16]; | ||
586 | float[] pp = new float[16]; | ||
587 | |||
588 | |||
589 | for (int i=31; i>=0; i--) | ||
590 | { | ||
591 | new_v[i] = 0.0f; | ||
592 | } | ||
593 | |||
594 | // float[] new_v = new float[32]; // new V[0-15] and V[33-48] of Figure 3-A.2 in ISO DIS 11172-3 | ||
595 | // float[] p = new float[16]; | ||
596 | // float[] pp = new float[16]; | ||
597 | |||
598 | float[] x1 = samples; | ||
599 | |||
600 | p[0] = x1[0] + x1[31]; | ||
601 | p[1] = x1[1] + x1[30]; | ||
602 | p[2] = x1[2] + x1[29]; | ||
603 | p[3] = x1[3] + x1[28]; | ||
604 | p[4] = x1[4] + x1[27]; | ||
605 | p[5] = x1[5] + x1[26]; | ||
606 | p[6] = x1[6] + x1[25]; | ||
607 | p[7] = x1[7] + x1[24]; | ||
608 | p[8] = x1[8] + x1[23]; | ||
609 | p[9] = x1[9] + x1[22]; | ||
610 | p[10] = x1[10] + x1[21]; | ||
611 | p[11] = x1[11] + x1[20]; | ||
612 | p[12] = x1[12] + x1[19]; | ||
613 | p[13] = x1[13] + x1[18]; | ||
614 | p[14] = x1[14] + x1[17]; | ||
615 | p[15] = x1[15] + x1[16]; | ||
616 | |||
617 | pp[0] = p[0] + p[15]; | ||
618 | pp[1] = p[1] + p[14]; | ||
619 | pp[2] = p[2] + p[13]; | ||
620 | pp[3] = p[3] + p[12]; | ||
621 | pp[4] = p[4] + p[11]; | ||
622 | pp[5] = p[5] + p[10]; | ||
623 | pp[6] = p[6] + p[9]; | ||
624 | pp[7] = p[7] + p[8]; | ||
625 | pp[8] = (p[0] - p[15]) * cos1_32; | ||
626 | pp[9] = (p[1] - p[14]) * cos3_32; | ||
627 | pp[10] = (p[2] - p[13]) * cos5_32; | ||
628 | pp[11] = (p[3] - p[12]) * cos7_32; | ||
629 | pp[12] = (p[4] - p[11]) * cos9_32; | ||
630 | pp[13] = (p[5] - p[10]) * cos11_32; | ||
631 | pp[14] = (p[6] - p[9]) * cos13_32; | ||
632 | pp[15] = (p[7] - p[8]) * cos15_32; | ||
633 | |||
634 | p[0] = pp[0] + pp[7]; | ||
635 | p[1] = pp[1] + pp[6]; | ||
636 | p[2] = pp[2] + pp[5]; | ||
637 | p[3] = pp[3] + pp[4]; | ||
638 | p[4] = (pp[0] - pp[7]) * cos1_16; | ||
639 | p[5] = (pp[1] - pp[6]) * cos3_16; | ||
640 | p[6] = (pp[2] - pp[5]) * cos5_16; | ||
641 | p[7] = (pp[3] - pp[4]) * cos7_16; | ||
642 | p[8] = pp[8] + pp[15]; | ||
643 | p[9] = pp[9] + pp[14]; | ||
644 | p[10] = pp[10] + pp[13]; | ||
645 | p[11] = pp[11] + pp[12]; | ||
646 | p[12] = (pp[8] - pp[15]) * cos1_16; | ||
647 | p[13] = (pp[9] - pp[14]) * cos3_16; | ||
648 | p[14] = (pp[10] - pp[13]) * cos5_16; | ||
649 | p[15] = (pp[11] - pp[12]) * cos7_16; | ||
650 | |||
651 | |||
652 | pp[0] = p[0] + p[3]; | ||
653 | pp[1] = p[1] + p[2]; | ||
654 | pp[2] = (p[0] - p[3]) * cos1_8; | ||
655 | pp[3] = (p[1] - p[2]) * cos3_8; | ||
656 | pp[4] = p[4] + p[7]; | ||
657 | pp[5] = p[5] + p[6]; | ||
658 | pp[6] = (p[4] - p[7]) * cos1_8; | ||
659 | pp[7] = (p[5] - p[6]) * cos3_8; | ||
660 | pp[8] = p[8] + p[11]; | ||
661 | pp[9] = p[9] + p[10]; | ||
662 | pp[10] = (p[8] - p[11]) * cos1_8; | ||
663 | pp[11] = (p[9] - p[10]) * cos3_8; | ||
664 | pp[12] = p[12] + p[15]; | ||
665 | pp[13] = p[13] + p[14]; | ||
666 | pp[14] = (p[12] - p[15]) * cos1_8; | ||
667 | pp[15] = (p[13] - p[14]) * cos3_8; | ||
668 | |||
669 | p[0] = pp[0] + pp[1]; | ||
670 | p[1] = (pp[0] - pp[1]) * cos1_4; | ||
671 | p[2] = pp[2] + pp[3]; | ||
672 | p[3] = (pp[2] - pp[3]) * cos1_4; | ||
673 | p[4] = pp[4] + pp[5]; | ||
674 | p[5] = (pp[4] - pp[5]) * cos1_4; | ||
675 | p[6] = pp[6] + pp[7]; | ||
676 | p[7] = (pp[6] - pp[7]) * cos1_4; | ||
677 | p[8] = pp[8] + pp[9]; | ||
678 | p[9] = (pp[8] - pp[9]) * cos1_4; | ||
679 | p[10] = pp[10] + pp[11]; | ||
680 | p[11] = (pp[10] - pp[11]) * cos1_4; | ||
681 | p[12] = pp[12] + pp[13]; | ||
682 | p[13] = (pp[12] - pp[13]) * cos1_4; | ||
683 | p[14] = pp[14] + pp[15]; | ||
684 | p[15] = (pp[14] - pp[15]) * cos1_4; | ||
685 | |||
686 | // this is pretty insane coding | ||
687 | float tmp1; | ||
688 | new_v[36-17] = -(new_v[4] = (new_v[12] = p[7]) + p[5]) - p[6]; | ||
689 | new_v[44-17] = -p[6] - p[7] - p[4]; | ||
690 | new_v[6] = (new_v[10] = (new_v[14] = p[15]) + p[11]) + p[13]; | ||
691 | new_v[34-17] = -(new_v[2] = p[15] + p[13] + p[9]) - p[14]; | ||
692 | new_v[38-17] = (tmp1 = -p[14] - p[15] - p[10] - p[11]) - p[13]; | ||
693 | new_v[46-17] = -p[14] - p[15] - p[12] - p[8]; | ||
694 | new_v[42-17] = tmp1 - p[12]; | ||
695 | new_v[48-17] = -p[0]; | ||
696 | new_v[0] = p[1]; | ||
697 | new_v[40-17] = -(new_v[8] = p[3]) - p[2]; | ||
698 | |||
699 | p[0] = (x1[0] - x1[31]) * cos1_64; | ||
700 | p[1] = (x1[1] - x1[30]) * cos3_64; | ||
701 | p[2] = (x1[2] - x1[29]) * cos5_64; | ||
702 | p[3] = (x1[3] - x1[28]) * cos7_64; | ||
703 | p[4] = (x1[4] - x1[27]) * cos9_64; | ||
704 | p[5] = (x1[5] - x1[26]) * cos11_64; | ||
705 | p[6] = (x1[6] - x1[25]) * cos13_64; | ||
706 | p[7] = (x1[7] - x1[24]) * cos15_64; | ||
707 | p[8] = (x1[8] - x1[23]) * cos17_64; | ||
708 | p[9] = (x1[9] - x1[22]) * cos19_64; | ||
709 | p[10] = (x1[10] - x1[21]) * cos21_64; | ||
710 | p[11] = (x1[11] - x1[20]) * cos23_64; | ||
711 | p[12] = (x1[12] - x1[19]) * cos25_64; | ||
712 | p[13] = (x1[13] - x1[18]) * cos27_64; | ||
713 | p[14] = (x1[14] - x1[17]) * cos29_64; | ||
714 | p[15] = (x1[15] - x1[16]) * cos31_64; | ||
715 | |||
716 | |||
717 | pp[0] = p[0] + p[15]; | ||
718 | pp[1] = p[1] + p[14]; | ||
719 | pp[2] = p[2] + p[13]; | ||
720 | pp[3] = p[3] + p[12]; | ||
721 | pp[4] = p[4] + p[11]; | ||
722 | pp[5] = p[5] + p[10]; | ||
723 | pp[6] = p[6] + p[9]; | ||
724 | pp[7] = p[7] + p[8]; | ||
725 | pp[8] = (p[0] - p[15]) * cos1_32; | ||
726 | pp[9] = (p[1] - p[14]) * cos3_32; | ||
727 | pp[10] = (p[2] - p[13]) * cos5_32; | ||
728 | pp[11] = (p[3] - p[12]) * cos7_32; | ||
729 | pp[12] = (p[4] - p[11]) * cos9_32; | ||
730 | pp[13] = (p[5] - p[10]) * cos11_32; | ||
731 | pp[14] = (p[6] - p[9]) * cos13_32; | ||
732 | pp[15] = (p[7] - p[8]) * cos15_32; | ||
733 | |||
734 | |||
735 | p[0] = pp[0] + pp[7]; | ||
736 | p[1] = pp[1] + pp[6]; | ||
737 | p[2] = pp[2] + pp[5]; | ||
738 | p[3] = pp[3] + pp[4]; | ||
739 | p[4] = (pp[0] - pp[7]) * cos1_16; | ||
740 | p[5] = (pp[1] - pp[6]) * cos3_16; | ||
741 | p[6] = (pp[2] - pp[5]) * cos5_16; | ||
742 | p[7] = (pp[3] - pp[4]) * cos7_16; | ||
743 | p[8] = pp[8] + pp[15]; | ||
744 | p[9] = pp[9] + pp[14]; | ||
745 | p[10] = pp[10] + pp[13]; | ||
746 | p[11] = pp[11] + pp[12]; | ||
747 | p[12] = (pp[8] - pp[15]) * cos1_16; | ||
748 | p[13] = (pp[9] - pp[14]) * cos3_16; | ||
749 | p[14] = (pp[10] - pp[13]) * cos5_16; | ||
750 | p[15] = (pp[11] - pp[12]) * cos7_16; | ||
751 | |||
752 | |||
753 | pp[0] = p[0] + p[3]; | ||
754 | pp[1] = p[1] + p[2]; | ||
755 | pp[2] = (p[0] - p[3]) * cos1_8; | ||
756 | pp[3] = (p[1] - p[2]) * cos3_8; | ||
757 | pp[4] = p[4] + p[7]; | ||
758 | pp[5] = p[5] + p[6]; | ||
759 | pp[6] = (p[4] - p[7]) * cos1_8; | ||
760 | pp[7] = (p[5] - p[6]) * cos3_8; | ||
761 | pp[8] = p[8] + p[11]; | ||
762 | pp[9] = p[9] + p[10]; | ||
763 | pp[10] = (p[8] - p[11]) * cos1_8; | ||
764 | pp[11] = (p[9] - p[10]) * cos3_8; | ||
765 | pp[12] = p[12] + p[15]; | ||
766 | pp[13] = p[13] + p[14]; | ||
767 | pp[14] = (p[12] - p[15]) * cos1_8; | ||
768 | pp[15] = (p[13] - p[14]) * cos3_8; | ||
769 | |||
770 | |||
771 | p[0] = pp[0] + pp[1]; | ||
772 | p[1] = (pp[0] - pp[1]) * cos1_4; | ||
773 | p[2] = pp[2] + pp[3]; | ||
774 | p[3] = (pp[2] - pp[3]) * cos1_4; | ||
775 | p[4] = pp[4] + pp[5]; | ||
776 | p[5] = (pp[4] - pp[5]) * cos1_4; | ||
777 | p[6] = pp[6] + pp[7]; | ||
778 | p[7] = (pp[6] - pp[7]) * cos1_4; | ||
779 | p[8] = pp[8] + pp[9]; | ||
780 | p[9] = (pp[8] - pp[9]) * cos1_4; | ||
781 | p[10] = pp[10] + pp[11]; | ||
782 | p[11] = (pp[10] - pp[11]) * cos1_4; | ||
783 | p[12] = pp[12] + pp[13]; | ||
784 | p[13] = (pp[12] - pp[13]) * cos1_4; | ||
785 | p[14] = pp[14] + pp[15]; | ||
786 | p[15] = (pp[14] - pp[15]) * cos1_4; | ||
787 | |||
788 | |||
789 | // manually doing something that a compiler should handle sucks | ||
790 | // coding like this is hard to read | ||
791 | float tmp2; | ||
792 | new_v[5] = (new_v[11] = (new_v[13] = (new_v[15] = p[15]) + p[7]) + p[11]) | ||
793 | + p[5] + p[13]; | ||
794 | new_v[7] = (new_v[9] = p[15] + p[11] + p[3]) + p[13]; | ||
795 | new_v[33-17] = -(new_v[1] = (tmp1 = p[13] + p[15] + p[9]) + p[1]) - p[14]; | ||
796 | new_v[35-17] = -(new_v[3] = tmp1 + p[5] + p[7]) - p[6] - p[14]; | ||
797 | |||
798 | new_v[39-17] = (tmp1 = -p[10] - p[11] - p[14] - p[15]) | ||
799 | - p[13] - p[2] - p[3]; | ||
800 | new_v[37-17] = tmp1 - p[13] - p[5] - p[6] - p[7]; | ||
801 | new_v[41-17] = tmp1 - p[12] - p[2] - p[3]; | ||
802 | new_v[43-17] = tmp1 - p[12] - (tmp2 = p[4] + p[6] + p[7]); | ||
803 | new_v[47-17] = (tmp1 = -p[8] - p[12] - p[14] - p[15]) - p[0]; | ||
804 | new_v[45-17] = tmp1 - tmp2; | ||
805 | |||
806 | // insert V[0-15] (== new_v[0-15]) into actual v: | ||
807 | x1 = new_v; | ||
808 | // float[] x2 = actual_v + actual_write_pos; | ||
809 | float[] dest = actual_v; | ||
810 | |||
811 | dest[0 + actual_write_pos] = x1[0]; | ||
812 | dest[16 + actual_write_pos] = x1[1]; | ||
813 | dest[32 + actual_write_pos] = x1[2]; | ||
814 | dest[48 + actual_write_pos] = x1[3]; | ||
815 | dest[64 + actual_write_pos] = x1[4]; | ||
816 | dest[80 + actual_write_pos] = x1[5]; | ||
817 | dest[96 + actual_write_pos] = x1[6]; | ||
818 | dest[112 + actual_write_pos] = x1[7]; | ||
819 | dest[128 + actual_write_pos] = x1[8]; | ||
820 | dest[144 + actual_write_pos] = x1[9]; | ||
821 | dest[160 + actual_write_pos] = x1[10]; | ||
822 | dest[176 + actual_write_pos] = x1[11]; | ||
823 | dest[192 + actual_write_pos] = x1[12]; | ||
824 | dest[208 + actual_write_pos] = x1[13]; | ||
825 | dest[224 + actual_write_pos] = x1[14]; | ||
826 | dest[240 + actual_write_pos] = x1[15]; | ||
827 | |||
828 | // V[16] is always 0.0: | ||
829 | dest[256 + actual_write_pos] = 0.0f; | ||
830 | |||
831 | // insert V[17-31] (== -new_v[15-1]) into actual v: | ||
832 | dest[272 + actual_write_pos] = -x1[15]; | ||
833 | dest[288 + actual_write_pos] = -x1[14]; | ||
834 | dest[304 + actual_write_pos] = -x1[13]; | ||
835 | dest[320 + actual_write_pos] = -x1[12]; | ||
836 | dest[336 + actual_write_pos] = -x1[11]; | ||
837 | dest[352 + actual_write_pos] = -x1[10]; | ||
838 | dest[368 + actual_write_pos] = -x1[9]; | ||
839 | dest[384 + actual_write_pos] = -x1[8]; | ||
840 | dest[400 + actual_write_pos] = -x1[7]; | ||
841 | dest[416 + actual_write_pos] = -x1[6]; | ||
842 | dest[432 + actual_write_pos] = -x1[5]; | ||
843 | dest[448 + actual_write_pos] = -x1[4]; | ||
844 | dest[464 + actual_write_pos] = -x1[3]; | ||
845 | dest[480 + actual_write_pos] = -x1[2]; | ||
846 | dest[496 + actual_write_pos] = -x1[1]; | ||
847 | |||
848 | // insert V[32] (== -new_v[0]) into other v: | ||
849 | |||
850 | } | ||
851 | |||
852 | /** | ||
853 | * Compute PCM Samples. | ||
854 | */ | ||
855 | |||
856 | private float[] _tmpOut = new float[32]; | ||
857 | |||
858 | |||
859 | private void compute_pcm_samples0(Obuffer buffer) | ||
860 | { | ||
861 | final float[] vp = actual_v; | ||
862 | //int inc = v_inc; | ||
863 | final float[] tmpOut = _tmpOut; | ||
864 | int dvp =0; | ||
865 | |||
866 | // fat chance of having this loop unroll | ||
867 | for( int i=0; i<32; i++) | ||
868 | { | ||
869 | float pcm_sample; | ||
870 | final float[] dp = d16[i]; | ||
871 | pcm_sample = (float)(((vp[0 + dvp] * dp[0]) + | ||
872 | (vp[15 + dvp] * dp[1]) + | ||
873 | (vp[14 + dvp] * dp[2]) + | ||
874 | (vp[13 + dvp] * dp[3]) + | ||
875 | (vp[12 + dvp] * dp[4]) + | ||
876 | (vp[11 + dvp] * dp[5]) + | ||
877 | (vp[10 + dvp] * dp[6]) + | ||
878 | (vp[9 + dvp] * dp[7]) + | ||
879 | (vp[8 + dvp] * dp[8]) + | ||
880 | (vp[7 + dvp] * dp[9]) + | ||
881 | (vp[6 + dvp] * dp[10]) + | ||
882 | (vp[5 + dvp] * dp[11]) + | ||
883 | (vp[4 + dvp] * dp[12]) + | ||
884 | (vp[3 + dvp] * dp[13]) + | ||
885 | (vp[2 + dvp] * dp[14]) + | ||
886 | (vp[1 + dvp] * dp[15]) | ||
887 | ) * scalefactor); | ||
888 | |||
889 | tmpOut[i] = pcm_sample; | ||
890 | |||
891 | dvp += 16; | ||
892 | } // for | ||
893 | } | ||
894 | |||
895 | private void compute_pcm_samples1(Obuffer buffer) | ||
896 | { | ||
897 | final float[] vp = actual_v; | ||
898 | //int inc = v_inc; | ||
899 | final float[] tmpOut = _tmpOut; | ||
900 | int dvp =0; | ||
901 | |||
902 | // fat chance of having this loop unroll | ||
903 | for( int i=0; i<32; i++) | ||
904 | { | ||
905 | final float[] dp = d16[i]; | ||
906 | float pcm_sample; | ||
907 | |||
908 | pcm_sample = (float)(((vp[1 + dvp] * dp[0]) + | ||
909 | (vp[0 + dvp] * dp[1]) + | ||
910 | (vp[15 + dvp] * dp[2]) + | ||
911 | (vp[14 + dvp] * dp[3]) + | ||
912 | (vp[13 + dvp] * dp[4]) + | ||
913 | (vp[12 + dvp] * dp[5]) + | ||
914 | (vp[11 + dvp] * dp[6]) + | ||
915 | (vp[10 + dvp] * dp[7]) + | ||
916 | (vp[9 + dvp] * dp[8]) + | ||
917 | (vp[8 + dvp] * dp[9]) + | ||
918 | (vp[7 + dvp] * dp[10]) + | ||
919 | (vp[6 + dvp] * dp[11]) + | ||
920 | (vp[5 + dvp] * dp[12]) + | ||
921 | (vp[4 + dvp] * dp[13]) + | ||
922 | (vp[3 + dvp] * dp[14]) + | ||
923 | (vp[2 + dvp] * dp[15]) | ||
924 | ) * scalefactor); | ||
925 | |||
926 | tmpOut[i] = pcm_sample; | ||
927 | |||
928 | dvp += 16; | ||
929 | } // for | ||
930 | } | ||
931 | private void compute_pcm_samples2(Obuffer buffer) | ||
932 | { | ||
933 | final float[] vp = actual_v; | ||
934 | |||
935 | //int inc = v_inc; | ||
936 | final float[] tmpOut = _tmpOut; | ||
937 | int dvp =0; | ||
938 | |||
939 | // fat chance of having this loop unroll | ||
940 | for( int i=0; i<32; i++) | ||
941 | { | ||
942 | final float[] dp = d16[i]; | ||
943 | float pcm_sample; | ||
944 | |||
945 | pcm_sample = (float)(((vp[2 + dvp] * dp[0]) + | ||
946 | (vp[1 + dvp] * dp[1]) + | ||
947 | (vp[0 + dvp] * dp[2]) + | ||
948 | (vp[15 + dvp] * dp[3]) + | ||
949 | (vp[14 + dvp] * dp[4]) + | ||
950 | (vp[13 + dvp] * dp[5]) + | ||
951 | (vp[12 + dvp] * dp[6]) + | ||
952 | (vp[11 + dvp] * dp[7]) + | ||
953 | (vp[10 + dvp] * dp[8]) + | ||
954 | (vp[9 + dvp] * dp[9]) + | ||
955 | (vp[8 + dvp] * dp[10]) + | ||
956 | (vp[7 + dvp] * dp[11]) + | ||
957 | (vp[6 + dvp] * dp[12]) + | ||
958 | (vp[5 + dvp] * dp[13]) + | ||
959 | (vp[4 + dvp] * dp[14]) + | ||
960 | (vp[3 + dvp] * dp[15]) | ||
961 | ) * scalefactor); | ||
962 | |||
963 | tmpOut[i] = pcm_sample; | ||
964 | |||
965 | dvp += 16; | ||
966 | } // for | ||
967 | } | ||
968 | |||
969 | private void compute_pcm_samples3(Obuffer buffer) | ||
970 | { | ||
971 | final float[] vp = actual_v; | ||
972 | |||
973 | int idx = 0; | ||
974 | //int inc = v_inc; | ||
975 | final float[] tmpOut = _tmpOut; | ||
976 | int dvp =0; | ||
977 | |||
978 | // fat chance of having this loop unroll | ||
979 | for( int i=0; i<32; i++) | ||
980 | { | ||
981 | final float[] dp = d16[i]; | ||
982 | float pcm_sample; | ||
983 | |||
984 | pcm_sample = (float)(((vp[3 + dvp] * dp[0]) + | ||
985 | (vp[2 + dvp] * dp[1]) + | ||
986 | (vp[1 + dvp] * dp[2]) + | ||
987 | (vp[0 + dvp] * dp[3]) + | ||
988 | (vp[15 + dvp] * dp[4]) + | ||
989 | (vp[14 + dvp] * dp[5]) + | ||
990 | (vp[13 + dvp] * dp[6]) + | ||
991 | (vp[12 + dvp] * dp[7]) + | ||
992 | (vp[11 + dvp] * dp[8]) + | ||
993 | (vp[10 + dvp] * dp[9]) + | ||
994 | (vp[9 + dvp] * dp[10]) + | ||
995 | (vp[8 + dvp] * dp[11]) + | ||
996 | (vp[7 + dvp] * dp[12]) + | ||
997 | (vp[6 + dvp] * dp[13]) + | ||
998 | (vp[5 + dvp] * dp[14]) + | ||
999 | (vp[4 + dvp] * dp[15]) | ||
1000 | ) * scalefactor); | ||
1001 | |||
1002 | tmpOut[i] = pcm_sample; | ||
1003 | |||
1004 | dvp += 16; | ||
1005 | } // for | ||
1006 | } | ||
1007 | |||
1008 | private void compute_pcm_samples4(Obuffer buffer) | ||
1009 | { | ||
1010 | final float[] vp = actual_v; | ||
1011 | |||
1012 | //int inc = v_inc; | ||
1013 | final float[] tmpOut = _tmpOut; | ||
1014 | int dvp =0; | ||
1015 | |||
1016 | // fat chance of having this loop unroll | ||
1017 | for( int i=0; i<32; i++) | ||
1018 | { | ||
1019 | final float[] dp = d16[i]; | ||
1020 | float pcm_sample; | ||
1021 | |||
1022 | pcm_sample = (float)(((vp[4 + dvp] * dp[0]) + | ||
1023 | (vp[3 + dvp] * dp[1]) + | ||
1024 | (vp[2 + dvp] * dp[2]) + | ||
1025 | (vp[1 + dvp] * dp[3]) + | ||
1026 | (vp[0 + dvp] * dp[4]) + | ||
1027 | (vp[15 + dvp] * dp[5]) + | ||
1028 | (vp[14 + dvp] * dp[6]) + | ||
1029 | (vp[13 + dvp] * dp[7]) + | ||
1030 | (vp[12 + dvp] * dp[8]) + | ||
1031 | (vp[11 + dvp] * dp[9]) + | ||
1032 | (vp[10 + dvp] * dp[10]) + | ||
1033 | (vp[9 + dvp] * dp[11]) + | ||
1034 | (vp[8 + dvp] * dp[12]) + | ||
1035 | (vp[7 + dvp] * dp[13]) + | ||
1036 | (vp[6 + dvp] * dp[14]) + | ||
1037 | (vp[5 + dvp] * dp[15]) | ||
1038 | ) * scalefactor); | ||
1039 | |||
1040 | tmpOut[i] = pcm_sample; | ||
1041 | |||
1042 | dvp += 16; | ||
1043 | } // for | ||
1044 | } | ||
1045 | |||
1046 | private void compute_pcm_samples5(Obuffer buffer) | ||
1047 | { | ||
1048 | final float[] vp = actual_v; | ||
1049 | |||
1050 | //int inc = v_inc; | ||
1051 | final float[] tmpOut = _tmpOut; | ||
1052 | int dvp =0; | ||
1053 | |||
1054 | // fat chance of having this loop unroll | ||
1055 | for( int i=0; i<32; i++) | ||
1056 | { | ||
1057 | final float[] dp = d16[i]; | ||
1058 | float pcm_sample; | ||
1059 | |||
1060 | pcm_sample = (float)(((vp[5 + dvp] * dp[0]) + | ||
1061 | (vp[4 + dvp] * dp[1]) + | ||
1062 | (vp[3 + dvp] * dp[2]) + | ||
1063 | (vp[2 + dvp] * dp[3]) + | ||
1064 | (vp[1 + dvp] * dp[4]) + | ||
1065 | (vp[0 + dvp] * dp[5]) + | ||
1066 | (vp[15 + dvp] * dp[6]) + | ||
1067 | (vp[14 + dvp] * dp[7]) + | ||
1068 | (vp[13 + dvp] * dp[8]) + | ||
1069 | (vp[12 + dvp] * dp[9]) + | ||
1070 | (vp[11 + dvp] * dp[10]) + | ||
1071 | (vp[10 + dvp] * dp[11]) + | ||
1072 | (vp[9 + dvp] * dp[12]) + | ||
1073 | (vp[8 + dvp] * dp[13]) + | ||
1074 | (vp[7 + dvp] * dp[14]) + | ||
1075 | (vp[6 + dvp] * dp[15]) | ||
1076 | ) * scalefactor); | ||
1077 | |||
1078 | tmpOut[i] = pcm_sample; | ||
1079 | |||
1080 | dvp += 16; | ||
1081 | } // for | ||
1082 | } | ||
1083 | |||
1084 | private void compute_pcm_samples6(Obuffer buffer) | ||
1085 | { | ||
1086 | final float[] vp = actual_v; | ||
1087 | //int inc = v_inc; | ||
1088 | final float[] tmpOut = _tmpOut; | ||
1089 | int dvp =0; | ||
1090 | |||
1091 | // fat chance of having this loop unroll | ||
1092 | for( int i=0; i<32; i++) | ||
1093 | { | ||
1094 | final float[] dp = d16[i]; | ||
1095 | float pcm_sample; | ||
1096 | |||
1097 | pcm_sample = (float)(((vp[6 + dvp] * dp[0]) + | ||
1098 | (vp[5 + dvp] * dp[1]) + | ||
1099 | (vp[4 + dvp] * dp[2]) + | ||
1100 | (vp[3 + dvp] * dp[3]) + | ||
1101 | (vp[2 + dvp] * dp[4]) + | ||
1102 | (vp[1 + dvp] * dp[5]) + | ||
1103 | (vp[0 + dvp] * dp[6]) + | ||
1104 | (vp[15 + dvp] * dp[7]) + | ||
1105 | (vp[14 + dvp] * dp[8]) + | ||
1106 | (vp[13 + dvp] * dp[9]) + | ||
1107 | (vp[12 + dvp] * dp[10]) + | ||
1108 | (vp[11 + dvp] * dp[11]) + | ||
1109 | (vp[10 + dvp] * dp[12]) + | ||
1110 | (vp[9 + dvp] * dp[13]) + | ||
1111 | (vp[8 + dvp] * dp[14]) + | ||
1112 | (vp[7 + dvp] * dp[15]) | ||
1113 | ) * scalefactor); | ||
1114 | |||
1115 | tmpOut[i] = pcm_sample; | ||
1116 | |||
1117 | dvp += 16; | ||
1118 | } // for | ||
1119 | } | ||
1120 | |||
1121 | private void compute_pcm_samples7(Obuffer buffer) | ||
1122 | { | ||
1123 | final float[] vp = actual_v; | ||
1124 | |||
1125 | //int inc = v_inc; | ||
1126 | final float[] tmpOut = _tmpOut; | ||
1127 | int dvp =0; | ||
1128 | |||
1129 | // fat chance of having this loop unroll | ||
1130 | for( int i=0; i<32; i++) | ||
1131 | { | ||
1132 | final float[] dp = d16[i]; | ||
1133 | float pcm_sample; | ||
1134 | |||
1135 | pcm_sample = (float)(((vp[7 + dvp] * dp[0]) + | ||
1136 | (vp[6 + dvp] * dp[1]) + | ||
1137 | (vp[5 + dvp] * dp[2]) + | ||
1138 | (vp[4 + dvp] * dp[3]) + | ||
1139 | (vp[3 + dvp] * dp[4]) + | ||
1140 | (vp[2 + dvp] * dp[5]) + | ||
1141 | (vp[1 + dvp] * dp[6]) + | ||
1142 | (vp[0 + dvp] * dp[7]) + | ||
1143 | (vp[15 + dvp] * dp[8]) + | ||
1144 | (vp[14 + dvp] * dp[9]) + | ||
1145 | (vp[13 + dvp] * dp[10]) + | ||
1146 | (vp[12 + dvp] * dp[11]) + | ||
1147 | (vp[11 + dvp] * dp[12]) + | ||
1148 | (vp[10 + dvp] * dp[13]) + | ||
1149 | (vp[9 + dvp] * dp[14]) + | ||
1150 | (vp[8 + dvp] * dp[15]) | ||
1151 | ) * scalefactor); | ||
1152 | |||
1153 | tmpOut[i] = pcm_sample; | ||
1154 | |||
1155 | dvp += 16; | ||
1156 | } // for | ||
1157 | } | ||
1158 | private void compute_pcm_samples8(Obuffer buffer) | ||
1159 | { | ||
1160 | final float[] vp = actual_v; | ||
1161 | |||
1162 | //int inc = v_inc; | ||
1163 | final float[] tmpOut = _tmpOut; | ||
1164 | int dvp =0; | ||
1165 | |||
1166 | // fat chance of having this loop unroll | ||
1167 | for( int i=0; i<32; i++) | ||
1168 | { | ||
1169 | final float[] dp = d16[i]; | ||
1170 | float pcm_sample; | ||
1171 | |||
1172 | pcm_sample = (float)(((vp[8 + dvp] * dp[0]) + | ||
1173 | (vp[7 + dvp] * dp[1]) + | ||
1174 | (vp[6 + dvp] * dp[2]) + | ||
1175 | (vp[5 + dvp] * dp[3]) + | ||
1176 | (vp[4 + dvp] * dp[4]) + | ||
1177 | (vp[3 + dvp] * dp[5]) + | ||
1178 | (vp[2 + dvp] * dp[6]) + | ||
1179 | (vp[1 + dvp] * dp[7]) + | ||
1180 | (vp[0 + dvp] * dp[8]) + | ||
1181 | (vp[15 + dvp] * dp[9]) + | ||
1182 | (vp[14 + dvp] * dp[10]) + | ||
1183 | (vp[13 + dvp] * dp[11]) + | ||
1184 | (vp[12 + dvp] * dp[12]) + | ||
1185 | (vp[11 + dvp] * dp[13]) + | ||
1186 | (vp[10 + dvp] * dp[14]) + | ||
1187 | (vp[9 + dvp] * dp[15]) | ||
1188 | ) * scalefactor); | ||
1189 | |||
1190 | tmpOut[i] = pcm_sample; | ||
1191 | |||
1192 | dvp += 16; | ||
1193 | } // for | ||
1194 | } | ||
1195 | |||
1196 | private void compute_pcm_samples9(Obuffer buffer) | ||
1197 | { | ||
1198 | final float[] vp = actual_v; | ||
1199 | |||
1200 | //int inc = v_inc; | ||
1201 | final float[] tmpOut = _tmpOut; | ||
1202 | int dvp =0; | ||
1203 | |||
1204 | // fat chance of having this loop unroll | ||
1205 | for( int i=0; i<32; i++) | ||
1206 | { | ||
1207 | final float[] dp = d16[i]; | ||
1208 | float pcm_sample; | ||
1209 | |||
1210 | pcm_sample = (float)(((vp[9 + dvp] * dp[0]) + | ||
1211 | (vp[8 + dvp] * dp[1]) + | ||
1212 | (vp[7 + dvp] * dp[2]) + | ||
1213 | (vp[6 + dvp] * dp[3]) + | ||
1214 | (vp[5 + dvp] * dp[4]) + | ||
1215 | (vp[4 + dvp] * dp[5]) + | ||
1216 | (vp[3 + dvp] * dp[6]) + | ||
1217 | (vp[2 + dvp] * dp[7]) + | ||
1218 | (vp[1 + dvp] * dp[8]) + | ||
1219 | (vp[0 + dvp] * dp[9]) + | ||
1220 | (vp[15 + dvp] * dp[10]) + | ||
1221 | (vp[14 + dvp] * dp[11]) + | ||
1222 | (vp[13 + dvp] * dp[12]) + | ||
1223 | (vp[12 + dvp] * dp[13]) + | ||
1224 | (vp[11 + dvp] * dp[14]) + | ||
1225 | (vp[10 + dvp] * dp[15]) | ||
1226 | ) * scalefactor); | ||
1227 | |||
1228 | tmpOut[i] = pcm_sample; | ||
1229 | |||
1230 | dvp += 16; | ||
1231 | } // for | ||
1232 | } | ||
1233 | |||
1234 | private void compute_pcm_samples10(Obuffer buffer) | ||
1235 | { | ||
1236 | final float[] vp = actual_v; | ||
1237 | //int inc = v_inc; | ||
1238 | final float[] tmpOut = _tmpOut; | ||
1239 | int dvp =0; | ||
1240 | |||
1241 | // fat chance of having this loop unroll | ||
1242 | for( int i=0; i<32; i++) | ||
1243 | { | ||
1244 | final float[] dp = d16[i]; | ||
1245 | float pcm_sample; | ||
1246 | |||
1247 | pcm_sample = (float)(((vp[10 + dvp] * dp[0]) + | ||
1248 | (vp[9 + dvp] * dp[1]) + | ||
1249 | (vp[8 + dvp] * dp[2]) + | ||
1250 | (vp[7 + dvp] * dp[3]) + | ||
1251 | (vp[6 + dvp] * dp[4]) + | ||
1252 | (vp[5 + dvp] * dp[5]) + | ||
1253 | (vp[4 + dvp] * dp[6]) + | ||
1254 | (vp[3 + dvp] * dp[7]) + | ||
1255 | (vp[2 + dvp] * dp[8]) + | ||
1256 | (vp[1 + dvp] * dp[9]) + | ||
1257 | (vp[0 + dvp] * dp[10]) + | ||
1258 | (vp[15 + dvp] * dp[11]) + | ||
1259 | (vp[14 + dvp] * dp[12]) + | ||
1260 | (vp[13 + dvp] * dp[13]) + | ||
1261 | (vp[12 + dvp] * dp[14]) + | ||
1262 | (vp[11 + dvp] * dp[15]) | ||
1263 | ) * scalefactor); | ||
1264 | |||
1265 | tmpOut[i] = pcm_sample; | ||
1266 | |||
1267 | dvp += 16; | ||
1268 | } // for | ||
1269 | } | ||
1270 | private void compute_pcm_samples11(Obuffer buffer) | ||
1271 | { | ||
1272 | final float[] vp = actual_v; | ||
1273 | |||
1274 | //int inc = v_inc; | ||
1275 | final float[] tmpOut = _tmpOut; | ||
1276 | int dvp =0; | ||
1277 | |||
1278 | // fat chance of having this loop unroll | ||
1279 | for( int i=0; i<32; i++) | ||
1280 | { | ||
1281 | final float[] dp = d16[i]; | ||
1282 | float pcm_sample; | ||
1283 | |||
1284 | pcm_sample = (float)(((vp[11 + dvp] * dp[0]) + | ||
1285 | (vp[10 + dvp] * dp[1]) + | ||
1286 | (vp[9 + dvp] * dp[2]) + | ||
1287 | (vp[8 + dvp] * dp[3]) + | ||
1288 | (vp[7 + dvp] * dp[4]) + | ||
1289 | (vp[6 + dvp] * dp[5]) + | ||
1290 | (vp[5 + dvp] * dp[6]) + | ||
1291 | (vp[4 + dvp] * dp[7]) + | ||
1292 | (vp[3 + dvp] * dp[8]) + | ||
1293 | (vp[2 + dvp] * dp[9]) + | ||
1294 | (vp[1 + dvp] * dp[10]) + | ||
1295 | (vp[0 + dvp] * dp[11]) + | ||
1296 | (vp[15 + dvp] * dp[12]) + | ||
1297 | (vp[14 + dvp] * dp[13]) + | ||
1298 | (vp[13 + dvp] * dp[14]) + | ||
1299 | (vp[12 + dvp] * dp[15]) | ||
1300 | ) * scalefactor); | ||
1301 | |||
1302 | tmpOut[i] = pcm_sample; | ||
1303 | |||
1304 | dvp += 16; | ||
1305 | } // for | ||
1306 | } | ||
1307 | private void compute_pcm_samples12(Obuffer buffer) | ||
1308 | { | ||
1309 | final float[] vp = actual_v; | ||
1310 | //int inc = v_inc; | ||
1311 | final float[] tmpOut = _tmpOut; | ||
1312 | int dvp =0; | ||
1313 | |||
1314 | // fat chance of having this loop unroll | ||
1315 | for( int i=0; i<32; i++) | ||
1316 | { | ||
1317 | final float[] dp = d16[i]; | ||
1318 | float pcm_sample; | ||
1319 | |||
1320 | pcm_sample = (float)(((vp[12 + dvp] * dp[0]) + | ||
1321 | (vp[11 + dvp] * dp[1]) + | ||
1322 | (vp[10 + dvp] * dp[2]) + | ||
1323 | (vp[9 + dvp] * dp[3]) + | ||
1324 | (vp[8 + dvp] * dp[4]) + | ||
1325 | (vp[7 + dvp] * dp[5]) + | ||
1326 | (vp[6 + dvp] * dp[6]) + | ||
1327 | (vp[5 + dvp] * dp[7]) + | ||
1328 | (vp[4 + dvp] * dp[8]) + | ||
1329 | (vp[3 + dvp] * dp[9]) + | ||
1330 | (vp[2 + dvp] * dp[10]) + | ||
1331 | (vp[1 + dvp] * dp[11]) + | ||
1332 | (vp[0 + dvp] * dp[12]) + | ||
1333 | (vp[15 + dvp] * dp[13]) + | ||
1334 | (vp[14 + dvp] * dp[14]) + | ||
1335 | (vp[13 + dvp] * dp[15]) | ||
1336 | ) * scalefactor); | ||
1337 | |||
1338 | tmpOut[i] = pcm_sample; | ||
1339 | |||
1340 | dvp += 16; | ||
1341 | } // for | ||
1342 | } | ||
1343 | private void compute_pcm_samples13(Obuffer buffer) | ||
1344 | { | ||
1345 | final float[] vp = actual_v; | ||
1346 | |||
1347 | //int inc = v_inc; | ||
1348 | final float[] tmpOut = _tmpOut; | ||
1349 | int dvp =0; | ||
1350 | |||
1351 | // fat chance of having this loop unroll | ||
1352 | for( int i=0; i<32; i++) | ||
1353 | { | ||
1354 | final float[] dp = d16[i]; | ||
1355 | float pcm_sample; | ||
1356 | |||
1357 | pcm_sample = (float)(((vp[13 + dvp] * dp[0]) + | ||
1358 | (vp[12 + dvp] * dp[1]) + | ||
1359 | (vp[11 + dvp] * dp[2]) + | ||
1360 | (vp[10 + dvp] * dp[3]) + | ||
1361 | (vp[9 + dvp] * dp[4]) + | ||
1362 | (vp[8 + dvp] * dp[5]) + | ||
1363 | (vp[7 + dvp] * dp[6]) + | ||
1364 | (vp[6 + dvp] * dp[7]) + | ||
1365 | (vp[5 + dvp] * dp[8]) + | ||
1366 | (vp[4 + dvp] * dp[9]) + | ||
1367 | (vp[3 + dvp] * dp[10]) + | ||
1368 | (vp[2 + dvp] * dp[11]) + | ||
1369 | (vp[1 + dvp] * dp[12]) + | ||
1370 | (vp[0 + dvp] * dp[13]) + | ||
1371 | (vp[15 + dvp] * dp[14]) + | ||
1372 | (vp[14 + dvp] * dp[15]) | ||
1373 | ) * scalefactor); | ||
1374 | |||
1375 | tmpOut[i] = pcm_sample; | ||
1376 | |||
1377 | dvp += 16; | ||
1378 | } // for | ||
1379 | } | ||
1380 | private void compute_pcm_samples14(Obuffer buffer) | ||
1381 | { | ||
1382 | final float[] vp = actual_v; | ||
1383 | |||
1384 | //int inc = v_inc; | ||
1385 | final float[] tmpOut = _tmpOut; | ||
1386 | int dvp =0; | ||
1387 | |||
1388 | // fat chance of having this loop unroll | ||
1389 | for( int i=0; i<32; i++) | ||
1390 | { | ||
1391 | final float[] dp = d16[i]; | ||
1392 | float pcm_sample; | ||
1393 | |||
1394 | pcm_sample = (float)(((vp[14 + dvp] * dp[0]) + | ||
1395 | (vp[13 + dvp] * dp[1]) + | ||
1396 | (vp[12 + dvp] * dp[2]) + | ||
1397 | (vp[11 + dvp] * dp[3]) + | ||
1398 | (vp[10 + dvp] * dp[4]) + | ||
1399 | (vp[9 + dvp] * dp[5]) + | ||
1400 | (vp[8 + dvp] * dp[6]) + | ||
1401 | (vp[7 + dvp] * dp[7]) + | ||
1402 | (vp[6 + dvp] * dp[8]) + | ||
1403 | (vp[5 + dvp] * dp[9]) + | ||
1404 | (vp[4 + dvp] * dp[10]) + | ||
1405 | (vp[3 + dvp] * dp[11]) + | ||
1406 | (vp[2 + dvp] * dp[12]) + | ||
1407 | (vp[1 + dvp] * dp[13]) + | ||
1408 | (vp[0 + dvp] * dp[14]) + | ||
1409 | (vp[15 + dvp] * dp[15]) | ||
1410 | ) * scalefactor); | ||
1411 | |||
1412 | tmpOut[i] = pcm_sample; | ||
1413 | |||
1414 | dvp += 16; | ||
1415 | } // for | ||
1416 | } | ||
1417 | private void compute_pcm_samples15(Obuffer buffer) | ||
1418 | { | ||
1419 | final float[] vp = actual_v; | ||
1420 | |||
1421 | //int inc = v_inc; | ||
1422 | final float[] tmpOut = _tmpOut; | ||
1423 | int dvp =0; | ||
1424 | |||
1425 | // fat chance of having this loop unroll | ||
1426 | for( int i=0; i<32; i++) | ||
1427 | { | ||
1428 | float pcm_sample; | ||
1429 | final float dp[] = d16[i]; | ||
1430 | pcm_sample = (float)(((vp[15 + dvp] * dp[0]) + | ||
1431 | (vp[14 + dvp] * dp[1]) + | ||
1432 | (vp[13 + dvp] * dp[2]) + | ||
1433 | (vp[12 + dvp] * dp[3]) + | ||
1434 | (vp[11 + dvp] * dp[4]) + | ||
1435 | (vp[10 + dvp] * dp[5]) + | ||
1436 | (vp[9 + dvp] * dp[6]) + | ||
1437 | (vp[8 + dvp] * dp[7]) + | ||
1438 | (vp[7 + dvp] * dp[8]) + | ||
1439 | (vp[6 + dvp] * dp[9]) + | ||
1440 | (vp[5 + dvp] * dp[10]) + | ||
1441 | (vp[4 + dvp] * dp[11]) + | ||
1442 | (vp[3 + dvp] * dp[12]) + | ||
1443 | (vp[2 + dvp] * dp[13]) + | ||
1444 | (vp[1 + dvp] * dp[14]) + | ||
1445 | (vp[0 + dvp] * dp[15]) | ||
1446 | ) * scalefactor); | ||
1447 | |||
1448 | tmpOut[i] = pcm_sample; | ||
1449 | dvp += 16; | ||
1450 | } // for | ||
1451 | } | ||
1452 | |||
1453 | private void compute_pcm_samples(Obuffer buffer) | ||
1454 | { | ||
1455 | |||
1456 | switch (actual_write_pos) | ||
1457 | { | ||
1458 | case 0: | ||
1459 | compute_pcm_samples0(buffer); | ||
1460 | break; | ||
1461 | case 1: | ||
1462 | compute_pcm_samples1(buffer); | ||
1463 | break; | ||
1464 | case 2: | ||
1465 | compute_pcm_samples2(buffer); | ||
1466 | break; | ||
1467 | case 3: | ||
1468 | compute_pcm_samples3(buffer); | ||
1469 | break; | ||
1470 | case 4: | ||
1471 | compute_pcm_samples4(buffer); | ||
1472 | break; | ||
1473 | case 5: | ||
1474 | compute_pcm_samples5(buffer); | ||
1475 | break; | ||
1476 | case 6: | ||
1477 | compute_pcm_samples6(buffer); | ||
1478 | break; | ||
1479 | case 7: | ||
1480 | compute_pcm_samples7(buffer); | ||
1481 | break; | ||
1482 | case 8: | ||
1483 | compute_pcm_samples8(buffer); | ||
1484 | break; | ||
1485 | case 9: | ||
1486 | compute_pcm_samples9(buffer); | ||
1487 | break; | ||
1488 | case 10: | ||
1489 | compute_pcm_samples10(buffer); | ||
1490 | break; | ||
1491 | case 11: | ||
1492 | compute_pcm_samples11(buffer); | ||
1493 | break; | ||
1494 | case 12: | ||
1495 | compute_pcm_samples12(buffer); | ||
1496 | break; | ||
1497 | case 13: | ||
1498 | compute_pcm_samples13(buffer); | ||
1499 | break; | ||
1500 | case 14: | ||
1501 | compute_pcm_samples14(buffer); | ||
1502 | break; | ||
1503 | case 15: | ||
1504 | compute_pcm_samples15(buffer); | ||
1505 | break; | ||
1506 | } | ||
1507 | |||
1508 | if (buffer!=null) | ||
1509 | { | ||
1510 | buffer.appendSamples(channel, _tmpOut); | ||
1511 | } | ||
1512 | |||
1513 | /* | ||
1514 | // MDM: I was considering putting in quality control for | ||
1515 | // low-spec CPUs, but the performance gain (about 10-15%) | ||
1516 | // did not justify the considerable drop in audio quality. | ||
1517 | switch (inc) | ||
1518 | { | ||
1519 | case 16: | ||
1520 | buffer.appendSamples(channel, tmpOut); | ||
1521 | break; | ||
1522 | case 32: | ||
1523 | for (int i=0; i<16; i++) | ||
1524 | { | ||
1525 | buffer.append(channel, (short)tmpOut[i]); | ||
1526 | buffer.append(channel, (short)tmpOut[i]); | ||
1527 | } | ||
1528 | break; | ||
1529 | case 64: | ||
1530 | for (int i=0; i<8; i++) | ||
1531 | { | ||
1532 | buffer.append(channel, (short)tmpOut[i]); | ||
1533 | buffer.append(channel, (short)tmpOut[i]); | ||
1534 | buffer.append(channel, (short)tmpOut[i]); | ||
1535 | buffer.append(channel, (short)tmpOut[i]); | ||
1536 | } | ||
1537 | break; | ||
1538 | |||
1539 | } | ||
1540 | */ | ||
1541 | } | ||
1542 | |||
1543 | /** | ||
1544 | * Calculate 32 PCM samples and put the into the Obuffer-object. | ||
1545 | */ | ||
1546 | |||
1547 | public void calculate_pcm_samples(Obuffer buffer) | ||
1548 | { | ||
1549 | compute_new_v(); | ||
1550 | compute_pcm_samples(buffer); | ||
1551 | |||
1552 | actual_write_pos = (actual_write_pos + 1) & 0xf; | ||
1553 | actual_v = (actual_v == v1) ? v2 : v1; | ||
1554 | |||
1555 | // initialize samples[]: | ||
1556 | //for (register float *floatp = samples + 32; floatp > samples; ) | ||
1557 | // *--floatp = 0.0f; | ||
1558 | |||
1559 | // MDM: this may not be necessary. The Layer III decoder always | ||
1560 | // outputs 32 subband samples, but I haven't checked layer I & II. | ||
1561 | for (int p=0;p<32;p++) | ||
1562 | samples[p] = 0.0f; | ||
1563 | } | ||
1564 | |||
1565 | |||
1566 | private static final double MY_PI = 3.14159265358979323846; | ||
1567 | private static final float cos1_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 64.0))); | ||
1568 | private static final float cos3_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 3.0 / 64.0))); | ||
1569 | private static final float cos5_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 5.0 / 64.0))); | ||
1570 | private static final float cos7_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 7.0 / 64.0))); | ||
1571 | private static final float cos9_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 9.0 / 64.0))); | ||
1572 | private static final float cos11_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 11.0 / 64.0))); | ||
1573 | private static final float cos13_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 13.0 / 64.0))); | ||
1574 | private static final float cos15_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 15.0 / 64.0))); | ||
1575 | private static final float cos17_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 17.0 / 64.0))); | ||
1576 | private static final float cos19_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 19.0 / 64.0))); | ||
1577 | private static final float cos21_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 21.0 / 64.0))); | ||
1578 | private static final float cos23_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 23.0 / 64.0))); | ||
1579 | private static final float cos25_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 25.0 / 64.0))); | ||
1580 | private static final float cos27_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 27.0 / 64.0))); | ||
1581 | private static final float cos29_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 29.0 / 64.0))); | ||
1582 | private static final float cos31_64 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 31.0 / 64.0))); | ||
1583 | private static final float cos1_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 32.0))); | ||
1584 | private static final float cos3_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 3.0 / 32.0))); | ||
1585 | private static final float cos5_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 5.0 / 32.0))); | ||
1586 | private static final float cos7_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 7.0 / 32.0))); | ||
1587 | private static final float cos9_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 9.0 / 32.0))); | ||
1588 | private static final float cos11_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 11.0 / 32.0))); | ||
1589 | private static final float cos13_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 13.0 / 32.0))); | ||
1590 | private static final float cos15_32 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 15.0 / 32.0))); | ||
1591 | private static final float cos1_16 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 16.0))); | ||
1592 | private static final float cos3_16 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 3.0 / 16.0))); | ||
1593 | private static final float cos5_16 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 5.0 / 16.0))); | ||
1594 | private static final float cos7_16 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 7.0 / 16.0))); | ||
1595 | private static final float cos1_8 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 8.0))); | ||
1596 | private static final float cos3_8 =(float) (1.0 / (2.0 * Math.cos(MY_PI * 3.0 / 8.0))); | ||
1597 | private static final float cos1_4 =(float) (1.0 / (2.0 * Math.cos(MY_PI / 4.0))); | ||
1598 | |||
1599 | // Note: These values are not in the same order | ||
1600 | // as in Annex 3-B.3 of the ISO/IEC DIS 11172-3 | ||
1601 | // private float d[] = {0.000000000, -4.000442505}; | ||
1602 | |||
1603 | private static float d[] = null; | ||
1604 | |||
1605 | /** | ||
1606 | * d[] split into subarrays of length 16. This provides for | ||
1607 | * more faster access by allowing a block of 16 to be addressed | ||
1608 | * with constant offset. | ||
1609 | **/ | ||
1610 | private static float d16[][] = null; | ||
1611 | |||
1612 | /** | ||
1613 | * Loads the data for the d[] from the resource SFd.ser. | ||
1614 | * @return the loaded values for d[]. | ||
1615 | */ | ||
1616 | static private float[] load_d() | ||
1617 | { | ||
1618 | try | ||
1619 | { | ||
1620 | Class elemType = Float.TYPE; | ||
1621 | Object o = JavaLayerUtils.deserializeArrayResource("sfd.ser", elemType, 512); | ||
1622 | return (float[])o; | ||
1623 | } | ||
1624 | catch (IOException ex) | ||
1625 | { | ||
1626 | throw new ExceptionInInitializerError(ex); | ||
1627 | } | ||
1628 | } | ||
1629 | |||
1630 | /** | ||
1631 | * Converts a 1D array into a number of smaller arrays. This is used | ||
1632 | * to achieve offset + constant indexing into an array. Each sub-array | ||
1633 | * represents a block of values of the original array. | ||
1634 | * @param array The array to split up into blocks. | ||
1635 | * @param blockSize The size of the blocks to split the array | ||
1636 | * into. This must be an exact divisor of | ||
1637 | * the length of the array, or some data | ||
1638 | * will be lost from the main array. | ||
1639 | * | ||
1640 | * @return An array of arrays in which each element in the returned | ||
1641 | * array will be of length <code>blockSize</code>. | ||
1642 | */ | ||
1643 | static private float[][] splitArray(final float[] array, final int blockSize) | ||
1644 | { | ||
1645 | int size = array.length / blockSize; | ||
1646 | float[][] split = new float[size][]; | ||
1647 | for (int i=0; i<size; i++) | ||
1648 | { | ||
1649 | split[i] = subArray(array, i*blockSize, blockSize); | ||
1650 | } | ||
1651 | return split; | ||
1652 | } | ||
1653 | |||
1654 | /** | ||
1655 | * Returns a subarray of an existing array. | ||
1656 | * | ||
1657 | * @param array The array to retrieve a subarra from. | ||
1658 | * @param offs The offset in the array that corresponds to | ||
1659 | * the first index of the subarray. | ||
1660 | * @param len The number of indeces in the subarray. | ||
1661 | * @return The subarray, which may be of length 0. | ||
1662 | */ | ||
1663 | static private float[] subArray(final float[] array, final int offs, int len) | ||
1664 | { | ||
1665 | if (offs+len > array.length) | ||
1666 | { | ||
1667 | len = array.length-offs; | ||
1668 | } | ||
1669 | |||
1670 | if (len < 0) | ||
1671 | len = 0; | ||
1672 | |||
1673 | float[] subarray = new float[len]; | ||
1674 | for (int i=0; i<len; i++) | ||
1675 | { | ||
1676 | subarray[i] = array[offs+i]; | ||
1677 | } | ||
1678 | |||
1679 | return subarray; | ||
1680 | } | ||
1681 | |||
1682 | // The original data for d[]. This data is loaded from a file | ||
1683 | // to reduce the overall package size and to improve performance. | ||
1684 | /* | ||
1685 | static final float d_data[] = { | ||
1686 | 0.000000000f, -0.000442505f, 0.003250122f, -0.007003784f, | ||
1687 | 0.031082153f, -0.078628540f, 0.100311279f, -0.572036743f, | ||
1688 | 1.144989014f, 0.572036743f, 0.100311279f, 0.078628540f, | ||
1689 | 0.031082153f, 0.007003784f, 0.003250122f, 0.000442505f, | ||
1690 | -0.000015259f, -0.000473022f, 0.003326416f, -0.007919312f, | ||
1691 | 0.030517578f, -0.084182739f, 0.090927124f, -0.600219727f, | ||
1692 | 1.144287109f, 0.543823242f, 0.108856201f, 0.073059082f, | ||
1693 | 0.031478882f, 0.006118774f, 0.003173828f, 0.000396729f, | ||
1694 | -0.000015259f, -0.000534058f, 0.003387451f, -0.008865356f, | ||
1695 | 0.029785156f, -0.089706421f, 0.080688477f, -0.628295898f, | ||
1696 | 1.142211914f, 0.515609741f, 0.116577148f, 0.067520142f, | ||
1697 | 0.031738281f, 0.005294800f, 0.003082275f, 0.000366211f, | ||
1698 | -0.000015259f, -0.000579834f, 0.003433228f, -0.009841919f, | ||
1699 | 0.028884888f, -0.095169067f, 0.069595337f, -0.656219482f, | ||
1700 | 1.138763428f, 0.487472534f, 0.123474121f, 0.061996460f, | ||
1701 | 0.031845093f, 0.004486084f, 0.002990723f, 0.000320435f, | ||
1702 | -0.000015259f, -0.000625610f, 0.003463745f, -0.010848999f, | ||
1703 | 0.027801514f, -0.100540161f, 0.057617188f, -0.683914185f, | ||
1704 | 1.133926392f, 0.459472656f, 0.129577637f, 0.056533813f, | ||
1705 | 0.031814575f, 0.003723145f, 0.002899170f, 0.000289917f, | ||
1706 | -0.000015259f, -0.000686646f, 0.003479004f, -0.011886597f, | ||
1707 | 0.026535034f, -0.105819702f, 0.044784546f, -0.711318970f, | ||
1708 | 1.127746582f, 0.431655884f, 0.134887695f, 0.051132202f, | ||
1709 | 0.031661987f, 0.003005981f, 0.002792358f, 0.000259399f, | ||
1710 | -0.000015259f, -0.000747681f, 0.003479004f, -0.012939453f, | ||
1711 | 0.025085449f, -0.110946655f, 0.031082153f, -0.738372803f, | ||
1712 | 1.120223999f, 0.404083252f, 0.139450073f, 0.045837402f, | ||
1713 | 0.031387329f, 0.002334595f, 0.002685547f, 0.000244141f, | ||
1714 | -0.000030518f, -0.000808716f, 0.003463745f, -0.014022827f, | ||
1715 | 0.023422241f, -0.115921021f, 0.016510010f, -0.765029907f, | ||
1716 | 1.111373901f, 0.376800537f, 0.143264771f, 0.040634155f, | ||
1717 | 0.031005859f, 0.001693726f, 0.002578735f, 0.000213623f, | ||
1718 | -0.000030518f, -0.000885010f, 0.003417969f, -0.015121460f, | ||
1719 | 0.021575928f, -0.120697021f, 0.001068115f, -0.791213989f, | ||
1720 | 1.101211548f, 0.349868774f, 0.146362305f, 0.035552979f, | ||
1721 | 0.030532837f, 0.001098633f, 0.002456665f, 0.000198364f, | ||
1722 | -0.000030518f, -0.000961304f, 0.003372192f, -0.016235352f, | ||
1723 | 0.019531250f, -0.125259399f, -0.015228271f, -0.816864014f, | ||
1724 | 1.089782715f, 0.323318481f, 0.148773193f, 0.030609131f, | ||
1725 | 0.029937744f, 0.000549316f, 0.002349854f, 0.000167847f, | ||
1726 | -0.000030518f, -0.001037598f, 0.003280640f, -0.017349243f, | ||
1727 | 0.017257690f, -0.129562378f, -0.032379150f, -0.841949463f, | ||
1728 | 1.077117920f, 0.297210693f, 0.150497437f, 0.025817871f, | ||
1729 | 0.029281616f, 0.000030518f, 0.002243042f, 0.000152588f, | ||
1730 | -0.000045776f, -0.001113892f, 0.003173828f, -0.018463135f, | ||
1731 | 0.014801025f, -0.133590698f, -0.050354004f, -0.866363525f, | ||
1732 | 1.063217163f, 0.271591187f, 0.151596069f, 0.021179199f, | ||
1733 | 0.028533936f, -0.000442505f, 0.002120972f, 0.000137329f, | ||
1734 | -0.000045776f, -0.001205444f, 0.003051758f, -0.019577026f, | ||
1735 | 0.012115479f, -0.137298584f, -0.069168091f, -0.890090942f, | ||
1736 | 1.048156738f, 0.246505737f, 0.152069092f, 0.016708374f, | ||
1737 | 0.027725220f, -0.000869751f, 0.002014160f, 0.000122070f, | ||
1738 | -0.000061035f, -0.001296997f, 0.002883911f, -0.020690918f, | ||
1739 | 0.009231567f, -0.140670776f, -0.088775635f, -0.913055420f, | ||
1740 | 1.031936646f, 0.221984863f, 0.151962280f, 0.012420654f, | ||
1741 | 0.026840210f, -0.001266479f, 0.001907349f, 0.000106812f, | ||
1742 | -0.000061035f, -0.001388550f, 0.002700806f, -0.021789551f, | ||
1743 | 0.006134033f, -0.143676758f, -0.109161377f, -0.935195923f, | ||
1744 | 1.014617920f, 0.198059082f, 0.151306152f, 0.008316040f, | ||
1745 | 0.025909424f, -0.001617432f, 0.001785278f, 0.000106812f, | ||
1746 | -0.000076294f, -0.001480103f, 0.002487183f, -0.022857666f, | ||
1747 | 0.002822876f, -0.146255493f, -0.130310059f, -0.956481934f, | ||
1748 | 0.996246338f, 0.174789429f, 0.150115967f, 0.004394531f, | ||
1749 | 0.024932861f, -0.001937866f, 0.001693726f, 0.000091553f, | ||
1750 | -0.000076294f, -0.001586914f, 0.002227783f, -0.023910522f, | ||
1751 | -0.000686646f, -0.148422241f, -0.152206421f, -0.976852417f, | ||
1752 | 0.976852417f, 0.152206421f, 0.148422241f, 0.000686646f, | ||
1753 | 0.023910522f, -0.002227783f, 0.001586914f, 0.000076294f, | ||
1754 | -0.000091553f, -0.001693726f, 0.001937866f, -0.024932861f, | ||
1755 | -0.004394531f, -0.150115967f, -0.174789429f, -0.996246338f, | ||
1756 | 0.956481934f, 0.130310059f, 0.146255493f, -0.002822876f, | ||
1757 | 0.022857666f, -0.002487183f, 0.001480103f, 0.000076294f, | ||
1758 | -0.000106812f, -0.001785278f, 0.001617432f, -0.025909424f, | ||
1759 | -0.008316040f, -0.151306152f, -0.198059082f, -1.014617920f, | ||
1760 | 0.935195923f, 0.109161377f, 0.143676758f, -0.006134033f, | ||
1761 | 0.021789551f, -0.002700806f, 0.001388550f, 0.000061035f, | ||
1762 | -0.000106812f, -0.001907349f, 0.001266479f, -0.026840210f, | ||
1763 | -0.012420654f, -0.151962280f, -0.221984863f, -1.031936646f, | ||
1764 | 0.913055420f, 0.088775635f, 0.140670776f, -0.009231567f, | ||
1765 | 0.020690918f, -0.002883911f, 0.001296997f, 0.000061035f, | ||
1766 | -0.000122070f, -0.002014160f, 0.000869751f, -0.027725220f, | ||
1767 | -0.016708374f, -0.152069092f, -0.246505737f, -1.048156738f, | ||
1768 | 0.890090942f, 0.069168091f, 0.137298584f, -0.012115479f, | ||
1769 | 0.019577026f, -0.003051758f, 0.001205444f, 0.000045776f, | ||
1770 | -0.000137329f, -0.002120972f, 0.000442505f, -0.028533936f, | ||
1771 | -0.021179199f, -0.151596069f, -0.271591187f, -1.063217163f, | ||
1772 | 0.866363525f, 0.050354004f, 0.133590698f, -0.014801025f, | ||
1773 | 0.018463135f, -0.003173828f, 0.001113892f, 0.000045776f, | ||
1774 | -0.000152588f, -0.002243042f, -0.000030518f, -0.029281616f, | ||
1775 | -0.025817871f, -0.150497437f, -0.297210693f, -1.077117920f, | ||
1776 | 0.841949463f, 0.032379150f, 0.129562378f, -0.017257690f, | ||
1777 | 0.017349243f, -0.003280640f, 0.001037598f, 0.000030518f, | ||
1778 | -0.000167847f, -0.002349854f, -0.000549316f, -0.029937744f, | ||
1779 | -0.030609131f, -0.148773193f, -0.323318481f, -1.089782715f, | ||
1780 | 0.816864014f, 0.015228271f, 0.125259399f, -0.019531250f, | ||
1781 | 0.016235352f, -0.003372192f, 0.000961304f, 0.000030518f, | ||
1782 | -0.000198364f, -0.002456665f, -0.001098633f, -0.030532837f, | ||
1783 | -0.035552979f, -0.146362305f, -0.349868774f, -1.101211548f, | ||
1784 | 0.791213989f, -0.001068115f, 0.120697021f, -0.021575928f, | ||
1785 | 0.015121460f, -0.003417969f, 0.000885010f, 0.000030518f, | ||
1786 | -0.000213623f, -0.002578735f, -0.001693726f, -0.031005859f, | ||
1787 | -0.040634155f, -0.143264771f, -0.376800537f, -1.111373901f, | ||
1788 | 0.765029907f, -0.016510010f, 0.115921021f, -0.023422241f, | ||
1789 | 0.014022827f, -0.003463745f, 0.000808716f, 0.000030518f, | ||
1790 | -0.000244141f, -0.002685547f, -0.002334595f, -0.031387329f, | ||
1791 | -0.045837402f, -0.139450073f, -0.404083252f, -1.120223999f, | ||
1792 | 0.738372803f, -0.031082153f, 0.110946655f, -0.025085449f, | ||
1793 | 0.012939453f, -0.003479004f, 0.000747681f, 0.000015259f, | ||
1794 | -0.000259399f, -0.002792358f, -0.003005981f, -0.031661987f, | ||
1795 | -0.051132202f, -0.134887695f, -0.431655884f, -1.127746582f, | ||
1796 | 0.711318970f, -0.044784546f, 0.105819702f, -0.026535034f, | ||
1797 | 0.011886597f, -0.003479004f, 0.000686646f, 0.000015259f, | ||
1798 | -0.000289917f, -0.002899170f, -0.003723145f, -0.031814575f, | ||
1799 | -0.056533813f, -0.129577637f, -0.459472656f, -1.133926392f, | ||
1800 | 0.683914185f, -0.057617188f, 0.100540161f, -0.027801514f, | ||
1801 | 0.010848999f, -0.003463745f, 0.000625610f, 0.000015259f, | ||
1802 | -0.000320435f, -0.002990723f, -0.004486084f, -0.031845093f, | ||
1803 | -0.061996460f, -0.123474121f, -0.487472534f, -1.138763428f, | ||
1804 | 0.656219482f, -0.069595337f, 0.095169067f, -0.028884888f, | ||
1805 | 0.009841919f, -0.003433228f, 0.000579834f, 0.000015259f, | ||
1806 | -0.000366211f, -0.003082275f, -0.005294800f, -0.031738281f, | ||
1807 | -0.067520142f, -0.116577148f, -0.515609741f, -1.142211914f, | ||
1808 | 0.628295898f, -0.080688477f, 0.089706421f, -0.029785156f, | ||
1809 | 0.008865356f, -0.003387451f, 0.000534058f, 0.000015259f, | ||
1810 | -0.000396729f, -0.003173828f, -0.006118774f, -0.031478882f, | ||
1811 | -0.073059082f, -0.108856201f, -0.543823242f, -1.144287109f, | ||
1812 | 0.600219727f, -0.090927124f, 0.084182739f, -0.030517578f, | ||
1813 | 0.007919312f, -0.003326416f, 0.000473022f, 0.000015259f | ||
1814 | }; | ||
1815 | */ | ||
1816 | |||
1817 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/au2lin.ser b/songdbj/javazoom/jl/decoder/au2lin.ser new file mode 100644 index 0000000000..de0d1f62d9 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/au2lin.ser | |||
Binary files differ | |||
diff --git a/songdbj/javazoom/jl/decoder/huffcodetab.java b/songdbj/javazoom/jl/decoder/huffcodetab.java new file mode 100644 index 0000000000..86975646f0 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/huffcodetab.java | |||
@@ -0,0 +1,600 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 16/11/99 Renamed class, added javadoc, and changed table | ||
4 | * name from String to 3 chars. mdm@techie.com | ||
5 | * 02/15/99 Java Conversion by E.B, javalayer@javazoom.net | ||
6 | * | ||
7 | * 04/19/97 : Adapted from the ISO MPEG Audio Subgroup Software Simulation | ||
8 | * Group's public c source for its MPEG audio decoder. Miscellaneous | ||
9 | * changes by Jeff Tsay (ctsay@pasteur.eecs.berkeley.edu). | ||
10 | *----------------------------------------------------------------------- | ||
11 | * Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved | ||
12 | * MPEG/audio coding/decoding software, work in progress | ||
13 | * NOT for public distribution until verified and approved by the | ||
14 | * MPEG/audio committee. For further information, please contact | ||
15 | * Davis Pan, 508-493-2241, e-mail: pan@3d.enet.dec.com | ||
16 | * | ||
17 | * VERSION 4.1 | ||
18 | * changes made since last update: | ||
19 | * date programmers comment | ||
20 | * 27.2.92 F.O.Witte (ITT Intermetall) | ||
21 | * 8/24/93 M. Iwadare Changed for 1 pass decoding. | ||
22 | * 7/14/94 J. Koller useless 'typedef' before huffcodetab removed | ||
23 | *----------------------------------------------------------------------- | ||
24 | * This program is free software; you can redistribute it and/or modify | ||
25 | * it under the terms of the GNU Library General Public License as published | ||
26 | * by the Free Software Foundation; either version 2 of the License, or | ||
27 | * (at your option) any later version. | ||
28 | * | ||
29 | * This program is distributed in the hope that it will be useful, | ||
30 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
32 | * GNU Library General Public License for more details. | ||
33 | * | ||
34 | * You should have received a copy of the GNU Library General Public | ||
35 | * License along with this program; if not, write to the Free Software | ||
36 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
37 | *---------------------------------------------------------------------- | ||
38 | */ | ||
39 | |||
40 | package javazoom.jl.decoder; | ||
41 | |||
42 | /** | ||
43 | * Class to implements Huffman decoder. | ||
44 | */ | ||
45 | final class huffcodetab | ||
46 | { | ||
47 | private static final int MXOFF=250; | ||
48 | private static final int HTN=34; | ||
49 | |||
50 | private char tablename0 = ' '; /* string, containing table_description */ | ||
51 | private char tablename1 = ' '; /* string, containing table_description */ | ||
52 | private char tablename2 = ' '; /* string, containing table_description */ | ||
53 | |||
54 | private int xlen; /* max. x-index+ */ | ||
55 | private int ylen; /* max. y-index+ */ | ||
56 | private int linbits; /* number of linbits */ | ||
57 | private int linmax; /* max number to be stored in linbits */ | ||
58 | private int ref; /* a positive value indicates a reference */ | ||
59 | private int[] table=null; /* pointer to array[xlen][ylen] */ | ||
60 | private int[] hlen=null; /* pointer to array[xlen][ylen] */ | ||
61 | private int[][] val=null; /* decoder tree */ | ||
62 | private int treelen; /* length of decoder tree */ | ||
63 | |||
64 | private static int ValTab0[][] = { | ||
65 | {0,0} // dummy | ||
66 | }; | ||
67 | |||
68 | private static int ValTab1[][] = { | ||
69 | {2,1},{0,0},{2,1},{0,16},{2,1},{0,1},{0,17}, | ||
70 | }; | ||
71 | |||
72 | private static int ValTab2[][] = { | ||
73 | {2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1},{2,1}, | ||
74 | {0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34}, | ||
75 | }; | ||
76 | |||
77 | private static int ValTab3[][] = { | ||
78 | {4,1},{2,1},{0,0},{0,1},{2,1},{0,17},{2,1},{0,16},{4,1},{2,1}, | ||
79 | {0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34}, | ||
80 | }; | ||
81 | |||
82 | private static int ValTab4[][] = {{0,0}}; // dummy | ||
83 | |||
84 | private static int ValTab5[][] = { | ||
85 | {2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{8,1},{4,1}, | ||
86 | {2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{8,1},{4,1},{2,1},{0,34}, | ||
87 | {0,48},{2,1},{0,3},{0,19},{2,1},{0,49},{2,1},{0,50},{2,1},{0,35}, | ||
88 | {0,51}, | ||
89 | }; | ||
90 | |||
91 | private static int ValTab6[][] = { | ||
92 | {6,1},{4,1},{2,1},{0,0},{0,16},{0,17},{6,1},{2,1},{0,1},{2,1}, | ||
93 | {0,32},{0,33},{6,1},{2,1},{0,18},{2,1},{0,2},{0,34},{4,1},{2,1}, | ||
94 | {0,49},{0,19},{4,1},{2,1},{0,48},{0,50},{2,1},{0,35},{2,1},{0,3}, | ||
95 | {0,51}, | ||
96 | }; | ||
97 | |||
98 | private static int ValTab7[][] = { | ||
99 | {2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{8,1},{2,1},{0,17},{4,1}, | ||
100 | {2,1},{0,32},{0,2},{0,33},{18,1},{6,1},{2,1},{0,18},{2,1},{0,34}, | ||
101 | {0,48},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1},{0,3},{0,50},{2,1}, | ||
102 | {0,35},{0,4},{10,1},{4,1},{2,1},{0,64},{0,65},{2,1},{0,20},{2,1}, | ||
103 | {0,66},{0,36},{12,1},{6,1},{4,1},{2,1},{0,51},{0,67},{0,80},{4,1}, | ||
104 | {2,1},{0,52},{0,5},{0,81},{6,1},{2,1},{0,21},{2,1},{0,82},{0,37}, | ||
105 | {4,1},{2,1},{0,68},{0,53},{4,1},{2,1},{0,83},{0,84},{2,1},{0,69}, | ||
106 | {0,85}, | ||
107 | }; | ||
108 | |||
109 | private static int ValTab8[][] = { | ||
110 | {6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1},{2,1}, | ||
111 | {0,33},{0,18},{14,1},{4,1},{2,1},{0,32},{0,2},{2,1},{0,34},{4,1}, | ||
112 | {2,1},{0,48},{0,3},{2,1},{0,49},{0,19},{14,1},{8,1},{4,1},{2,1}, | ||
113 | {0,50},{0,35},{2,1},{0,64},{0,4},{2,1},{0,65},{2,1},{0,20},{0,66}, | ||
114 | {12,1},{6,1},{2,1},{0,36},{2,1},{0,51},{0,80},{4,1},{2,1},{0,67}, | ||
115 | {0,52},{0,81},{6,1},{2,1},{0,21},{2,1},{0,5},{0,82},{6,1},{2,1}, | ||
116 | {0,37},{2,1},{0,68},{0,53},{2,1},{0,83},{2,1},{0,69},{2,1},{0,84}, | ||
117 | {0,85}, | ||
118 | }; | ||
119 | |||
120 | private static int ValTab9[][] = { | ||
121 | {8,1},{4,1},{2,1},{0,0},{0,16},{2,1},{0,1},{0,17},{10,1},{4,1}, | ||
122 | {2,1},{0,32},{0,33},{2,1},{0,18},{2,1},{0,2},{0,34},{12,1},{6,1}, | ||
123 | {4,1},{2,1},{0,48},{0,3},{0,49},{2,1},{0,19},{2,1},{0,50},{0,35}, | ||
124 | {12,1},{4,1},{2,1},{0,65},{0,20},{4,1},{2,1},{0,64},{0,51},{2,1}, | ||
125 | {0,66},{0,36},{10,1},{6,1},{4,1},{2,1},{0,4},{0,80},{0,67},{2,1}, | ||
126 | {0,52},{0,81},{8,1},{4,1},{2,1},{0,21},{0,82},{2,1},{0,37},{0,68}, | ||
127 | {6,1},{4,1},{2,1},{0,5},{0,84},{0,83},{2,1},{0,53},{2,1},{0,69}, | ||
128 | {0,85}, | ||
129 | }; | ||
130 | |||
131 | private static int ValTab10[][] = { | ||
132 | {2,1},{0,0},{4,1},{2,1},{0,16},{0,1},{10,1},{2,1},{0,17},{4,1}, | ||
133 | {2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{28,1},{8,1},{4,1},{2,1}, | ||
134 | {0,34},{0,48},{2,1},{0,49},{0,19},{8,1},{4,1},{2,1},{0,3},{0,50}, | ||
135 | {2,1},{0,35},{0,64},{4,1},{2,1},{0,65},{0,20},{4,1},{2,1},{0,4}, | ||
136 | {0,51},{2,1},{0,66},{0,36},{28,1},{10,1},{6,1},{4,1},{2,1},{0,80}, | ||
137 | {0,5},{0,96},{2,1},{0,97},{0,22},{12,1},{6,1},{4,1},{2,1},{0,67}, | ||
138 | {0,52},{0,81},{2,1},{0,21},{2,1},{0,82},{0,37},{4,1},{2,1},{0,38}, | ||
139 | {0,54},{0,113},{20,1},{8,1},{2,1},{0,23},{4,1},{2,1},{0,68},{0,83}, | ||
140 | {0,6},{6,1},{4,1},{2,1},{0,53},{0,69},{0,98},{2,1},{0,112},{2,1}, | ||
141 | {0,7},{0,100},{14,1},{4,1},{2,1},{0,114},{0,39},{6,1},{2,1},{0,99}, | ||
142 | {2,1},{0,84},{0,85},{2,1},{0,70},{0,115},{8,1},{4,1},{2,1},{0,55}, | ||
143 | {0,101},{2,1},{0,86},{0,116},{6,1},{2,1},{0,71},{2,1},{0,102},{0,117}, | ||
144 | {4,1},{2,1},{0,87},{0,118},{2,1},{0,103},{0,119}, | ||
145 | }; | ||
146 | |||
147 | private static int ValTab11[][] = { | ||
148 | {6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{8,1},{2,1},{0,17},{4,1}, | ||
149 | {2,1},{0,32},{0,2},{0,18},{24,1},{8,1},{2,1},{0,33},{2,1},{0,34}, | ||
150 | {2,1},{0,48},{0,3},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1},{0,50}, | ||
151 | {0,35},{4,1},{2,1},{0,64},{0,4},{2,1},{0,65},{0,20},{30,1},{16,1}, | ||
152 | {10,1},{4,1},{2,1},{0,66},{0,36},{4,1},{2,1},{0,51},{0,67},{0,80}, | ||
153 | {4,1},{2,1},{0,52},{0,81},{0,97},{6,1},{2,1},{0,22},{2,1},{0,6}, | ||
154 | {0,38},{2,1},{0,98},{2,1},{0,21},{2,1},{0,5},{0,82},{16,1},{10,1}, | ||
155 | {6,1},{4,1},{2,1},{0,37},{0,68},{0,96},{2,1},{0,99},{0,54},{4,1}, | ||
156 | {2,1},{0,112},{0,23},{0,113},{16,1},{6,1},{4,1},{2,1},{0,7},{0,100}, | ||
157 | {0,114},{2,1},{0,39},{4,1},{2,1},{0,83},{0,53},{2,1},{0,84},{0,69}, | ||
158 | {10,1},{4,1},{2,1},{0,70},{0,115},{2,1},{0,55},{2,1},{0,101},{0,86}, | ||
159 | {10,1},{6,1},{4,1},{2,1},{0,85},{0,87},{0,116},{2,1},{0,71},{0,102}, | ||
160 | {4,1},{2,1},{0,117},{0,118},{2,1},{0,103},{0,119}, | ||
161 | }; | ||
162 | |||
163 | private static int ValTab12[][] = { | ||
164 | {12,1},{4,1},{2,1},{0,16},{0,1},{2,1},{0,17},{2,1},{0,0},{2,1}, | ||
165 | {0,32},{0,2},{16,1},{4,1},{2,1},{0,33},{0,18},{4,1},{2,1},{0,34}, | ||
166 | {0,49},{2,1},{0,19},{2,1},{0,48},{2,1},{0,3},{0,64},{26,1},{8,1}, | ||
167 | {4,1},{2,1},{0,50},{0,35},{2,1},{0,65},{0,51},{10,1},{4,1},{2,1}, | ||
168 | {0,20},{0,66},{2,1},{0,36},{2,1},{0,4},{0,80},{4,1},{2,1},{0,67}, | ||
169 | {0,52},{2,1},{0,81},{0,21},{28,1},{14,1},{8,1},{4,1},{2,1},{0,82}, | ||
170 | {0,37},{2,1},{0,83},{0,53},{4,1},{2,1},{0,96},{0,22},{0,97},{4,1}, | ||
171 | {2,1},{0,98},{0,38},{6,1},{4,1},{2,1},{0,5},{0,6},{0,68},{2,1}, | ||
172 | {0,84},{0,69},{18,1},{10,1},{4,1},{2,1},{0,99},{0,54},{4,1},{2,1}, | ||
173 | {0,112},{0,7},{0,113},{4,1},{2,1},{0,23},{0,100},{2,1},{0,70},{0,114}, | ||
174 | {10,1},{6,1},{2,1},{0,39},{2,1},{0,85},{0,115},{2,1},{0,55},{0,86}, | ||
175 | {8,1},{4,1},{2,1},{0,101},{0,116},{2,1},{0,71},{0,102},{4,1},{2,1}, | ||
176 | {0,117},{0,87},{2,1},{0,118},{2,1},{0,103},{0,119}, | ||
177 | }; | ||
178 | |||
179 | private static int ValTab13[][] = { | ||
180 | {2,1},{0,0},{6,1},{2,1},{0,16},{2,1},{0,1},{0,17},{28,1},{8,1}, | ||
181 | {4,1},{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{8,1},{4,1},{2,1}, | ||
182 | {0,34},{0,48},{2,1},{0,3},{0,49},{6,1},{2,1},{0,19},{2,1},{0,50}, | ||
183 | {0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{70,1},{28,1},{14,1},{6,1}, | ||
184 | {2,1},{0,20},{2,1},{0,51},{0,66},{4,1},{2,1},{0,36},{0,80},{2,1}, | ||
185 | {0,67},{0,52},{4,1},{2,1},{0,81},{0,21},{4,1},{2,1},{0,5},{0,82}, | ||
186 | {2,1},{0,37},{2,1},{0,68},{0,83},{14,1},{8,1},{4,1},{2,1},{0,96}, | ||
187 | {0,6},{2,1},{0,97},{0,22},{4,1},{2,1},{0,128},{0,8},{0,129},{16,1}, | ||
188 | {8,1},{4,1},{2,1},{0,53},{0,98},{2,1},{0,38},{0,84},{4,1},{2,1}, | ||
189 | {0,69},{0,99},{2,1},{0,54},{0,112},{6,1},{4,1},{2,1},{0,7},{0,85}, | ||
190 | {0,113},{2,1},{0,23},{2,1},{0,39},{0,55},{72,1},{24,1},{12,1},{4,1}, | ||
191 | {2,1},{0,24},{0,130},{2,1},{0,40},{4,1},{2,1},{0,100},{0,70},{0,114}, | ||
192 | {8,1},{4,1},{2,1},{0,132},{0,72},{2,1},{0,144},{0,9},{2,1},{0,145}, | ||
193 | {0,25},{24,1},{14,1},{8,1},{4,1},{2,1},{0,115},{0,101},{2,1},{0,86}, | ||
194 | {0,116},{4,1},{2,1},{0,71},{0,102},{0,131},{6,1},{2,1},{0,56},{2,1}, | ||
195 | {0,117},{0,87},{2,1},{0,146},{0,41},{14,1},{8,1},{4,1},{2,1},{0,103}, | ||
196 | {0,133},{2,1},{0,88},{0,57},{2,1},{0,147},{2,1},{0,73},{0,134},{6,1}, | ||
197 | {2,1},{0,160},{2,1},{0,104},{0,10},{2,1},{0,161},{0,26},{68,1},{24,1}, | ||
198 | {12,1},{4,1},{2,1},{0,162},{0,42},{4,1},{2,1},{0,149},{0,89},{2,1}, | ||
199 | {0,163},{0,58},{8,1},{4,1},{2,1},{0,74},{0,150},{2,1},{0,176},{0,11}, | ||
200 | {2,1},{0,177},{0,27},{20,1},{8,1},{2,1},{0,178},{4,1},{2,1},{0,118}, | ||
201 | {0,119},{0,148},{6,1},{4,1},{2,1},{0,135},{0,120},{0,164},{4,1},{2,1}, | ||
202 | {0,105},{0,165},{0,43},{12,1},{6,1},{4,1},{2,1},{0,90},{0,136},{0,179}, | ||
203 | {2,1},{0,59},{2,1},{0,121},{0,166},{6,1},{4,1},{2,1},{0,106},{0,180}, | ||
204 | {0,192},{4,1},{2,1},{0,12},{0,152},{0,193},{60,1},{22,1},{10,1},{6,1}, | ||
205 | {2,1},{0,28},{2,1},{0,137},{0,181},{2,1},{0,91},{0,194},{4,1},{2,1}, | ||
206 | {0,44},{0,60},{4,1},{2,1},{0,182},{0,107},{2,1},{0,196},{0,76},{16,1}, | ||
207 | {8,1},{4,1},{2,1},{0,168},{0,138},{2,1},{0,208},{0,13},{2,1},{0,209}, | ||
208 | {2,1},{0,75},{2,1},{0,151},{0,167},{12,1},{6,1},{2,1},{0,195},{2,1}, | ||
209 | {0,122},{0,153},{4,1},{2,1},{0,197},{0,92},{0,183},{4,1},{2,1},{0,29}, | ||
210 | {0,210},{2,1},{0,45},{2,1},{0,123},{0,211},{52,1},{28,1},{12,1},{4,1}, | ||
211 | {2,1},{0,61},{0,198},{4,1},{2,1},{0,108},{0,169},{2,1},{0,154},{0,212}, | ||
212 | {8,1},{4,1},{2,1},{0,184},{0,139},{2,1},{0,77},{0,199},{4,1},{2,1}, | ||
213 | {0,124},{0,213},{2,1},{0,93},{0,224},{10,1},{4,1},{2,1},{0,225},{0,30}, | ||
214 | {4,1},{2,1},{0,14},{0,46},{0,226},{8,1},{4,1},{2,1},{0,227},{0,109}, | ||
215 | {2,1},{0,140},{0,228},{4,1},{2,1},{0,229},{0,186},{0,240},{38,1},{16,1}, | ||
216 | {4,1},{2,1},{0,241},{0,31},{6,1},{4,1},{2,1},{0,170},{0,155},{0,185}, | ||
217 | {2,1},{0,62},{2,1},{0,214},{0,200},{12,1},{6,1},{2,1},{0,78},{2,1}, | ||
218 | {0,215},{0,125},{2,1},{0,171},{2,1},{0,94},{0,201},{6,1},{2,1},{0,15}, | ||
219 | {2,1},{0,156},{0,110},{2,1},{0,242},{0,47},{32,1},{16,1},{6,1},{4,1}, | ||
220 | {2,1},{0,216},{0,141},{0,63},{6,1},{2,1},{0,243},{2,1},{0,230},{0,202}, | ||
221 | {2,1},{0,244},{0,79},{8,1},{4,1},{2,1},{0,187},{0,172},{2,1},{0,231}, | ||
222 | {0,245},{4,1},{2,1},{0,217},{0,157},{2,1},{0,95},{0,232},{30,1},{12,1}, | ||
223 | {6,1},{2,1},{0,111},{2,1},{0,246},{0,203},{4,1},{2,1},{0,188},{0,173}, | ||
224 | {0,218},{8,1},{2,1},{0,247},{4,1},{2,1},{0,126},{0,127},{0,142},{6,1}, | ||
225 | {4,1},{2,1},{0,158},{0,174},{0,204},{2,1},{0,248},{0,143},{18,1},{8,1}, | ||
226 | {4,1},{2,1},{0,219},{0,189},{2,1},{0,234},{0,249},{4,1},{2,1},{0,159}, | ||
227 | {0,235},{2,1},{0,190},{2,1},{0,205},{0,250},{14,1},{4,1},{2,1},{0,221}, | ||
228 | {0,236},{6,1},{4,1},{2,1},{0,233},{0,175},{0,220},{2,1},{0,206},{0,251}, | ||
229 | {8,1},{4,1},{2,1},{0,191},{0,222},{2,1},{0,207},{0,238},{4,1},{2,1}, | ||
230 | {0,223},{0,239},{2,1},{0,255},{2,1},{0,237},{2,1},{0,253},{2,1},{0,252}, | ||
231 | {0,254}, | ||
232 | }; | ||
233 | |||
234 | private static int ValTab14[][] = { | ||
235 | {0,0} // dummy | ||
236 | }; | ||
237 | |||
238 | private static int ValTab15[][] = { | ||
239 | {16,1},{6,1},{2,1},{0,0},{2,1},{0,16},{0,1},{2,1},{0,17},{4,1}, | ||
240 | {2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{50,1},{16,1},{6,1},{2,1}, | ||
241 | {0,34},{2,1},{0,48},{0,49},{6,1},{2,1},{0,19},{2,1},{0,3},{0,64}, | ||
242 | {2,1},{0,50},{0,35},{14,1},{6,1},{4,1},{2,1},{0,4},{0,20},{0,65}, | ||
243 | {4,1},{2,1},{0,51},{0,66},{2,1},{0,36},{0,67},{10,1},{6,1},{2,1}, | ||
244 | {0,52},{2,1},{0,80},{0,5},{2,1},{0,81},{0,21},{4,1},{2,1},{0,82}, | ||
245 | {0,37},{4,1},{2,1},{0,68},{0,83},{0,97},{90,1},{36,1},{18,1},{10,1}, | ||
246 | {6,1},{2,1},{0,53},{2,1},{0,96},{0,6},{2,1},{0,22},{0,98},{4,1}, | ||
247 | {2,1},{0,38},{0,84},{2,1},{0,69},{0,99},{10,1},{6,1},{2,1},{0,54}, | ||
248 | {2,1},{0,112},{0,7},{2,1},{0,113},{0,85},{4,1},{2,1},{0,23},{0,100}, | ||
249 | {2,1},{0,114},{0,39},{24,1},{16,1},{8,1},{4,1},{2,1},{0,70},{0,115}, | ||
250 | {2,1},{0,55},{0,101},{4,1},{2,1},{0,86},{0,128},{2,1},{0,8},{0,116}, | ||
251 | {4,1},{2,1},{0,129},{0,24},{2,1},{0,130},{0,40},{16,1},{8,1},{4,1}, | ||
252 | {2,1},{0,71},{0,102},{2,1},{0,131},{0,56},{4,1},{2,1},{0,117},{0,87}, | ||
253 | {2,1},{0,132},{0,72},{6,1},{4,1},{2,1},{0,144},{0,25},{0,145},{4,1}, | ||
254 | {2,1},{0,146},{0,118},{2,1},{0,103},{0,41},{92,1},{36,1},{18,1},{10,1}, | ||
255 | {4,1},{2,1},{0,133},{0,88},{4,1},{2,1},{0,9},{0,119},{0,147},{4,1}, | ||
256 | {2,1},{0,57},{0,148},{2,1},{0,73},{0,134},{10,1},{6,1},{2,1},{0,104}, | ||
257 | {2,1},{0,160},{0,10},{2,1},{0,161},{0,26},{4,1},{2,1},{0,162},{0,42}, | ||
258 | {2,1},{0,149},{0,89},{26,1},{14,1},{6,1},{2,1},{0,163},{2,1},{0,58}, | ||
259 | {0,135},{4,1},{2,1},{0,120},{0,164},{2,1},{0,74},{0,150},{6,1},{4,1}, | ||
260 | {2,1},{0,105},{0,176},{0,177},{4,1},{2,1},{0,27},{0,165},{0,178},{14,1}, | ||
261 | {8,1},{4,1},{2,1},{0,90},{0,43},{2,1},{0,136},{0,151},{2,1},{0,179}, | ||
262 | {2,1},{0,121},{0,59},{8,1},{4,1},{2,1},{0,106},{0,180},{2,1},{0,75}, | ||
263 | {0,193},{4,1},{2,1},{0,152},{0,137},{2,1},{0,28},{0,181},{80,1},{34,1}, | ||
264 | {16,1},{6,1},{4,1},{2,1},{0,91},{0,44},{0,194},{6,1},{4,1},{2,1}, | ||
265 | {0,11},{0,192},{0,166},{2,1},{0,167},{0,122},{10,1},{4,1},{2,1},{0,195}, | ||
266 | {0,60},{4,1},{2,1},{0,12},{0,153},{0,182},{4,1},{2,1},{0,107},{0,196}, | ||
267 | {2,1},{0,76},{0,168},{20,1},{10,1},{4,1},{2,1},{0,138},{0,197},{4,1}, | ||
268 | {2,1},{0,208},{0,92},{0,209},{4,1},{2,1},{0,183},{0,123},{2,1},{0,29}, | ||
269 | {2,1},{0,13},{0,45},{12,1},{4,1},{2,1},{0,210},{0,211},{4,1},{2,1}, | ||
270 | {0,61},{0,198},{2,1},{0,108},{0,169},{6,1},{4,1},{2,1},{0,154},{0,184}, | ||
271 | {0,212},{4,1},{2,1},{0,139},{0,77},{2,1},{0,199},{0,124},{68,1},{34,1}, | ||
272 | {18,1},{10,1},{4,1},{2,1},{0,213},{0,93},{4,1},{2,1},{0,224},{0,14}, | ||
273 | {0,225},{4,1},{2,1},{0,30},{0,226},{2,1},{0,170},{0,46},{8,1},{4,1}, | ||
274 | {2,1},{0,185},{0,155},{2,1},{0,227},{0,214},{4,1},{2,1},{0,109},{0,62}, | ||
275 | {2,1},{0,200},{0,140},{16,1},{8,1},{4,1},{2,1},{0,228},{0,78},{2,1}, | ||
276 | {0,215},{0,125},{4,1},{2,1},{0,229},{0,186},{2,1},{0,171},{0,94},{8,1}, | ||
277 | {4,1},{2,1},{0,201},{0,156},{2,1},{0,241},{0,31},{6,1},{4,1},{2,1}, | ||
278 | {0,240},{0,110},{0,242},{2,1},{0,47},{0,230},{38,1},{18,1},{8,1},{4,1}, | ||
279 | {2,1},{0,216},{0,243},{2,1},{0,63},{0,244},{6,1},{2,1},{0,79},{2,1}, | ||
280 | {0,141},{0,217},{2,1},{0,187},{0,202},{8,1},{4,1},{2,1},{0,172},{0,231}, | ||
281 | {2,1},{0,126},{0,245},{8,1},{4,1},{2,1},{0,157},{0,95},{2,1},{0,232}, | ||
282 | {0,142},{2,1},{0,246},{0,203},{34,1},{18,1},{10,1},{6,1},{4,1},{2,1}, | ||
283 | {0,15},{0,174},{0,111},{2,1},{0,188},{0,218},{4,1},{2,1},{0,173},{0,247}, | ||
284 | {2,1},{0,127},{0,233},{8,1},{4,1},{2,1},{0,158},{0,204},{2,1},{0,248}, | ||
285 | {0,143},{4,1},{2,1},{0,219},{0,189},{2,1},{0,234},{0,249},{16,1},{8,1}, | ||
286 | {4,1},{2,1},{0,159},{0,220},{2,1},{0,205},{0,235},{4,1},{2,1},{0,190}, | ||
287 | {0,250},{2,1},{0,175},{0,221},{14,1},{6,1},{4,1},{2,1},{0,236},{0,206}, | ||
288 | {0,251},{4,1},{2,1},{0,191},{0,237},{2,1},{0,222},{0,252},{6,1},{4,1}, | ||
289 | {2,1},{0,207},{0,253},{0,238},{4,1},{2,1},{0,223},{0,254},{2,1},{0,239}, | ||
290 | {0,255}, | ||
291 | }; | ||
292 | |||
293 | private static int ValTab16[][] = { | ||
294 | {2,1},{0,0},{6,1},{2,1},{0,16},{2,1},{0,1},{0,17},{42,1},{8,1}, | ||
295 | {4,1},{2,1},{0,32},{0,2},{2,1},{0,33},{0,18},{10,1},{6,1},{2,1}, | ||
296 | {0,34},{2,1},{0,48},{0,3},{2,1},{0,49},{0,19},{10,1},{4,1},{2,1}, | ||
297 | {0,50},{0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{6,1},{2,1},{0,20}, | ||
298 | {2,1},{0,51},{0,66},{4,1},{2,1},{0,36},{0,80},{2,1},{0,67},{0,52}, | ||
299 | {138,1},{40,1},{16,1},{6,1},{4,1},{2,1},{0,5},{0,21},{0,81},{4,1}, | ||
300 | {2,1},{0,82},{0,37},{4,1},{2,1},{0,68},{0,53},{0,83},{10,1},{6,1}, | ||
301 | {4,1},{2,1},{0,96},{0,6},{0,97},{2,1},{0,22},{0,98},{8,1},{4,1}, | ||
302 | {2,1},{0,38},{0,84},{2,1},{0,69},{0,99},{4,1},{2,1},{0,54},{0,112}, | ||
303 | {0,113},{40,1},{18,1},{8,1},{2,1},{0,23},{2,1},{0,7},{2,1},{0,85}, | ||
304 | {0,100},{4,1},{2,1},{0,114},{0,39},{4,1},{2,1},{0,70},{0,101},{0,115}, | ||
305 | {10,1},{6,1},{2,1},{0,55},{2,1},{0,86},{0,8},{2,1},{0,128},{0,129}, | ||
306 | {6,1},{2,1},{0,24},{2,1},{0,116},{0,71},{2,1},{0,130},{2,1},{0,40}, | ||
307 | {0,102},{24,1},{14,1},{8,1},{4,1},{2,1},{0,131},{0,56},{2,1},{0,117}, | ||
308 | {0,132},{4,1},{2,1},{0,72},{0,144},{0,145},{6,1},{2,1},{0,25},{2,1}, | ||
309 | {0,9},{0,118},{2,1},{0,146},{0,41},{14,1},{8,1},{4,1},{2,1},{0,133}, | ||
310 | {0,88},{2,1},{0,147},{0,57},{4,1},{2,1},{0,160},{0,10},{0,26},{8,1}, | ||
311 | {2,1},{0,162},{2,1},{0,103},{2,1},{0,87},{0,73},{6,1},{2,1},{0,148}, | ||
312 | {2,1},{0,119},{0,134},{2,1},{0,161},{2,1},{0,104},{0,149},{220,1},{126,1}, | ||
313 | {50,1},{26,1},{12,1},{6,1},{2,1},{0,42},{2,1},{0,89},{0,58},{2,1}, | ||
314 | {0,163},{2,1},{0,135},{0,120},{8,1},{4,1},{2,1},{0,164},{0,74},{2,1}, | ||
315 | {0,150},{0,105},{4,1},{2,1},{0,176},{0,11},{0,177},{10,1},{4,1},{2,1}, | ||
316 | {0,27},{0,178},{2,1},{0,43},{2,1},{0,165},{0,90},{6,1},{2,1},{0,179}, | ||
317 | {2,1},{0,166},{0,106},{4,1},{2,1},{0,180},{0,75},{2,1},{0,12},{0,193}, | ||
318 | {30,1},{14,1},{6,1},{4,1},{2,1},{0,181},{0,194},{0,44},{4,1},{2,1}, | ||
319 | {0,167},{0,195},{2,1},{0,107},{0,196},{8,1},{2,1},{0,29},{4,1},{2,1}, | ||
320 | {0,136},{0,151},{0,59},{4,1},{2,1},{0,209},{0,210},{2,1},{0,45},{0,211}, | ||
321 | {18,1},{6,1},{4,1},{2,1},{0,30},{0,46},{0,226},{6,1},{4,1},{2,1}, | ||
322 | {0,121},{0,152},{0,192},{2,1},{0,28},{2,1},{0,137},{0,91},{14,1},{6,1}, | ||
323 | {2,1},{0,60},{2,1},{0,122},{0,182},{4,1},{2,1},{0,76},{0,153},{2,1}, | ||
324 | {0,168},{0,138},{6,1},{2,1},{0,13},{2,1},{0,197},{0,92},{4,1},{2,1}, | ||
325 | {0,61},{0,198},{2,1},{0,108},{0,154},{88,1},{86,1},{36,1},{16,1},{8,1}, | ||
326 | {4,1},{2,1},{0,139},{0,77},{2,1},{0,199},{0,124},{4,1},{2,1},{0,213}, | ||
327 | {0,93},{2,1},{0,224},{0,14},{8,1},{2,1},{0,227},{4,1},{2,1},{0,208}, | ||
328 | {0,183},{0,123},{6,1},{4,1},{2,1},{0,169},{0,184},{0,212},{2,1},{0,225}, | ||
329 | {2,1},{0,170},{0,185},{24,1},{10,1},{6,1},{4,1},{2,1},{0,155},{0,214}, | ||
330 | {0,109},{2,1},{0,62},{0,200},{6,1},{4,1},{2,1},{0,140},{0,228},{0,78}, | ||
331 | {4,1},{2,1},{0,215},{0,229},{2,1},{0,186},{0,171},{12,1},{4,1},{2,1}, | ||
332 | {0,156},{0,230},{4,1},{2,1},{0,110},{0,216},{2,1},{0,141},{0,187},{8,1}, | ||
333 | {4,1},{2,1},{0,231},{0,157},{2,1},{0,232},{0,142},{4,1},{2,1},{0,203}, | ||
334 | {0,188},{0,158},{0,241},{2,1},{0,31},{2,1},{0,15},{0,47},{66,1},{56,1}, | ||
335 | {2,1},{0,242},{52,1},{50,1},{20,1},{8,1},{2,1},{0,189},{2,1},{0,94}, | ||
336 | {2,1},{0,125},{0,201},{6,1},{2,1},{0,202},{2,1},{0,172},{0,126},{4,1}, | ||
337 | {2,1},{0,218},{0,173},{0,204},{10,1},{6,1},{2,1},{0,174},{2,1},{0,219}, | ||
338 | {0,220},{2,1},{0,205},{0,190},{6,1},{4,1},{2,1},{0,235},{0,237},{0,238}, | ||
339 | {6,1},{4,1},{2,1},{0,217},{0,234},{0,233},{2,1},{0,222},{4,1},{2,1}, | ||
340 | {0,221},{0,236},{0,206},{0,63},{0,240},{4,1},{2,1},{0,243},{0,244},{2,1}, | ||
341 | {0,79},{2,1},{0,245},{0,95},{10,1},{2,1},{0,255},{4,1},{2,1},{0,246}, | ||
342 | {0,111},{2,1},{0,247},{0,127},{12,1},{6,1},{2,1},{0,143},{2,1},{0,248}, | ||
343 | {0,249},{4,1},{2,1},{0,159},{0,250},{0,175},{8,1},{4,1},{2,1},{0,251}, | ||
344 | {0,191},{2,1},{0,252},{0,207},{4,1},{2,1},{0,253},{0,223},{2,1},{0,254}, | ||
345 | {0,239}, | ||
346 | }; | ||
347 | |||
348 | private static int ValTab24[][] = { | ||
349 | {60,1},{8,1},{4,1},{2,1},{0,0},{0,16},{2,1},{0,1},{0,17},{14,1}, | ||
350 | {6,1},{4,1},{2,1},{0,32},{0,2},{0,33},{2,1},{0,18},{2,1},{0,34}, | ||
351 | {2,1},{0,48},{0,3},{14,1},{4,1},{2,1},{0,49},{0,19},{4,1},{2,1}, | ||
352 | {0,50},{0,35},{4,1},{2,1},{0,64},{0,4},{0,65},{8,1},{4,1},{2,1}, | ||
353 | {0,20},{0,51},{2,1},{0,66},{0,36},{6,1},{4,1},{2,1},{0,67},{0,52}, | ||
354 | {0,81},{6,1},{4,1},{2,1},{0,80},{0,5},{0,21},{2,1},{0,82},{0,37}, | ||
355 | {250,1},{98,1},{34,1},{18,1},{10,1},{4,1},{2,1},{0,68},{0,83},{2,1}, | ||
356 | {0,53},{2,1},{0,96},{0,6},{4,1},{2,1},{0,97},{0,22},{2,1},{0,98}, | ||
357 | {0,38},{8,1},{4,1},{2,1},{0,84},{0,69},{2,1},{0,99},{0,54},{4,1}, | ||
358 | {2,1},{0,113},{0,85},{2,1},{0,100},{0,70},{32,1},{14,1},{6,1},{2,1}, | ||
359 | {0,114},{2,1},{0,39},{0,55},{2,1},{0,115},{4,1},{2,1},{0,112},{0,7}, | ||
360 | {0,23},{10,1},{4,1},{2,1},{0,101},{0,86},{4,1},{2,1},{0,128},{0,8}, | ||
361 | {0,129},{4,1},{2,1},{0,116},{0,71},{2,1},{0,24},{0,130},{16,1},{8,1}, | ||
362 | {4,1},{2,1},{0,40},{0,102},{2,1},{0,131},{0,56},{4,1},{2,1},{0,117}, | ||
363 | {0,87},{2,1},{0,132},{0,72},{8,1},{4,1},{2,1},{0,145},{0,25},{2,1}, | ||
364 | {0,146},{0,118},{4,1},{2,1},{0,103},{0,41},{2,1},{0,133},{0,88},{92,1}, | ||
365 | {34,1},{16,1},{8,1},{4,1},{2,1},{0,147},{0,57},{2,1},{0,148},{0,73}, | ||
366 | {4,1},{2,1},{0,119},{0,134},{2,1},{0,104},{0,161},{8,1},{4,1},{2,1}, | ||
367 | {0,162},{0,42},{2,1},{0,149},{0,89},{4,1},{2,1},{0,163},{0,58},{2,1}, | ||
368 | {0,135},{2,1},{0,120},{0,74},{22,1},{12,1},{4,1},{2,1},{0,164},{0,150}, | ||
369 | {4,1},{2,1},{0,105},{0,177},{2,1},{0,27},{0,165},{6,1},{2,1},{0,178}, | ||
370 | {2,1},{0,90},{0,43},{2,1},{0,136},{0,179},{16,1},{10,1},{6,1},{2,1}, | ||
371 | {0,144},{2,1},{0,9},{0,160},{2,1},{0,151},{0,121},{4,1},{2,1},{0,166}, | ||
372 | {0,106},{0,180},{12,1},{6,1},{2,1},{0,26},{2,1},{0,10},{0,176},{2,1}, | ||
373 | {0,59},{2,1},{0,11},{0,192},{4,1},{2,1},{0,75},{0,193},{2,1},{0,152}, | ||
374 | {0,137},{67,1},{34,1},{16,1},{8,1},{4,1},{2,1},{0,28},{0,181},{2,1}, | ||
375 | {0,91},{0,194},{4,1},{2,1},{0,44},{0,167},{2,1},{0,122},{0,195},{10,1}, | ||
376 | {6,1},{2,1},{0,60},{2,1},{0,12},{0,208},{2,1},{0,182},{0,107},{4,1}, | ||
377 | {2,1},{0,196},{0,76},{2,1},{0,153},{0,168},{16,1},{8,1},{4,1},{2,1}, | ||
378 | {0,138},{0,197},{2,1},{0,92},{0,209},{4,1},{2,1},{0,183},{0,123},{2,1}, | ||
379 | {0,29},{0,210},{9,1},{4,1},{2,1},{0,45},{0,211},{2,1},{0,61},{0,198}, | ||
380 | {85,250},{4,1},{2,1},{0,108},{0,169},{2,1},{0,154},{0,212},{32,1},{16,1}, | ||
381 | {8,1},{4,1},{2,1},{0,184},{0,139},{2,1},{0,77},{0,199},{4,1},{2,1}, | ||
382 | {0,124},{0,213},{2,1},{0,93},{0,225},{8,1},{4,1},{2,1},{0,30},{0,226}, | ||
383 | {2,1},{0,170},{0,185},{4,1},{2,1},{0,155},{0,227},{2,1},{0,214},{0,109}, | ||
384 | {20,1},{10,1},{6,1},{2,1},{0,62},{2,1},{0,46},{0,78},{2,1},{0,200}, | ||
385 | {0,140},{4,1},{2,1},{0,228},{0,215},{4,1},{2,1},{0,125},{0,171},{0,229}, | ||
386 | {10,1},{4,1},{2,1},{0,186},{0,94},{2,1},{0,201},{2,1},{0,156},{0,110}, | ||
387 | {8,1},{2,1},{0,230},{2,1},{0,13},{2,1},{0,224},{0,14},{4,1},{2,1}, | ||
388 | {0,216},{0,141},{2,1},{0,187},{0,202},{74,1},{2,1},{0,255},{64,1},{58,1}, | ||
389 | {32,1},{16,1},{8,1},{4,1},{2,1},{0,172},{0,231},{2,1},{0,126},{0,217}, | ||
390 | {4,1},{2,1},{0,157},{0,232},{2,1},{0,142},{0,203},{8,1},{4,1},{2,1}, | ||
391 | {0,188},{0,218},{2,1},{0,173},{0,233},{4,1},{2,1},{0,158},{0,204},{2,1}, | ||
392 | {0,219},{0,189},{16,1},{8,1},{4,1},{2,1},{0,234},{0,174},{2,1},{0,220}, | ||
393 | {0,205},{4,1},{2,1},{0,235},{0,190},{2,1},{0,221},{0,236},{8,1},{4,1}, | ||
394 | {2,1},{0,206},{0,237},{2,1},{0,222},{0,238},{0,15},{4,1},{2,1},{0,240}, | ||
395 | {0,31},{0,241},{4,1},{2,1},{0,242},{0,47},{2,1},{0,243},{0,63},{18,1}, | ||
396 | {8,1},{4,1},{2,1},{0,244},{0,79},{2,1},{0,245},{0,95},{4,1},{2,1}, | ||
397 | {0,246},{0,111},{2,1},{0,247},{2,1},{0,127},{0,143},{10,1},{4,1},{2,1}, | ||
398 | {0,248},{0,249},{4,1},{2,1},{0,159},{0,175},{0,250},{8,1},{4,1},{2,1}, | ||
399 | {0,251},{0,191},{2,1},{0,252},{0,207},{4,1},{2,1},{0,253},{0,223},{2,1}, | ||
400 | {0,254},{0,239}, | ||
401 | }; | ||
402 | |||
403 | private static int ValTab32[][] = { | ||
404 | {2,1},{0,0},{8,1},{4,1},{2,1},{0,8},{0,4},{2,1},{0,1},{0,2}, | ||
405 | {8,1},{4,1},{2,1},{0,12},{0,10},{2,1},{0,3},{0,6},{6,1},{2,1}, | ||
406 | {0,9},{2,1},{0,5},{0,7},{4,1},{2,1},{0,14},{0,13},{2,1},{0,15}, | ||
407 | {0,11}, | ||
408 | }; | ||
409 | |||
410 | private static int ValTab33[][] = { | ||
411 | {16,1},{8,1},{4,1},{2,1},{0,0},{0,1},{2,1},{0,2},{0,3},{4,1}, | ||
412 | {2,1},{0,4},{0,5},{2,1},{0,6},{0,7},{8,1},{4,1},{2,1},{0,8}, | ||
413 | {0,9},{2,1},{0,10},{0,11},{4,1},{2,1},{0,12},{0,13},{2,1},{0,14}, | ||
414 | {0,15}, | ||
415 | }; | ||
416 | |||
417 | |||
418 | public static huffcodetab[] ht = null; /* Simulate extern struct */ | ||
419 | |||
420 | private static int[] bitbuf = new int[32]; | ||
421 | |||
422 | /** | ||
423 | * Big Constructor : Computes all Huffman Tables. | ||
424 | */ | ||
425 | private huffcodetab(String S,int XLEN, int YLEN, int LINBITS, int LINMAX, int REF, | ||
426 | int[] TABLE, int[] HLEN, int[][] VAL, int TREELEN) | ||
427 | { | ||
428 | tablename0 = S.charAt(0); | ||
429 | tablename1 = S.charAt(1); | ||
430 | tablename2 = S.charAt(2); | ||
431 | xlen = XLEN; | ||
432 | ylen = YLEN; | ||
433 | linbits = LINBITS; | ||
434 | linmax = LINMAX; | ||
435 | ref = REF; | ||
436 | table = TABLE; | ||
437 | hlen = HLEN; | ||
438 | val = VAL; | ||
439 | treelen = TREELEN; | ||
440 | } | ||
441 | |||
442 | |||
443 | |||
444 | /** | ||
445 | * Do the huffman-decoding. | ||
446 | * note! for counta,countb -the 4 bit value is returned in y, | ||
447 | * discard x. | ||
448 | */ | ||
449 | public static int huffman_decoder(huffcodetab h, int[] x, int[] y, int[] v, int[] w, BitReserve br) | ||
450 | { | ||
451 | // array of all huffcodtable headers | ||
452 | // 0..31 Huffman code table 0..31 | ||
453 | // 32,33 count1-tables | ||
454 | |||
455 | int dmask = 1 << ((4 * 8) - 1); | ||
456 | int hs = 4 * 8; | ||
457 | int level; | ||
458 | int point = 0; | ||
459 | int error = 1; | ||
460 | level = dmask; | ||
461 | |||
462 | if (h.val == null) return 2; | ||
463 | |||
464 | /* table 0 needs no bits */ | ||
465 | if ( h.treelen == 0) | ||
466 | { | ||
467 | x[0] = y[0] = 0; | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | /* Lookup in Huffman table. */ | ||
472 | |||
473 | /*int bitsAvailable = 0; | ||
474 | int bitIndex = 0; | ||
475 | |||
476 | int bits[] = bitbuf;*/ | ||
477 | do | ||
478 | { | ||
479 | if (h.val[point][0]==0) | ||
480 | { /*end of tree*/ | ||
481 | x[0] = h.val[point][1] >>> 4; | ||
482 | y[0] = h.val[point][1] & 0xf; | ||
483 | error = 0; | ||
484 | break; | ||
485 | } | ||
486 | |||
487 | // hget1bit() is called thousands of times, and so needs to be | ||
488 | // ultra fast. | ||
489 | /* | ||
490 | if (bitIndex==bitsAvailable) | ||
491 | { | ||
492 | bitsAvailable = br.readBits(bits, 32); | ||
493 | bitIndex = 0; | ||
494 | } | ||
495 | */ | ||
496 | //if (bits[bitIndex++]!=0) | ||
497 | if (br.hget1bit()!=0) | ||
498 | { | ||
499 | while (h.val[point][1] >= MXOFF) point += h.val[point][1]; | ||
500 | point += h.val[point][1]; | ||
501 | } | ||
502 | else | ||
503 | { | ||
504 | while (h.val[point][0] >= MXOFF) point += h.val[point][0]; | ||
505 | point += h.val[point][0]; | ||
506 | } | ||
507 | level >>>= 1; | ||
508 | // MDM: ht[0] is always 0; | ||
509 | } while ((level !=0 ) || (point < 0 /*ht[0].treelen*/) ); | ||
510 | |||
511 | // put back any bits not consumed | ||
512 | /* | ||
513 | int unread = (bitsAvailable-bitIndex); | ||
514 | if (unread>0) | ||
515 | br.rewindNbits(unread); | ||
516 | */ | ||
517 | /* Process sign encodings for quadruples tables. */ | ||
518 | // System.out.println(h.tablename); | ||
519 | if (h.tablename0 == '3' && (h.tablename1 == '2' || h.tablename1 == '3')) | ||
520 | { | ||
521 | v[0] = (y[0]>>3) & 1; | ||
522 | w[0] = (y[0]>>2) & 1; | ||
523 | x[0] = (y[0]>>1) & 1; | ||
524 | y[0] = y[0] & 1; | ||
525 | |||
526 | /* v, w, x and y are reversed in the bitstream. | ||
527 | switch them around to make test bistream work. */ | ||
528 | |||
529 | if (v[0]!=0) | ||
530 | if (br.hget1bit() != 0) v[0] = -v[0]; | ||
531 | if (w[0]!=0) | ||
532 | if (br.hget1bit() != 0) w[0] = -w[0]; | ||
533 | if (x[0]!=0) | ||
534 | if (br.hget1bit() != 0) x[0] = -x[0]; | ||
535 | if (y[0]!=0) | ||
536 | if (br.hget1bit() != 0) y[0] = -y[0]; | ||
537 | } | ||
538 | else | ||
539 | { | ||
540 | // Process sign and escape encodings for dual tables. | ||
541 | // x and y are reversed in the test bitstream. | ||
542 | // Reverse x and y here to make test bitstream work. | ||
543 | |||
544 | if (h.linbits != 0) | ||
545 | if ((h.xlen-1) == x[0]) | ||
546 | x[0] += br.hgetbits(h.linbits); | ||
547 | if (x[0] != 0) | ||
548 | if (br.hget1bit() != 0) x[0] = -x[0]; | ||
549 | if (h.linbits != 0) | ||
550 | if ((h.ylen-1) == y[0]) | ||
551 | y[0] += br.hgetbits(h.linbits); | ||
552 | if (y[0] != 0) | ||
553 | if (br.hget1bit() != 0) y[0] = -y[0]; | ||
554 | } | ||
555 | return error; | ||
556 | } | ||
557 | |||
558 | public static void inithuff() | ||
559 | { | ||
560 | |||
561 | if (ht!=null) | ||
562 | return; | ||
563 | |||
564 | ht = new huffcodetab[HTN]; | ||
565 | ht[0] = new huffcodetab("0 ",0,0,0,0,-1,null,null,ValTab0,0); | ||
566 | ht[1] = new huffcodetab("1 ",2,2,0,0,-1,null,null,ValTab1,7); | ||
567 | ht[2] = new huffcodetab("2 ",3,3,0,0,-1,null,null,ValTab2,17); | ||
568 | ht[3] = new huffcodetab("3 ",3,3,0,0,-1,null,null,ValTab3,17); | ||
569 | ht[4] = new huffcodetab("4 ",0,0,0,0,-1,null,null,ValTab4,0); | ||
570 | ht[5] = new huffcodetab("5 ",4,4,0,0,-1,null,null,ValTab5,31); | ||
571 | ht[6] = new huffcodetab("6 ",4,4,0,0,-1,null,null,ValTab6,31); | ||
572 | ht[7] = new huffcodetab("7 ",6,6,0,0,-1,null,null,ValTab7,71); | ||
573 | ht[8] = new huffcodetab("8 ",6,6,0,0,-1,null,null,ValTab8,71); | ||
574 | ht[9] = new huffcodetab("9 ",6,6,0,0,-1,null,null,ValTab9,71); | ||
575 | ht[10] = new huffcodetab("10 ",8,8,0,0,-1,null,null,ValTab10,127); | ||
576 | ht[11] = new huffcodetab("11 ",8,8,0,0,-1,null,null,ValTab11,127); | ||
577 | ht[12] = new huffcodetab("12 ",8,8,0,0,-1,null,null,ValTab12,127); | ||
578 | ht[13] = new huffcodetab("13 ",16,16,0,0,-1,null,null,ValTab13,511); | ||
579 | ht[14] = new huffcodetab("14 ",0,0,0,0,-1,null,null,ValTab14,0); | ||
580 | ht[15] = new huffcodetab("15 ",16,16,0,0,-1,null,null,ValTab15,511); | ||
581 | ht[16] = new huffcodetab("16 ",16,16,1,1,-1,null,null,ValTab16,511); | ||
582 | ht[17] = new huffcodetab("17 ",16,16,2,3,16,null,null,ValTab16,511); | ||
583 | ht[18] = new huffcodetab("18 ",16,16,3,7,16,null,null,ValTab16,511); | ||
584 | ht[19] = new huffcodetab("19 ",16,16,4,15,16,null,null,ValTab16,511); | ||
585 | ht[20] = new huffcodetab("20 ",16,16,6,63,16,null,null,ValTab16,511); | ||
586 | ht[21] = new huffcodetab("21 ",16,16,8,255,16,null,null,ValTab16,511); | ||
587 | ht[22] = new huffcodetab("22 ",16,16,10,1023,16,null,null,ValTab16,511); | ||
588 | ht[23] = new huffcodetab("23 ",16,16,13,8191,16,null,null,ValTab16,511); | ||
589 | ht[24] = new huffcodetab("24 ",16,16,4,15,-1,null,null,ValTab24,512); | ||
590 | ht[25] = new huffcodetab("25 ",16,16,5,31,24,null,null,ValTab24,512); | ||
591 | ht[26] = new huffcodetab("26 ",16,16,6,63,24,null,null,ValTab24,512); | ||
592 | ht[27] = new huffcodetab("27 ",16,16,7,127,24,null,null,ValTab24,512); | ||
593 | ht[28] = new huffcodetab("28 ",16,16,8,255,24,null,null,ValTab24,512); | ||
594 | ht[29] = new huffcodetab("29 ",16,16,9,511,24,null,null,ValTab24,512); | ||
595 | ht[30] = new huffcodetab("30 ",16,16,11,2047,24,null,null,ValTab24,512); | ||
596 | ht[31] = new huffcodetab("31 ",16,16,13,8191,24,null,null,ValTab24,512); | ||
597 | ht[32] = new huffcodetab("32 ",1,16,0,0,-1,null,null,ValTab32,31); | ||
598 | ht[33] = new huffcodetab("33 ",1,16,0,0,-1,null,null,ValTab33,31); | ||
599 | } | ||
600 | } | ||
diff --git a/songdbj/javazoom/jl/decoder/l3reorder.ser b/songdbj/javazoom/jl/decoder/l3reorder.ser new file mode 100644 index 0000000000..d7e3e0fa61 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/l3reorder.ser | |||
Binary files differ | |||
diff --git a/songdbj/javazoom/jl/decoder/lin2au.ser b/songdbj/javazoom/jl/decoder/lin2au.ser new file mode 100644 index 0000000000..258231516e --- /dev/null +++ b/songdbj/javazoom/jl/decoder/lin2au.ser | |||
Binary files differ | |||
diff --git a/songdbj/javazoom/jl/decoder/readme.txt b/songdbj/javazoom/jl/decoder/readme.txt new file mode 100644 index 0000000000..7a765ec7dc --- /dev/null +++ b/songdbj/javazoom/jl/decoder/readme.txt | |||
@@ -0,0 +1,15 @@ | |||
1 | |||
2 | TODO: | ||
3 | |||
4 | |||
5 | Implement high-level Player and Converter classes. | ||
6 | |||
7 | Add MP1 and MP2 support and test. | ||
8 | |||
9 | Add option to run each "stage" on own thread. | ||
10 | E.g. read & parse input, decode subbands, subband synthesis, audio output. | ||
11 | |||
12 | Retrofit seek support (temporarily removed when reworking classes.) | ||
13 | |||
14 | |||
15 | Document and give example code. \ No newline at end of file | ||
diff --git a/songdbj/javazoom/jl/decoder/sfd.ser b/songdbj/javazoom/jl/decoder/sfd.ser new file mode 100644 index 0000000000..e65b782f36 --- /dev/null +++ b/songdbj/javazoom/jl/decoder/sfd.ser | |||
Binary files differ | |||
diff --git a/songdbj/javazoom/jl/player/AudioDevice.java b/songdbj/javazoom/jl/player/AudioDevice.java new file mode 100644 index 0000000000..45c28600e6 --- /dev/null +++ b/songdbj/javazoom/jl/player/AudioDevice.java | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 29/01/00 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.player; | ||
22 | |||
23 | import javazoom.jl.decoder.Decoder; | ||
24 | import javazoom.jl.decoder.JavaLayerException; | ||
25 | |||
26 | /** | ||
27 | * The <code>AudioDevice</code> interface provides an abstraction for | ||
28 | * a device capable of sounding audio samples. Samples are written to | ||
29 | * the device wia the write() method. The device assumes | ||
30 | * that these samples are signed 16-bit samples taken at the output frequency | ||
31 | * of the decoder. If the decoder outputs more than one channel, the samples for | ||
32 | * each channel are assumed to appear consecutively, with the lower numbered | ||
33 | * channels preceeding higher-numbered channels. E.g. if there are two | ||
34 | * channels, the samples will appear in this order: | ||
35 | * <pre><code> | ||
36 | * | ||
37 | * l0, r0, l1, r1, l2, r2... | ||
38 | * | ||
39 | * where | ||
40 | * l<i>x</i> indicates the <i>x</i>th sample on channel 0 | ||
41 | * r<i>x</i> indicates the <i>x</i>th sample on channel 1 | ||
42 | * </code></pre> | ||
43 | * | ||
44 | * @since 0.0.8 | ||
45 | * @author Mat McGowan | ||
46 | */ | ||
47 | public interface AudioDevice | ||
48 | { | ||
49 | /** | ||
50 | * Prepares the AudioDevice for playback of audio samples. | ||
51 | * @param decoder The decoder that will be providing the audio | ||
52 | * samples. | ||
53 | * | ||
54 | * If the audio device is already open, this method returns silently. | ||
55 | * | ||
56 | */ | ||
57 | public void open(Decoder decoder) throws JavaLayerException; | ||
58 | |||
59 | /** | ||
60 | * Retrieves the open state of this audio device. | ||
61 | * | ||
62 | * @return <code>true</code> if this audio device is open and playing | ||
63 | * audio samples, or <code>false</code> otherwise. | ||
64 | */ | ||
65 | public boolean isOpen(); | ||
66 | |||
67 | /** | ||
68 | * Writes a number of samples to this <code>AudioDevice</code>. | ||
69 | * | ||
70 | * @param samples The array of signed 16-bit samples to write | ||
71 | * to the audio device. | ||
72 | * @param offs The offset of the first sample. | ||
73 | * @param len The number of samples to write. | ||
74 | * | ||
75 | * This method may return prior to the samples actually being played | ||
76 | * by the audio device. | ||
77 | */ | ||
78 | public void write(short[] samples, int offs, int len) throws JavaLayerException; | ||
79 | |||
80 | |||
81 | /** | ||
82 | * Closes this audio device. Any currently playing audio is stopped | ||
83 | * as soon as possible. Any previously written audio data that has not been heard | ||
84 | * is discarded. | ||
85 | * | ||
86 | * The implementation should ensure that any threads currently blocking | ||
87 | * on the device (e.g. during a <code>write</code> or <code>flush</code> | ||
88 | * operation should be unblocked by this method. | ||
89 | */ | ||
90 | public void close(); | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Blocks until all audio samples previously written to this audio device have | ||
95 | * been heard. | ||
96 | */ | ||
97 | public void flush(); | ||
98 | |||
99 | /** | ||
100 | * Retrieves the current playback position in milliseconds. | ||
101 | */ | ||
102 | public int getPosition(); | ||
103 | } | ||
diff --git a/songdbj/javazoom/jl/player/AudioDeviceBase.java b/songdbj/javazoom/jl/player/AudioDeviceBase.java new file mode 100644 index 0000000000..d9c84f08e7 --- /dev/null +++ b/songdbj/javazoom/jl/player/AudioDeviceBase.java | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 29/01/00 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.player; | ||
22 | |||
23 | import javazoom.jl.decoder.Decoder; | ||
24 | import javazoom.jl.decoder.JavaLayerException; | ||
25 | |||
26 | /** | ||
27 | * The <code>AudioDeviceBase</code> class provides a simple thread-safe | ||
28 | * implementation of the <code>AudioDevice</code> interface. | ||
29 | * Template methods are provided for subclasses to override and | ||
30 | * in doing so provide the implementation for the main operations | ||
31 | * of the <code>AudioDevice</code> interface. | ||
32 | * | ||
33 | * @since 0.0.8 | ||
34 | * @author Mat McGowan | ||
35 | */ | ||
36 | /* | ||
37 | * REVIEW: It is desirable to be able to use the decoder whe | ||
38 | * in the implementation of open(), but the decoder | ||
39 | * has not yet read a frame, and so much of the | ||
40 | * desired information (sample rate, channels etc.) | ||
41 | * are not available. | ||
42 | */ | ||
43 | public abstract class AudioDeviceBase implements AudioDevice | ||
44 | { | ||
45 | private boolean open = false; | ||
46 | |||
47 | private Decoder decoder = null; | ||
48 | |||
49 | /** | ||
50 | * Opens this audio device. | ||
51 | * | ||
52 | * @param decoder The decoder that will provide audio data | ||
53 | * to this audio device. | ||
54 | */ | ||
55 | public synchronized void open(Decoder decoder) throws JavaLayerException | ||
56 | { | ||
57 | if (!isOpen()) | ||
58 | { | ||
59 | this.decoder = decoder; | ||
60 | openImpl(); | ||
61 | setOpen(true); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | * Template method to provide the | ||
67 | * implementation for the opening of the audio device. | ||
68 | */ | ||
69 | protected void openImpl() throws JavaLayerException | ||
70 | { | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Sets the open state for this audio device. | ||
75 | */ | ||
76 | protected void setOpen(boolean open) | ||
77 | { | ||
78 | this.open = open; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * Determines if this audio device is open or not. | ||
83 | * | ||
84 | * @return <code>true</code> if the audio device is open, | ||
85 | * <code>false</code> if it is not. | ||
86 | */ | ||
87 | public synchronized boolean isOpen() | ||
88 | { | ||
89 | return open; | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * Closes this audio device. If the device is currently playing | ||
94 | * audio, playback is stopped immediately without flushing | ||
95 | * any buffered audio data. | ||
96 | */ | ||
97 | public synchronized void close() | ||
98 | { | ||
99 | if (isOpen()) | ||
100 | { | ||
101 | closeImpl(); | ||
102 | setOpen(false); | ||
103 | decoder = null; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * Template method to provide the implementation for | ||
109 | * closing the audio device. | ||
110 | */ | ||
111 | protected void closeImpl() | ||
112 | { | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * Writes audio data to this audio device. Audio data is | ||
117 | * assumed to be in the output format of the decoder. This | ||
118 | * method may return before the data has actually been sounded | ||
119 | * by the device if the device buffers audio samples. | ||
120 | * | ||
121 | * @param samples The samples to write to the audio device. | ||
122 | * @param offs The offset into the array of the first sample to write. | ||
123 | * @param len The number of samples from the array to write. | ||
124 | * @throws JavaLayerException if the audio data could not be | ||
125 | * written to the audio device. | ||
126 | * If the audio device is not open, this method does nthing. | ||
127 | */ | ||
128 | public void write(short[] samples, int offs, int len) | ||
129 | throws JavaLayerException | ||
130 | { | ||
131 | if (isOpen()) | ||
132 | { | ||
133 | writeImpl(samples, offs, len); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * Template method to provide the implementation for | ||
139 | * writing audio samples to the audio device. | ||
140 | */ | ||
141 | protected void writeImpl(short[] samples, int offs, int len) | ||
142 | throws JavaLayerException | ||
143 | { | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * Waits for any buffered audio samples to be played by the | ||
148 | * audio device. This method should only be called prior | ||
149 | * to closing the device. | ||
150 | */ | ||
151 | public void flush() | ||
152 | { | ||
153 | if (isOpen()) | ||
154 | { | ||
155 | flushImpl(); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * Template method to provide the implementation for | ||
161 | * flushing any buffered audio data. | ||
162 | */ | ||
163 | protected void flushImpl() | ||
164 | { | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * Retrieves the decoder that provides audio data to this | ||
169 | * audio device. | ||
170 | * | ||
171 | * @return The associated decoder. | ||
172 | */ | ||
173 | protected Decoder getDecoder() | ||
174 | { | ||
175 | return decoder; | ||
176 | } | ||
177 | } | ||
diff --git a/songdbj/javazoom/jl/player/AudioDeviceFactory.java b/songdbj/javazoom/jl/player/AudioDeviceFactory.java new file mode 100644 index 0000000000..2d502d2aad --- /dev/null +++ b/songdbj/javazoom/jl/player/AudioDeviceFactory.java | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 29/01/00 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.player; | ||
22 | |||
23 | import javazoom.jl.decoder.JavaLayerException; | ||
24 | |||
25 | /** | ||
26 | * An <code>AudioDeviceFactory</code> class is responsible for creating | ||
27 | * a specific <code>AudioDevice</code> implementation. A factory implementation | ||
28 | * can be as simple or complex as desired and may support just one implementation | ||
29 | * or may return several implementations depending upon the execution | ||
30 | * environment. | ||
31 | * <p> | ||
32 | * When implementing a factory that provides an AudioDevice that uses | ||
33 | * class that may not be present, the factory should dynamically link to any | ||
34 | * specific implementation classes required to instantiate or test the audio | ||
35 | * implementation. This is so that the application as a whole | ||
36 | * can run without these classes being present. The audio | ||
37 | * device implementation, however, will usually statically link to the classes | ||
38 | * required. (See the JavaSound deivce and factory for an example | ||
39 | * of this.) | ||
40 | * | ||
41 | * @see FactoryRegistry | ||
42 | * | ||
43 | * @since 0.0.8 | ||
44 | * @author Mat McGowan | ||
45 | */ | ||
46 | public abstract class AudioDeviceFactory | ||
47 | { | ||
48 | /** | ||
49 | * Creates a new <code>AudioDevice</code>. | ||
50 | * | ||
51 | * @return a new instance of a specific class of <code>AudioDevice</code>. | ||
52 | * @throws JavaLayerException if an instance of AudioDevice could not | ||
53 | * be created. | ||
54 | */ | ||
55 | public abstract AudioDevice createAudioDevice() throws JavaLayerException; | ||
56 | |||
57 | /** | ||
58 | * Creates an instance of an AudioDevice implementation. | ||
59 | * @param loader The <code>ClassLoader</code> to use to | ||
60 | * load the named class, or null to use the | ||
61 | * system class loader. | ||
62 | * @param name The name of the class to load. | ||
63 | * @return A newly-created instance of the audio device class. | ||
64 | */ | ||
65 | protected AudioDevice instantiate(ClassLoader loader, String name) | ||
66 | throws ClassNotFoundException, | ||
67 | IllegalAccessException, | ||
68 | InstantiationException | ||
69 | { | ||
70 | AudioDevice dev = null; | ||
71 | |||
72 | Class cls = null; | ||
73 | if (loader==null) | ||
74 | { | ||
75 | cls = Class.forName(name); | ||
76 | } | ||
77 | else | ||
78 | { | ||
79 | cls = loader.loadClass(name); | ||
80 | } | ||
81 | |||
82 | Object o = cls.newInstance(); | ||
83 | dev = (AudioDevice)o; | ||
84 | |||
85 | return dev; | ||
86 | } | ||
87 | } | ||
diff --git a/songdbj/javazoom/jl/player/FactoryRegistry.java b/songdbj/javazoom/jl/player/FactoryRegistry.java new file mode 100644 index 0000000000..8919995802 --- /dev/null +++ b/songdbj/javazoom/jl/player/FactoryRegistry.java | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 29/01/00 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.player; | ||
22 | |||
23 | import java.util.Enumeration; | ||
24 | import java.util.Hashtable; | ||
25 | |||
26 | import javazoom.jl.decoder.JavaLayerException; | ||
27 | |||
28 | /** | ||
29 | * The <code>FactoryRegistry</code> class stores the factories | ||
30 | * for all the audio device implementations available in the system. | ||
31 | * <p> | ||
32 | * Instances of this class are thread-safe. | ||
33 | * | ||
34 | * @since 0.0.8 | ||
35 | * @author Mat McGowan | ||
36 | */ | ||
37 | |||
38 | public class FactoryRegistry extends AudioDeviceFactory | ||
39 | { | ||
40 | static private FactoryRegistry instance = null; | ||
41 | |||
42 | static synchronized public FactoryRegistry systemRegistry() | ||
43 | { | ||
44 | if (instance==null) | ||
45 | { | ||
46 | instance = new FactoryRegistry(); | ||
47 | instance.registerDefaultFactories(); | ||
48 | } | ||
49 | return instance; | ||
50 | } | ||
51 | |||
52 | |||
53 | protected Hashtable factories = new Hashtable(); | ||
54 | |||
55 | /** | ||
56 | * Registers an <code>AudioDeviceFactory</code> instance | ||
57 | * with this registry. | ||
58 | */ | ||
59 | public void addFactory(AudioDeviceFactory factory) | ||
60 | { | ||
61 | factories.put(factory.getClass(), factory); | ||
62 | } | ||
63 | |||
64 | public void removeFactoryType(Class cls) | ||
65 | { | ||
66 | factories.remove(cls); | ||
67 | } | ||
68 | |||
69 | public void removeFactory(AudioDeviceFactory factory) | ||
70 | { | ||
71 | factories.remove(factory.getClass()); | ||
72 | } | ||
73 | |||
74 | public AudioDevice createAudioDevice() throws JavaLayerException | ||
75 | { | ||
76 | AudioDevice device = null; | ||
77 | AudioDeviceFactory[] factories = getFactoriesPriority(); | ||
78 | |||
79 | if (factories==null) | ||
80 | throw new JavaLayerException(this+": no factories registered"); | ||
81 | |||
82 | JavaLayerException lastEx = null; | ||
83 | for (int i=0; (device==null) && (i<factories.length); i++) | ||
84 | { | ||
85 | try | ||
86 | { | ||
87 | device = factories[i].createAudioDevice(); | ||
88 | } | ||
89 | catch (JavaLayerException ex) | ||
90 | { | ||
91 | lastEx = ex; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | if (device==null && lastEx!=null) | ||
96 | { | ||
97 | throw new JavaLayerException("Cannot create AudioDevice", lastEx); | ||
98 | } | ||
99 | |||
100 | return device; | ||
101 | } | ||
102 | |||
103 | |||
104 | protected AudioDeviceFactory[] getFactoriesPriority() | ||
105 | { | ||
106 | AudioDeviceFactory[] fa = null; | ||
107 | synchronized (factories) | ||
108 | { | ||
109 | int size = factories.size(); | ||
110 | if (size!=0) | ||
111 | { | ||
112 | fa = new AudioDeviceFactory[size]; | ||
113 | int idx = 0; | ||
114 | Enumeration e = factories.elements(); | ||
115 | while (e.hasMoreElements()) | ||
116 | { | ||
117 | AudioDeviceFactory factory = (AudioDeviceFactory)e.nextElement(); | ||
118 | fa[idx++] = factory; | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | return fa; | ||
123 | } | ||
124 | |||
125 | protected void registerDefaultFactories() | ||
126 | { | ||
127 | addFactory(new JavaSoundAudioDeviceFactory()); | ||
128 | } | ||
129 | } | ||
diff --git a/songdbj/javazoom/jl/player/JavaSoundAudioDevice.java b/songdbj/javazoom/jl/player/JavaSoundAudioDevice.java new file mode 100644 index 0000000000..caa92cd6fc --- /dev/null +++ b/songdbj/javazoom/jl/player/JavaSoundAudioDevice.java | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * 11/26/04 Buffer size modified to support JRE 1.5 optimizations. | ||
3 | * (CPU usage < 1% under P4/2Ghz, RAM < 12MB). | ||
4 | * jlayer@javazoom.net | ||
5 | * 11/19/04 1.0 moved to LGPL. | ||
6 | * 06/04/01 Too fast playback fixed. mdm@techie.com | ||
7 | * 29/01/00 Initial version. mdm@techie.com | ||
8 | *----------------------------------------------------------------------- | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Library General Public License as published | ||
11 | * by the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU Library General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Library General Public | ||
20 | * License along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | *---------------------------------------------------------------------- | ||
23 | */ | ||
24 | |||
25 | package javazoom.jl.player; | ||
26 | |||
27 | import javax.sound.sampled.AudioFormat; | ||
28 | import javax.sound.sampled.AudioSystem; | ||
29 | import javax.sound.sampled.DataLine; | ||
30 | import javax.sound.sampled.Line; | ||
31 | import javax.sound.sampled.LineUnavailableException; | ||
32 | import javax.sound.sampled.SourceDataLine; | ||
33 | |||
34 | import javazoom.jl.decoder.Decoder; | ||
35 | import javazoom.jl.decoder.JavaLayerException; | ||
36 | |||
37 | /** | ||
38 | * The <code>JavaSoundAudioDevice</code> implements an audio | ||
39 | * device by using the JavaSound API. | ||
40 | * | ||
41 | * @since 0.0.8 | ||
42 | * @author Mat McGowan | ||
43 | */ | ||
44 | public class JavaSoundAudioDevice extends AudioDeviceBase | ||
45 | { | ||
46 | private SourceDataLine source = null; | ||
47 | |||
48 | private AudioFormat fmt = null; | ||
49 | |||
50 | private byte[] byteBuf = new byte[4096]; | ||
51 | |||
52 | protected void setAudioFormat(AudioFormat fmt0) | ||
53 | { | ||
54 | fmt = fmt0; | ||
55 | } | ||
56 | |||
57 | protected AudioFormat getAudioFormat() | ||
58 | { | ||
59 | if (fmt==null) | ||
60 | { | ||
61 | Decoder decoder = getDecoder(); | ||
62 | fmt = new AudioFormat(decoder.getOutputFrequency(), | ||
63 | 16, | ||
64 | decoder.getOutputChannels(), | ||
65 | true, | ||
66 | false); | ||
67 | } | ||
68 | return fmt; | ||
69 | } | ||
70 | |||
71 | protected DataLine.Info getSourceLineInfo() | ||
72 | { | ||
73 | AudioFormat fmt = getAudioFormat(); | ||
74 | //DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt, 4000); | ||
75 | DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt); | ||
76 | return info; | ||
77 | } | ||
78 | |||
79 | public void open(AudioFormat fmt) throws JavaLayerException | ||
80 | { | ||
81 | if (!isOpen()) | ||
82 | { | ||
83 | setAudioFormat(fmt); | ||
84 | openImpl(); | ||
85 | setOpen(true); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | protected void openImpl() | ||
90 | throws JavaLayerException | ||
91 | { | ||
92 | } | ||
93 | |||
94 | |||
95 | // createSource fix. | ||
96 | protected void createSource() throws JavaLayerException | ||
97 | { | ||
98 | Throwable t = null; | ||
99 | try | ||
100 | { | ||
101 | Line line = AudioSystem.getLine(getSourceLineInfo()); | ||
102 | if (line instanceof SourceDataLine) | ||
103 | { | ||
104 | source = (SourceDataLine)line; | ||
105 | //source.open(fmt, millisecondsToBytes(fmt, 2000)); | ||
106 | source.open(fmt); | ||
107 | /* | ||
108 | if (source.isControlSupported(FloatControl.Type.MASTER_GAIN)) | ||
109 | { | ||
110 | FloatControl c = (FloatControl)source.getControl(FloatControl.Type.MASTER_GAIN); | ||
111 | c.setValue(c.getMaximum()); | ||
112 | }*/ | ||
113 | source.start(); | ||
114 | |||
115 | } | ||
116 | } catch (RuntimeException ex) | ||
117 | { | ||
118 | t = ex; | ||
119 | } | ||
120 | catch (LinkageError ex) | ||
121 | { | ||
122 | t = ex; | ||
123 | } | ||
124 | catch (LineUnavailableException ex) | ||
125 | { | ||
126 | t = ex; | ||
127 | } | ||
128 | if (source==null) throw new JavaLayerException("cannot obtain source audio line", t); | ||
129 | } | ||
130 | |||
131 | public int millisecondsToBytes(AudioFormat fmt, int time) | ||
132 | { | ||
133 | return (int)(time*(fmt.getSampleRate()*fmt.getChannels()*fmt.getSampleSizeInBits())/8000.0); | ||
134 | } | ||
135 | |||
136 | protected void closeImpl() | ||
137 | { | ||
138 | if (source!=null) | ||
139 | { | ||
140 | source.close(); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | protected void writeImpl(short[] samples, int offs, int len) | ||
145 | throws JavaLayerException | ||
146 | { | ||
147 | if (source==null) | ||
148 | createSource(); | ||
149 | |||
150 | byte[] b = toByteArray(samples, offs, len); | ||
151 | source.write(b, 0, len*2); | ||
152 | } | ||
153 | |||
154 | protected byte[] getByteArray(int length) | ||
155 | { | ||
156 | if (byteBuf.length < length) | ||
157 | { | ||
158 | byteBuf = new byte[length+1024]; | ||
159 | } | ||
160 | return byteBuf; | ||
161 | } | ||
162 | |||
163 | protected byte[] toByteArray(short[] samples, int offs, int len) | ||
164 | { | ||
165 | byte[] b = getByteArray(len*2); | ||
166 | int idx = 0; | ||
167 | short s; | ||
168 | while (len-- > 0) | ||
169 | { | ||
170 | s = samples[offs++]; | ||
171 | b[idx++] = (byte)s; | ||
172 | b[idx++] = (byte)(s>>>8); | ||
173 | } | ||
174 | return b; | ||
175 | } | ||
176 | |||
177 | protected void flushImpl() | ||
178 | { | ||
179 | if (source!=null) | ||
180 | { | ||
181 | source.drain(); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | public int getPosition() | ||
186 | { | ||
187 | int pos = 0; | ||
188 | if (source!=null) | ||
189 | { | ||
190 | pos = (int)(source.getMicrosecondPosition()/1000); | ||
191 | } | ||
192 | return pos; | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * Runs a short test by playing a short silent sound. | ||
197 | */ | ||
198 | public void test() | ||
199 | throws JavaLayerException | ||
200 | { | ||
201 | try | ||
202 | { | ||
203 | open(new AudioFormat(22050, 16, 1, true, false)); | ||
204 | short[] data = new short[22050/10]; | ||
205 | write(data, 0, data.length); | ||
206 | flush(); | ||
207 | close(); | ||
208 | } | ||
209 | catch (RuntimeException ex) | ||
210 | { | ||
211 | throw new JavaLayerException("Device test failed: "+ex); | ||
212 | } | ||
213 | |||
214 | } | ||
215 | } | ||
diff --git a/songdbj/javazoom/jl/player/JavaSoundAudioDeviceFactory.java b/songdbj/javazoom/jl/player/JavaSoundAudioDeviceFactory.java new file mode 100644 index 0000000000..92af492f65 --- /dev/null +++ b/songdbj/javazoom/jl/player/JavaSoundAudioDeviceFactory.java | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 29/01/00 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.player; | ||
22 | |||
23 | import javazoom.jl.decoder.JavaLayerException; | ||
24 | |||
25 | /** | ||
26 | * This class is responsible for creating instances of the | ||
27 | * JavaSoundAudioDevice. The audio device implementation is loaded | ||
28 | * and tested dynamically as not all systems will have support | ||
29 | * for JavaSound, or they may have the incorrect version. | ||
30 | */ | ||
31 | public class JavaSoundAudioDeviceFactory extends AudioDeviceFactory | ||
32 | { | ||
33 | private boolean tested = false; | ||
34 | |||
35 | static private final String DEVICE_CLASS_NAME = "javazoom.jl.player.JavaSoundAudioDevice"; | ||
36 | |||
37 | public synchronized AudioDevice createAudioDevice() | ||
38 | throws JavaLayerException | ||
39 | { | ||
40 | if (!tested) | ||
41 | { | ||
42 | testAudioDevice(); | ||
43 | tested = true; | ||
44 | } | ||
45 | |||
46 | try | ||
47 | { | ||
48 | return createAudioDeviceImpl(); | ||
49 | } | ||
50 | catch (Exception ex) | ||
51 | { | ||
52 | throw new JavaLayerException("unable to create JavaSound device: "+ex); | ||
53 | } | ||
54 | catch (LinkageError ex) | ||
55 | { | ||
56 | throw new JavaLayerException("unable to create JavaSound device: "+ex); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | protected JavaSoundAudioDevice createAudioDeviceImpl() | ||
61 | throws JavaLayerException | ||
62 | { | ||
63 | ClassLoader loader = getClass().getClassLoader(); | ||
64 | try | ||
65 | { | ||
66 | JavaSoundAudioDevice dev = (JavaSoundAudioDevice)instantiate(loader, DEVICE_CLASS_NAME); | ||
67 | return dev; | ||
68 | } | ||
69 | catch (Exception ex) | ||
70 | { | ||
71 | throw new JavaLayerException("Cannot create JavaSound device", ex); | ||
72 | } | ||
73 | catch (LinkageError ex) | ||
74 | { | ||
75 | throw new JavaLayerException("Cannot create JavaSound device", ex); | ||
76 | } | ||
77 | |||
78 | } | ||
79 | |||
80 | public void testAudioDevice() throws JavaLayerException | ||
81 | { | ||
82 | JavaSoundAudioDevice dev = createAudioDeviceImpl(); | ||
83 | dev.test(); | ||
84 | } | ||
85 | } | ||
diff --git a/songdbj/javazoom/jl/player/NullAudioDevice.java b/songdbj/javazoom/jl/player/NullAudioDevice.java new file mode 100644 index 0000000000..4145feecd4 --- /dev/null +++ b/songdbj/javazoom/jl/player/NullAudioDevice.java | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved o LGPL. | ||
3 | * 29/01/00 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.player; | ||
22 | |||
23 | /** | ||
24 | * The <code>NullAudioDevice</code> implements a silent, no-op | ||
25 | * audio device. This is useful for testing purposes. | ||
26 | * | ||
27 | * @since 0.0.8 | ||
28 | * @author Mat McGowan | ||
29 | */ | ||
30 | public class NullAudioDevice extends AudioDeviceBase | ||
31 | { | ||
32 | |||
33 | public int getPosition() | ||
34 | { | ||
35 | return 0; | ||
36 | } | ||
37 | } | ||
diff --git a/songdbj/javazoom/jl/player/Player.java b/songdbj/javazoom/jl/player/Player.java new file mode 100644 index 0000000000..32fb1f3051 --- /dev/null +++ b/songdbj/javazoom/jl/player/Player.java | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 29/01/00 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.player; | ||
22 | |||
23 | import java.io.InputStream; | ||
24 | |||
25 | import javazoom.jl.decoder.Bitstream; | ||
26 | import javazoom.jl.decoder.BitstreamException; | ||
27 | import javazoom.jl.decoder.Decoder; | ||
28 | import javazoom.jl.decoder.Header; | ||
29 | import javazoom.jl.decoder.JavaLayerException; | ||
30 | import javazoom.jl.decoder.SampleBuffer; | ||
31 | |||
32 | /** | ||
33 | * The <code>Player</code> class implements a simple player for playback | ||
34 | * of an MPEG audio stream. | ||
35 | * | ||
36 | * @author Mat McGowan | ||
37 | * @since 0.0.8 | ||
38 | */ | ||
39 | |||
40 | // REVIEW: the audio device should not be opened until the | ||
41 | // first MPEG audio frame has been decoded. | ||
42 | public class Player | ||
43 | { | ||
44 | /** | ||
45 | * The current frame number. | ||
46 | */ | ||
47 | private int frame = 0; | ||
48 | |||
49 | /** | ||
50 | * The MPEG audio bitstream. | ||
51 | */ | ||
52 | // javac blank final bug. | ||
53 | /*final*/ private Bitstream bitstream; | ||
54 | |||
55 | /** | ||
56 | * The MPEG audio decoder. | ||
57 | */ | ||
58 | /*final*/ private Decoder decoder; | ||
59 | |||
60 | /** | ||
61 | * The AudioDevice the audio samples are written to. | ||
62 | */ | ||
63 | private AudioDevice audio; | ||
64 | |||
65 | /** | ||
66 | * Has the player been closed? | ||
67 | */ | ||
68 | private boolean closed = false; | ||
69 | |||
70 | /** | ||
71 | * Has the player played back all frames from the stream? | ||
72 | */ | ||
73 | private boolean complete = false; | ||
74 | |||
75 | private int lastPosition = 0; | ||
76 | |||
77 | /** | ||
78 | * Creates a new <code>Player</code> instance. | ||
79 | */ | ||
80 | public Player(InputStream stream) throws JavaLayerException | ||
81 | { | ||
82 | this(stream, null); | ||
83 | } | ||
84 | |||
85 | public Player(InputStream stream, AudioDevice device) throws JavaLayerException | ||
86 | { | ||
87 | bitstream = new Bitstream(stream); | ||
88 | decoder = new Decoder(); | ||
89 | |||
90 | if (device!=null) | ||
91 | { | ||
92 | audio = device; | ||
93 | } | ||
94 | else | ||
95 | { | ||
96 | FactoryRegistry r = FactoryRegistry.systemRegistry(); | ||
97 | audio = r.createAudioDevice(); | ||
98 | } | ||
99 | audio.open(decoder); | ||
100 | } | ||
101 | |||
102 | public void play() throws JavaLayerException | ||
103 | { | ||
104 | play(Integer.MAX_VALUE); | ||
105 | } | ||
106 | |||
107 | /** | ||
108 | * Plays a number of MPEG audio frames. | ||
109 | * | ||
110 | * @param frames The number of frames to play. | ||
111 | * @return true if the last frame was played, or false if there are | ||
112 | * more frames. | ||
113 | */ | ||
114 | public boolean play(int frames) throws JavaLayerException | ||
115 | { | ||
116 | boolean ret = true; | ||
117 | |||
118 | while (frames-- > 0 && ret) | ||
119 | { | ||
120 | ret = decodeFrame(); | ||
121 | } | ||
122 | |||
123 | if (!ret) | ||
124 | { | ||
125 | // last frame, ensure all data flushed to the audio device. | ||
126 | AudioDevice out = audio; | ||
127 | if (out!=null) | ||
128 | { | ||
129 | out.flush(); | ||
130 | synchronized (this) | ||
131 | { | ||
132 | complete = (!closed); | ||
133 | close(); | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * Cloases this player. Any audio currently playing is stopped | ||
142 | * immediately. | ||
143 | */ | ||
144 | public synchronized void close() | ||
145 | { | ||
146 | AudioDevice out = audio; | ||
147 | if (out!=null) | ||
148 | { | ||
149 | closed = true; | ||
150 | audio = null; | ||
151 | // this may fail, so ensure object state is set up before | ||
152 | // calling this method. | ||
153 | out.close(); | ||
154 | lastPosition = out.getPosition(); | ||
155 | try | ||
156 | { | ||
157 | bitstream.close(); | ||
158 | } | ||
159 | catch (BitstreamException ex) | ||
160 | { | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * Returns the completed status of this player. | ||
167 | * | ||
168 | * @return true if all available MPEG audio frames have been | ||
169 | * decoded, or false otherwise. | ||
170 | */ | ||
171 | public synchronized boolean isComplete() | ||
172 | { | ||
173 | return complete; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * Retrieves the position in milliseconds of the current audio | ||
178 | * sample being played. This method delegates to the <code> | ||
179 | * AudioDevice</code> that is used by this player to sound | ||
180 | * the decoded audio samples. | ||
181 | */ | ||
182 | public int getPosition() | ||
183 | { | ||
184 | int position = lastPosition; | ||
185 | |||
186 | AudioDevice out = audio; | ||
187 | if (out!=null) | ||
188 | { | ||
189 | position = out.getPosition(); | ||
190 | } | ||
191 | return position; | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * Decodes a single frame. | ||
196 | * | ||
197 | * @return true if there are no more frames to decode, false otherwise. | ||
198 | */ | ||
199 | protected boolean decodeFrame() throws JavaLayerException | ||
200 | { | ||
201 | try | ||
202 | { | ||
203 | AudioDevice out = audio; | ||
204 | if (out==null) | ||
205 | return false; | ||
206 | |||
207 | Header h = bitstream.readFrame(); | ||
208 | |||
209 | if (h==null) | ||
210 | return false; | ||
211 | |||
212 | // sample buffer set when decoder constructed | ||
213 | SampleBuffer output = (SampleBuffer)decoder.decodeFrame(h, bitstream); | ||
214 | |||
215 | synchronized (this) | ||
216 | { | ||
217 | out = audio; | ||
218 | if (out!=null) | ||
219 | { | ||
220 | out.write(output.getBuffer(), 0, output.getBufferLength()); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | bitstream.closeFrame(); | ||
225 | } | ||
226 | catch (RuntimeException ex) | ||
227 | { | ||
228 | throw new JavaLayerException("Exception decoding audio frame", ex); | ||
229 | } | ||
230 | /* | ||
231 | catch (IOException ex) | ||
232 | { | ||
233 | System.out.println("exception decoding audio frame: "+ex); | ||
234 | return false; | ||
235 | } | ||
236 | catch (BitstreamException bitex) | ||
237 | { | ||
238 | System.out.println("exception decoding audio frame: "+bitex); | ||
239 | return false; | ||
240 | } | ||
241 | catch (DecoderException decex) | ||
242 | { | ||
243 | System.out.println("exception decoding audio frame: "+decex); | ||
244 | return false; | ||
245 | } | ||
246 | */ | ||
247 | return true; | ||
248 | } | ||
249 | |||
250 | |||
251 | } | ||
diff --git a/songdbj/javazoom/jl/player/PlayerApplet.java b/songdbj/javazoom/jl/player/PlayerApplet.java new file mode 100644 index 0000000000..d7c7dc2ffc --- /dev/null +++ b/songdbj/javazoom/jl/player/PlayerApplet.java | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * 29/01/00 Initial version. mdm@techie.com | ||
4 | *----------------------------------------------------------------------- | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU Library General Public License as published | ||
7 | * by the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU Library General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Library General Public | ||
16 | * License along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | *---------------------------------------------------------------------- | ||
19 | */ | ||
20 | |||
21 | package javazoom.jl.player; | ||
22 | |||
23 | import java.applet.Applet; | ||
24 | import java.io.IOException; | ||
25 | import java.io.InputStream; | ||
26 | import java.net.URL; | ||
27 | |||
28 | import javazoom.jl.decoder.JavaLayerException; | ||
29 | |||
30 | /** | ||
31 | * A simple applet that plays an MPEG audio file. | ||
32 | * The URL (relative to the document base) | ||
33 | * is passed as the "audioURL" parameter. | ||
34 | * | ||
35 | * @author Mat McGowan | ||
36 | * @since 0.0.8 | ||
37 | */ | ||
38 | public class PlayerApplet extends Applet implements Runnable | ||
39 | { | ||
40 | static public final String AUDIO_PARAMETER = "audioURL"; | ||
41 | |||
42 | /** | ||
43 | * The Player used to play the MPEG audio file. | ||
44 | */ | ||
45 | private Player player = null; | ||
46 | |||
47 | /** | ||
48 | * The thread that runs the player. | ||
49 | */ | ||
50 | private Thread playerThread = null; | ||
51 | |||
52 | private String fileName = null; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Retrieves the <code>AudioDevice</code> instance that will | ||
57 | * be used to sound the audio data. | ||
58 | * | ||
59 | * @return an audio device instance that will be used to | ||
60 | * sound the audio stream. | ||
61 | */ | ||
62 | protected AudioDevice getAudioDevice() throws JavaLayerException | ||
63 | { | ||
64 | return FactoryRegistry.systemRegistry().createAudioDevice(); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Retrieves the InputStream that provides the MPEG audio | ||
69 | * stream data. | ||
70 | * | ||
71 | * @return an InputStream from which the MPEG audio data | ||
72 | * is read, or null if an error occurs. | ||
73 | */ | ||
74 | protected InputStream getAudioStream() | ||
75 | { | ||
76 | InputStream in = null; | ||
77 | |||
78 | try | ||
79 | { | ||
80 | URL url = getAudioURL(); | ||
81 | if (url!=null) | ||
82 | in = url.openStream(); | ||
83 | } | ||
84 | catch (IOException ex) | ||
85 | { | ||
86 | System.err.println(ex); | ||
87 | } | ||
88 | return in; | ||
89 | } | ||
90 | |||
91 | protected String getAudioFileName() | ||
92 | { | ||
93 | String urlString = fileName; | ||
94 | if (urlString==null) | ||
95 | { | ||
96 | urlString = getParameter(AUDIO_PARAMETER); | ||
97 | } | ||
98 | return urlString; | ||
99 | } | ||
100 | |||
101 | protected URL getAudioURL() | ||
102 | { | ||
103 | String urlString = getAudioFileName(); | ||
104 | URL url = null; | ||
105 | if (urlString!=null) | ||
106 | { | ||
107 | try | ||
108 | { | ||
109 | url = new URL(getDocumentBase(), urlString); | ||
110 | } | ||
111 | catch (Exception ex) | ||
112 | { | ||
113 | System.err.println(ex); | ||
114 | } | ||
115 | } | ||
116 | return url; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * Sets the URL of the audio stream to play. | ||
121 | */ | ||
122 | public void setFileName(String name) | ||
123 | { | ||
124 | fileName = name; | ||
125 | } | ||
126 | |||
127 | public String getFileName() | ||
128 | { | ||
129 | return fileName; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Stops the audio player. If the player is already stopped | ||
134 | * this method is a no-op. | ||
135 | */ | ||
136 | protected void stopPlayer() throws JavaLayerException | ||
137 | { | ||
138 | if (player!=null) | ||
139 | { | ||
140 | player.close(); | ||
141 | player = null; | ||
142 | playerThread = null; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * Decompresses audio data from an InputStream and plays it | ||
148 | * back through an AudioDevice. The playback is run on a newly | ||
149 | * created thread. | ||
150 | * | ||
151 | * @param in The InputStream that provides the MPEG audio data. | ||
152 | * @param dev The AudioDevice to use to sound the decompressed data. | ||
153 | * | ||
154 | * @throws JavaLayerException if there was a problem decoding | ||
155 | * or playing the audio data. | ||
156 | */ | ||
157 | protected void play(InputStream in, AudioDevice dev) throws JavaLayerException | ||
158 | { | ||
159 | stopPlayer(); | ||
160 | |||
161 | if (in!=null && dev!=null) | ||
162 | { | ||
163 | player = new Player(in, dev); | ||
164 | playerThread = createPlayerThread(); | ||
165 | playerThread.start(); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Creates a new thread used to run the audio player. | ||
171 | * @return A new Thread that, once started, runs the audio player. | ||
172 | */ | ||
173 | protected Thread createPlayerThread() | ||
174 | { | ||
175 | return new Thread(this, "Audio player thread"); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * Initializes this applet. | ||
180 | */ | ||
181 | public void init() | ||
182 | { | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * Starts this applet. An input stream and audio device | ||
187 | * are created and passed to the play() method. | ||
188 | */ | ||
189 | public void start() | ||
190 | { | ||
191 | String name = getAudioFileName(); | ||
192 | try | ||
193 | { | ||
194 | InputStream in = getAudioStream(); | ||
195 | AudioDevice dev = getAudioDevice(); | ||
196 | play(in, dev); | ||
197 | } | ||
198 | catch (JavaLayerException ex) | ||
199 | { | ||
200 | synchronized (System.err) | ||
201 | { | ||
202 | System.err.println("Unable to play "+name); | ||
203 | ex.printStackTrace(System.err); | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * Stops this applet. If audio is currently playing, it is | ||
210 | * stopped. | ||
211 | */ | ||
212 | public void stop() | ||
213 | { | ||
214 | try | ||
215 | { | ||
216 | stopPlayer(); | ||
217 | } | ||
218 | catch (JavaLayerException ex) | ||
219 | { | ||
220 | System.err.println(ex); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | public void destroy() | ||
225 | { | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * The run method for the audio player thread. Simply calls | ||
230 | * play() on the player to play the entire stream. | ||
231 | */ | ||
232 | public void run() | ||
233 | { | ||
234 | if (player!=null) | ||
235 | { | ||
236 | try | ||
237 | { | ||
238 | player.play(); | ||
239 | } | ||
240 | catch (JavaLayerException ex) | ||
241 | { | ||
242 | System.err.println("Problem playing audio: "+ex); | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | } | ||
diff --git a/songdbj/javazoom/jl/player/advanced/AdvancedPlayer.java b/songdbj/javazoom/jl/player/advanced/AdvancedPlayer.java new file mode 100644 index 0000000000..45a31e46e1 --- /dev/null +++ b/songdbj/javazoom/jl/player/advanced/AdvancedPlayer.java | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | *----------------------------------------------------------------------- | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Library General Public License as published | ||
6 | * by the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library General Public | ||
15 | * License along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | *---------------------------------------------------------------------- | ||
18 | */ | ||
19 | |||
20 | package javazoom.jl.player.advanced; | ||
21 | |||
22 | import java.io.InputStream; | ||
23 | |||
24 | import javazoom.jl.decoder.Bitstream; | ||
25 | import javazoom.jl.decoder.BitstreamException; | ||
26 | import javazoom.jl.decoder.Decoder; | ||
27 | import javazoom.jl.decoder.Header; | ||
28 | import javazoom.jl.decoder.JavaLayerException; | ||
29 | import javazoom.jl.decoder.SampleBuffer; | ||
30 | import javazoom.jl.player.AudioDevice; | ||
31 | import javazoom.jl.player.FactoryRegistry; | ||
32 | |||
33 | /** | ||
34 | * a hybrid of javazoom.jl.player.Player tweeked to include <code>play(startFrame, endFrame)</code> | ||
35 | * hopefully this will be included in the api | ||
36 | */ | ||
37 | public class AdvancedPlayer | ||
38 | { | ||
39 | /** The MPEG audio bitstream.*/ | ||
40 | private Bitstream bitstream; | ||
41 | /** The MPEG audio decoder. */ | ||
42 | private Decoder decoder; | ||
43 | /** The AudioDevice the audio samples are written to. */ | ||
44 | private AudioDevice audio; | ||
45 | /** Has the player been closed? */ | ||
46 | private boolean closed = false; | ||
47 | /** Has the player played back all frames from the stream? */ | ||
48 | private boolean complete = false; | ||
49 | private int lastPosition = 0; | ||
50 | /** Listener for the playback process */ | ||
51 | private PlaybackListener listener; | ||
52 | |||
53 | /** | ||
54 | * Creates a new <code>Player</code> instance. | ||
55 | */ | ||
56 | public AdvancedPlayer(InputStream stream) throws JavaLayerException | ||
57 | { | ||
58 | this(stream, null); | ||
59 | } | ||
60 | |||
61 | public AdvancedPlayer(InputStream stream, AudioDevice device) throws JavaLayerException | ||
62 | { | ||
63 | bitstream = new Bitstream(stream); | ||
64 | |||
65 | if (device!=null) audio = device; | ||
66 | else audio = FactoryRegistry.systemRegistry().createAudioDevice(); | ||
67 | audio.open(decoder = new Decoder()); | ||
68 | } | ||
69 | |||
70 | public void play() throws JavaLayerException | ||
71 | { | ||
72 | play(Integer.MAX_VALUE); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * Plays a number of MPEG audio frames. | ||
77 | * | ||
78 | * @param frames The number of frames to play. | ||
79 | * @return true if the last frame was played, or false if there are | ||
80 | * more frames. | ||
81 | */ | ||
82 | public boolean play(int frames) throws JavaLayerException | ||
83 | { | ||
84 | boolean ret = true; | ||
85 | |||
86 | // report to listener | ||
87 | if(listener != null) listener.playbackStarted(createEvent(PlaybackEvent.STARTED)); | ||
88 | |||
89 | while (frames-- > 0 && ret) | ||
90 | { | ||
91 | ret = decodeFrame(); | ||
92 | } | ||
93 | |||
94 | // if (!ret) | ||
95 | { | ||
96 | // last frame, ensure all data flushed to the audio device. | ||
97 | AudioDevice out = audio; | ||
98 | if (out != null) | ||
99 | { | ||
100 | // System.out.println(audio.getPosition()); | ||
101 | out.flush(); | ||
102 | // System.out.println(audio.getPosition()); | ||
103 | synchronized (this) | ||
104 | { | ||
105 | complete = (!closed); | ||
106 | close(); | ||
107 | } | ||
108 | |||
109 | // report to listener | ||
110 | if(listener != null) listener.playbackFinished(createEvent(out, PlaybackEvent.STOPPED)); | ||
111 | } | ||
112 | } | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * Cloases this player. Any audio currently playing is stopped | ||
118 | * immediately. | ||
119 | */ | ||
120 | public synchronized void close() | ||
121 | { | ||
122 | AudioDevice out = audio; | ||
123 | if (out != null) | ||
124 | { | ||
125 | closed = true; | ||
126 | audio = null; | ||
127 | // this may fail, so ensure object state is set up before | ||
128 | // calling this method. | ||
129 | out.close(); | ||
130 | lastPosition = out.getPosition(); | ||
131 | try | ||
132 | { | ||
133 | bitstream.close(); | ||
134 | } | ||
135 | catch (BitstreamException ex) | ||
136 | {} | ||
137 | } | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * Decodes a single frame. | ||
142 | * | ||
143 | * @return true if there are no more frames to decode, false otherwise. | ||
144 | */ | ||
145 | protected boolean decodeFrame() throws JavaLayerException | ||
146 | { | ||
147 | try | ||
148 | { | ||
149 | AudioDevice out = audio; | ||
150 | if (out == null) return false; | ||
151 | |||
152 | Header h = bitstream.readFrame(); | ||
153 | if (h == null) return false; | ||
154 | |||
155 | // sample buffer set when decoder constructed | ||
156 | SampleBuffer output = (SampleBuffer) decoder.decodeFrame(h, bitstream); | ||
157 | |||
158 | synchronized (this) | ||
159 | { | ||
160 | out = audio; | ||
161 | if(out != null) | ||
162 | { | ||
163 | out.write(output.getBuffer(), 0, output.getBufferLength()); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | bitstream.closeFrame(); | ||
168 | } | ||
169 | catch (RuntimeException ex) | ||
170 | { | ||
171 | throw new JavaLayerException("Exception decoding audio frame", ex); | ||
172 | } | ||
173 | return true; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * skips over a single frame | ||
178 | * @return false if there are no more frames to decode, true otherwise. | ||
179 | */ | ||
180 | protected boolean skipFrame() throws JavaLayerException | ||
181 | { | ||
182 | Header h = bitstream.readFrame(); | ||
183 | if (h == null) return false; | ||
184 | bitstream.closeFrame(); | ||
185 | return true; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * Plays a range of MPEG audio frames | ||
190 | * @param start The first frame to play | ||
191 | * @param end The last frame to play | ||
192 | * @return true if the last frame was played, or false if there are more frames. | ||
193 | */ | ||
194 | public boolean play(final int start, final int end) throws JavaLayerException | ||
195 | { | ||
196 | boolean ret = true; | ||
197 | int offset = start; | ||
198 | while (offset-- > 0 && ret) ret = skipFrame(); | ||
199 | return play(end - start); | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * Constructs a <code>PlaybackEvent</code> | ||
204 | */ | ||
205 | private PlaybackEvent createEvent(int id) | ||
206 | { | ||
207 | return createEvent(audio, id); | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * Constructs a <code>PlaybackEvent</code> | ||
212 | */ | ||
213 | private PlaybackEvent createEvent(AudioDevice dev, int id) | ||
214 | { | ||
215 | return new PlaybackEvent(this, id, dev.getPosition()); | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * sets the <code>PlaybackListener</code> | ||
220 | */ | ||
221 | public void setPlayBackListener(PlaybackListener listener) | ||
222 | { | ||
223 | this.listener = listener; | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * gets the <code>PlaybackListener</code> | ||
228 | */ | ||
229 | public PlaybackListener getPlayBackListener() | ||
230 | { | ||
231 | return listener; | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * closes the player and notifies <code>PlaybackListener</code> | ||
236 | */ | ||
237 | public void stop() | ||
238 | { | ||
239 | listener.playbackFinished(createEvent(PlaybackEvent.STOPPED)); | ||
240 | close(); | ||
241 | } | ||
242 | } \ No newline at end of file | ||
diff --git a/songdbj/javazoom/jl/player/advanced/PlaybackEvent.java b/songdbj/javazoom/jl/player/advanced/PlaybackEvent.java new file mode 100644 index 0000000000..08e3cae958 --- /dev/null +++ b/songdbj/javazoom/jl/player/advanced/PlaybackEvent.java | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | *----------------------------------------------------------------------- | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Library General Public License as published | ||
6 | * by the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library General Public | ||
15 | * License along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | *---------------------------------------------------------------------- | ||
18 | */ | ||
19 | |||
20 | package javazoom.jl.player.advanced; | ||
21 | |||
22 | /** | ||
23 | * An event which indicates a <code>Player</code> has performed an 'playback action' | ||
24 | * @author Paul Stanton (http://wanto.f2o.org/) | ||
25 | */ | ||
26 | public class PlaybackEvent | ||
27 | { | ||
28 | public static int STOPPED = 1; | ||
29 | public static int STARTED = 2; | ||
30 | |||
31 | private AdvancedPlayer source; | ||
32 | private int frame; | ||
33 | private int id; | ||
34 | |||
35 | public PlaybackEvent(AdvancedPlayer source, int id, int frame) | ||
36 | { | ||
37 | this.id = id; | ||
38 | this.source = source; | ||
39 | this.frame = frame; | ||
40 | } | ||
41 | |||
42 | public int getId(){return id;} | ||
43 | public void setId(int id){this.id = id;} | ||
44 | |||
45 | public int getFrame(){return frame;} | ||
46 | public void setFrame(int frame){this.frame = frame;} | ||
47 | |||
48 | public AdvancedPlayer getSource(){return source;} | ||
49 | public void setSource(AdvancedPlayer source){this.source = source;} | ||
50 | |||
51 | } | ||
diff --git a/songdbj/javazoom/jl/player/advanced/PlaybackListener.java b/songdbj/javazoom/jl/player/advanced/PlaybackListener.java new file mode 100644 index 0000000000..9b042988b8 --- /dev/null +++ b/songdbj/javazoom/jl/player/advanced/PlaybackListener.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | *----------------------------------------------------------------------- | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Library General Public License as published | ||
6 | * by the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library General Public | ||
15 | * License along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | *---------------------------------------------------------------------- | ||
18 | */ | ||
19 | |||
20 | package javazoom.jl.player.advanced; | ||
21 | |||
22 | /** | ||
23 | * Listener for javalayer Player playback | ||
24 | * @author Paul Stanton (http://wanto.f2o.org/) | ||
25 | */ | ||
26 | public abstract class PlaybackListener | ||
27 | { | ||
28 | public void playbackStarted(PlaybackEvent evt){} | ||
29 | public void playbackFinished(PlaybackEvent evt){} | ||
30 | } | ||
diff --git a/songdbj/javazoom/jl/player/advanced/jlap.java b/songdbj/javazoom/jl/player/advanced/jlap.java new file mode 100644 index 0000000000..beedea6716 --- /dev/null +++ b/songdbj/javazoom/jl/player/advanced/jlap.java | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | *----------------------------------------------------------------------- | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU Library General Public License as published | ||
6 | * by the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library General Public | ||
15 | * License along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | *---------------------------------------------------------------------- | ||
18 | */ | ||
19 | |||
20 | package javazoom.jl.player.advanced; | ||
21 | |||
22 | import java.io.BufferedInputStream; | ||
23 | import java.io.File; | ||
24 | import java.io.FileInputStream; | ||
25 | import java.io.IOException; | ||
26 | import java.io.InputStream; | ||
27 | |||
28 | import javazoom.jl.decoder.JavaLayerException; | ||
29 | |||
30 | /** | ||
31 | * This class implements a sample player using Playback listener. | ||
32 | */ | ||
33 | public class jlap | ||
34 | { | ||
35 | |||
36 | public static void main(String[] args) | ||
37 | { | ||
38 | jlap test = new jlap(); | ||
39 | if (args.length != 1) | ||
40 | { | ||
41 | test.showUsage(); | ||
42 | System.exit(0); | ||
43 | } | ||
44 | else | ||
45 | { | ||
46 | try | ||
47 | { | ||
48 | test.play(args[0]); | ||
49 | } | ||
50 | catch (Exception ex) | ||
51 | { | ||
52 | System.err.println(ex.getMessage()); | ||
53 | System.exit(0); | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | |||
58 | public void play(String filename) throws JavaLayerException, IOException | ||
59 | { | ||
60 | InfoListener lst = new InfoListener(); | ||
61 | playMp3(new File(filename), lst); | ||
62 | } | ||
63 | |||
64 | public void showUsage() | ||
65 | { | ||
66 | System.out.println("Usage: jla <filename>"); | ||
67 | System.out.println(""); | ||
68 | System.out.println(" e.g. : java javazoom.jl.player.advanced.jlap localfile.mp3"); | ||
69 | } | ||
70 | |||
71 | public static AdvancedPlayer playMp3(File mp3, PlaybackListener listener) throws IOException, JavaLayerException | ||
72 | { | ||
73 | return playMp3(mp3, 0, Integer.MAX_VALUE, listener); | ||
74 | } | ||
75 | |||
76 | public static AdvancedPlayer playMp3(File mp3, int start, int end, PlaybackListener listener) throws IOException, JavaLayerException | ||
77 | { | ||
78 | return playMp3(new BufferedInputStream(new FileInputStream(mp3)), start, end, listener); | ||
79 | } | ||
80 | |||
81 | public static AdvancedPlayer playMp3(final InputStream is, final int start, final int end, PlaybackListener listener) throws JavaLayerException | ||
82 | { | ||
83 | final AdvancedPlayer player = new AdvancedPlayer(is); | ||
84 | player.setPlayBackListener(listener); | ||
85 | // run in new thread | ||
86 | new Thread() | ||
87 | { | ||
88 | public void run() | ||
89 | { | ||
90 | try | ||
91 | { | ||
92 | player.play(start, end); | ||
93 | } | ||
94 | catch (Exception e) | ||
95 | { | ||
96 | throw new RuntimeException(e.getMessage()); | ||
97 | } | ||
98 | } | ||
99 | }.start(); | ||
100 | return player; | ||
101 | } | ||
102 | |||
103 | public class InfoListener extends PlaybackListener | ||
104 | { | ||
105 | public void playbackStarted(PlaybackEvent evt) | ||
106 | { | ||
107 | System.out.println("Play started from frame " + evt.getFrame()); | ||
108 | } | ||
109 | |||
110 | public void playbackFinished(PlaybackEvent evt) | ||
111 | { | ||
112 | System.out.println("Play completed at frame " + evt.getFrame()); | ||
113 | System.exit(0); | ||
114 | } | ||
115 | } | ||
116 | } \ No newline at end of file | ||
diff --git a/songdbj/javazoom/jl/player/jlp.java b/songdbj/javazoom/jl/player/jlp.java new file mode 100644 index 0000000000..ddb3d5ecca --- /dev/null +++ b/songdbj/javazoom/jl/player/jlp.java | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * 11/19/04 1.0 moved to LGPL. | ||
3 | * | ||
4 | * 06/04/01 Streaming support added. javalayer@javazoom.net | ||
5 | * | ||
6 | * 29/01/00 Initial version. mdm@techie.com | ||
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.jl.player; | ||
25 | |||
26 | import java.io.BufferedInputStream; | ||
27 | import java.io.FileInputStream; | ||
28 | import java.io.IOException; | ||
29 | import java.io.InputStream; | ||
30 | import java.net.URL; | ||
31 | |||
32 | import javazoom.jl.decoder.JavaLayerException; | ||
33 | |||
34 | /** | ||
35 | * The <code>jlp</code> class implements a simple command-line | ||
36 | * player for MPEG audio files. | ||
37 | * | ||
38 | * @author Mat McGowan (mdm@techie.com) | ||
39 | */ | ||
40 | public class jlp | ||
41 | { | ||
42 | private String fFilename = null; | ||
43 | private boolean remote = false; | ||
44 | |||
45 | public static void main(String[] args) | ||
46 | { | ||
47 | int retval = 0; | ||
48 | try | ||
49 | { | ||
50 | jlp player = createInstance(args); | ||
51 | if (player!=null) | ||
52 | player.play(); | ||
53 | } | ||
54 | catch (Exception ex) | ||
55 | { | ||
56 | System.err.println(ex); | ||
57 | ex.printStackTrace(System.err); | ||
58 | retval = 1; | ||
59 | } | ||
60 | System.exit(retval); | ||
61 | } | ||
62 | |||
63 | static public jlp createInstance(String[] args) | ||
64 | { | ||
65 | jlp player = new jlp(); | ||
66 | if (!player.parseArgs(args)) | ||
67 | player = null; | ||
68 | return player; | ||
69 | } | ||
70 | |||
71 | private jlp() | ||
72 | { | ||
73 | } | ||
74 | |||
75 | public jlp(String filename) | ||
76 | { | ||
77 | init(filename); | ||
78 | } | ||
79 | |||
80 | protected void init(String filename) | ||
81 | { | ||
82 | fFilename = filename; | ||
83 | } | ||
84 | |||
85 | protected boolean parseArgs(String[] args) | ||
86 | { | ||
87 | boolean parsed = false; | ||
88 | if (args.length == 1) | ||
89 | { | ||
90 | init(args[0]); | ||
91 | parsed = true; | ||
92 | remote = false; | ||
93 | } | ||
94 | else if (args.length == 2) | ||
95 | { | ||
96 | if (!(args[0].equals("-url"))) | ||
97 | { | ||
98 | showUsage(); | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | init(args[1]); | ||
103 | parsed = true; | ||
104 | remote = true; | ||
105 | } | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | showUsage(); | ||
110 | } | ||
111 | return parsed; | ||
112 | } | ||
113 | |||
114 | public void showUsage() | ||
115 | { | ||
116 | System.out.println("Usage: jlp [-url] <filename>"); | ||
117 | System.out.println(""); | ||
118 | System.out.println(" e.g. : java javazoom.jl.player.jlp localfile.mp3"); | ||
119 | System.out.println(" java javazoom.jl.player.jlp -url http://www.server.com/remotefile.mp3"); | ||
120 | System.out.println(" java javazoom.jl.player.jlp -url http://www.shoutcastserver.com:8000"); | ||
121 | } | ||
122 | |||
123 | public void play() | ||
124 | throws JavaLayerException | ||
125 | { | ||
126 | try | ||
127 | { | ||
128 | System.out.println("playing "+fFilename+"..."); | ||
129 | InputStream in = null; | ||
130 | if (remote == true) in = getURLInputStream(); | ||
131 | else in = getInputStream(); | ||
132 | AudioDevice dev = getAudioDevice(); | ||
133 | Player player = new Player(in, dev); | ||
134 | player.play(); | ||
135 | } | ||
136 | catch (IOException ex) | ||
137 | { | ||
138 | throw new JavaLayerException("Problem playing file "+fFilename, ex); | ||
139 | } | ||
140 | catch (Exception ex) | ||
141 | { | ||
142 | throw new JavaLayerException("Problem playing file "+fFilename, ex); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * Playing file from URL (Streaming). | ||
148 | */ | ||
149 | protected InputStream getURLInputStream() | ||
150 | throws Exception | ||
151 | { | ||
152 | |||
153 | URL url = new URL(fFilename); | ||
154 | InputStream fin = url.openStream(); | ||
155 | BufferedInputStream bin = new BufferedInputStream(fin); | ||
156 | return bin; | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * Playing file from FileInputStream. | ||
161 | */ | ||
162 | protected InputStream getInputStream() | ||
163 | throws IOException | ||
164 | { | ||
165 | FileInputStream fin = new FileInputStream(fFilename); | ||
166 | BufferedInputStream bin = new BufferedInputStream(fin); | ||
167 | return bin; | ||
168 | } | ||
169 | |||
170 | protected AudioDevice getAudioDevice() | ||
171 | throws JavaLayerException | ||
172 | { | ||
173 | return FactoryRegistry.systemRegistry().createAudioDevice(); | ||
174 | } | ||
175 | |||
176 | } | ||
diff --git a/songdbj/javazoom/spi/PropertiesContainer.java b/songdbj/javazoom/spi/PropertiesContainer.java new file mode 100644 index 0000000000..27ed85f904 --- /dev/null +++ b/songdbj/javazoom/spi/PropertiesContainer.java | |||
@@ -0,0 +1,31 @@ | |||
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 new file mode 100644 index 0000000000..e4e6fed00a --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/convert/DecodedMpegAudioInputStream.java | |||
@@ -0,0 +1,334 @@ | |||
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 new file mode 100644 index 0000000000..1a3d51d9ad --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/convert/MpegFormatConversionProvider.java | |||
@@ -0,0 +1,120 @@ | |||
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 new file mode 100644 index 0000000000..8e49e6e2ef --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/IcyListener.java | |||
@@ -0,0 +1,131 @@ | |||
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 new file mode 100644 index 0000000000..afdc4c5e9c --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFileFormat.java | |||
@@ -0,0 +1,103 @@ | |||
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 new file mode 100644 index 0000000000..54440551a1 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFileReader.java | |||
@@ -0,0 +1,772 @@ | |||
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 new file mode 100644 index 0000000000..29a66a3d93 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/MpegAudioFormat.java | |||
@@ -0,0 +1,67 @@ | |||
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 new file mode 100644 index 0000000000..6306d9ec80 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/MpegEncoding.java | |||
@@ -0,0 +1,47 @@ | |||
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 new file mode 100644 index 0000000000..2c59ad8621 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/MpegFileFormatType.java | |||
@@ -0,0 +1,40 @@ | |||
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 new file mode 100644 index 0000000000..22aa4439fe --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/tag/IcyInputStream.java | |||
@@ -0,0 +1,412 @@ | |||
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 new file mode 100644 index 0000000000..bbe70f1f3c --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/tag/IcyTag.java | |||
@@ -0,0 +1,42 @@ | |||
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 new file mode 100644 index 0000000000..81511064b8 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3MetadataParser.java | |||
@@ -0,0 +1,50 @@ | |||
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 new file mode 100644 index 0000000000..b545356240 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3Tag.java | |||
@@ -0,0 +1,52 @@ | |||
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 new file mode 100644 index 0000000000..1ab6525512 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/tag/MP3TagParseSupport.java | |||
@@ -0,0 +1,62 @@ | |||
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 new file mode 100644 index 0000000000..685c5207f9 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/tag/StringableTag.java | |||
@@ -0,0 +1,36 @@ | |||
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 new file mode 100644 index 0000000000..97e9ec1e19 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/tag/TagParseEvent.java | |||
@@ -0,0 +1,44 @@ | |||
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 new file mode 100644 index 0000000000..a630827297 --- /dev/null +++ b/songdbj/javazoom/spi/mpeg/sampled/file/tag/TagParseListener.java | |||
@@ -0,0 +1,37 @@ | |||
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 new file mode 100644 index 0000000000..b8e8577e13 --- /dev/null +++ b/songdbj/javazoom/spi/vorbis/sampled/convert/DecodedVorbisAudioInputStream.java | |||
@@ -0,0 +1,519 @@ | |||
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 new file mode 100644 index 0000000000..d1321f2590 --- /dev/null +++ b/songdbj/javazoom/spi/vorbis/sampled/convert/VorbisFormatConversionProvider.java | |||
@@ -0,0 +1,244 @@ | |||
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 new file mode 100644 index 0000000000..28b7c92a2a --- /dev/null +++ b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFileFormat.java | |||
@@ -0,0 +1,85 @@ | |||
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 new file mode 100644 index 0000000000..40bc9cadee --- /dev/null +++ b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFileReader.java | |||
@@ -0,0 +1,502 @@ | |||
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 new file mode 100644 index 0000000000..829ab2f8cd --- /dev/null +++ b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisAudioFormat.java | |||
@@ -0,0 +1,66 @@ | |||
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 new file mode 100644 index 0000000000..7800f1556d --- /dev/null +++ b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisEncoding.java | |||
@@ -0,0 +1,41 @@ | |||
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 new file mode 100644 index 0000000000..f006bbfe1d --- /dev/null +++ b/songdbj/javazoom/spi/vorbis/sampled/file/VorbisFileFormatType.java | |||
@@ -0,0 +1,41 @@ | |||
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 | } | ||