more changes to pass the flow-down rule
[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 \r
131   /**\r
132    * Decodes one frame from an MPEG audio bitstream.\r
133    * \r
134    * @param header\r
135    *          The header describing the frame to decode.\r
136    * @param bitstream\r
137    *          The bistream that provides the bits for te body of the frame.\r
138    * \r
139    * @return A SampleBuffer containing the decoded samples.\r
140    */\r
141   @LATTICE("THIS<VAR,THISLOC=THIS,VAR*")\r
142   public void decodeFrame(@LOC("THIS,Decoder.H") Header header) throws DecoderException {\r
143 \r
144     if (!initialized) {\r
145       @LOC("VAR") float scalefactor = 32700.0f;\r
146 \r
147       @LOC("THIS,Decoder.PARAM") int mode = header.mode();\r
148       @LOC("THIS,Decoder.PARAM") int layer = header.layer();\r
149       @LOC("THIS,Decoder.PARAM") int channels = mode == Header.SINGLE_CHANNEL ? 1 : 2;\r
150 \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
155 \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
159 \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
164       }\r
165 \r
166       outputChannels = channels;\r
167       outputFrequency = header.frequency();\r
168 \r
169       l3decoder = new LayerIIIDecoder(filter1, filter2, OutputChannels.BOTH_CHANNELS);\r
170 \r
171       initialized = true;\r
172     }\r
173 \r
174     SampleBufferWrapper.clear_buffer();\r
175     l3decoder.decode(header);\r
176     // SampleBufferWrapper.getOutput().write_buffer(1);\r
177 \r
178   }\r
179 \r
180   /**\r
181    * Changes the output buffer. This will take effect the next time\r
182    * decodeFrame() is called.\r
183    */\r
184   // public void setOutputBuffer(Obuffer out) {\r
185   // output = out;\r
186   // }\r
187 \r
188   /**\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
191    * stream.\r
192    * \r
193    * @param the\r
194    *          sample rate (in Hz) of the samples written to the output buffer\r
195    *          when decoding.\r
196    */\r
197   public int getOutputFrequency() {\r
198     return outputFrequency;\r
199   }\r
200 \r
201   /**\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
205    * \r
206    * @return The number of output channels in the decoded samples: 1 for mono,\r
207    *         or 2 for stereo.\r
208    * \r
209    */\r
210   public int getOutputChannels() {\r
211     return outputChannels;\r
212   }\r
213 \r
214   /**\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
220    * channels.\r
221    * \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
224    */\r
225   public int getOutputBlockSize() {\r
226     return Obuffer.OBUFFERSIZE;\r
227   }\r
228 \r
229   protected DecoderException newDecoderException(int errorcode) {\r
230     return new DecoderException(errorcode, null);\r
231   }\r
232 \r
233   protected DecoderException newDecoderException(int errorcode, Throwable throwable) {\r
234     return new DecoderException(errorcode, throwable);\r
235   }\r
236 \r
237   /**\r
238    * The <code>Params</code> class presents the customizable aspects of the\r
239    * decoder.\r
240    * <p>\r
241    * Instances of this class are not thread safe.\r
242    */\r
243   public static class Params implements Cloneable {\r
244 \r
245     // private OutputChannels outputChannels = OutputChannels.BOTH;\r
246     private OutputChannels outputChannels = new OutputChannels(0);\r
247 \r
248     private Equalizer equalizer = new Equalizer();\r
249 \r
250     public Params() {\r
251     }\r
252 \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
258       return clone;\r
259       // try\r
260       // {\r
261       // return super.clone();\r
262       // }\r
263       // catch (CloneNotSupportedException ex)\r
264       // {\r
265       // throw new InternalError(this+": "+ex);\r
266       // }\r
267     }\r
268 \r
269     public void setOutputChannels(OutputChannels out) {\r
270       if (out == null)\r
271         throw new NullPointerException("out");\r
272 \r
273       outputChannels = out;\r
274     }\r
275 \r
276     public OutputChannels getOutputChannels() {\r
277       return outputChannels;\r
278     }\r
279 \r
280     /**\r
281      * Retrieves the equalizer settings that the decoder's equalizer will be\r
282      * initialized from.\r
283      * <p>\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
288      * \r
289      * @return The <code>Equalizer</code> used to initialize the EQ settings of\r
290      *         the decoder.\r
291      */\r
292     public Equalizer getInitialEqualizerSettings() {\r
293       return equalizer;\r
294     }\r
295 \r
296   };\r
297 }\r