Path: blob/main/src/lwjgl/java/javazoom/jl/decoder/Decoder.java
8650 views
/*1* 11/19/04 1.0 moved to LGPL.2* 01/12/99 Initial version. [email protected]3*-----------------------------------------------------------------------4* This program is free software; you can redistribute it and/or modify5* it under the terms of the GNU Library General Public License as published6* by the Free Software Foundation; either version 2 of the License, or7* (at your option) any later version.8*9* This program is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12* GNU Library General Public License for more details.13*14* You should have received a copy of the GNU Library General Public15* License along with this program; if not, write to the Free Software16* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.17*----------------------------------------------------------------------18*/1920package javazoom.jl.decoder;2122/**23* The <code>Decoder</code> class encapsulates the details of24* decoding an MPEG audio frame.25*26* @author MDM27* @version 0.0.7 12/12/9928* @since 0.0.529*/30public class Decoder implements DecoderErrors31{32private static final Params DEFAULT_PARAMS = new Params();3334/**35* The Bitstream from which the MPEG audio frames are read.36*/37//private Bitstream stream;3839/**40* The Obuffer instance that will receive the decoded41* PCM samples.42*/43private Obuffer output;4445/**46* Synthesis filter for the left channel.47*/48private SynthesisFilter filter1;4950/**51* Synthesis filter for the right channel.52*/53private SynthesisFilter filter2;5455/**56* The decoder used to decode layer III frames.57*/58private LayerIIIDecoder l3decoder;59private LayerIIDecoder l2decoder;60private LayerIDecoder l1decoder;6162private int outputFrequency;63private int outputChannels;6465private Equalizer equalizer = new Equalizer();6667private Params params;6869private boolean initialized;707172/**73* Creates a new <code>Decoder</code> instance with default74* parameters.75*/7677public Decoder()78{79this(null);80}8182/**83* Creates a new <code>Decoder</code> instance with default84* parameters.85*86* @param params The <code>Params</code> instance that describes87* the customizable aspects of the decoder.88*/89public Decoder(Params params0)90{91if (params0==null)92params0 = DEFAULT_PARAMS;9394params = params0;9596Equalizer eq = params.getInitialEqualizerSettings();97if (eq!=null)98{99equalizer.setFrom(eq);100}101}102103public static Params getDefaultParams() throws CloneNotSupportedException104{105return (Params)DEFAULT_PARAMS.clone();106}107108public void setEqualizer(Equalizer eq)109{110if (eq==null)111eq = Equalizer.PASS_THRU_EQ;112113equalizer.setFrom(eq);114115float[] factors = equalizer.getBandFactors();116117if (filter1!=null)118filter1.setEQ(factors);119120if (filter2!=null)121filter2.setEQ(factors);122}123124/**125* Decodes one frame from an MPEG audio bitstream.126*127* @param header The header describing the frame to decode.128* @param bitstream The bitstream that provides the bits for te body of the frame.129*130* @return A SampleBuffer containing the decoded samples.131*/132public Obuffer decodeFrame(Header header, Bitstream stream)133throws DecoderException134{135if (!initialized)136{137initialize(header);138}139140int layer = header.layer();141142output.clear_buffer();143144FrameDecoder decoder = retrieveDecoder(header, stream, layer);145146decoder.decodeFrame();147148output.write_buffer(1);149150return output;151}152153/**154* Changes the output buffer. This will take effect the next time155* decodeFrame() is called.156*/157public void setOutputBuffer(Obuffer out)158{159output = out;160}161162/**163* Retrieves the sample frequency of the PCM samples output164* by this decoder. This typically corresponds to the sample165* rate encoded in the MPEG audio stream.166*167* @param the sample rate (in Hz) of the samples written to the168* output buffer when decoding.169*/170public int getOutputFrequency()171{172return outputFrequency;173}174175/**176* Retrieves the number of channels of PCM samples output by177* this decoder. This usually corresponds to the number of178* channels in the MPEG audio stream, although it may differ.179*180* @return The number of output channels in the decoded samples: 1181* for mono, or 2 for stereo.182*183*/184public int getOutputChannels()185{186return outputChannels;187}188189/**190* Retrieves the maximum number of samples that will be written to191* the output buffer when one frame is decoded. This can be used to192* help calculate the size of other buffers whose size is based upon193* the number of samples written to the output buffer. NB: this is194* an upper bound and fewer samples may actually be written, depending195* upon the sample rate and number of channels.196*197* @return The maximum number of samples that are written to the198* output buffer when decoding a single frame of MPEG audio.199*/200public int getOutputBlockSize()201{202return Obuffer.OBUFFERSIZE;203}204205206protected DecoderException newDecoderException(int errorcode)207{208return new DecoderException(errorcode, null);209}210211protected DecoderException newDecoderException(int errorcode, Throwable throwable)212{213return new DecoderException(errorcode, throwable);214}215216protected FrameDecoder retrieveDecoder(Header header, Bitstream stream, int layer)217throws DecoderException218{219FrameDecoder decoder = null;220221// REVIEW: allow channel output selection type222// (LEFT, RIGHT, BOTH, DOWNMIX)223switch (layer)224{225case 3:226if (l3decoder==null)227{228l3decoder = new LayerIIIDecoder(stream,229header, filter1, filter2,230output, OutputChannels.BOTH_CHANNELS);231}232233decoder = l3decoder;234break;235case 2:236if (l2decoder==null)237{238l2decoder = new LayerIIDecoder();239l2decoder.create(stream,240header, filter1, filter2,241output, OutputChannels.BOTH_CHANNELS);242}243decoder = l2decoder;244break;245case 1:246if (l1decoder==null)247{248l1decoder = new LayerIDecoder();249l1decoder.create(stream,250header, filter1, filter2,251output, OutputChannels.BOTH_CHANNELS);252}253decoder = l1decoder;254break;255}256257if (decoder==null)258{259throw newDecoderException(UNSUPPORTED_LAYER, null);260}261262return decoder;263}264265private void initialize(Header header)266throws DecoderException267{268269// REVIEW: allow customizable scale factor270float scalefactor = 32700.0f;271272int mode = header.mode();273int layer = header.layer();274int channels = mode==Header.SINGLE_CHANNEL ? 1 : 2;275276277// set up output buffer if not set up by client.278if (output==null)279output = new SampleBuffer(header.frequency(), channels);280281float[] factors = equalizer.getBandFactors();282filter1 = new SynthesisFilter(0, scalefactor, factors);283284// REVIEW: allow mono output for stereo285if (channels==2)286filter2 = new SynthesisFilter(1, scalefactor, factors);287288outputChannels = channels;289outputFrequency = header.frequency();290291initialized = true;292}293294/**295* The <code>Params</code> class presents the customizable296* aspects of the decoder.297* <p>298* Instances of this class are not thread safe.299*/300public static class Params implements Cloneable301{302private OutputChannels outputChannels = OutputChannels.BOTH;303304private Equalizer equalizer = new Equalizer();305306public Params()307{308}309310public Object clone() throws CloneNotSupportedException {311try312{313return super.clone();314}315catch (CloneNotSupportedException ex)316{317throw new InternalError(this+": "+ex);318}319}320321public void setOutputChannels(OutputChannels out)322{323if (out==null)324throw new NullPointerException("out");325326outputChannels = out;327}328329public OutputChannels getOutputChannels()330{331return outputChannels;332}333334/**335* Retrieves the equalizer settings that the decoder's equalizer336* will be initialized from.337* <p>338* The <code>Equalizer</code> instance returned339* cannot be changed in real time to affect the340* decoder output as it is used only to initialize the decoders341* EQ settings. To affect the decoder's output in realtime,342* use the Equalizer returned from the getEqualizer() method on343* the decoder.344*345* @return The <code>Equalizer</code> used to initialize the346* EQ settings of the decoder.347*/348public Equalizer getInitialEqualizerSettings()349{350return equalizer;351}352353};354}355356357358