adding a test case
[IRC.git] / Robust / src / Tests / ssJava / mp3decoder / Decoder.java
1 /*\r
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
9  *\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
14  *\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
19  */\r
20 \r
21 /**\r
22  * The <code>Decoder</code> class encapsulates the details of decoding an MPEG\r
23  * audio frame.\r
24  * \r
25  * @author MDM\r
26  * @version 0.0.7 12/12/99\r
27  * @since 0.0.5\r
28  */\r
29 @LATTICE("OUT<DE,DE<FILTER,FILTER<FACTORS,FACTORS<EQ,EQ<PARAM,PARAM<H,H<INIT,PARAM*,INIT*")\r
30 @METHODDEFAULT("THIS,THISLOC=THIS,RETURNLOC=THIS")\r
31 public class Decoder implements DecoderErrors {\r
32 \r
33   static private final Params DEFAULT_PARAMS = new Params();\r
34 \r
35   /**\r
36    * The Bistream from which the MPEG audio frames are read.\r
37    */\r
38   // @LOC("ST")\r
39   // private Bitstream stream;\r
40 \r
41   /**\r
42    * The Obuffer instance that will receive the decoded PCM samples.\r
43    */\r
44   // @LOC("OUT")\r
45   // private Obuffer output;\r
46 \r
47   /**\r
48    * Synthesis filter for the left channel.\r
49    */\r
50   // @LOC("FIL")\r
51   // private SynthesisFilter filter1;\r
52 \r
53   /**\r
54    * Sythesis filter for the right channel.\r
55    */\r
56   // @LOC("FIL")\r
57   // private SynthesisFilter filter2;\r
58 \r
59   /**\r
60    * The decoder used to decode layer III frames.\r
61    */\r
62   @LOC("DE")\r
63   private LayerIIIDecoder l3decoder;\r
64   // @LOC("DE")\r
65   // private LayerIIDecoder l2decoder;\r
66   // @LOC("DE")\r
67   // private LayerIDecoder l1decoder;\r
68 \r
69   @LOC("OUT")\r
70   private int outputFrequency;\r
71   @LOC("OUT")\r
72   private int outputChannels;\r
73 \r
74   @LOC("EQ")\r
75   private Equalizer equalizer = new Equalizer();\r
76 \r
77   @LOC("PARAM")\r
78   private Params params;\r
79 \r
80   @LOC("INIT")\r
81   private boolean initialized;\r
82 \r
83   /**\r
84    * Creates a new <code>Decoder</code> instance with default parameters.\r
85    */\r
86 \r
87   public Decoder() {\r
88     this(null);\r
89   }\r
90 \r
91   /**\r
92    * Creates a new <code>Decoder</code> instance with default parameters.\r
93    * \r
94    * @param params\r
95    *          The <code>Params</code> instance that describes the customizable\r
96    *          aspects of the decoder.\r
97    */\r
98   public Decoder(@DELEGATE Params params0) {\r
99 \r
100     if (params0 == null) {\r
101       params0 = getDefaultParams();\r
102     }\r
103 \r
104     params = params0;\r
105 \r
106     Equalizer eq = params.getInitialEqualizerSettings();\r
107     if (eq != null) {\r
108       equalizer.setFrom(eq);\r
109     }\r
110   }\r
111 \r
112   static public Params getDefaultParams() {\r
113     return (Params) DEFAULT_PARAMS.clone();\r
114   }\r
115 \r
116   // public void setEqualizer(Equalizer eq) {\r
117   // if (eq == null)\r
118   // eq = Equalizer.PASS_THRU_EQ;\r
119   //\r
120   // equalizer.setFrom(eq);\r
121   //\r
122   // float[] factors = equalizer.getBandFactors();\r
123   //\r
124   // if (filter1 != null)\r
125   // filter1.setEQ(factors);\r
126   //\r
127   // if (filter2 != null)\r
128   // filter2.setEQ(factors);\r
129   // }\r
130   @LATTICE("THIS<VAR,THISLOC=THIS,VAR*")\r
131   public void init( @LOC("THIS,Decoder.H") Header header) {\r
132     @LOC("VAR") float scalefactor = 32700.0f;\r
133 \r
134     @LOC("THIS,Decoder.PARAM") int mode = header.mode();\r
135     @LOC("THIS,Decoder.PARAM") int layer = header.layer();\r
136     @LOC("THIS,Decoder.PARAM") int channels = mode == Header.SINGLE_CHANNEL ? 1 : 2;\r
137 \r
138     // set up output buffer if not set up by client.\r
139     // if (output == null)\r
140     // output = new SampleBuffer(header.frequency(), channels);\r
141     SampleBufferWrapper.init(header.frequency(), channels);\r
142 \r
143     @LOC("THIS,Decoder.FACTORS") float[] factors = equalizer.getBandFactors();\r
144     @LOC("THIS,Decoder.FILTER") SynthesisFilter filter1 =\r
145         new SynthesisFilter(0, scalefactor, factors);\r
146 \r
147     // REVIEW: allow mono output for stereo\r
148     @LOC("THIS,Decoder.FILTER") SynthesisFilter filter2 = null;\r
149     if (channels == 2) {\r
150       filter2 = new SynthesisFilter(1, scalefactor, factors);\r
151     }\r
152 \r
153     outputChannels = channels;\r
154     outputFrequency = header.frequency();\r
155 \r
156     l3decoder = new LayerIIIDecoder(header,filter1, filter2, OutputChannels.BOTH_CHANNELS);\r
157 \r
158   }\r
159 \r
160   /**\r
161    * Decodes one frame from an MPEG audio bitstream.\r
162    * \r
163    * @param header\r
164    *          The header describing the frame to decode.\r
165    * @param bitstream\r
166    *          The bistream that provides the bits for te body of the frame.\r
167    * \r
168    * @return A SampleBuffer containing the decoded samples.\r
169    */\r
170   @LATTICE("THIS<VAR,THISLOC=THIS,VAR*")\r
171   public void decodeFrame(@LOC("THIS,Decoder.H") Header header) throws DecoderException {\r
172 \r
173     SampleBufferWrapper.clear_buffer();\r
174     l3decoder.decode(header);\r
175     // SampleBufferWrapper.getOutput().write_buffer(1);\r
176 \r
177   }\r
178 \r
179   /**\r
180    * Changes the output buffer. This will take effect the next time\r
181    * decodeFrame() is called.\r
182    */\r
183   // public void setOutputBuffer(Obuffer out) {\r
184   // output = out;\r
185   // }\r
186 \r
187   /**\r
188    * Retrieves the sample frequency of the PCM samples output by this decoder.\r
189    * This typically corresponds to the sample rate encoded in the MPEG audio\r
190    * stream.\r
191    * \r
192    * @param the\r
193    *          sample rate (in Hz) of the samples written to the output buffer\r
194    *          when decoding.\r
195    */\r
196   public int getOutputFrequency() {\r
197     return outputFrequency;\r
198   }\r
199 \r
200   /**\r
201    * Retrieves the number of channels of PCM samples output by this decoder.\r
202    * This usually corresponds to the number of channels in the MPEG audio\r
203    * stream, although it may differ.\r
204    * \r
205    * @return The number of output channels in the decoded samples: 1 for mono,\r
206    *         or 2 for stereo.\r
207    * \r
208    */\r
209   public int getOutputChannels() {\r
210     return outputChannels;\r
211   }\r
212 \r
213   /**\r
214    * Retrieves the maximum number of samples that will be written to the output\r
215    * buffer when one frame is decoded. This can be used to help calculate the\r
216    * size of other buffers whose size is based upon the number of samples\r
217    * written to the output buffer. NB: this is an upper bound and fewer samples\r
218    * may actually be written, depending upon the sample rate and number of\r
219    * channels.\r
220    * \r
221    * @return The maximum number of samples that are written to the output buffer\r
222    *         when decoding a single frame of MPEG audio.\r
223    */\r
224   public int getOutputBlockSize() {\r
225     return Obuffer.OBUFFERSIZE;\r
226   }\r
227 \r
228   protected DecoderException newDecoderException(int errorcode) {\r
229     return new DecoderException(errorcode, null);\r
230   }\r
231 \r
232   protected DecoderException newDecoderException(int errorcode, Throwable throwable) {\r
233     return new DecoderException(errorcode, throwable);\r
234   }\r
235 \r
236   /**\r
237    * The <code>Params</code> class presents the customizable aspects of the\r
238    * decoder.\r
239    * <p>\r
240    * Instances of this class are not thread safe.\r
241    */\r
242   public static class Params implements Cloneable {\r
243 \r
244     // private OutputChannels outputChannels = OutputChannels.BOTH;\r
245     private OutputChannels outputChannels = new OutputChannels(0);\r
246 \r
247     private Equalizer equalizer = new Equalizer();\r
248 \r
249     public Params() {\r
250     }\r
251 \r
252     public Object clone() {\r
253       // TODO: need to have better clone method\r
254       Params clone = new Params();\r
255       clone.outputChannels = new OutputChannels(outputChannels.getChannelsOutputCode());\r
256       clone.equalizer = new Equalizer();\r
257       return clone;\r
258       // try\r
259       // {\r
260       // return super.clone();\r
261       // }\r
262       // catch (CloneNotSupportedException ex)\r
263       // {\r
264       // throw new InternalError(this+": "+ex);\r
265       // }\r
266     }\r
267 \r
268     public void setOutputChannels(OutputChannels out) {\r
269       if (out == null)\r
270         throw new NullPointerException("out");\r
271 \r
272       outputChannels = out;\r
273     }\r
274 \r
275     public OutputChannels getOutputChannels() {\r
276       return outputChannels;\r
277     }\r
278 \r
279     /**\r
280      * Retrieves the equalizer settings that the decoder's equalizer will be\r
281      * initialized from.\r
282      * <p>\r
283      * The <code>Equalizer</code> instance returned cannot be changed in real\r
284      * time to affect the decoder output as it is used only to initialize the\r
285      * decoders EQ settings. To affect the decoder's output in realtime, use the\r
286      * Equalizer returned from the getEqualizer() method on the decoder.\r
287      * \r
288      * @return The <code>Equalizer</code> used to initialize the EQ settings of\r
289      *         the decoder.\r
290      */\r
291     public Equalizer getInitialEqualizerSettings() {\r
292       return equalizer;\r
293     }\r
294 \r
295   };\r
296 }\r