2 * 11/19/04 1.0 moved to LGPL.
\r
3 * 01/12/99 Initial version. mdm@techie.com
\r
4 *-----------------------------------------------------------------------
\r
5 * This program is free software; you can redistribute it and/or modify
\r
6 * it under the terms of the GNU Library General Public License as published
\r
7 * by the Free Software Foundation; either version 2 of the License, or
\r
8 * (at your option) any later version.
\r
10 * This program is distributed in the hope that it will be useful,
\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 * GNU Library General Public License for more details.
\r
15 * You should have received a copy of the GNU Library General Public
\r
16 * License along with this program; if not, write to the Free Software
\r
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
\r
18 *----------------------------------------------------------------------
\r
23 * The <code>Decoder</code> class encapsulates the details of
\r
24 * decoding an MPEG audio frame.
\r
27 * @version 0.0.7 12/12/99
\r
30 public class Decoder implements DecoderErrors
\r
32 static private final Params DEFAULT_PARAMS = new Params();
\r
35 * The Bistream from which the MPEG audio frames are read.
\r
37 private Bitstream stream;
\r
40 * The Obuffer instance that will receive the decoded
\r
43 private Obuffer output;
\r
46 * Synthesis filter for the left channel.
\r
48 private SynthesisFilter filter1;
\r
51 * Sythesis filter for the right channel.
\r
53 private SynthesisFilter filter2;
\r
56 * The decoder used to decode layer III frames.
\r
58 private LayerIIIDecoder l3decoder;
\r
59 private LayerIIDecoder l2decoder;
\r
60 private LayerIDecoder l1decoder;
\r
62 private int outputFrequency;
\r
63 private int outputChannels;
\r
65 private Equalizer equalizer = new Equalizer();
\r
67 private Params params;
\r
69 private boolean initialized;
\r
73 * Creates a new <code>Decoder</code> instance with default
\r
83 * Creates a new <code>Decoder</code> instance with default
\r
86 * @param params The <code>Params</code> instance that describes
\r
87 * the customizable aspects of the decoder.
\r
89 public Decoder(Params params0)
\r
92 params0 = DEFAULT_PARAMS;
\r
96 Equalizer eq = params.getInitialEqualizerSettings();
\r
99 equalizer.setFrom(eq);
\r
103 static public Params getDefaultParams()
\r
105 return (Params)DEFAULT_PARAMS.clone();
\r
108 public void setEqualizer(Equalizer eq)
\r
111 eq = Equalizer.PASS_THRU_EQ;
\r
113 equalizer.setFrom(eq);
\r
115 float[] factors = equalizer.getBandFactors();
\r
118 filter1.setEQ(factors);
\r
121 filter2.setEQ(factors);
\r
125 * Decodes one frame from an MPEG audio bitstream.
\r
127 * @param header The header describing the frame to decode.
\r
128 * @param bitstream The bistream that provides the bits for te body of the frame.
\r
130 * @return A SampleBuffer containing the decoded samples.
\r
132 public Obuffer decodeFrame(Header header, Bitstream stream)
\r
133 throws DecoderException
\r
137 initialize(header,stream);
\r
140 int layer = header.layer();
\r
142 output.clear_buffer();
\r
144 FrameDecoder decoder = retrieveDecoder(header, stream, layer);
\r
146 decoder.decodeFrame();
\r
148 output.write_buffer(1);
\r
154 * Changes the output buffer. This will take effect the next time
\r
155 * decodeFrame() is called.
\r
157 public void setOutputBuffer(Obuffer out)
\r
163 * Retrieves the sample frequency of the PCM samples output
\r
164 * by this decoder. This typically corresponds to the sample
\r
165 * rate encoded in the MPEG audio stream.
\r
167 * @param the sample rate (in Hz) of the samples written to the
\r
168 * output buffer when decoding.
\r
170 public int getOutputFrequency()
\r
172 return outputFrequency;
\r
176 * Retrieves the number of channels of PCM samples output by
\r
177 * this decoder. This usually corresponds to the number of
\r
178 * channels in the MPEG audio stream, although it may differ.
\r
180 * @return The number of output channels in the decoded samples: 1
\r
181 * for mono, or 2 for stereo.
\r
184 public int getOutputChannels()
\r
186 return outputChannels;
\r
190 * Retrieves the maximum number of samples that will be written to
\r
191 * the output buffer when one frame is decoded. This can be used to
\r
192 * help calculate the size of other buffers whose size is based upon
\r
193 * the number of samples written to the output buffer. NB: this is
\r
194 * an upper bound and fewer samples may actually be written, depending
\r
195 * upon the sample rate and number of channels.
\r
197 * @return The maximum number of samples that are written to the
\r
198 * output buffer when decoding a single frame of MPEG audio.
\r
200 public int getOutputBlockSize()
\r
202 return Obuffer.OBUFFERSIZE;
\r
206 protected DecoderException newDecoderException(int errorcode)
\r
208 return new DecoderException(errorcode, null);
\r
211 protected DecoderException newDecoderException(int errorcode, Throwable throwable)
\r
213 return new DecoderException(errorcode, throwable);
\r
216 protected FrameDecoder retrieveDecoder(Header header, Bitstream stream, int layer)
\r
217 throws DecoderException
\r
219 FrameDecoder decoder = null;
\r
221 // REVIEW: allow channel output selection type
\r
222 // (LEFT, RIGHT, BOTH, DOWNMIX)
\r
226 if (l3decoder==null)
\r
228 l3decoder = new LayerIIIDecoder(stream,
\r
229 header, filter1, filter2,
\r
230 output, OutputChannels.BOTH_CHANNELS);
\r
233 decoder = l3decoder;
\r
236 if (l2decoder==null)
\r
238 l2decoder = new LayerIIDecoder();
\r
239 l2decoder.create(stream,
\r
240 header, filter1, filter2,
\r
241 output, OutputChannels.BOTH_CHANNELS);
\r
243 decoder = l2decoder;
\r
246 if (l1decoder==null)
\r
248 l1decoder = new LayerIDecoder();
\r
249 l1decoder.create(stream,
\r
250 header, filter1, filter2,
\r
251 output, OutputChannels.BOTH_CHANNELS);
\r
253 decoder = l1decoder;
\r
259 throw newDecoderException(UNSUPPORTED_LAYER, null);
\r
265 public void initialize(Header header, Bitstream stream)
\r
266 throws DecoderException
\r
269 // REVIEW: allow customizable scale factor
\r
270 float scalefactor = 32700.0f;
\r
272 int mode = header.mode();
\r
273 int layer = header.layer();
\r
274 int channels = mode==Header.SINGLE_CHANNEL ? 1 : 2;
\r
277 // set up output buffer if not set up by client.
\r
279 output = new SampleBuffer(header.frequency(), channels);
\r
281 float[] factors = equalizer.getBandFactors();
\r
282 filter1 = new SynthesisFilter(0, scalefactor, factors);
\r
284 // REVIEW: allow mono output for stereo
\r
286 filter2 = new SynthesisFilter(1, scalefactor, factors);
\r
288 outputChannels = channels;
\r
289 outputFrequency = header.frequency();
\r
291 l3decoder = new LayerIIIDecoder(stream, header, filter1, filter2,
\r
292 output, OutputChannels.BOTH_CHANNELS);
\r
293 l2decoder = new LayerIIDecoder();
\r
294 l2decoder.create(stream, header, filter1, filter2,
\r
295 output, OutputChannels.BOTH_CHANNELS);
\r
297 l1decoder = new LayerIDecoder();
\r
298 l1decoder.create(stream,header, filter1, filter2,
\r
299 output, OutputChannels.BOTH_CHANNELS);
\r
301 initialized = true;
\r
305 * The <code>Params</code> class presents the customizable
\r
306 * aspects of the decoder.
\r
308 * Instances of this class are not thread safe.
\r
310 public static class Params implements Cloneable
\r
312 private OutputChannels outputChannels = OutputChannels.BOTH;
\r
314 private Equalizer equalizer = new Equalizer();
\r
320 public Object clone()
\r
324 return super.clone();
\r
326 catch (CloneNotSupportedException ex)
\r
328 throw new InternalError(this+": "+ex);
\r
332 public void setOutputChannels(OutputChannels out)
\r
335 throw new NullPointerException("out");
\r
337 outputChannels = out;
\r
340 public OutputChannels getOutputChannels()
\r
342 return outputChannels;
\r
346 * Retrieves the equalizer settings that the decoder's equalizer
\r
347 * will be initialized from.
\r
349 * The <code>Equalizer</code> instance returned
\r
350 * cannot be changed in real time to affect the
\r
351 * decoder output as it is used only to initialize the decoders
\r
352 * EQ settings. To affect the decoder's output in realtime,
\r
353 * use the Equalizer returned from the getEqualizer() method on
\r
356 * @return The <code>Equalizer</code> used to initialize the
\r
357 * EQ settings of the decoder.
\r
359 public Equalizer getInitialEqualizerSettings()
\r