summaryrefslogtreecommitdiff
path: root/songdbj/javazoom/jl/decoder/Decoder.java
diff options
context:
space:
mode:
Diffstat (limited to 'songdbj/javazoom/jl/decoder/Decoder.java')
-rw-r--r--songdbj/javazoom/jl/decoder/Decoder.java357
1 files changed, 357 insertions, 0 deletions
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
21package 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 */
31public 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