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("ST,DE<OUT,DE<FIL,DE<LA,O,EQ,PA,INIT,DE*")
\r
30 public class Decoder implements DecoderErrors {
\r
31 static private final Params DEFAULT_PARAMS = new Params();
\r
34 * 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 PCM samples.
\r
43 // private Obuffer output;
\r
46 * Synthesis filter for the left channel.
\r
49 // private SynthesisFilter filter1;
\r
52 * Sythesis filter for the right channel.
\r
55 // private SynthesisFilter filter2;
\r
58 * The decoder used to decode layer III frames.
\r
61 private LayerIIIDecoder l3decoder;
\r
63 // private LayerIIDecoder l2decoder;
\r
65 // private LayerIDecoder l1decoder;
\r
68 private int outputFrequency;
\r
70 private int outputChannels;
\r
73 private Equalizer equalizer = new Equalizer();
\r
76 private Params params;
\r
79 private boolean initialized;
\r
82 * Creates a new <code>Decoder</code> instance with default parameters.
\r
90 * Creates a new <code>Decoder</code> instance with default parameters.
\r
93 * The <code>Params</code> instance that describes the customizable
\r
94 * aspects of the decoder.
\r
96 public Decoder(@DELEGATE Params params0) {
\r
98 if (params0 == null) {
\r
99 params0 = getDefaultParams();
\r
104 Equalizer eq = params.getInitialEqualizerSettings();
\r
106 equalizer.setFrom(eq);
\r
110 static public Params getDefaultParams() {
\r
111 return (Params) DEFAULT_PARAMS.clone();
\r
114 // public void setEqualizer(Equalizer eq) {
\r
116 // eq = Equalizer.PASS_THRU_EQ;
\r
118 // equalizer.setFrom(eq);
\r
120 // float[] factors = equalizer.getBandFactors();
\r
122 // if (filter1 != null)
\r
123 // filter1.setEQ(factors);
\r
125 // if (filter2 != null)
\r
126 // filter2.setEQ(factors);
\r
130 * Decodes one frame from an MPEG audio bitstream.
\r
133 * The header describing the frame to decode.
\r
135 * The bistream that provides the bits for te body of the frame.
\r
137 * @return A SampleBuffer containing the decoded samples.
\r
139 @LATTICE("O<DE,DE<TH,TH<IN,THISLOC=TH")
\r
141 public Obuffer decodeFrame(@LOC("IN") Header header) throws DecoderException {
\r
143 if (!initialized) {
\r
144 float scalefactor = 32700.0f;
\r
146 int mode = header.mode();
\r
147 int layer = header.layer();
\r
148 int channels = mode == Header.SINGLE_CHANNEL ? 1 : 2;
\r
150 // set up output buffer if not set up by client.
\r
151 // if (output == null)
\r
152 // output = new SampleBuffer(header.frequency(), channels);
\r
153 SampleBufferWrapper.init(header.frequency(), channels);
\r
155 float[] factors = equalizer.getBandFactors();
\r
156 SynthesisFilter filter1 = new SynthesisFilter(0, scalefactor, factors);
\r
158 // REVIEW: allow mono output for stereo
\r
159 SynthesisFilter filter2 = null;
\r
160 if (channels == 2) {
\r
161 filter2 = new SynthesisFilter(1, scalefactor, factors);
\r
164 outputChannels = channels;
\r
165 outputFrequency = header.frequency();
\r
167 l3decoder = new LayerIIIDecoder(filter1, filter2, OutputChannels.BOTH_CHANNELS);
\r
169 initialized = true;
\r
172 @LOC("TH") int layer = header.layer();
\r
174 SampleBufferWrapper.getOutput().clear_buffer();
\r
175 // output.clear_buffer();
\r
177 // @LOC("DE,Decoder.DE") FrameDecoder decoder = retrieveDecoder(header,
\r
179 // decoder.decodeFrame();
\r
181 l3decoder.decodeFrame(header);
\r
183 SampleBufferWrapper.getOutput().write_buffer(1);
\r
184 // output.write_buffer(1);
\r
190 * Changes the output buffer. This will take effect the next time
\r
191 * decodeFrame() is called.
\r
193 // public void setOutputBuffer(Obuffer out) {
\r
198 * Retrieves the sample frequency of the PCM samples output by this decoder.
\r
199 * This typically corresponds to the sample rate encoded in the MPEG audio
\r
203 * sample rate (in Hz) of the samples written to the output buffer
\r
206 public int getOutputFrequency() {
\r
207 return outputFrequency;
\r
211 * Retrieves the number of channels of PCM samples output by this decoder.
\r
212 * This usually corresponds to the number of channels in the MPEG audio
\r
213 * stream, although it may differ.
\r
215 * @return The number of output channels in the decoded samples: 1 for mono,
\r
219 public int getOutputChannels() {
\r
220 return outputChannels;
\r
224 * Retrieves the maximum number of samples that will be written to the output
\r
225 * buffer when one frame is decoded. This can be used to help calculate the
\r
226 * size of other buffers whose size is based upon the number of samples
\r
227 * written to the output buffer. NB: this is an upper bound and fewer samples
\r
228 * may actually be written, depending upon the sample rate and number of
\r
231 * @return The maximum number of samples that are written to the output buffer
\r
232 * when decoding a single frame of MPEG audio.
\r
234 public int getOutputBlockSize() {
\r
235 return Obuffer.OBUFFERSIZE;
\r
238 protected DecoderException newDecoderException(int errorcode) {
\r
239 return new DecoderException(errorcode, null);
\r
242 protected DecoderException newDecoderException(int errorcode, Throwable throwable) {
\r
243 return new DecoderException(errorcode, throwable);
\r
247 * The <code>Params</code> class presents the customizable aspects of the
\r
250 * Instances of this class are not thread safe.
\r
252 public static class Params implements Cloneable {
\r
254 // private OutputChannels outputChannels = OutputChannels.BOTH;
\r
255 private OutputChannels outputChannels = new OutputChannels(0);
\r
257 private Equalizer equalizer = new Equalizer();
\r
262 public Object clone() {
\r
263 // TODO: need to have better clone method
\r
264 Params clone = new Params();
\r
265 clone.outputChannels = new OutputChannels(outputChannels.getChannelsOutputCode());
\r
266 clone.equalizer = new Equalizer();
\r
270 // return super.clone();
\r
272 // catch (CloneNotSupportedException ex)
\r
274 // throw new InternalError(this+": "+ex);
\r
278 public void setOutputChannels(OutputChannels out) {
\r
280 throw new NullPointerException("out");
\r
282 outputChannels = out;
\r
285 public OutputChannels getOutputChannels() {
\r
286 return outputChannels;
\r
290 * Retrieves the equalizer settings that the decoder's equalizer will be
\r
291 * initialized from.
\r
293 * The <code>Equalizer</code> instance returned cannot be changed in real
\r
294 * time to affect the decoder output as it is used only to initialize the
\r
295 * decoders EQ settings. To affect the decoder's output in realtime, use the
\r
296 * Equalizer returned from the getEqualizer() method on the decoder.
\r
298 * @return The <code>Equalizer</code> used to initialize the EQ settings of
\r
301 public Equalizer getInitialEqualizerSettings() {
\r