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.
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.
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 *----------------------------------------------------------------------
22 * The <code>Decoder</code> class encapsulates the details of decoding an MPEG
26 * @version 0.0.7 12/12/99
29 @LATTICE("OUT<DE,DE<FILTER,FILTER<FACTORS,FACTORS<EQ,EQ<PARAM,PARAM<H,H<INIT,PARAM*,INIT*")
30 @METHODDEFAULT("THIS,THISLOC=THIS,RETURNLOC=THIS")
31 public class Decoder implements DecoderErrors {
33 static private final Params DEFAULT_PARAMS = new Params();
36 * The Bistream from which the MPEG audio frames are read.
39 // private Bitstream stream;
42 * The Obuffer instance that will receive the decoded PCM samples.
45 // private Obuffer output;
48 * Synthesis filter for the left channel.
51 // private SynthesisFilter filter1;
54 * Sythesis filter for the right channel.
57 // private SynthesisFilter filter2;
60 * The decoder used to decode layer III frames.
63 private LayerIIIDecoder l3decoder;
65 // private LayerIIDecoder l2decoder;
67 // private LayerIDecoder l1decoder;
70 private int outputFrequency;
72 private int outputChannels;
75 private Equalizer equalizer = new Equalizer();
78 private Params params;
81 private boolean initialized;
84 * Creates a new <code>Decoder</code> instance with default parameters.
92 * Creates a new <code>Decoder</code> instance with default parameters.
95 * The <code>Params</code> instance that describes the customizable
96 * aspects of the decoder.
98 public Decoder(@DELEGATE Params params0) {
100 if (params0 == null) {
101 params0 = getDefaultParams();
106 Equalizer eq = params.getInitialEqualizerSettings();
108 equalizer.setFrom(eq);
112 static public Params getDefaultParams() {
113 return (Params) DEFAULT_PARAMS.clone();
116 // public void setEqualizer(Equalizer eq) {
118 // eq = Equalizer.PASS_THRU_EQ;
120 // equalizer.setFrom(eq);
122 // float[] factors = equalizer.getBandFactors();
124 // if (filter1 != null)
125 // filter1.setEQ(factors);
127 // if (filter2 != null)
128 // filter2.setEQ(factors);
130 @LATTICE("THIS<VAR,THISLOC=THIS,VAR*")
131 public void init( @LOC("THIS,Decoder.H") Header header) {
132 @LOC("VAR") float scalefactor = 32700.0f;
134 @LOC("THIS,Decoder.PARAM") int mode = header.mode();
135 @LOC("THIS,Decoder.PARAM") int layer = header.layer();
136 @LOC("THIS,Decoder.PARAM") int channels = mode == Header.SINGLE_CHANNEL ? 1 : 2;
138 // set up output buffer if not set up by client.
139 // if (output == null)
140 // output = new SampleBuffer(header.frequency(), channels);
141 SampleBufferWrapper.init(header.frequency(), channels);
143 @LOC("THIS,Decoder.FACTORS") float[] factors = equalizer.getBandFactors();
144 @LOC("THIS,Decoder.FILTER") SynthesisFilter filter1 =
145 new SynthesisFilter(0, scalefactor, factors);
147 // REVIEW: allow mono output for stereo
148 @LOC("THIS,Decoder.FILTER") SynthesisFilter filter2 = null;
150 filter2 = new SynthesisFilter(1, scalefactor, factors);
153 outputChannels = channels;
154 outputFrequency = header.frequency();
156 l3decoder = new LayerIIIDecoder(header,filter1, filter2, OutputChannels.BOTH_CHANNELS);
161 * Decodes one frame from an MPEG audio bitstream.
164 * The header describing the frame to decode.
166 * The bistream that provides the bits for te body of the frame.
168 * @return A SampleBuffer containing the decoded samples.
170 @LATTICE("THIS<VAR,THISLOC=THIS,VAR*")
171 public void decodeFrame(@LOC("THIS,Decoder.H") Header header) throws DecoderException {
173 SampleBufferWrapper.clear_buffer();
174 l3decoder.decode(header);
175 // SampleBufferWrapper.getOutput().write_buffer(1);
180 * Changes the output buffer. This will take effect the next time
181 * decodeFrame() is called.
183 // public void setOutputBuffer(Obuffer out) {
188 * Retrieves the sample frequency of the PCM samples output by this decoder.
189 * This typically corresponds to the sample rate encoded in the MPEG audio
193 * sample rate (in Hz) of the samples written to the output buffer
196 public int getOutputFrequency() {
197 return outputFrequency;
201 * Retrieves the number of channels of PCM samples output by this decoder.
202 * This usually corresponds to the number of channels in the MPEG audio
203 * stream, although it may differ.
205 * @return The number of output channels in the decoded samples: 1 for mono,
209 public int getOutputChannels() {
210 return outputChannels;
214 * Retrieves the maximum number of samples that will be written to the output
215 * buffer when one frame is decoded. This can be used to help calculate the
216 * size of other buffers whose size is based upon the number of samples
217 * written to the output buffer. NB: this is an upper bound and fewer samples
218 * may actually be written, depending upon the sample rate and number of
221 * @return The maximum number of samples that are written to the output buffer
222 * when decoding a single frame of MPEG audio.
224 public int getOutputBlockSize() {
225 return Obuffer.OBUFFERSIZE;
228 protected DecoderException newDecoderException(int errorcode) {
229 return new DecoderException(errorcode, null);
232 protected DecoderException newDecoderException(int errorcode, Throwable throwable) {
233 return new DecoderException(errorcode, throwable);
242 * The <code>Params</code> class presents the customizable aspects of the
245 * Instances of this class are not thread safe.
247 public class Params implements Cloneable {
249 // private OutputChannels outputChannels = OutputChannels.BOTH;
250 private OutputChannels outputChannels = new OutputChannels(0);
252 private Equalizer equalizer = new Equalizer();
257 public Object clone() {
258 // TODO: need to have better clone method
259 Params clone = new Params();
260 clone.outputChannels = new OutputChannels(outputChannels.getChannelsOutputCode());
261 clone.equalizer = new Equalizer();
265 // return super.clone();
267 // catch (CloneNotSupportedException ex)
269 // throw new InternalError(this+": "+ex);
273 public void setOutputChannels(OutputChannels out) {
275 throw new NullPointerException("out");
277 outputChannels = out;
280 public OutputChannels getOutputChannels() {
281 return outputChannels;
285 * Retrieves the equalizer settings that the decoder's equalizer will be
288 * The <code>Equalizer</code> instance returned cannot be changed in real
289 * time to affect the decoder output as it is used only to initialize the
290 * decoders EQ settings. To affect the decoder's output in realtime, use the
291 * Equalizer returned from the getEqualizer() method on the decoder.
293 * @return The <code>Equalizer</code> used to initialize the EQ settings of
296 public Equalizer getInitialEqualizerSettings() {