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
22 * The <code>Decoder</code> class encapsulates the details of decoding an MPEG
\r
26 * @version 0.0.7 12/12/99
\r
29 @LATTICE("OUT<DE,DE<FILTER,FILTER<FACTORS,FACTORS<EQ,EQ<PARAM,PARAM<INIT")
\r
30 @METHODDEFAULT("THIS,THISLOC=THIS,RETURNLOC=THIS")
\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
39 // private Bitstream stream;
\r
42 * The Obuffer instance that will receive the decoded PCM samples.
\r
45 // private Obuffer output;
\r
48 * Synthesis filter for the left channel.
\r
51 // private SynthesisFilter filter1;
\r
54 * Sythesis filter for the right channel.
\r
57 // private SynthesisFilter filter2;
\r
60 * The decoder used to decode layer III frames.
\r
63 private LayerIIIDecoder l3decoder;
\r
65 // private LayerIIDecoder l2decoder;
\r
67 // private LayerIDecoder l1decoder;
\r
70 private int outputFrequency;
\r
72 private int outputChannels;
\r
75 private Equalizer equalizer = new Equalizer();
\r
78 private Params params;
\r
81 private boolean initialized;
\r
84 * Creates a new <code>Decoder</code> instance with default parameters.
\r
92 * Creates a new <code>Decoder</code> instance with default parameters.
\r
95 * The <code>Params</code> instance that describes the customizable
\r
96 * aspects of the decoder.
\r
98 public Decoder(@DELEGATE Params params0) {
\r
100 if (params0 == null) {
\r
101 params0 = getDefaultParams();
\r
106 Equalizer eq = params.getInitialEqualizerSettings();
\r
108 equalizer.setFrom(eq);
\r
112 static public Params getDefaultParams() {
\r
113 return (Params) DEFAULT_PARAMS.clone();
\r
116 // public void setEqualizer(Equalizer eq) {
\r
118 // eq = Equalizer.PASS_THRU_EQ;
\r
120 // equalizer.setFrom(eq);
\r
122 // float[] factors = equalizer.getBandFactors();
\r
124 // if (filter1 != null)
\r
125 // filter1.setEQ(factors);
\r
127 // if (filter2 != null)
\r
128 // filter2.setEQ(factors);
\r
132 * Decodes one frame from an MPEG audio bitstream.
\r
135 * The header describing the frame to decode.
\r
137 * The bistream that provides the bits for te body of the frame.
\r
139 * @return A SampleBuffer containing the decoded samples.
\r
141 @LATTICE("THIS<VAR,THISLOC=THIS,VAR*")
\r
142 public void decodeFrame(@LOC("VAR") Header header) throws DecoderException {
\r
144 if (!initialized) {
\r
145 @LOC("VAR") float scalefactor = 32700.0f;
\r
147 @LOC("VAR") int mode = header.mode();
\r
148 @LOC("VAR") int layer = header.layer();
\r
149 @LOC("VAR") int channels = mode == Header.SINGLE_CHANNEL ? 1 : 2;
\r
151 // set up output buffer if not set up by client.
\r
152 // if (output == null)
\r
153 // output = new SampleBuffer(header.frequency(), channels);
\r
154 SampleBufferWrapper.init(header.frequency(), channels);
\r
156 @LOC("THIS,Decoder.FACTORS") float[] factors = equalizer.getBandFactors();
\r
157 @LOC("THIS,Decoder.FILTER") SynthesisFilter filter1 =
\r
158 new SynthesisFilter(0, scalefactor, factors);
\r
160 // REVIEW: allow mono output for stereo
\r
161 @LOC("THIS,Decoder.FILTER") SynthesisFilter filter2 = null;
\r
162 if (channels == 2) {
\r
163 filter2 = new SynthesisFilter(1, scalefactor, factors);
\r
166 outputChannels = channels;
\r
167 outputFrequency = header.frequency();
\r
169 l3decoder = new LayerIIIDecoder(filter1, filter2, OutputChannels.BOTH_CHANNELS);
\r
171 initialized = true;
\r
174 SampleBufferWrapper.getOutput().clear_buffer();
\r
175 l3decoder.decodeFrame(header);
\r
176 SampleBufferWrapper.getOutput().write_buffer(1);
\r
181 * Changes the output buffer. This will take effect the next time
\r
182 * decodeFrame() is called.
\r
184 // public void setOutputBuffer(Obuffer out) {
\r
189 * Retrieves the sample frequency of the PCM samples output by this decoder.
\r
190 * This typically corresponds to the sample rate encoded in the MPEG audio
\r
194 * sample rate (in Hz) of the samples written to the output buffer
\r
197 public int getOutputFrequency() {
\r
198 return outputFrequency;
\r
202 * Retrieves the number of channels of PCM samples output by this decoder.
\r
203 * This usually corresponds to the number of channels in the MPEG audio
\r
204 * stream, although it may differ.
\r
206 * @return The number of output channels in the decoded samples: 1 for mono,
\r
210 public int getOutputChannels() {
\r
211 return outputChannels;
\r
215 * Retrieves the maximum number of samples that will be written to the output
\r
216 * buffer when one frame is decoded. This can be used to help calculate the
\r
217 * size of other buffers whose size is based upon the number of samples
\r
218 * written to the output buffer. NB: this is an upper bound and fewer samples
\r
219 * may actually be written, depending upon the sample rate and number of
\r
222 * @return The maximum number of samples that are written to the output buffer
\r
223 * when decoding a single frame of MPEG audio.
\r
225 public int getOutputBlockSize() {
\r
226 return Obuffer.OBUFFERSIZE;
\r
229 protected DecoderException newDecoderException(int errorcode) {
\r
230 return new DecoderException(errorcode, null);
\r
233 protected DecoderException newDecoderException(int errorcode, Throwable throwable) {
\r
234 return new DecoderException(errorcode, throwable);
\r
238 * The <code>Params</code> class presents the customizable aspects of the
\r
241 * Instances of this class are not thread safe.
\r
243 public static class Params implements Cloneable {
\r
245 // private OutputChannels outputChannels = OutputChannels.BOTH;
\r
246 private OutputChannels outputChannels = new OutputChannels(0);
\r
248 private Equalizer equalizer = new Equalizer();
\r
253 public Object clone() {
\r
254 // TODO: need to have better clone method
\r
255 Params clone = new Params();
\r
256 clone.outputChannels = new OutputChannels(outputChannels.getChannelsOutputCode());
\r
257 clone.equalizer = new Equalizer();
\r
261 // return super.clone();
\r
263 // catch (CloneNotSupportedException ex)
\r
265 // throw new InternalError(this+": "+ex);
\r
269 public void setOutputChannels(OutputChannels out) {
\r
271 throw new NullPointerException("out");
\r
273 outputChannels = out;
\r
276 public OutputChannels getOutputChannels() {
\r
277 return outputChannels;
\r
281 * Retrieves the equalizer settings that the decoder's equalizer will be
\r
282 * initialized from.
\r
284 * The <code>Equalizer</code> instance returned cannot be changed in real
\r
285 * time to affect the decoder output as it is used only to initialize the
\r
286 * decoders EQ settings. To affect the decoder's output in realtime, use the
\r
287 * Equalizer returned from the getEqualizer() method on the decoder.
\r
289 * @return The <code>Equalizer</code> used to initialize the EQ settings of
\r
292 public Equalizer getInitialEqualizerSettings() {
\r