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
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
38 // private Bitstream stream;
\r
41 * The Obuffer instance that will receive the decoded PCM samples.
\r
44 // private Obuffer output;
\r
47 * Synthesis filter for the left channel.
\r
50 // private SynthesisFilter filter1;
\r
53 * Sythesis filter for the right channel.
\r
56 // private SynthesisFilter filter2;
\r
59 * The decoder used to decode layer III frames.
\r
62 private LayerIIIDecoder l3decoder;
\r
64 // private LayerIIDecoder l2decoder;
\r
66 // private LayerIDecoder l1decoder;
\r
68 private int outputFrequency;
\r
70 private int outputChannels;
\r
72 private Equalizer equalizer = new Equalizer();
\r
74 private Params params;
\r
76 private boolean initialized;
\r
79 * Creates a new <code>Decoder</code> instance with default parameters.
\r
87 * Creates a new <code>Decoder</code> instance with default parameters.
\r
90 * The <code>Params</code> instance that describes the customizable
\r
91 * aspects of the decoder.
\r
93 public Decoder(@DELEGATE Params params0) {
\r
95 if (params0 == null) {
\r
96 params0 = getDefaultParams();
\r
101 Equalizer eq = params.getInitialEqualizerSettings();
\r
103 equalizer.setFrom(eq);
\r
107 static public Params getDefaultParams() {
\r
108 return (Params) DEFAULT_PARAMS.clone();
\r
111 // public void setEqualizer(Equalizer eq) {
\r
113 // eq = Equalizer.PASS_THRU_EQ;
\r
115 // equalizer.setFrom(eq);
\r
117 // float[] factors = equalizer.getBandFactors();
\r
119 // if (filter1 != null)
\r
120 // filter1.setEQ(factors);
\r
122 // if (filter2 != null)
\r
123 // filter2.setEQ(factors);
\r
126 public void init(Header header) {
\r
127 float scalefactor = 32700.0f;
\r
129 int mode = header.mode();
\r
130 int layer = header.layer();
\r
131 int channels = mode == Header.SINGLE_CHANNEL ? 1 : 2;
\r
133 // set up output buffer if not set up by client.
\r
134 // if (output == null)
\r
135 // output = new SampleBuffer(header.frequency(), channels);
\r
136 SampleBufferWrapper.init(header.frequency(), channels);
\r
138 float[] factors = equalizer.getBandFactors();
\r
139 SynthesisFilter filter1 = new SynthesisFilter(0, scalefactor, factors);
\r
141 // REVIEW: allow mono output for stereo
\r
142 SynthesisFilter filter2 = null;
\r
143 if (channels == 2) {
\r
144 filter2 = new SynthesisFilter(1, scalefactor, factors);
\r
147 outputChannels = channels;
\r
148 outputFrequency = header.frequency();
\r
150 l3decoder = new LayerIIIDecoder(header, filter1, filter2, OutputChannels.BOTH_CHANNELS);
\r
155 * Decodes one frame from an MPEG audio bitstream.
\r
158 * The header describing the frame to decode.
\r
160 * The bistream that provides the bits for te body of the frame.
\r
162 * @return A SampleBuffer containing the decoded samples.
\r
165 public void decodeFrame(Header header) throws DecoderException {
\r
167 SampleBufferWrapper.clear_buffer();
\r
168 l3decoder.decode(header);
\r
169 // SampleBufferWrapper.getOutput().write_buffer(1);
\r
174 * Changes the output buffer. This will take effect the next time
\r
175 * decodeFrame() is called.
\r
177 // public void setOutputBuffer(Obuffer out) {
\r
182 * Retrieves the sample frequency of the PCM samples output by this decoder.
\r
183 * This typically corresponds to the sample rate encoded in the MPEG audio
\r
187 * sample rate (in Hz) of the samples written to the output buffer
\r
190 public int getOutputFrequency() {
\r
191 return outputFrequency;
\r
195 * Retrieves the number of channels of PCM samples output by this decoder.
\r
196 * This usually corresponds to the number of channels in the MPEG audio
\r
197 * stream, although it may differ.
\r
199 * @return The number of output channels in the decoded samples: 1 for mono,
\r
203 public int getOutputChannels() {
\r
204 return outputChannels;
\r
208 * Retrieves the maximum number of samples that will be written to the output
\r
209 * buffer when one frame is decoded. This can be used to help calculate the
\r
210 * size of other buffers whose size is based upon the number of samples
\r
211 * written to the output buffer. NB: this is an upper bound and fewer samples
\r
212 * may actually be written, depending upon the sample rate and number of
\r
215 * @return The maximum number of samples that are written to the output buffer
\r
216 * when decoding a single frame of MPEG audio.
\r
218 public int getOutputBlockSize() {
\r
219 return Obuffer.OBUFFERSIZE;
\r
222 protected DecoderException newDecoderException(int errorcode) {
\r
223 return new DecoderException(errorcode, null);
\r
226 protected DecoderException newDecoderException(int errorcode, Throwable throwable) {
\r
227 return new DecoderException(errorcode, throwable);
\r
232 * The <code>Params</code> class presents the customizable aspects of the
\r
235 * Instances of this class are not thread safe.
\r
237 public class Params implements Cloneable {
\r
239 // private OutputChannels outputChannels = OutputChannels.BOTH;
\r
240 private OutputChannels outputChannels = new OutputChannels(0);
\r
242 private Equalizer equalizer = new Equalizer();
\r
247 public Object clone() {
\r
248 // TODO: need to have better clone method
\r
249 Params clone = new Params();
\r
250 clone.outputChannels = new OutputChannels(outputChannels.getChannelsOutputCode());
\r
251 clone.equalizer = new Equalizer();
\r
255 // return super.clone();
\r
257 // catch (CloneNotSupportedException ex)
\r
259 // throw new InternalError(this+": "+ex);
\r
263 public void setOutputChannels(OutputChannels out) {
\r
265 throw new NullPointerException("out");
\r
267 outputChannels = out;
\r
270 public OutputChannels getOutputChannels() {
\r
271 return outputChannels;
\r
275 * Retrieves the equalizer settings that the decoder's equalizer will be
\r
276 * initialized from.
\r
278 * The <code>Equalizer</code> instance returned cannot be changed in real time
\r
279 * to affect the decoder output as it is used only to initialize the decoders
\r
280 * EQ settings. To affect the decoder's output in realtime, use the Equalizer
\r
281 * returned from the getEqualizer() method on the decoder.
\r
283 * @return The <code>Equalizer</code> used to initialize the EQ settings of
\r
286 public Equalizer getInitialEqualizerSettings() {
\r