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
135 // throw decoder initialization out of ssjava loop since it is invoked once
\r
136 // if (!initialized)
\r
138 // initialize(header,stream);
\r
141 int layer = header.layer();
\r
143 output.clear_buffer();
\r
145 FrameDecoder decoder = retrieveDecoder(header, stream, layer);
\r
147 decoder.decodeFrame();
\r
149 output.write_buffer(1);
\r
155 * Changes the output buffer. This will take effect the next time
\r
156 * decodeFrame() is called.
\r
158 public void setOutputBuffer(Obuffer out)
\r
164 * Retrieves the sample frequency of the PCM samples output
\r
165 * by this decoder. This typically corresponds to the sample
\r
166 * rate encoded in the MPEG audio stream.
\r
168 * @param the sample rate (in Hz) of the samples written to the
\r
169 * output buffer when decoding.
\r
171 public int getOutputFrequency()
\r
173 return outputFrequency;
\r
177 * Retrieves the number of channels of PCM samples output by
\r
178 * this decoder. This usually corresponds to the number of
\r
179 * channels in the MPEG audio stream, although it may differ.
\r
181 * @return The number of output channels in the decoded samples: 1
\r
182 * for mono, or 2 for stereo.
\r
185 public int getOutputChannels()
\r
187 return outputChannels;
\r
191 * Retrieves the maximum number of samples that will be written to
\r
192 * the output buffer when one frame is decoded. This can be used to
\r
193 * help calculate the size of other buffers whose size is based upon
\r
194 * the number of samples written to the output buffer. NB: this is
\r
195 * an upper bound and fewer samples may actually be written, depending
\r
196 * upon the sample rate and number of channels.
\r
198 * @return The maximum number of samples that are written to the
\r
199 * output buffer when decoding a single frame of MPEG audio.
\r
201 public int getOutputBlockSize()
\r
203 return Obuffer.OBUFFERSIZE;
\r
207 protected DecoderException newDecoderException(int errorcode)
\r
209 return new DecoderException(errorcode, null);
\r
212 protected DecoderException newDecoderException(int errorcode, Throwable throwable)
\r
214 return new DecoderException(errorcode, throwable);
\r
217 protected FrameDecoder retrieveDecoder(Header header, Bitstream stream, int layer)
\r
218 throws DecoderException
\r
220 FrameDecoder decoder = null;
\r
222 // REVIEW: allow channel output selection type
\r
223 // (LEFT, RIGHT, BOTH, DOWNMIX)
\r
227 if (l3decoder==null)
\r
229 l3decoder = new LayerIIIDecoder(stream,
\r
230 header, filter1, filter2,
\r
231 output, OutputChannels.BOTH_CHANNELS);
\r
234 decoder = l3decoder;
\r
237 if (l2decoder==null)
\r
239 l2decoder = new LayerIIDecoder();
\r
240 l2decoder.create(stream,
\r
241 header, filter1, filter2,
\r
242 output, OutputChannels.BOTH_CHANNELS);
\r
244 decoder = l2decoder;
\r
247 if (l1decoder==null)
\r
249 l1decoder = new LayerIDecoder();
\r
250 l1decoder.create(stream,
\r
251 header, filter1, filter2,
\r
252 output, OutputChannels.BOTH_CHANNELS);
\r
254 decoder = l1decoder;
\r
260 throw newDecoderException(UNSUPPORTED_LAYER, null);
\r
266 public void initialize(Header header, Bitstream stream)
\r
267 throws DecoderException
\r
270 // REVIEW: allow customizable scale factor
\r
271 float scalefactor = 32700.0f;
\r
273 int mode = header.mode();
\r
274 int layer = header.layer();
\r
275 int channels = mode==Header.SINGLE_CHANNEL ? 1 : 2;
\r
278 // set up output buffer if not set up by client.
\r
280 output = new SampleBuffer(header.frequency(), channels);
\r
282 float[] factors = equalizer.getBandFactors();
\r
283 filter1 = new SynthesisFilter(0, scalefactor, factors);
\r
285 // REVIEW: allow mono output for stereo
\r
287 filter2 = new SynthesisFilter(1, scalefactor, factors);
\r
289 outputChannels = channels;
\r
290 outputFrequency = header.frequency();
\r
292 l3decoder = new LayerIIIDecoder(stream, header, filter1, filter2,
\r
293 output, OutputChannels.BOTH_CHANNELS);
\r
294 l2decoder = new LayerIIDecoder();
\r
295 l2decoder.create(stream, header, filter1, filter2,
\r
296 output, OutputChannels.BOTH_CHANNELS);
\r
298 l1decoder = new LayerIDecoder();
\r
299 l1decoder.create(stream,header, filter1, filter2,
\r
300 output, OutputChannels.BOTH_CHANNELS);
\r
302 initialized = true;
\r
306 * The <code>Params</code> class presents the customizable
\r
307 * aspects of the decoder.
\r
309 * Instances of this class are not thread safe.
\r
311 public static class Params implements Cloneable
\r
313 private OutputChannels outputChannels = OutputChannels.BOTH;
\r
315 private Equalizer equalizer = new Equalizer();
\r
321 public Object clone()
\r
323 //TODO: need to have better clone method
\r
324 Params clone=new Params();
\r
325 clone.outputChannels=outputChannels;
\r
326 clone.equalizer=equalizer;
\r
330 // return super.clone();
\r
332 // catch (CloneNotSupportedException ex)
\r
334 // throw new InternalError(this+": "+ex);
\r
338 public void setOutputChannels(OutputChannels out)
\r
341 throw new NullPointerException("out");
\r
343 outputChannels = out;
\r
346 public OutputChannels getOutputChannels()
\r
348 return outputChannels;
\r
352 * Retrieves the equalizer settings that the decoder's equalizer
\r
353 * will be initialized from.
\r
355 * The <code>Equalizer</code> instance returned
\r
356 * cannot be changed in real time to affect the
\r
357 * decoder output as it is used only to initialize the decoders
\r
358 * EQ settings. To affect the decoder's output in realtime,
\r
359 * use the Equalizer returned from the getEqualizer() method on
\r
362 * @return The <code>Equalizer</code> used to initialize the
\r
363 * EQ settings of the decoder.
\r
365 public Equalizer getInitialEqualizerSettings()
\r