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 @LATTICE("ST,OUT,FIL,DE,O,EQ,PA,INIT")
\r
31 public class Decoder implements DecoderErrors
\r
33 static private final Params DEFAULT_PARAMS = new Params();
\r
36 * The Bistream from which the MPEG audio frames are read.
\r
38 @LOC("ST") private Bitstream stream;
\r
41 * The Obuffer instance that will receive the decoded
\r
44 @LOC("OUT") private Obuffer output;
\r
47 * Synthesis filter for the left channel.
\r
49 @LOC("FIL") private SynthesisFilter filter1;
\r
52 * Sythesis filter for the right channel.
\r
54 @LOC("FIL") private SynthesisFilter filter2;
\r
57 * The decoder used to decode layer III frames.
\r
59 @LOC("DE") private LayerIIIDecoder l3decoder;
\r
60 @LOC("DE") private LayerIIDecoder l2decoder;
\r
61 @LOC("DE") private LayerIDecoder l1decoder;
\r
63 @LOC("O") private int outputFrequency;
\r
64 @LOC("O") private int outputChannels;
\r
66 @LOC("EQ") private Equalizer equalizer = new Equalizer();
\r
68 @LOC("PA") private Params params;
\r
70 @LOC("INIT") private boolean initialized;
\r
74 * Creates a new <code>Decoder</code> instance with default
\r
84 * Creates a new <code>Decoder</code> instance with default
\r
87 * @param params The <code>Params</code> instance that describes
\r
88 * the customizable aspects of the decoder.
\r
90 public Decoder(Params params0)
\r
93 params0 = DEFAULT_PARAMS;
\r
97 Equalizer eq = params.getInitialEqualizerSettings();
\r
100 equalizer.setFrom(eq);
\r
104 static public Params getDefaultParams()
\r
106 return (Params)DEFAULT_PARAMS.clone();
\r
109 public void setEqualizer(Equalizer eq)
\r
112 eq = Equalizer.PASS_THRU_EQ;
\r
114 equalizer.setFrom(eq);
\r
116 float[] factors = equalizer.getBandFactors();
\r
119 filter1.setEQ(factors);
\r
122 filter2.setEQ(factors);
\r
126 * Decodes one frame from an MPEG audio bitstream.
\r
128 * @param header The header describing the frame to decode.
\r
129 * @param bitstream The bistream that provides the bits for te body of the frame.
\r
131 * @return A SampleBuffer containing the decoded samples.
\r
133 @LATTICE("O<DE,DE<TH,TH<IN,THISLOC=TH")
\r
135 public Obuffer decodeFrame(@LOC("IN") Header header, @LOC("IN") Bitstream stream)
\r
136 throws DecoderException
\r
138 // throw decoder initialization out of ssjava loop since it is invoked once
\r
139 // if (!initialized)
\r
141 // initialize(header,stream);
\r
144 @LOC("DELTA(TH)") int layer = header.layer();
\r
146 output.clear_buffer();
\r
148 @LOC("DE") FrameDecoder decoder = retrieveDecoder(header, stream, layer);
\r
150 decoder.decodeFrame();
\r
152 output.write_buffer(1);
\r
158 * Changes the output buffer. This will take effect the next time
\r
159 * decodeFrame() is called.
\r
161 public void setOutputBuffer(Obuffer out)
\r
167 * Retrieves the sample frequency of the PCM samples output
\r
168 * by this decoder. This typically corresponds to the sample
\r
169 * rate encoded in the MPEG audio stream.
\r
171 * @param the sample rate (in Hz) of the samples written to the
\r
172 * output buffer when decoding.
\r
174 public int getOutputFrequency()
\r
176 return outputFrequency;
\r
180 * Retrieves the number of channels of PCM samples output by
\r
181 * this decoder. This usually corresponds to the number of
\r
182 * channels in the MPEG audio stream, although it may differ.
\r
184 * @return The number of output channels in the decoded samples: 1
\r
185 * for mono, or 2 for stereo.
\r
188 public int getOutputChannels()
\r
190 return outputChannels;
\r
194 * Retrieves the maximum number of samples that will be written to
\r
195 * the output buffer when one frame is decoded. This can be used to
\r
196 * help calculate the size of other buffers whose size is based upon
\r
197 * the number of samples written to the output buffer. NB: this is
\r
198 * an upper bound and fewer samples may actually be written, depending
\r
199 * upon the sample rate and number of channels.
\r
201 * @return The maximum number of samples that are written to the
\r
202 * output buffer when decoding a single frame of MPEG audio.
\r
204 public int getOutputBlockSize()
\r
206 return Obuffer.OBUFFERSIZE;
\r
210 protected DecoderException newDecoderException(int errorcode)
\r
212 return new DecoderException(errorcode, null);
\r
215 protected DecoderException newDecoderException(int errorcode, Throwable throwable)
\r
217 return new DecoderException(errorcode, throwable);
\r
220 @LATTICE("DE<IN,THISLOC=IN")
\r
222 protected FrameDecoder retrieveDecoder(@LOC("IN") Header header, @LOC("IN") Bitstream stream, @LOC("IN") int layer)
\r
223 throws DecoderException
\r
225 @LOC("DE") FrameDecoder decoder = null;
\r
227 // REVIEW: allow channel output selection type
\r
228 // (LEFT, RIGHT, BOTH, DOWNMIX)
\r
232 if (l3decoder==null)
\r
234 l3decoder = new LayerIIIDecoder(stream,
\r
235 header, filter1, filter2,
\r
236 output, OutputChannels.BOTH_CHANNELS);
\r
239 decoder = l3decoder;
\r
242 if (l2decoder==null)
\r
244 l2decoder = new LayerIIDecoder();
\r
245 l2decoder.create(stream,
\r
246 header, filter1, filter2,
\r
247 output, OutputChannels.BOTH_CHANNELS);
\r
249 decoder = l2decoder;
\r
252 if (l1decoder==null)
\r
254 l1decoder = new LayerIDecoder();
\r
255 l1decoder.create(stream,
\r
256 header, filter1, filter2,
\r
257 output, OutputChannels.BOTH_CHANNELS);
\r
259 decoder = l1decoder;
\r
265 throw newDecoderException(UNSUPPORTED_LAYER, null);
\r
271 public void initialize(Header header, Bitstream stream)
\r
272 throws DecoderException
\r
275 // REVIEW: allow customizable scale factor
\r
276 float scalefactor = 32700.0f;
\r
278 int mode = header.mode();
\r
279 int layer = header.layer();
\r
280 int channels = mode==Header.SINGLE_CHANNEL ? 1 : 2;
\r
283 // set up output buffer if not set up by client.
\r
285 output = new SampleBuffer(header.frequency(), channels);
\r
287 float[] factors = equalizer.getBandFactors();
\r
288 filter1 = new SynthesisFilter(0, scalefactor, factors);
\r
290 // REVIEW: allow mono output for stereo
\r
292 filter2 = new SynthesisFilter(1, scalefactor, factors);
\r
294 outputChannels = channels;
\r
295 outputFrequency = header.frequency();
\r
297 l3decoder = new LayerIIIDecoder(stream, header, filter1, filter2,
\r
298 output, OutputChannels.BOTH_CHANNELS);
\r
299 l2decoder = new LayerIIDecoder();
\r
300 l2decoder.create(stream, header, filter1, filter2,
\r
301 output, OutputChannels.BOTH_CHANNELS);
\r
303 l1decoder = new LayerIDecoder();
\r
304 l1decoder.create(stream,header, filter1, filter2,
\r
305 output, OutputChannels.BOTH_CHANNELS);
\r
307 initialized = true;
\r
311 * The <code>Params</code> class presents the customizable
\r
312 * aspects of the decoder.
\r
314 * Instances of this class are not thread safe.
\r
316 public static class Params implements Cloneable
\r
318 private OutputChannels outputChannels = OutputChannels.BOTH;
\r
320 private Equalizer equalizer = new Equalizer();
\r
326 public Object clone()
\r
328 //TODO: need to have better clone method
\r
329 Params clone=new Params();
\r
330 clone.outputChannels=outputChannels;
\r
331 clone.equalizer=equalizer;
\r
335 // return super.clone();
\r
337 // catch (CloneNotSupportedException ex)
\r
339 // throw new InternalError(this+": "+ex);
\r
343 public void setOutputChannels(OutputChannels out)
\r
346 throw new NullPointerException("out");
\r
348 outputChannels = out;
\r
351 public OutputChannels getOutputChannels()
\r
353 return outputChannels;
\r
357 * Retrieves the equalizer settings that the decoder's equalizer
\r
358 * will be initialized from.
\r
360 * The <code>Equalizer</code> instance returned
\r
361 * cannot be changed in real time to affect the
\r
362 * decoder output as it is used only to initialize the decoders
\r
363 * EQ settings. To affect the decoder's output in realtime,
\r
364 * use the Equalizer returned from the getEqualizer() method on
\r
367 * @return The <code>Equalizer</code> used to initialize the
\r
368 * EQ settings of the decoder.
\r
370 public Equalizer getInitialEqualizerSettings()
\r