start revising the linear type checking
authoryeom <yeom>
Fri, 5 Aug 2011 01:52:32 +0000 (01:52 +0000)
committeryeom <yeom>
Fri, 5 Aug 2011 01:52:32 +0000 (01:52 +0000)
Robust/src/Analysis/SSJava/LinearTypeCheck.java [new file with mode: 0644]
Robust/src/Analysis/SSJava/MethodAnnotationCheck.java
Robust/src/Analysis/SSJava/SSJavaAnalysis.java
Robust/src/Analysis/SSJava/SingleReferenceCheck.java [deleted file]
Robust/src/Tests/ssJava/mp3decoder/Decoder.java
Robust/src/Tests/ssJava/mp3decoder/Header.java
Robust/src/Tests/ssJava/mp3decoder/LayerIDecoder.java
Robust/src/Tests/ssJava/mp3decoder/Player.java

diff --git a/Robust/src/Analysis/SSJava/LinearTypeCheck.java b/Robust/src/Analysis/SSJava/LinearTypeCheck.java
new file mode 100644 (file)
index 0000000..90aee1e
--- /dev/null
@@ -0,0 +1,402 @@
+package Analysis.SSJava;
+
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+
+import IR.AnnotationDescriptor;
+import IR.ClassDescriptor;
+import IR.Descriptor;
+import IR.MethodDescriptor;
+import IR.State;
+import IR.SymbolTable;
+import IR.TaskDescriptor;
+import IR.TypeDescriptor;
+import IR.VarDescriptor;
+import IR.Tree.ArrayAccessNode;
+import IR.Tree.ArrayInitializerNode;
+import IR.Tree.AssignmentNode;
+import IR.Tree.AtomicNode;
+import IR.Tree.BlockExpressionNode;
+import IR.Tree.BlockNode;
+import IR.Tree.BlockStatementNode;
+import IR.Tree.CastNode;
+import IR.Tree.ClassTypeNode;
+import IR.Tree.ContinueBreakNode;
+import IR.Tree.CreateObjectNode;
+import IR.Tree.DeclarationNode;
+import IR.Tree.ExpressionNode;
+import IR.Tree.FieldAccessNode;
+import IR.Tree.IfStatementNode;
+import IR.Tree.InstanceOfNode;
+import IR.Tree.Kind;
+import IR.Tree.LiteralNode;
+import IR.Tree.LoopNode;
+import IR.Tree.MethodInvokeNode;
+import IR.Tree.NameNode;
+import IR.Tree.OffsetNode;
+import IR.Tree.OpNode;
+import IR.Tree.ReturnNode;
+import IR.Tree.SubBlockNode;
+import IR.Tree.SwitchBlockNode;
+import IR.Tree.SwitchLabelNode;
+import IR.Tree.SwitchStatementNode;
+import IR.Tree.SynchronizedNode;
+import IR.Tree.TagDeclarationNode;
+import IR.Tree.TaskExitNode;
+import IR.Tree.TertiaryNode;
+
+public class LinearTypeCheck {
+
+  State state;
+  SSJavaAnalysis ssjava;
+  String needToNullify = null;
+
+  Hashtable<MethodDescriptor, Set<VarDescriptor>> md2DelegateParamSet;
+
+  public LinearTypeCheck(SSJavaAnalysis ssjava, State state) {
+    this.ssjava = ssjava;
+    this.state = state;
+    md2DelegateParamSet = new Hashtable<MethodDescriptor, Set<VarDescriptor>>();
+  }
+
+  public void linearTypeCheck() {
+
+    // first, parsing DELEGATE annotation from method declarations
+    Iterator it = state.getClassSymbolTable().getDescriptorsIterator();
+    while (it.hasNext()) {
+      ClassDescriptor cd = (ClassDescriptor) it.next();
+      for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
+        MethodDescriptor md = (MethodDescriptor) method_it.next();
+        parseAnnotations(md);
+      }
+    }
+    System.out.println("###");
+    System.out.println("md2DelegateParamSet=" + md2DelegateParamSet);
+
+    // second, check the linear type
+    it = state.getClassSymbolTable().getDescriptorsIterator();
+    while (it.hasNext()) {
+      ClassDescriptor cd = (ClassDescriptor) it.next();
+      for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
+        MethodDescriptor md = (MethodDescriptor) method_it.next();
+        if (ssjava.needTobeAnnotated(md)) {
+          checkMethodBody(cd, md);
+        }
+      }
+    }
+
+  }
+
+  private void parseAnnotations(MethodDescriptor md) {
+
+    for (int i = 0; i < md.numParameters(); i++) {
+      // process annotations on method parameters
+      VarDescriptor vd = (VarDescriptor) md.getParameter(i);
+
+      Vector<AnnotationDescriptor> annotationVec = vd.getType().getAnnotationMarkers();
+
+      for (int anIdx = 0; anIdx < annotationVec.size(); anIdx++) {
+        AnnotationDescriptor ad = annotationVec.elementAt(anIdx);
+        if (ad.getMarker().equals(SSJavaAnalysis.DELEGATE)) {
+
+          Set<VarDescriptor> delegateSet = md2DelegateParamSet.get(md);
+          if (delegateSet == null) {
+            delegateSet = new HashSet<VarDescriptor>();
+            md2DelegateParamSet.put(md, delegateSet);
+          }
+          delegateSet.add(vd);
+        }
+      }
+
+    }
+
+  }
+
+  private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
+    BlockNode bn = state.getMethodBody(md);
+    checkBlockNode(md, md.getParameterTable(), bn);
+  }
+
+  private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
+    for (int i = 0; i < bn.size(); i++) {
+      BlockStatementNode bsn = bn.get(i);
+      checkBlockStatementNode(md, bn.getVarTable(), bsn);
+    }
+  }
+
+  private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
+      BlockStatementNode bsn) {
+
+    if (needToNullify != null) {
+      if (!checkNullifying(bsn)) {
+        throw new Error(
+            "Reference field, which is read by a method, should be assigned to null before executing any following statement of the reference copy statement at "
+                + md.getClassDesc().getSourceFileName() + "::" + bsn.getNumLine());
+      }
+    }
+
+    switch (bsn.kind()) {
+
+    case Kind.BlockExpressionNode:
+      checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn);
+      return;
+
+    case Kind.DeclarationNode:
+      checkDeclarationNode(md, nametable, (DeclarationNode) bsn);
+      return;
+
+    case Kind.IfStatementNode:
+      checkIfStatementNode(md, nametable, (IfStatementNode) bsn);
+      return;
+
+    case Kind.SwitchStatementNode:
+      checkSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn);
+      return;
+
+    case Kind.LoopNode:
+      checkLoopNode(md, nametable, (LoopNode) bsn);
+      return;
+
+    case Kind.ReturnNode:
+      checkReturnNode(md, nametable, (ReturnNode) bsn);
+      return;
+
+    case Kind.SubBlockNode:
+      checkSubBlockNode(md, nametable, (SubBlockNode) bsn);
+      return;
+
+    case Kind.SynchronizedNode:
+      checkSynchronizedNode(md, nametable, (SynchronizedNode) bsn);
+      return;
+    }
+
+    throw new Error();
+  }
+
+  private void checkSynchronizedNode(MethodDescriptor md, SymbolTable nametable,
+      SynchronizedNode sbn) {
+    checkBlockNode(md, nametable, sbn.getBlockNode());
+    // todo this could be Object
+    checkExpressionNode(md, nametable, sbn.getExpr());
+  }
+
+  private void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn) {
+    if (rn.getReturnExpression() != null) {
+      checkExpressionNode(md, nametable, rn.getReturnExpression());
+    }
+  }
+
+  private void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) {
+    checkBlockNode(md, nametable, sbn.getBlockNode());
+  }
+
+  private void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn) {
+    checkExpressionNode(md, nametable, isn.getCondition());
+    checkBlockNode(md, nametable, isn.getTrueBlock());
+    if (isn.getFalseBlock() != null)
+      checkBlockNode(md, nametable, isn.getFalseBlock());
+  }
+
+  private void checkSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
+      SwitchStatementNode ssn) {
+
+    checkExpressionNode(md, nametable, ssn.getCondition());
+
+    BlockNode sbn = ssn.getSwitchBody();
+    for (int i = 0; i < sbn.size(); i++) {
+      checkSwitchBlockNode(md, nametable, (SwitchBlockNode) sbn.get(i));
+    }
+  }
+
+  private void checkSwitchBlockNode(MethodDescriptor md, SymbolTable nametable, SwitchBlockNode sbn) {
+    checkBlockNode(md, nametable, sbn.getSwitchBlockStatement());
+  }
+
+  private void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
+      BlockExpressionNode ben) {
+    checkExpressionNode(md, nametable, ben.getExpression());
+  }
+
+  private void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en) {
+    switch (en.kind()) {
+    case Kind.AssignmentNode:
+      checkAssignmentNode(md, nametable, (AssignmentNode) en);
+      return;
+
+    case Kind.CastNode:
+      checkCastNode(md, nametable, (CastNode) en);
+      return;
+
+    case Kind.CreateObjectNode:
+      checkCreateObjectNode(md, nametable, (CreateObjectNode) en);
+      return;
+
+    case Kind.FieldAccessNode:
+      checkFieldAccessNode(md, nametable, (FieldAccessNode) en);
+      return;
+
+    case Kind.ArrayAccessNode:
+      checkArrayAccessNode(md, nametable, (ArrayAccessNode) en);
+      return;
+
+      // case Kind.LiteralNode:
+      // checkLiteralNode(md, nametable, (LiteralNode) en);
+      // return;
+
+    case Kind.MethodInvokeNode:
+      checkMethodInvokeNode(md, nametable, (MethodInvokeNode) en);
+      return;
+
+    case Kind.NameNode:
+      checkNameNode(md, nametable, (NameNode) en);
+      return;
+
+    case Kind.OpNode:
+      checkOpNode(md, nametable, (OpNode) en);
+      return;
+
+    case Kind.OffsetNode:
+      checkOffsetNode(md, nametable, (OffsetNode) en);
+      return;
+
+    case Kind.TertiaryNode:
+      checkTertiaryNode(md, nametable, (TertiaryNode) en);
+      return;
+
+      // case Kind.InstanceOfNode:
+      // checkInstanceOfNode(md, nametable, (InstanceOfNode) en);
+      // return;
+
+      // case Kind.ArrayInitializerNode:
+      // checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en);
+      // return;
+
+      // case Kind.ClassTypeNode:
+      // checkClassTypeNode(md, nametable, (ClassTypeNode) ens);
+      // return;
+    }
+    throw new Error();
+  }
+
+  private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode en) {
+    // TODO Auto-generated method stub
+
+  }
+
+  private void checkOffsetNode(MethodDescriptor md, SymbolTable nametable, OffsetNode en) {
+    // TODO Auto-generated method stub
+
+  }
+
+  private void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode en) {
+    // TODO Auto-generated method stub
+
+  }
+
+  private void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode en) {
+    // TODO Auto-generated method stub
+
+  }
+
+  private void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode en) {
+    // TODO Auto-generated method stub
+
+  }
+
+  private void checkArrayAccessNode(MethodDescriptor md, SymbolTable nametable, ArrayAccessNode en) {
+    // TODO Auto-generated method stub
+
+  }
+
+  private void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan) {
+
+  }
+
+  private void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
+      CreateObjectNode con) {
+    TypeDescriptor[] tdarray = new TypeDescriptor[con.numArgs()];
+    for (int i = 0; i < con.numArgs(); i++) {
+      ExpressionNode en = con.getArg(i);
+      checkExpressionNode(md, nametable, en);
+      tdarray[i] = en.getType();
+    }
+
+    if ((con.getArrayInitializer() != null)) {
+      checkArrayInitializerNode(md, nametable, con.getArrayInitializer());
+    }
+
+  }
+
+  private void checkArrayInitializerNode(MethodDescriptor md, SymbolTable nametable,
+      ArrayInitializerNode arrayInitializer) {
+    // TODO Auto-generated method stub
+
+  }
+
+  private void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn) {
+    ExpressionNode en = cn.getExpression();
+    checkExpressionNode(md, nametable, en);
+  }
+
+  private boolean checkNullifying(BlockStatementNode bsn) {
+
+    if (bsn.kind() == Kind.BlockExpressionNode) {
+      ExpressionNode en = ((BlockExpressionNode) bsn).getExpression();
+      if (en.kind() == Kind.AssignmentNode) {
+        AssignmentNode an = (AssignmentNode) en;
+
+        if (an.getSrc().getType().isNull() && an.getDest().printNode(0).equals(needToNullify)) {
+          needToNullify = null;
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
+    if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
+      checkExpressionNode(md, nametable, ln.getCondition());
+      checkBlockNode(md, nametable, ln.getBody());
+    } else {
+      // For loop case
+      /* Link in the initializer naming environment */
+      BlockNode bn = ln.getInitializer();
+      for (int i = 0; i < bn.size(); i++) {
+        BlockStatementNode bsn = bn.get(i);
+        checkBlockStatementNode(md, bn.getVarTable(), bsn);
+      }
+      // check the condition
+      checkExpressionNode(md, bn.getVarTable(), ln.getCondition());
+      checkBlockNode(md, bn.getVarTable(), ln.getBody());
+      checkBlockNode(md, bn.getVarTable(), ln.getUpdate());
+    }
+  }
+
+  private void checkAssignmentNode(Descriptor md, SymbolTable nametable, AssignmentNode an) {
+    needToNullify(an.getSrc());
+  }
+
+  private void checkDeclarationNode(Descriptor md, SymbolTable nametable, DeclarationNode dn) {
+    needToNullify(dn.getExpression());
+  }
+
+  private void needToNullify(ExpressionNode en) {
+
+    if (en != null && en.getType().isPtr() && !en.getType().isString()) {
+      if (en.kind() != Kind.CreateObjectNode && en.kind() != Kind.LiteralNode) {
+        if (en.kind() == Kind.CastNode) {
+          needToNullify = ((CastNode) en).getExpression().printNode(0);
+        } else {
+          needToNullify = en.printNode(0);
+        }
+      }
+    }
+
+  }
+
+}
index 6c3dac6..eba5f77 100644 (file)
@@ -97,8 +97,6 @@ public class MethodAnnotationCheck {
             Set<MethodDescriptor> possibleCalleeSet =
                 (Set<MethodDescriptor>) ssjava.getCallGraph().getMethods(calleeMD);
 
-            System.out.println("caller=" + callerMD + " callee=" + possibleCalleeSet);
-
             for (Iterator iterator2 = possibleCalleeSet.iterator(); iterator2.hasNext();) {
               MethodDescriptor possibleCallee = (MethodDescriptor) iterator2.next();
 
index 4e62c25..41396e9 100644 (file)
@@ -35,6 +35,7 @@ public class SSJavaAnalysis {
   public static final String LOC = "LOC";
   public static final String DELTA = "DELTA";
   public static final String TERMINATE = "TERMINATE";
+  public static final String DELEGATE = "DELEGATE";
 
   State state;
   TypeUtil tu;
@@ -78,6 +79,7 @@ public class SSJavaAnalysis {
   }
 
   public void doCheck() {
+    doLinearTypeCheck();
     doMethodAnnotationCheck();
     if (state.SSJAVADEBUG) {
       debugPrint();
@@ -85,7 +87,11 @@ public class SSJavaAnalysis {
     parseLocationAnnotation();
     doFlowDownCheck();
     doDefinitelyWrittenCheck();
-    doSingleReferenceCheck();
+  }
+
+  private void doLinearTypeCheck() {
+    LinearTypeCheck checker = new LinearTypeCheck(this, state);
+    checker.linearTypeCheck();
   }
 
   public void debugPrint() {
@@ -113,11 +119,6 @@ public class SSJavaAnalysis {
     checker.definitelyWrittenCheck();
   }
 
-  public void doSingleReferenceCheck() {
-    SingleReferenceCheck checker = new SingleReferenceCheck(this, state);
-    checker.singleReferenceCheck();
-  }
-
   private void parseLocationAnnotation() {
     Iterator it = state.getClassSymbolTable().getDescriptorsIterator();
     while (it.hasNext()) {
diff --git a/Robust/src/Analysis/SSJava/SingleReferenceCheck.java b/Robust/src/Analysis/SSJava/SingleReferenceCheck.java
deleted file mode 100644 (file)
index 8bc6a8c..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-package Analysis.SSJava;
-
-import java.util.Iterator;
-
-import IR.ClassDescriptor;
-import IR.MethodDescriptor;
-import IR.State;
-import IR.Tree.AssignmentNode;
-import IR.Tree.BlockExpressionNode;
-import IR.Tree.BlockNode;
-import IR.Tree.BlockStatementNode;
-import IR.Tree.CastNode;
-import IR.Tree.DeclarationNode;
-import IR.Tree.ExpressionNode;
-import IR.Tree.Kind;
-import IR.Tree.LoopNode;
-import IR.Tree.SubBlockNode;
-
-public class SingleReferenceCheck {
-
-  State state;
-  SSJavaAnalysis ssjava;
-  String needToNullify = null;
-
-  public SingleReferenceCheck(SSJavaAnalysis ssjava, State state) {
-    this.ssjava = ssjava;
-    this.state = state;
-  }
-
-  public void singleReferenceCheck() {
-    Iterator it = state.getClassSymbolTable().getDescriptorsIterator();
-    while (it.hasNext()) {
-      ClassDescriptor cd = (ClassDescriptor) it.next();
-      for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
-        MethodDescriptor md = (MethodDescriptor) method_it.next();
-        if (ssjava.needTobeAnnotated(md)) {
-          checkMethodBody(cd, md);
-        }
-      }
-    }
-  }
-
-  private void checkMethodBody(ClassDescriptor cd, MethodDescriptor fm) {
-    BlockNode bn = state.getMethodBody(fm);
-    for (int i = 0; i < bn.size(); i++) {
-      checkBlockStatementNode(cd, bn.get(i));
-    }
-
-  }
-
-  private boolean checkNullifying(BlockStatementNode bsn) {
-
-    if (bsn.kind() == Kind.BlockExpressionNode) {
-      ExpressionNode en = ((BlockExpressionNode) bsn).getExpression();
-      if (en.kind() == Kind.AssignmentNode) {
-        AssignmentNode an = (AssignmentNode) en;
-
-        if (an.getSrc().getType().isNull() && an.getDest().printNode(0).equals(needToNullify)) {
-          needToNullify = null;
-          return true;
-        }
-      }
-    }
-
-    return false;
-  }
-
-  private void checkBlockStatementNode(ClassDescriptor cd, BlockStatementNode bsn) {
-
-    if (needToNullify != null) {
-      if (!checkNullifying(bsn)) {
-        throw new Error(
-            "Reference field, which is read by a method, should be assigned to null before executing any following statement of the reference copy statement at "
-                + cd.getSourceFileName() + "::" + bsn.getNumLine());
-      }
-    }
-
-    switch (bsn.kind()) {
-    case Kind.BlockExpressionNode:
-      checkExpressionNode(((BlockExpressionNode) bsn).getExpression());
-      break;
-
-    case Kind.DeclarationNode:
-      checkDeclarationNode((DeclarationNode) bsn);
-      break;
-
-    case Kind.SubBlockNode:
-      checkSubBlockNode(cd, (SubBlockNode) bsn);
-      return;
-
-    case Kind.LoopNode:
-      checkLoopNode(cd, (LoopNode) bsn);
-      break;
-    }
-
-  }
-
-  private void checkLoopNode(ClassDescriptor cd, LoopNode ln) {
-    if (ln.getType() == LoopNode.FORLOOP) {
-      checkBlockNode(cd, ln.getInitializer());
-    }
-    checkBlockNode(cd, ln.getBody());
-  }
-
-  private void checkSubBlockNode(ClassDescriptor cd, SubBlockNode sbn) {
-    checkBlockNode(cd, sbn.getBlockNode());
-  }
-
-  private void checkBlockNode(ClassDescriptor cd, BlockNode bn) {
-    for (int i = 0; i < bn.size(); i++) {
-      checkBlockStatementNode(cd, bn.get(i));
-    }
-  }
-
-  private void checkExpressionNode(ExpressionNode en) {
-
-    switch (en.kind()) {
-    case Kind.AssignmentNode:
-      checkAssignmentNode((AssignmentNode) en);
-      break;
-    }
-
-  }
-
-  private void checkAssignmentNode(AssignmentNode an) {
-    needToNullify(an.getSrc());
-  }
-
-  private void checkDeclarationNode(DeclarationNode dn) {
-    needToNullify(dn.getExpression());
-  }
-
-  private void needToNullify(ExpressionNode en) {
-
-    if (en != null && en.getType().isPtr() && !en.getType().isString()) {
-      if (en.kind() != Kind.CreateObjectNode && en.kind() != Kind.LiteralNode) {
-        if (en.kind() == Kind.CastNode) {
-          needToNullify = ((CastNode) en).getExpression().printNode(0);
-        } else {
-          needToNullify = en.printNode(0);
-        }
-      }
-    }
-
-  }
-
-}
index ec4bf7d..e871eec 100644 (file)
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
  *----------------------------------------------------------------------\r
  */\r
\r
 \r
 /**\r
- * The <code>Decoder</code> class encapsulates the details of\r
- * decoding an MPEG audio frame. \r
+ * The <code>Decoder</code> class encapsulates the details of decoding an MPEG\r
+ * audio frame.\r
  * \r
- * @author     MDM     \r
+ * @author MDM\r
  * @version 0.0.7 12/12/99\r
- * @since      0.0.5\r
+ * @since 0.0.5\r
  */\r
 @LATTICE("ST,DE<OUT,DE<FIL,DE<LA,O,EQ,PA,INIT,DE*")\r
-public class Decoder implements DecoderErrors\r
-{\r
-       static private final Params DEFAULT_PARAMS = new Params();\r
-       \r
-       /**\r
-        * The Bistream from which the MPEG audio frames are read.\r
-        */\r
-       @LOC("ST") private Bitstream                            stream;\r
-       \r
-       /**\r
-        * The Obuffer instance that will receive the decoded\r
-        * PCM samples.\r
-        */\r
-       @LOC("OUT") private Obuffer                     output;\r
-               \r
-       /**\r
-        * Synthesis filter for the left channel.\r
-        */\r
-       @LOC("FIL") private SynthesisFilter                     filter1;\r
-       \r
-       /**\r
-        * Sythesis filter for the right channel.\r
-        */\r
-       @LOC("FIL") private SynthesisFilter                     filter2;        \r
-                       \r
-       /**\r
-        * The decoder used to decode layer III frames.\r
-        */\r
-       @LOC("DE") private LayerIIIDecoder                      l3decoder;\r
-       @LOC("DE") private LayerIIDecoder                       l2decoder;\r
-       @LOC("DE") private LayerIDecoder                        l1decoder;\r
-       \r
-       @LOC("O") private int                                           outputFrequency;\r
-       @LOC("O") private int                                           outputChannels;\r
-       \r
-       @LOC("EQ") private Equalizer                            equalizer = new Equalizer();\r
-       \r
-       @LOC("PA") private Params                                       params;\r
-       \r
-       @LOC("INIT") private boolean                                    initialized;\r
-               \r
-       \r
-       /**\r
-        * Creates a new <code>Decoder</code> instance with default \r
-        * parameters.\r
-        */\r
-       \r
-       public Decoder()\r
-       {\r
-               this(null);\r
-       }\r
-\r
-       /**\r
-        * Creates a new <code>Decoder</code> instance with default \r
-        * parameters.\r
-        * \r
-        * @param params        The <code>Params</code> instance that describes\r
-        *                                      the customizable aspects of the decoder.  \r
-        */\r
-       public Decoder(Params params0)\r
-       {\r
-               if (params0==null)\r
-                       params0 = DEFAULT_PARAMS;\r
-       \r
-               params = params0;\r
-               \r
-               Equalizer eq = params.getInitialEqualizerSettings();\r
-               if (eq!=null)\r
-               {\r
-                       equalizer.setFrom(eq);\r
-               }\r
-       }\r
-       \r
-       static public Params getDefaultParams()\r
-       {\r
-               return (Params)DEFAULT_PARAMS.clone();\r
-       }\r
-       \r
-       public void setEqualizer(Equalizer eq)\r
-       {\r
-               if (eq==null)\r
-                       eq = Equalizer.PASS_THRU_EQ;\r
-               \r
-               equalizer.setFrom(eq);\r
-               \r
-               float[] factors = equalizer.getBandFactors();\r
-\r
-               if (filter1!=null)\r
-                       filter1.setEQ(factors);\r
-               \r
-               if (filter2!=null)\r
-                       filter2.setEQ(factors);                 \r
-       }\r
-       \r
-       /**\r
-        * Decodes one frame from an MPEG audio bitstream.\r
-        * \r
-        * @param header                The header describing the frame to decode.\r
-        * @param bitstream             The bistream that provides the bits for te body of the frame. \r
-        * \r
-        * @return A SampleBuffer containing the decoded samples.\r
-        */\r
-       @LATTICE("O<DE,DE<TH,TH<IN,THISLOC=TH")\r
-       @RETURNLOC("O")\r
-       public Obuffer decodeFrame(@LOC("IN") Header header, @LOC("IN") Bitstream stream)\r
-       throws DecoderException\r
-       {\r
-         // throw decoder initialization out of ssjava loop since it is invoked once\r
-         //            if (!initialized)\r
-         //            {\r
-         //                initialize(header,stream);\r
-         //            }\r
-\r
-         @LOC("TH") int layer = header.layer();\r
-\r
-         output.clear_buffer();\r
-\r
-//       @LOC("DE,Decoder.DE") FrameDecoder decoder = retrieveDecoder(header, stream, layer); // return ceil=DELTA(TH)\r
-//       decoder.decodeFrame();\r
-\r
-         if(layer==3){\r
-           if (l3decoder==null)\r
-           {\r
-             l3decoder = new LayerIIIDecoder(stream, \r
-                 header, filter1, filter2, \r
-                 output, OutputChannels.BOTH_CHANNELS);\r
-           }                             \r
-           l3decoder.decodeFrame();\r
-         }else if(layer==2){\r
-           if (l2decoder==null)\r
-           {\r
-             l2decoder = new LayerIIDecoder();\r
-             l2decoder.create(stream, \r
-                 header, filter1, filter2, \r
-                 output, OutputChannels.BOTH_CHANNELS);                 \r
-           }\r
-           l2decoder.decodeFrame();\r
-         }else{\r
-           if (l1decoder==null)\r
-           {\r
-             l1decoder = new LayerIDecoder();\r
-             l1decoder.create(stream, \r
-                 header, filter1, filter2, \r
-                 output, OutputChannels.BOTH_CHANNELS);                 \r
-           }\r
-           l1decoder.decodeFrame();\r
-         }\r
-\r
-         output.write_buffer(1);\r
-\r
-         return output;        \r
-       }\r
-       \r
-       /**\r
-        * Changes the output buffer. This will take effect the next time\r
-        * decodeFrame() is called. \r
-        */\r
-       public void setOutputBuffer(Obuffer out)\r
-       {\r
-               output = out;\r
-       }\r
-       \r
-       /**\r
-        * Retrieves the sample frequency of the PCM samples output\r
-        * by this decoder. This typically corresponds to the sample\r
-        * rate encoded in the MPEG audio stream.\r
-        * \r
-        * @param the sample rate (in Hz) of the samples written to the\r
-        *              output buffer when decoding. \r
-        */\r
-       public int getOutputFrequency()\r
-       {\r
-               return outputFrequency;\r
-       }\r
-       \r
-       /**\r
-        * Retrieves the number of channels of PCM samples output by\r
-        * this decoder. This usually corresponds to the number of\r
-        * channels in the MPEG audio stream, although it may differ.\r
-        * \r
-        * @return The number of output channels in the decoded samples: 1 \r
-        *              for mono, or 2 for stereo.\r
-        *              \r
-        */\r
-       public int getOutputChannels()\r
-       {\r
-               return outputChannels;  \r
-       }\r
-       \r
-       /**\r
-        * Retrieves the maximum number of samples that will be written to\r
-        * the output buffer when one frame is decoded. This can be used to\r
-        * help calculate the size of other buffers whose size is based upon \r
-        * the number of samples written to the output buffer. NB: this is\r
-        * an upper bound and fewer samples may actually be written, depending\r
-        * upon the sample rate and number of channels.\r
-        * \r
-        * @return The maximum number of samples that are written to the \r
-        *              output buffer when decoding a single frame of MPEG audio.\r
-        */\r
-       public int getOutputBlockSize()\r
-       {\r
-               return Obuffer.OBUFFERSIZE;\r
-       }\r
-       \r
-       \r
-       protected DecoderException newDecoderException(int errorcode)\r
-       {\r
-               return new DecoderException(errorcode, null);\r
-       }\r
-       \r
-       protected DecoderException newDecoderException(int errorcode, Throwable throwable)\r
-       {\r
-               return new DecoderException(errorcode, throwable);\r
-       }\r
-       \r
-       @LATTICE("IN,TH,THISLOC=TH")\r
-       @RETURNLOC("TH")\r
-       protected FrameDecoder retrieveDecoder(@LOC("IN") Header header, @LOC("IN") Bitstream stream, @LOC("IN") int layer)\r
-               throws DecoderException\r
-       {\r
-//             @LOC("DE") FrameDecoder decoder = null;\r
-               \r
-               // REVIEW: allow channel output selection type\r
-               // (LEFT, RIGHT, BOTH, DOWNMIX)\r
-               switch (layer)\r
-               {\r
-               case 3:\r
-                       if (l3decoder==null)\r
-                       {\r
-                               l3decoder = new LayerIIIDecoder(stream, \r
-                                       header, filter1, filter2, \r
-                                       output, OutputChannels.BOTH_CHANNELS);\r
-                       }                                               \r
-                       \r
-                       return l3decoder;\r
-//                     decoder = l3decoder;\r
-                       break;\r
-               case 2:\r
-                       if (l2decoder==null)\r
-                       {\r
-                               l2decoder = new LayerIIDecoder();\r
-                               l2decoder.create(stream, \r
-                                       header, filter1, filter2, \r
-                                       output, OutputChannels.BOTH_CHANNELS);                          \r
-                       }\r
-              return l2decoder;\r
-//                     decoder = l2decoder;\r
-                       break;\r
-               case 1:\r
-                       if (l1decoder==null)\r
-                       {\r
-                               l1decoder = new LayerIDecoder();\r
-                               l1decoder.create(stream, \r
-                                       header, filter1, filter2, \r
-                                       output, OutputChannels.BOTH_CHANNELS);                          \r
-                       }\r
-              return l1decoder;\r
-//                     decoder = l1decoder;\r
-                       break;\r
-               }\r
-//                                             \r
-//             if (decoder==null)\r
-//             {\r
-//                     throw newDecoderException(UNSUPPORTED_LAYER, null);\r
-//             }\r
-//             \r
-//             return decoder;\r
-       }\r
-       \r
-        public void initialize(Header header, Bitstream stream)\r
-               throws DecoderException\r
-       {\r
-               \r
-               // REVIEW: allow customizable scale factor\r
-               float scalefactor = 32700.0f;\r
-               \r
-               int mode = header.mode();\r
-               int layer = header.layer();\r
-               int channels = mode==Header.SINGLE_CHANNEL ? 1 : 2;\r
-\r
-                                       \r
-               // set up output buffer if not set up by client.\r
-               if (output==null)\r
-                       output = new SampleBuffer(header.frequency(), channels);\r
-               \r
-               float[] factors = equalizer.getBandFactors();\r
-               filter1 = new SynthesisFilter(0, scalefactor, factors);\r
-               \r
-               // REVIEW: allow mono output for stereo\r
-               if (channels==2) \r
-                       filter2 = new SynthesisFilter(1, scalefactor, factors);\r
-\r
-               outputChannels = channels;\r
-               outputFrequency = header.frequency();\r
-\r
-               l3decoder = new LayerIIIDecoder(stream, header, filter1, filter2, \r
-                                               output, OutputChannels.BOTH_CHANNELS);\r
-               l2decoder = new LayerIIDecoder();\r
-               l2decoder.create(stream, header, filter1, filter2, \r
-                                output, OutputChannels.BOTH_CHANNELS);\r
-\r
-               l1decoder = new LayerIDecoder();\r
-               l1decoder.create(stream,header, filter1, filter2, \r
-                                output, OutputChannels.BOTH_CHANNELS); \r
-\r
-               initialized = true;\r
-       }\r
-       \r
-       /**\r
-        * The <code>Params</code> class presents the customizable\r
-        * aspects of the decoder. \r
-        * <p>\r
-        * Instances of this class are not thread safe. \r
-        */\r
-       public static class Params implements Cloneable\r
-       {\r
-               private OutputChannels  outputChannels = OutputChannels.BOTH;\r
-               \r
-               private Equalizer               equalizer = new Equalizer();\r
-               \r
-               public Params()\r
-               {                       \r
-               }\r
-               \r
-               public Object clone()\r
-               {\r
-                 //TODO: need to have better clone method\r
-                   Params clone=new Params();\r
-                   clone.outputChannels=outputChannels;\r
-                   clone.equalizer=equalizer;\r
-                   return clone;\r
-//                     try\r
-//                     {\r
-//                             return super.clone();\r
-//                     }\r
-//                     catch (CloneNotSupportedException ex)\r
-//                     {                               \r
-//                             throw new InternalError(this+": "+ex);\r
-//                     }\r
-               }\r
-                               \r
-               public void setOutputChannels(OutputChannels out)\r
-               {\r
-                       if (out==null)\r
-                               throw new NullPointerException("out");\r
-                       \r
-                       outputChannels = out;\r
-               }\r
-               \r
-               public OutputChannels getOutputChannels()\r
-               {\r
-                       return outputChannels;\r
-               }\r
-               \r
-               /**\r
-                * Retrieves the equalizer settings that the decoder's equalizer\r
-                * will be initialized from.\r
-                * <p>\r
-                * The <code>Equalizer</code> instance returned \r
-                * cannot be changed in real time to affect the \r
-                * decoder output as it is used only to initialize the decoders\r
-                * EQ settings. To affect the decoder's output in realtime,\r
-                * use the Equalizer returned from the getEqualizer() method on\r
-                * the decoder. \r
-                * \r
-                * @return      The <code>Equalizer</code> used to initialize the\r
-                *                      EQ settings of the decoder. \r
-                */\r
-               public Equalizer getInitialEqualizerSettings()\r
-               {\r
-                       return equalizer;       \r
-               }\r
-                               \r
-       };\r
-}\r
+public class Decoder implements DecoderErrors {\r
+  static private final Params DEFAULT_PARAMS = new Params();\r
+\r
+  /**\r
+   * The Bistream from which the MPEG audio frames are read.\r
+   */\r
+  @LOC("ST")\r
+  private Bitstream stream;\r
+\r
+  /**\r
+   * The Obuffer instance that will receive the decoded PCM samples.\r
+   */\r
+  @LOC("OUT")\r
+  private Obuffer output;\r
+\r
+  /**\r
+   * Synthesis filter for the left channel.\r
+   */\r
+  @LOC("FIL")\r
+  private SynthesisFilter filter1;\r
+\r
+  /**\r
+   * Sythesis filter for the right channel.\r
+   */\r
+  @LOC("FIL")\r
+  private SynthesisFilter filter2;\r
+\r
+  /**\r
+   * The decoder used to decode layer III frames.\r
+   */\r
+  @LOC("DE")\r
+  private LayerIIIDecoder l3decoder;\r
+  @LOC("DE")\r
+  private LayerIIDecoder l2decoder;\r
+  @LOC("DE")\r
+  private LayerIDecoder l1decoder;\r
+\r
+  @LOC("O")\r
+  private int outputFrequency;\r
+  @LOC("O")\r
+  private int outputChannels;\r
+\r
+  @LOC("EQ")\r
+  private Equalizer equalizer = new Equalizer();\r
+\r
+  @LOC("PA")\r
+  private Params params;\r
+\r
+  @LOC("INIT")\r
+  private boolean initialized;\r
+\r
+  /**\r
+   * Creates a new <code>Decoder</code> instance with default parameters.\r
+   */\r
+\r
+  public Decoder() {\r
+    this(null);\r
+  }\r
+\r
+  /**\r
+   * Creates a new <code>Decoder</code> instance with default parameters.\r
+   * \r
+   * @param params\r
+   *          The <code>Params</code> instance that describes the customizable\r
+   *          aspects of the decoder.\r
+   */\r
+  public Decoder(Params params0) {\r
+    if (params0 == null)\r
+      params0 = DEFAULT_PARAMS;\r
+\r
+    params = params0;\r
+\r
+    Equalizer eq = params.getInitialEqualizerSettings();\r
+    if (eq != null) {\r
+      equalizer.setFrom(eq);\r
+    }\r
+  }\r
+\r
+  static public Params getDefaultParams() {\r
+    return (Params) DEFAULT_PARAMS.clone();\r
+  }\r
+\r
+  public void setEqualizer(Equalizer eq) {\r
+    if (eq == null)\r
+      eq = Equalizer.PASS_THRU_EQ;\r
+\r
+    equalizer.setFrom(eq);\r
+\r
+    float[] factors = equalizer.getBandFactors();\r
+\r
+    if (filter1 != null)\r
+      filter1.setEQ(factors);\r
+\r
+    if (filter2 != null)\r
+      filter2.setEQ(factors);\r
+  }\r
+\r
+  /**\r
+   * Decodes one frame from an MPEG audio bitstream.\r
+   * \r
+   * @param header\r
+   *          The header describing the frame to decode.\r
+   * @param bitstream\r
+   *          The bistream that provides the bits for te body of the frame.\r
+   * \r
+   * @return A SampleBuffer containing the decoded samples.\r
+   */\r
+  @LATTICE("O<DE,DE<TH,TH<IN,THISLOC=TH")\r
+  @RETURNLOC("O")\r
+  public Obuffer decodeFrame(@LOC("IN") Header header, @LOC("IN") Bitstream stream)\r
+      throws DecoderException {\r
+\r
+    if (!initialized) {\r
+      initialize(header);\r
+    }\r
+\r
+    @LOC("TH") int layer = header.layer();\r
+\r
+    output.clear_buffer();\r
+\r
+    @LOC("DE,Decoder.DE") FrameDecoder decoder = retrieveDecoder(header, stream, layer); // return\r
+                                                                                         // ceil=DELTA(TH)\r
+    decoder.decodeFrame();\r
+\r
+    // if (layer == 3) {\r
+    // if (l3decoder == null) {\r
+    // l3decoder =\r
+    // new LayerIIIDecoder(stream, header, filter1, filter2, output,\r
+    // OutputChannels.BOTH_CHANNELS);\r
+    // }\r
+    // l3decoder.decodeFrame();\r
+    // } else if (layer == 2) {\r
+    // if (l2decoder == null) {\r
+    // l2decoder = new LayerIIDecoder();\r
+    // l2decoder.create(stream, header, filter1, filter2, output,\r
+    // OutputChannels.BOTH_CHANNELS);\r
+    // }\r
+    // l2decoder.decodeFrame();\r
+    // } else {\r
+    // if (l1decoder == null) {\r
+    // l1decoder = new LayerIDecoder();\r
+    // l1decoder.create(stream, header, filter1, filter2, output,\r
+    // OutputChannels.BOTH_CHANNELS);\r
+    // }\r
+    // l1decoder.decodeFrame();\r
+    // }\r
+\r
+    output.write_buffer(1);\r
 \r
+    return output;\r
+  }\r
+\r
+  /**\r
+   * Changes the output buffer. This will take effect the next time\r
+   * decodeFrame() is called.\r
+   */\r
+  public void setOutputBuffer(Obuffer out) {\r
+    output = out;\r
+  }\r
+\r
+  /**\r
+   * Retrieves the sample frequency of the PCM samples output by this decoder.\r
+   * This typically corresponds to the sample rate encoded in the MPEG audio\r
+   * stream.\r
+   * \r
+   * @param the\r
+   *          sample rate (in Hz) of the samples written to the output buffer\r
+   *          when decoding.\r
+   */\r
+  public int getOutputFrequency() {\r
+    return outputFrequency;\r
+  }\r
+\r
+  /**\r
+   * Retrieves the number of channels of PCM samples output by this decoder.\r
+   * This usually corresponds to the number of channels in the MPEG audio\r
+   * stream, although it may differ.\r
+   * \r
+   * @return The number of output channels in the decoded samples: 1 for mono,\r
+   *         or 2 for stereo.\r
+   * \r
+   */\r
+  public int getOutputChannels() {\r
+    return outputChannels;\r
+  }\r
+\r
+  /**\r
+   * Retrieves the maximum number of samples that will be written to the output\r
+   * buffer when one frame is decoded. This can be used to help calculate the\r
+   * size of other buffers whose size is based upon the number of samples\r
+   * written to the output buffer. NB: this is an upper bound and fewer samples\r
+   * may actually be written, depending upon the sample rate and number of\r
+   * channels.\r
+   * \r
+   * @return The maximum number of samples that are written to the output buffer\r
+   *         when decoding a single frame of MPEG audio.\r
+   */\r
+  public int getOutputBlockSize() {\r
+    return Obuffer.OBUFFERSIZE;\r
+  }\r
+\r
+  protected DecoderException newDecoderException(int errorcode) {\r
+    return new DecoderException(errorcode, null);\r
+  }\r
+\r
+  protected DecoderException newDecoderException(int errorcode, Throwable throwable) {\r
+    return new DecoderException(errorcode, throwable);\r
+  }\r
+\r
+  @LATTICE("IN,TH,THISLOC=TH")\r
+  @RETURNLOC("TH")\r
+  protected FrameDecoder retrieveDecoder(@LOC("IN") Header header, @LOC("IN") Bitstream stream,\r
+      @LOC("IN") int layer) throws DecoderException {\r
+    // @LOC("DE") FrameDecoder decoder = null;\r
+\r
+    // REVIEW: allow channel output selection type\r
+    // (LEFT, RIGHT, BOTH, DOWNMIX)\r
+    switch (layer) {\r
+    case 3:\r
+      if (l3decoder == null) {\r
+        l3decoder =\r
+            new LayerIIIDecoder(stream, header, filter1, filter2, output,\r
+                OutputChannels.BOTH_CHANNELS);\r
+      }\r
+\r
+      return l3decoder;\r
+      // decoder = l3decoder;\r
+      break;\r
+    case 2:\r
+      if (l2decoder == null) {\r
+        l2decoder = new LayerIIDecoder();\r
+        l2decoder.create(stream, header, filter1, filter2, output, OutputChannels.BOTH_CHANNELS);\r
+      }\r
+      return l2decoder;\r
+      // decoder = l2decoder;\r
+      break;\r
+    case 1:\r
+      if (l1decoder == null) {\r
+        l1decoder = new LayerIDecoder();\r
+        l1decoder.create(stream, header, filter1, filter2, output, OutputChannels.BOTH_CHANNELS);\r
+      }\r
+      return l1decoder;\r
+      // decoder = l1decoder;\r
+      break;\r
+    }\r
+    //\r
+    // if (decoder==null)\r
+    // {\r
+    // throw newDecoderException(UNSUPPORTED_LAYER, null);\r
+    // }\r
+    //\r
+    // return decoder;\r
+  }\r
+\r
+  public void initialize(Header header) throws DecoderException {\r
+\r
+    // REVIEW: allow customizable scale factor\r
+    float scalefactor = 32700.0f;\r
+\r
+    int mode = header.mode();\r
+    int layer = header.layer();\r
+    int channels = mode == Header.SINGLE_CHANNEL ? 1 : 2;\r
+\r
+    // set up output buffer if not set up by client.\r
+    if (output == null)\r
+      output = new SampleBuffer(header.frequency(), channels);\r
+\r
+    float[] factors = equalizer.getBandFactors();\r
+    filter1 = new SynthesisFilter(0, scalefactor, factors);\r
+\r
+    // REVIEW: allow mono output for stereo\r
+    if (channels == 2)\r
+      filter2 = new SynthesisFilter(1, scalefactor, factors);\r
+\r
+    outputChannels = channels;\r
+    outputFrequency = header.frequency();\r
+\r
+    initialized = true;\r
+  }\r
+\r
+  /**\r
+   * The <code>Params</code> class presents the customizable aspects of the\r
+   * decoder.\r
+   * <p>\r
+   * Instances of this class are not thread safe.\r
+   */\r
+  public static class Params implements Cloneable {\r
+    private OutputChannels outputChannels = OutputChannels.BOTH;\r
+\r
+    private Equalizer equalizer = new Equalizer();\r
+\r
+    public Params() {\r
+    }\r
+\r
+    public Object clone() {\r
+      // TODO: need to have better clone method\r
+      Params clone = new Params();\r
+      clone.outputChannels = outputChannels;\r
+      clone.equalizer = equalizer;\r
+      return clone;\r
+      // try\r
+      // {\r
+      // return super.clone();\r
+      // }\r
+      // catch (CloneNotSupportedException ex)\r
+      // {\r
+      // throw new InternalError(this+": "+ex);\r
+      // }\r
+    }\r
+\r
+    public void setOutputChannels(OutputChannels out) {\r
+      if (out == null)\r
+        throw new NullPointerException("out");\r
+\r
+      outputChannels = out;\r
+    }\r
+\r
+    public OutputChannels getOutputChannels() {\r
+      return outputChannels;\r
+    }\r
+\r
+    /**\r
+     * Retrieves the equalizer settings that the decoder's equalizer will be\r
+     * initialized from.\r
+     * <p>\r
+     * The <code>Equalizer</code> instance returned cannot be changed in real\r
+     * time to affect the decoder output as it is used only to initialize the\r
+     * decoders EQ settings. To affect the decoder's output in realtime, use the\r
+     * Equalizer returned from the getEqualizer() method on the decoder.\r
+     * \r
+     * @return The <code>Equalizer</code> used to initialize the EQ settings of\r
+     *         the decoder.\r
+     */\r
+    public Equalizer getInitialEqualizerSettings() {\r
+      return equalizer;\r
+    }\r
+\r
+  };\r
+}\r
index cd7fb01..f4cef5c 100644 (file)
  */\r
 @LATTICE("HI<HNS,HNS<H,C<H,NS<FS,FS<H,FS<HV,H<SYNC,HV<SYNC,HV<T,SYNC*,HV*,FS*,HI*")\r
 @METHODDEFAULT("OUT<V,V<THIS,THIS<SH,SH<IN,SH*,THISLOC=THIS,GLOBALLOC=IN")\r
-public final class Header\r
-{\r
-        @LOC("T") public  static final int[][] frequencies =\r
-                                               {{22050, 24000, 16000, 1},\r
-                                               {44100, 48000, 32000, 1},\r
-                                               {11025, 12000, 8000, 1}};       // SZD: MPEG25\r
-\r
-       /**\r
-        * Constant for MPEG-2 LSF version\r
-        */\r
-        @LOC("T") public static final int              MPEG2_LSF = 0;\r
-        @LOC("T") public static final int              MPEG25_LSF = 2; // SZD\r
-\r
-       /**\r
-        * Constant for MPEG-1 version\r
-        */\r
-        @LOC("T") public static final int              MPEG1 = 1;\r
-\r
-        @LOC("T") public static final int              STEREO = 0;\r
-        @LOC("T") public static final int              JOINT_STEREO = 1;\r
-        @LOC("T") public static final int              DUAL_CHANNEL = 2;\r
-        @LOC("T") public static final int              SINGLE_CHANNEL = 3;\r
-        @LOC("T") public static final int              FOURTYFOUR_POINT_ONE = 0;\r
-        @LOC("T") public static final int              FOURTYEIGHT=1;\r
-        @LOC("T") public static final int              THIRTYTWO=2;\r
-\r
-    @LOC("H") private int                              h_layer;\r
-    @LOC("H") private int  h_protection_bit;\r
-    @LOC("H") private int h_bitrate_index;\r
-    @LOC("H") private int h_padding_bit;\r
-    @LOC("H") private int h_mode_extension;\r
-    @LOC("HV") private int                             h_version;\r
-    @LOC("H") private int                              h_mode;\r
-    @LOC("H") private int                              h_sample_frequency;\r
-    @LOC("HNS") private int                            h_number_of_subbands;\r
-    @LOC("HI") private int h_intensity_stereo_bound;\r
-    @LOC("H") private boolean                  h_copyright;\r
-    @LOC("H") private boolean h_original;\r
-       // VBR support added by E.B\r
-    @LOC("T") private double[]                 h_vbr_time_per_frame = {-1.0, 384.0, 1152.0, 1152.0};\r
-    @LOC("T") private boolean                  h_vbr;\r
-    @LOC("T") private int                              h_vbr_frames;\r
-    @LOC("T") private int                              h_vbr_scale;\r
-    @LOC("T") private int                              h_vbr_bytes;\r
-    @LOC("T") private byte[]                   h_vbr_toc;\r
-       \r
-    @LOC("SYNC") private byte                  syncmode = Bitstream.INITIAL_SYNC;\r
-    @LOC("C") private Crc16                    crc;\r
-\r
-    @LOC("C") public short                     checksum;\r
-    @LOC("FS") public int                              framesize;\r
-    @LOC("NS") public int                              nSlots;\r
-\r
-    @LOC("T") private int                              _headerstring = -1; // E.B\r
-\r
-       Header()\r
-       {\r
-       }\r
-       public String toString()\r
-       {\r
-               StringBuffer buffer = new StringBuffer(200);\r
-               buffer.append("Layer ");\r
-               buffer.append(layer_string());\r
-               buffer.append(" frame ");\r
-               buffer.append(mode_string());\r
-               buffer.append(' ');\r
-               buffer.append(version_string());\r
-               if (!checksums())\r
-                       buffer.append(" no");\r
-               buffer.append(" checksums");\r
-               buffer.append(' ');\r
-               buffer.append(sample_frequency_string());\r
-               buffer.append(',');\r
-               buffer.append(' ');\r
-               buffer.append(bitrate_string());\r
-\r
-               String s =  buffer.toString();\r
-               return s;\r
-       }\r
-\r
-       /**\r
-        * Read a 32-bit header from the bitstream.\r
-        */\r
-       void read_header(Bitstream stream, Crc16[] crcp) throws BitstreamException\r
-       {\r
-               int headerstring;\r
-               int channel_bitrate;\r
-               boolean sync = false;\r
-               do\r
-               {\r
-                       headerstring = stream.syncHeader(syncmode);\r
-                       _headerstring = headerstring; // E.B\r
-                       if (syncmode == Bitstream.INITIAL_SYNC)\r
-                       {\r
-                               h_version = ((headerstring >>> 19) & 1);\r
-                               if (((headerstring >>> 20) & 1) == 0) // SZD: MPEG2.5 detection\r
-                                       if (h_version == MPEG2_LSF)\r
-                                               h_version = MPEG25_LSF;\r
-                                       else\r
-                                               throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);\r
-                               if ((h_sample_frequency = ((headerstring >>> 10) & 3)) == 3)\r
-                               {\r
-                                       throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);\r
-                               }\r
-                       }\r
-                       h_layer = 4 - (headerstring >>> 17) & 3;\r
-                       h_protection_bit = (headerstring >>> 16) & 1;\r
-                       h_bitrate_index = (headerstring >>> 12) & 0xF;\r
-                       h_padding_bit = (headerstring >>> 9) & 1;\r
-                       h_mode = ((headerstring >>> 6) & 3);\r
-                       h_mode_extension = (headerstring >>> 4) & 3;\r
-                       if (h_mode == JOINT_STEREO)\r
-                               h_intensity_stereo_bound = (h_mode_extension << 2) + 4;\r
-                       else\r
-                               h_intensity_stereo_bound = 0; // should never be used\r
-                       if (((headerstring >>> 3) & 1) == 1)\r
-                               h_copyright = true;\r
-                       if (((headerstring >>> 2) & 1) == 1)\r
-                               h_original = true;\r
-                       // calculate number of subbands:\r
-                       if (h_layer == 1)\r
-                               h_number_of_subbands = 32;\r
-                       else\r
-                       {\r
-                               channel_bitrate = h_bitrate_index;\r
-                               // calculate bitrate per channel:\r
-                               if (h_mode != SINGLE_CHANNEL)\r
-                                       if (channel_bitrate == 4)\r
-                                               channel_bitrate = 1;\r
-                                       else\r
-                                               channel_bitrate -= 4;\r
-                               if ((channel_bitrate == 1) || (channel_bitrate == 2))\r
-                                       if (h_sample_frequency == THIRTYTWO)\r
-                                               h_number_of_subbands = 12;\r
-                                       else\r
-                                               h_number_of_subbands = 8;\r
-                               else if ((h_sample_frequency == FOURTYEIGHT) || ((channel_bitrate >= 3) && (channel_bitrate <= 5)))\r
-                                       h_number_of_subbands = 27;\r
-                               else\r
-                                       h_number_of_subbands = 30;\r
-                       }\r
-                       if (h_intensity_stereo_bound > h_number_of_subbands)\r
-                               h_intensity_stereo_bound = h_number_of_subbands;\r
-                       // calculate framesize and nSlots\r
-                       calculate_framesize();\r
-                       // read framedata:\r
-                       int framesizeloaded = stream.read_frame_data(framesize);\r
-                       if ((framesize >=0) && (framesizeloaded != framesize))\r
-                       {\r
-                               // Data loaded does not match to expected framesize,\r
-                               // it might be an ID3v1 TAG. (Fix 11/17/04).\r
-                               throw stream.newBitstreamException(Bitstream.INVALIDFRAME);\r
-                       }\r
-                       if (stream.isSyncCurrentPosition(syncmode))\r
-                       {\r
-                               if (syncmode == Bitstream.INITIAL_SYNC)\r
-                               {\r
-                                       syncmode = Bitstream.STRICT_SYNC;\r
-                                       stream.set_syncword(headerstring & 0xFFF80CC0);\r
-                               }\r
-                               sync = true;\r
-                       }\r
-                       else\r
-                       {\r
-                               stream.unreadFrame();\r
-                       }\r
-               }\r
-               while (!sync);\r
-               stream.parse_frame();\r
-               if (h_protection_bit == 0)\r
-               {\r
-                       // frame contains a crc checksum\r
-                       checksum = (short) stream.get_bits(16);\r
-                       if (crc == null)\r
-                               crc = new Crc16();\r
-                       crc.add_bits(headerstring, 16);\r
-                       crcp[0] = crc;\r
-               }\r
-               else\r
-                       crcp[0] = null;\r
-               if (h_sample_frequency == FOURTYFOUR_POINT_ONE)\r
-               {\r
-                       /*\r
-                               if (offset == null)\r
-                         {\r
-                                 int max = max_number_of_frames(stream);\r
-                                 offset = new int[max];\r
-                            for(int i=0; i<max; i++) offset[i] = 0;\r
-                         }\r
-                         // E.B : Investigate more\r
-                         int cf = stream.current_frame();\r
-                         int lf = stream.last_frame();\r
-                         if ((cf > 0) && (cf == lf))\r
-                         {\r
-                                  offset[cf] = offset[cf-1] + h_padding_bit;\r
-                         }\r
-                         else\r
-                         {\r
-                                      offset[0] = h_padding_bit;\r
-                         }\r
-                       */\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Parse frame to extract optionnal VBR frame.\r
-        * @param firstframe\r
-        * @author E.B (javalayer@javazoom.net)\r
-        */\r
-       void parseVBR(byte[] firstframe) throws BitstreamException\r
-       {\r
-               // Trying Xing header.\r
-               String xing = "Xing";\r
-               byte tmp[] = new byte[4];\r
-               int offset = 0;\r
-               // Compute "Xing" offset depending on MPEG version and channels.\r
-               if (h_version == MPEG1) \r
-               {\r
-                 if (h_mode == SINGLE_CHANNEL)  offset=21-4;\r
-                 else offset=36-4;\r
-               } \r
-               else \r
-               {\r
-                 if (h_mode == SINGLE_CHANNEL) offset=13-4;\r
-                 else offset = 21-4;             \r
-               }\r
-               try\r
-               {\r
-                       System.arraycopy(firstframe, offset, tmp, 0, 4);\r
-                       // Is "Xing" ?\r
-                       if (xing.equals(new String(tmp)))\r
-                       {\r
-                               //Yes.\r
-                               h_vbr = true;\r
-                               h_vbr_frames = -1;\r
-                               h_vbr_bytes = -1;\r
-                               h_vbr_scale = -1;\r
-                               h_vbr_toc = new byte[100];\r
-                                                               \r
-                               int length = 4;\r
-                               // Read flags.\r
-                               byte flags[] = new byte[4];\r
-                               System.arraycopy(firstframe, offset + length, flags, 0, flags.length);\r
-                               length += flags.length;\r
-                               // Read number of frames (if available).\r
-                               if ((flags[3] & (byte) (1 << 0)) != 0)\r
-                               {\r
-                                       System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
-                                       h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
-                                       length += 4;    \r
-                               }\r
-                               // Read size (if available).\r
-                               if ((flags[3] & (byte) (1 << 1)) != 0)\r
-                               {\r
-                                       System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
-                                       h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
-                                       length += 4;    \r
-                               }\r
-                               // Read TOC (if available).\r
-                               if ((flags[3] & (byte) (1 << 2)) != 0)\r
-                               {\r
-                                       System.arraycopy(firstframe, offset + length, h_vbr_toc, 0, h_vbr_toc.length);\r
-                                       length += h_vbr_toc.length;     \r
-                               }\r
-                               // Read scale (if available).\r
-                               if ((flags[3] & (byte) (1 << 3)) != 0)\r
-                               {\r
-                                       System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
-                                       h_vbr_scale = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
-                                       length += 4;    \r
-                               }\r
-                               //System.out.println("VBR:"+xing+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes);                       \r
-                       }                               \r
-               }\r
-               catch (ArrayIndexOutOfBoundsException e)\r
-               {\r
-                       throw new BitstreamException("XingVBRHeader Corrupted",e);\r
-               }\r
-               \r
-               // Trying VBRI header.                  \r
-               String vbri = "VBRI";\r
-               offset = 36-4;\r
-               try\r
-               {\r
-                       System.arraycopy(firstframe, offset, tmp, 0, 4);\r
-                       // Is "VBRI" ?\r
-                       if (vbri.equals(new String(tmp)))\r
-                       {\r
-                               //Yes.\r
-                               h_vbr = true;\r
-                               h_vbr_frames = -1;\r
-                               h_vbr_bytes = -1;\r
-                               h_vbr_scale = -1;\r
-                               h_vbr_toc = new byte[100];\r
-                               // Bytes.                               \r
-                               int length = 4 + 6;\r
-                               System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
-                               h_vbr_bytes = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
-                               length += 4;    \r
-                               // Frames.      \r
-                               System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
-                               h_vbr_frames = (tmp[0] << 24)&0xFF000000 | (tmp[1] << 16)&0x00FF0000 | (tmp[2] << 8)&0x0000FF00 | tmp[3]&0x000000FF;\r
-                               length += 4;    \r
-                               //System.out.println("VBR:"+vbri+" Frames:"+ h_vbr_frames +" Size:"+h_vbr_bytes);\r
-                               // TOC\r
-                               // TODO                         \r
-                       }\r
-               }\r
-               catch (ArrayIndexOutOfBoundsException e)\r
-               {\r
-                       throw new BitstreamException("VBRIVBRHeader Corrupted",e);\r
-               }\r
-       }\r
-       \r
-       // Functions to query header contents:\r
-       /**\r
-        * Returns version.\r
-        */\r
-     @RETURNLOC("OUT")\r
-       public int version() { return h_version; }\r
-\r
-       /**\r
-        * Returns Layer ID.\r
-        */\r
-       @RETURNLOC("OUT")\r
-       public int layer() { return h_layer; }\r
-\r
-       /**\r
-        * Returns bitrate index.\r
-        */\r
-       @RETURNLOC("OUT")\r
-       public int bitrate_index() { return h_bitrate_index; }\r
-\r
-       /**\r
-        * Returns Sample Frequency.\r
-        */\r
-       public int sample_frequency() { return h_sample_frequency; }\r
-\r
-       /**\r
-        * Returns Frequency.\r
-        */\r
-       public int frequency() {return frequencies[h_version][h_sample_frequency];}\r
-\r
-       /**\r
-        * Returns Mode.\r
-        */\r
-       @RETURNLOC("OUT")\r
-       public int mode() { return h_mode; }\r
-\r
-       /**\r
-        * Returns Protection bit.\r
-        */\r
-       public boolean checksums()\r
-       {\r
-               if (h_protection_bit == 0) return true;\r
-         else return false;\r
-       }\r
-\r
-       /**\r
-        * Returns Copyright.\r
-        */\r
-       public boolean copyright() { return h_copyright; }\r
-\r
-       /**\r
-        * Returns Original.\r
-        */\r
-       public boolean original() { return h_original; }\r
-\r
-       /**\r
-        * Return VBR.\r
-        * @return true if VBR header is found\r
-        */\r
-       public boolean vbr() { return h_vbr; }\r
-\r
-       /**\r
-        * Return VBR scale.\r
-        * @return scale of -1 if not available\r
-        */\r
-       public int vbr_scale() { return h_vbr_scale; }\r
-\r
-       /**\r
-        * Return VBR TOC.\r
-        * @return vbr toc ot null if not available\r
-        */\r
-       public byte[] vbr_toc() { return h_vbr_toc; }\r
-\r
-       /**\r
-        * Returns Checksum flag.\r
-        * Compares computed checksum with stream checksum.\r
-        */\r
-       @RETURNLOC("OUT")\r
-       public boolean checksum_ok () { return (checksum == crc.checksum()); }\r
-\r
-       // Seeking and layer III stuff\r
-       /**\r
-        * Returns Layer III Padding bit.\r
-        */\r
-       public boolean padding()\r
-       {\r
-               if (h_padding_bit == 0) return false;\r
-         else return true;\r
-       }\r
-\r
-       /**\r
-        * Returns Slots.\r
-        */\r
-       @RETURNLOC("OUT")\r
-       public int slots() { return nSlots; }\r
-\r
-       /**\r
-        * Returns Mode Extension.\r
-        */\r
-       @RETURNLOC("OUT")\r
-       public int mode_extension() { return h_mode_extension; }\r
-\r
-       // E.B -> private to public\r
-    @LOC("T") public static final int bitrates[][][] = {\r
-               {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,\r
-         112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0},\r
-               {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,\r
-         56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},\r
-               {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,\r
-         56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},\r
-\r
-               {{0 /*free format*/, 32000, 64000, 96000, 128000, 160000, 192000,\r
-          224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0},\r
-         {0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,\r
-          112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0},\r
-         {0 /*free format*/, 32000, 40000, 48000, 56000, 64000, 80000,\r
-          96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}},\r
-               // SZD: MPEG2.5\r
-               {{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,\r
-         112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0},\r
-               {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,\r
-         56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},\r
-               {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,\r
-         56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},\r
-\r
-               };\r
-\r
-       // E.B -> private to public\r
-       /**\r
-        * Calculate Frame size.\r
-        * Calculates framesize in bytes excluding header size.\r
-        */\r
-       public int calculate_framesize()\r
-       {\r
-\r
-        if (h_layer == 1)\r
-        {\r
-          framesize = (12 * bitrates[h_version][0][h_bitrate_index]) /\r
-                      frequencies[h_version][h_sample_frequency];\r
-          if (h_padding_bit != 0 ) framesize++;\r
-          framesize <<= 2;             // one slot is 4 bytes long\r
-          nSlots = 0;\r
-        }\r
-        else\r
-        {\r
-          framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index]) /\r
-                      frequencies[h_version][h_sample_frequency];\r
-          if (h_version == MPEG2_LSF || h_version == MPEG25_LSF) framesize >>= 1;      // SZD\r
-          if (h_padding_bit != 0) framesize++;\r
-          // Layer III slots\r
-          if (h_layer == 3)\r
-          {\r
-            if (h_version == MPEG1)\r
-            {\r
-                        nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 17 : 32) // side info size\r
-                                                                         -  ((h_protection_bit!=0) ? 0 : 2)                   // CRC size\r
-                                                                         - 4;                                                                       // header size\r
-            }\r
-            else\r
-                {  // MPEG-2 LSF, SZD: MPEG-2.5 LSF\r
-               nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ?  9 : 17) // side info size\r
-                                                                 -  ((h_protection_bit!=0) ? 0 : 2)                   // CRC size\r
-                                                                         - 4;                                                                       // header size\r
-            }\r
-          }\r
-          else\r
-          {\r
-                nSlots = 0;\r
-          }\r
-        }\r
-        framesize -= 4;             // subtract header size\r
-        return framesize;\r
-       }\r
-\r
-       /**\r
-        * Returns the maximum number of frames in the stream.\r
-        * @param streamsize\r
-        * @return number of frames\r
-        */\r
-       public int max_number_of_frames(int streamsize)  // E.B\r
-       {\r
-               if (h_vbr == true) return h_vbr_frames;\r
-               else\r
-               {\r
-                       if ((framesize + 4 - h_padding_bit) == 0) return 0;\r
-                       else return(streamsize / (framesize + 4 - h_padding_bit));\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Returns the maximum number of frames in the stream.\r
-        * @param streamsize\r
-        * @return number of frames\r
-        */\r
-       public int min_number_of_frames(int streamsize) // E.B\r
-       {\r
-               if (h_vbr == true) return h_vbr_frames;\r
-               else\r
-               {\r
-                       if ((framesize + 5 - h_padding_bit) == 0) return 0;\r
-                       else return(streamsize / (framesize + 5 - h_padding_bit));\r
-               }\r
-       }\r
-\r
-\r
-       /**\r
-        * Returns ms/frame.\r
-        * @return milliseconds per frame\r
-        */\r
-       public float ms_per_frame() // E.B\r
-       {\r
-               if (h_vbr == true)\r
-               {                       \r
-                       double tpf = h_vbr_time_per_frame[layer()] / frequency();\r
-                       if ((h_version == MPEG2_LSF) || (h_version == MPEG25_LSF)) tpf /= 2;\r
-                       return ((float) (tpf * 1000));\r
-               }\r
-               else\r
-               {\r
-                       float ms_per_frame_array[][] = {{8.707483f,  8.0f, 12.0f},\r
-                                                                                       {26.12245f, 24.0f, 36.0f},\r
-                                                                                       {26.12245f, 24.0f, 36.0f}};\r
-                       return(ms_per_frame_array[h_layer-1][h_sample_frequency]);\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Returns total ms.\r
-        * @param streamsize\r
-        * @return total milliseconds\r
-        */\r
-       public float total_ms(int streamsize) // E.B\r
-       {\r
-               return(max_number_of_frames(streamsize) * ms_per_frame());\r
-       }\r
-\r
-       /**\r
-        * Returns synchronized header.\r
-        */\r
-       public int getSyncHeader() // E.B\r
-       {\r
-               return _headerstring;\r
-       }\r
-\r
-       // functions which return header informations as strings:\r
-       /**\r
-        * Return Layer version.\r
-        */\r
-       public String layer_string()\r
-       {\r
-               switch (h_layer)\r
-               {\r
-          case 1:\r
-               return "I";\r
-          case 2:\r
-               return "II";\r
-          case 3:\r
-               return "III";\r
-               }\r
-         return null;\r
-       }\r
-\r
-       // E.B -> private to public\r
-    @LOC("T") public static final String bitrate_str[][][] = {\r
-               {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",\r
-         "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",\r
-         "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",\r
-         "forbidden"},\r
-         {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",\r
-         "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
-         "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",\r
-         "forbidden"},\r
-         {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",\r
-         "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
-         "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",\r
-         "forbidden"}},\r
-\r
-         {{"free format", "32 kbit/s", "64 kbit/s", "96 kbit/s", "128 kbit/s",\r
-         "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "288 kbit/s",\r
-         "320 kbit/s", "352 kbit/s", "384 kbit/s", "416 kbit/s", "448 kbit/s",\r
-         "forbidden"},\r
-         {"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",\r
-         "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s",\r
-         "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s", "384 kbit/s",\r
-         "forbidden"},\r
-         {"free format", "32 kbit/s", "40 kbit/s", "48 kbit/s", "56 kbit/s",\r
-         "64 kbit/s", "80 kbit/s" , "96 kbit/s", "112 kbit/s", "128 kbit/s",\r
-         "160 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s", "320 kbit/s",\r
-         "forbidden"}},\r
-               // SZD: MPEG2.5\r
-               {{"free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",\r
-         "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s",\r
-         "160 kbit/s", "176 kbit/s", "192 kbit/s", "224 kbit/s", "256 kbit/s",\r
-         "forbidden"},\r
-         {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",\r
-         "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
-         "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",\r
-         "forbidden"},\r
-         {"free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s",\r
-         "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
-         "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s",\r
-         "forbidden"}},\r
-         };\r
-\r
-       /**\r
-        * Return Bitrate.\r
-        * @return bitrate in bps\r
-        */\r
-       public String bitrate_string()\r
-       {\r
-               if (h_vbr == true)\r
-               {\r
-                       return Integer.toString(bitrate()/1000)+" kb/s";                \r
-               }\r
-         else return bitrate_str[h_version][h_layer - 1][h_bitrate_index];\r
-       }\r
-\r
-       /**\r
-        * Return Bitrate.\r
-        * @return bitrate in bps and average bitrate for VBR header\r
-        */\r
-       public int bitrate()\r
-       {\r
-               if (h_vbr == true)\r
-               {\r
-                       return ((int) ((h_vbr_bytes * 8) / (ms_per_frame() * h_vbr_frames)))*1000;              \r
-               }\r
-               else return bitrates[h_version][h_layer - 1][h_bitrate_index];\r
-       }\r
-\r
-       /**\r
-        * Return Instant Bitrate.\r
-        * Bitrate for VBR is not constant.\r
-        * @return bitrate in bps\r
-        */\r
-       public int bitrate_instant()\r
-       {\r
-               return bitrates[h_version][h_layer - 1][h_bitrate_index];\r
-       }\r
-\r
-       /**\r
-        * Returns Frequency\r
-        * @return frequency string in kHz\r
-        */\r
-       public String sample_frequency_string()\r
-       {\r
-               switch (h_sample_frequency)\r
-               {\r
-           case THIRTYTWO:\r
-               if (h_version == MPEG1)\r
-                       return "32 kHz";\r
-               else if (h_version == MPEG2_LSF)\r
-               return "16 kHz";\r
-           else        // SZD\r
-               return "8 kHz";\r
-           case FOURTYFOUR_POINT_ONE:\r
-               if (h_version == MPEG1)\r
-                       return "44.1 kHz";\r
-               else if (h_version == MPEG2_LSF)\r
-               return "22.05 kHz";\r
-               else    // SZD\r
-               return "11.025 kHz";\r
-           case FOURTYEIGHT:\r
-               if (h_version == MPEG1)\r
-                       return "48 kHz";\r
-               else if (h_version == MPEG2_LSF)\r
-               return "24 kHz";\r
-               else    // SZD\r
-                       return "12 kHz";\r
-         }\r
-         return(null);\r
-       }\r
-\r
-       /**\r
-        * Returns Mode.\r
-        */\r
-       public String mode_string()\r
-       {\r
-          switch (h_mode)\r
-          {\r
-            case STEREO:\r
-               return "Stereo";\r
-            case JOINT_STEREO:\r
-               return "Joint stereo";\r
-            case DUAL_CHANNEL:\r
-               return "Dual channel";\r
-            case SINGLE_CHANNEL:\r
-               return "Single channel";\r
-          }\r
-          return null;\r
-       }\r
-\r
-       /**\r
-        * Returns Version.\r
-        * @return MPEG-1 or MPEG-2 LSF or MPEG-2.5 LSF\r
-        */\r
-       public String version_string()\r
-       {\r
-         switch (h_version)\r
-         {\r
-           case MPEG1:\r
-             return "MPEG-1";\r
-           case MPEG2_LSF:\r
-             return "MPEG-2 LSF";\r
-           case MPEG25_LSF:    // SZD\r
-             return "MPEG-2.5 LSF";\r
-         }\r
-         return(null);\r
-       }\r
-\r
-       /**\r
-        * Returns the number of subbands in the current frame.\r
-        * @return number of subbands\r
-        */\r
-       @RETURNLOC("OUT")\r
-       public int number_of_subbands() {return h_number_of_subbands;}\r
-\r
-       /**\r
-        * Returns Intensity Stereo.\r
-        * (Layer II joint stereo only).\r
-        * Returns the number of subbands which are in stereo mode,\r
-        * subbands above that limit are in intensity stereo mode.\r
-        * @return intensity\r
-        */\r
-       @RETURNLOC("OUT")\r
-       public int intensity_stereo_bound() {return h_intensity_stereo_bound;}\r
+public final class Header {\r
+\r
+  public static final int[][] frequencies = { { 22050, 24000, 16000, 1 },\r
+      { 44100, 48000, 32000, 1 }, { 11025, 12000, 8000, 1 } }; // SZD: MPEG25\r
+\r
+  /**\r
+   * Constant for MPEG-2 LSF version\r
+   */\r
+  public static final int MPEG2_LSF = 0;\r
+  public static final int MPEG25_LSF = 2; // SZD\r
+\r
+  /**\r
+   * Constant for MPEG-1 version\r
+   */\r
+  public static final int MPEG1 = 1;\r
+\r
+  public static final int STEREO = 0;\r
+  public static final int JOINT_STEREO = 1;\r
+  public static final int DUAL_CHANNEL = 2;\r
+  public static final int SINGLE_CHANNEL = 3;\r
+  public static final int FOURTYFOUR_POINT_ONE = 0;\r
+  public static final int FOURTYEIGHT = 1;\r
+  public static final int THIRTYTWO = 2;\r
+\r
+  @LOC("H")\r
+  private int h_layer;\r
+  @LOC("H")\r
+  private int h_protection_bit;\r
+  @LOC("H")\r
+  private int h_bitrate_index;\r
+  @LOC("H")\r
+  private int h_padding_bit;\r
+  @LOC("H")\r
+  private int h_mode_extension;\r
+  @LOC("HV")\r
+  private int h_version;\r
+  @LOC("H")\r
+  private int h_mode;\r
+  @LOC("H")\r
+  private int h_sample_frequency;\r
+  @LOC("HNS")\r
+  private int h_number_of_subbands;\r
+  @LOC("HI")\r
+  private int h_intensity_stereo_bound;\r
+  @LOC("H")\r
+  private boolean h_copyright;\r
+  @LOC("H")\r
+  private boolean h_original;\r
+  // VBR support added by E.B\r
+  @LOC("T")\r
+  private double[] h_vbr_time_per_frame = { -1.0, 384.0, 1152.0, 1152.0 };\r
+  @LOC("T")\r
+  private boolean h_vbr;\r
+  @LOC("T")\r
+  private int h_vbr_frames;\r
+  @LOC("T")\r
+  private int h_vbr_scale;\r
+  @LOC("T")\r
+  private int h_vbr_bytes;\r
+  @LOC("T")\r
+  private byte[] h_vbr_toc;\r
+\r
+  @LOC("SYNC")\r
+  private byte syncmode = Bitstream.INITIAL_SYNC;\r
+  @LOC("C")\r
+  private Crc16 crc;\r
+\r
+  @LOC("C")\r
+  public short checksum;\r
+  @LOC("FS")\r
+  public int framesize;\r
+  @LOC("NS")\r
+  public int nSlots;\r
+\r
+  @LOC("T")\r
+  private int _headerstring = -1; // E.B\r
+\r
+  Header() {\r
+  }\r
+\r
+  public String toString() {\r
+    StringBuffer buffer = new StringBuffer(200);\r
+    buffer.append("Layer ");\r
+    buffer.append(layer_string());\r
+    buffer.append(" frame ");\r
+    buffer.append(mode_string());\r
+    buffer.append(' ');\r
+    buffer.append(version_string());\r
+    if (!checksums())\r
+      buffer.append(" no");\r
+    buffer.append(" checksums");\r
+    buffer.append(' ');\r
+    buffer.append(sample_frequency_string());\r
+    buffer.append(',');\r
+    buffer.append(' ');\r
+    buffer.append(bitrate_string());\r
+\r
+    String s = buffer.toString();\r
+    return s;\r
+  }\r
+\r
+  /**\r
+   * Read a 32-bit header from the bitstream.\r
+   */\r
+  void read_header(Bitstream stream, Crc16[] crcp) throws BitstreamException {\r
+    int headerstring;\r
+    int channel_bitrate;\r
+    boolean sync = false;\r
+    do {\r
+      headerstring = stream.syncHeader(syncmode);\r
+      _headerstring = headerstring; // E.B\r
+      if (syncmode == Bitstream.INITIAL_SYNC) {\r
+        h_version = ((headerstring >>> 19) & 1);\r
+        if (((headerstring >>> 20) & 1) == 0) // SZD: MPEG2.5 detection\r
+          if (h_version == MPEG2_LSF)\r
+            h_version = MPEG25_LSF;\r
+          else\r
+            throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);\r
+        if ((h_sample_frequency = ((headerstring >>> 10) & 3)) == 3) {\r
+          throw stream.newBitstreamException(Bitstream.UNKNOWN_ERROR);\r
+        }\r
+      }\r
+      h_layer = 4 - (headerstring >>> 17) & 3;\r
+      h_protection_bit = (headerstring >>> 16) & 1;\r
+      h_bitrate_index = (headerstring >>> 12) & 0xF;\r
+      h_padding_bit = (headerstring >>> 9) & 1;\r
+      h_mode = ((headerstring >>> 6) & 3);\r
+      h_mode_extension = (headerstring >>> 4) & 3;\r
+      if (h_mode == JOINT_STEREO)\r
+        h_intensity_stereo_bound = (h_mode_extension << 2) + 4;\r
+      else\r
+        h_intensity_stereo_bound = 0; // should never be used\r
+      if (((headerstring >>> 3) & 1) == 1)\r
+        h_copyright = true;\r
+      if (((headerstring >>> 2) & 1) == 1)\r
+        h_original = true;\r
+      // calculate number of subbands:\r
+      if (h_layer == 1)\r
+        h_number_of_subbands = 32;\r
+      else {\r
+        channel_bitrate = h_bitrate_index;\r
+        // calculate bitrate per channel:\r
+        if (h_mode != SINGLE_CHANNEL)\r
+          if (channel_bitrate == 4)\r
+            channel_bitrate = 1;\r
+          else\r
+            channel_bitrate -= 4;\r
+        if ((channel_bitrate == 1) || (channel_bitrate == 2))\r
+          if (h_sample_frequency == THIRTYTWO)\r
+            h_number_of_subbands = 12;\r
+          else\r
+            h_number_of_subbands = 8;\r
+        else if ((h_sample_frequency == FOURTYEIGHT)\r
+            || ((channel_bitrate >= 3) && (channel_bitrate <= 5)))\r
+          h_number_of_subbands = 27;\r
+        else\r
+          h_number_of_subbands = 30;\r
+      }\r
+      if (h_intensity_stereo_bound > h_number_of_subbands)\r
+        h_intensity_stereo_bound = h_number_of_subbands;\r
+      // calculate framesize and nSlots\r
+      calculate_framesize();\r
+      // read framedata:\r
+      int framesizeloaded = stream.read_frame_data(framesize);\r
+      if ((framesize >= 0) && (framesizeloaded != framesize)) {\r
+        // Data loaded does not match to expected framesize,\r
+        // it might be an ID3v1 TAG. (Fix 11/17/04).\r
+        throw stream.newBitstreamException(Bitstream.INVALIDFRAME);\r
+      }\r
+      if (stream.isSyncCurrentPosition(syncmode)) {\r
+        if (syncmode == Bitstream.INITIAL_SYNC) {\r
+          syncmode = Bitstream.STRICT_SYNC;\r
+          stream.set_syncword(headerstring & 0xFFF80CC0);\r
+        }\r
+        sync = true;\r
+      } else {\r
+        stream.unreadFrame();\r
+      }\r
+    } while (!sync);\r
+    stream.parse_frame();\r
+    if (h_protection_bit == 0) {\r
+      // frame contains a crc checksum\r
+      checksum = (short) stream.get_bits(16);\r
+      if (crc == null)\r
+        crc = new Crc16();\r
+      crc.add_bits(headerstring, 16);\r
+      crcp[0] = crc;\r
+    } else\r
+      crcp[0] = null;\r
+    if (h_sample_frequency == FOURTYFOUR_POINT_ONE) {\r
+      /*\r
+       * if (offset == null) { int max = max_number_of_frames(stream); offset =\r
+       * new int[max]; for(int i=0; i<max; i++) offset[i] = 0; } // E.B :\r
+       * Investigate more int cf = stream.current_frame(); int lf =\r
+       * stream.last_frame(); if ((cf > 0) && (cf == lf)) { offset[cf] =\r
+       * offset[cf-1] + h_padding_bit; } else { offset[0] = h_padding_bit; }\r
+       */\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Parse frame to extract optionnal VBR frame.\r
+   * \r
+   * @param firstframe\r
+   * @author E.B (javalayer@javazoom.net)\r
+   */\r
+  void parseVBR(byte[] firstframe) throws BitstreamException {\r
+    // Trying Xing header.\r
+    String xing = "Xing";\r
+    byte tmp[] = new byte[4];\r
+    int offset = 0;\r
+    // Compute "Xing" offset depending on MPEG version and channels.\r
+    if (h_version == MPEG1) {\r
+      if (h_mode == SINGLE_CHANNEL)\r
+        offset = 21 - 4;\r
+      else\r
+        offset = 36 - 4;\r
+    } else {\r
+      if (h_mode == SINGLE_CHANNEL)\r
+        offset = 13 - 4;\r
+      else\r
+        offset = 21 - 4;\r
+    }\r
+    try {\r
+      System.arraycopy(firstframe, offset, tmp, 0, 4);\r
+      // Is "Xing" ?\r
+      if (xing.equals(new String(tmp))) {\r
+        // Yes.\r
+        h_vbr = true;\r
+        h_vbr_frames = -1;\r
+        h_vbr_bytes = -1;\r
+        h_vbr_scale = -1;\r
+        h_vbr_toc = new byte[100];\r
+\r
+        int length = 4;\r
+        // Read flags.\r
+        byte flags[] = new byte[4];\r
+        System.arraycopy(firstframe, offset + length, flags, 0, flags.length);\r
+        length += flags.length;\r
+        // Read number of frames (if available).\r
+        if ((flags[3] & (byte) (1 << 0)) != 0) {\r
+          System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+          h_vbr_frames =\r
+              (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8)\r
+                  & 0x0000FF00 | tmp[3] & 0x000000FF;\r
+          length += 4;\r
+        }\r
+        // Read size (if available).\r
+        if ((flags[3] & (byte) (1 << 1)) != 0) {\r
+          System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+          h_vbr_bytes =\r
+              (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8)\r
+                  & 0x0000FF00 | tmp[3] & 0x000000FF;\r
+          length += 4;\r
+        }\r
+        // Read TOC (if available).\r
+        if ((flags[3] & (byte) (1 << 2)) != 0) {\r
+          System.arraycopy(firstframe, offset + length, h_vbr_toc, 0, h_vbr_toc.length);\r
+          length += h_vbr_toc.length;\r
+        }\r
+        // Read scale (if available).\r
+        if ((flags[3] & (byte) (1 << 3)) != 0) {\r
+          System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+          h_vbr_scale =\r
+              (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8)\r
+                  & 0x0000FF00 | tmp[3] & 0x000000FF;\r
+          length += 4;\r
+        }\r
+        // System.out.println("VBR:"+xing+" Frames:"+ h_vbr_frames\r
+        // +" Size:"+h_vbr_bytes);\r
+      }\r
+    } catch (ArrayIndexOutOfBoundsException e) {\r
+      throw new BitstreamException("XingVBRHeader Corrupted", e);\r
+    }\r
+\r
+    // Trying VBRI header.\r
+    String vbri = "VBRI";\r
+    offset = 36 - 4;\r
+    try {\r
+      System.arraycopy(firstframe, offset, tmp, 0, 4);\r
+      // Is "VBRI" ?\r
+      if (vbri.equals(new String(tmp))) {\r
+        // Yes.\r
+        h_vbr = true;\r
+        h_vbr_frames = -1;\r
+        h_vbr_bytes = -1;\r
+        h_vbr_scale = -1;\r
+        h_vbr_toc = new byte[100];\r
+        // Bytes.\r
+        int length = 4 + 6;\r
+        System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+        h_vbr_bytes =\r
+            (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8) & 0x0000FF00\r
+                | tmp[3] & 0x000000FF;\r
+        length += 4;\r
+        // Frames.\r
+        System.arraycopy(firstframe, offset + length, tmp, 0, tmp.length);\r
+        h_vbr_frames =\r
+            (tmp[0] << 24) & 0xFF000000 | (tmp[1] << 16) & 0x00FF0000 | (tmp[2] << 8) & 0x0000FF00\r
+                | tmp[3] & 0x000000FF;\r
+        length += 4;\r
+        // System.out.println("VBR:"+vbri+" Frames:"+ h_vbr_frames\r
+        // +" Size:"+h_vbr_bytes);\r
+        // TOC\r
+        // TODO\r
+      }\r
+    } catch (ArrayIndexOutOfBoundsException e) {\r
+      throw new BitstreamException("VBRIVBRHeader Corrupted", e);\r
+    }\r
+  }\r
+\r
+  // Functions to query header contents:\r
+  /**\r
+   * Returns version.\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public int version() {\r
+    return h_version;\r
+  }\r
+\r
+  /**\r
+   * Returns Layer ID.\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public int layer() {\r
+    return h_layer;\r
+  }\r
+\r
+  /**\r
+   * Returns bitrate index.\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public int bitrate_index() {\r
+    return h_bitrate_index;\r
+  }\r
+\r
+  /**\r
+   * Returns Sample Frequency.\r
+   */\r
+  public int sample_frequency() {\r
+    return h_sample_frequency;\r
+  }\r
+\r
+  /**\r
+   * Returns Frequency.\r
+   */\r
+  public int frequency() {\r
+    return frequencies[h_version][h_sample_frequency];\r
+  }\r
+\r
+  /**\r
+   * Returns Mode.\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public int mode() {\r
+    return h_mode;\r
+  }\r
+\r
+  /**\r
+   * Returns Protection bit.\r
+   */\r
+  public boolean checksums() {\r
+    if (h_protection_bit == 0)\r
+      return true;\r
+    else\r
+      return false;\r
+  }\r
+\r
+  /**\r
+   * Returns Copyright.\r
+   */\r
+  public boolean copyright() {\r
+    return h_copyright;\r
+  }\r
+\r
+  /**\r
+   * Returns Original.\r
+   */\r
+  public boolean original() {\r
+    return h_original;\r
+  }\r
+\r
+  /**\r
+   * Return VBR.\r
+   * \r
+   * @return true if VBR header is found\r
+   */\r
+  public boolean vbr() {\r
+    return h_vbr;\r
+  }\r
+\r
+  /**\r
+   * Return VBR scale.\r
+   * \r
+   * @return scale of -1 if not available\r
+   */\r
+  public int vbr_scale() {\r
+    return h_vbr_scale;\r
+  }\r
+\r
+  /**\r
+   * Return VBR TOC.\r
+   * \r
+   * @return vbr toc ot null if not available\r
+   */\r
+  public byte[] vbr_toc() {\r
+    return h_vbr_toc;\r
+  }\r
+\r
+  /**\r
+   * Returns Checksum flag. Compares computed checksum with stream checksum.\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public boolean checksum_ok() {\r
+    return (checksum == crc.checksum());\r
+  }\r
+\r
+  // Seeking and layer III stuff\r
+  /**\r
+   * Returns Layer III Padding bit.\r
+   */\r
+  public boolean padding() {\r
+    if (h_padding_bit == 0)\r
+      return false;\r
+    else\r
+      return true;\r
+  }\r
+\r
+  /**\r
+   * Returns Slots.\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public int slots() {\r
+    return nSlots;\r
+  }\r
+\r
+  /**\r
+   * Returns Mode Extension.\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public int mode_extension() {\r
+    return h_mode_extension;\r
+  }\r
+\r
+  // E.B -> private to public\r
+  @LOC("T")\r
+  public static final int bitrates[][][] = {\r
+      {\r
+          { 0 /* free format */, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000,\r
+              160000, 176000, 192000, 224000, 256000, 0 },\r
+          { 0 /* free format */, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000,\r
+              96000, 112000, 128000, 144000, 160000, 0 },\r
+          { 0 /* free format */, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000,\r
+              96000, 112000, 128000, 144000, 160000, 0 } },\r
+\r
+      {\r
+          { 0 /* free format */, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000,\r
+              288000, 320000, 352000, 384000, 416000, 448000, 0 },\r
+          { 0 /* free format */, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000,\r
+              192000, 224000, 256000, 320000, 384000, 0 },\r
+          { 0 /* free format */, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000,\r
+              160000, 192000, 224000, 256000, 320000, 0 } },\r
+      // SZD: MPEG2.5\r
+      {\r
+          { 0 /* free format */, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000,\r
+              160000, 176000, 192000, 224000, 256000, 0 },\r
+          { 0 /* free format */, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000,\r
+              96000, 112000, 128000, 144000, 160000, 0 },\r
+          { 0 /* free format */, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000,\r
+              96000, 112000, 128000, 144000, 160000, 0 } },\r
+\r
+  };\r
+\r
+  // E.B -> private to public\r
+  /**\r
+   * Calculate Frame size. Calculates framesize in bytes excluding header size.\r
+   */\r
+  public int calculate_framesize() {\r
+\r
+    if (h_layer == 1) {\r
+      framesize =\r
+          (12 * bitrates[h_version][0][h_bitrate_index])\r
+              / frequencies[h_version][h_sample_frequency];\r
+      if (h_padding_bit != 0)\r
+        framesize++;\r
+      framesize <<= 2; // one slot is 4 bytes long\r
+      nSlots = 0;\r
+    } else {\r
+      framesize =\r
+          (144 * bitrates[h_version][h_layer - 1][h_bitrate_index])\r
+              / frequencies[h_version][h_sample_frequency];\r
+      if (h_version == MPEG2_LSF || h_version == MPEG25_LSF)\r
+        framesize >>= 1; // SZD\r
+      if (h_padding_bit != 0)\r
+        framesize++;\r
+      // Layer III slots\r
+      if (h_layer == 3) {\r
+        if (h_version == MPEG1) {\r
+          nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 17 : 32) // side\r
+                                                                      // info\r
+                                                                      // size\r
+              - ((h_protection_bit != 0) ? 0 : 2) // CRC size\r
+              - 4; // header size\r
+        } else { // MPEG-2 LSF, SZD: MPEG-2.5 LSF\r
+          nSlots = framesize - ((h_mode == SINGLE_CHANNEL) ? 9 : 17) // side\r
+                                                                     // info\r
+                                                                     // size\r
+              - ((h_protection_bit != 0) ? 0 : 2) // CRC size\r
+              - 4; // header size\r
+        }\r
+      } else {\r
+        nSlots = 0;\r
+      }\r
+    }\r
+    framesize -= 4; // subtract header size\r
+    return framesize;\r
+  }\r
+\r
+  /**\r
+   * Returns the maximum number of frames in the stream.\r
+   * \r
+   * @param streamsize\r
+   * @return number of frames\r
+   */\r
+  public int max_number_of_frames(int streamsize) // E.B\r
+  {\r
+    if (h_vbr == true)\r
+      return h_vbr_frames;\r
+    else {\r
+      if ((framesize + 4 - h_padding_bit) == 0)\r
+        return 0;\r
+      else\r
+        return (streamsize / (framesize + 4 - h_padding_bit));\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns the maximum number of frames in the stream.\r
+   * \r
+   * @param streamsize\r
+   * @return number of frames\r
+   */\r
+  public int min_number_of_frames(int streamsize) // E.B\r
+  {\r
+    if (h_vbr == true)\r
+      return h_vbr_frames;\r
+    else {\r
+      if ((framesize + 5 - h_padding_bit) == 0)\r
+        return 0;\r
+      else\r
+        return (streamsize / (framesize + 5 - h_padding_bit));\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns ms/frame.\r
+   * \r
+   * @return milliseconds per frame\r
+   */\r
+  public float ms_per_frame() // E.B\r
+  {\r
+    if (h_vbr == true) {\r
+      double tpf = h_vbr_time_per_frame[layer()] / frequency();\r
+      if ((h_version == MPEG2_LSF) || (h_version == MPEG25_LSF))\r
+        tpf /= 2;\r
+      return ((float) (tpf * 1000));\r
+    } else {\r
+      float ms_per_frame_array[][] =\r
+          { { 8.707483f, 8.0f, 12.0f }, { 26.12245f, 24.0f, 36.0f }, { 26.12245f, 24.0f, 36.0f } };\r
+      return (ms_per_frame_array[h_layer - 1][h_sample_frequency]);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns total ms.\r
+   * \r
+   * @param streamsize\r
+   * @return total milliseconds\r
+   */\r
+  public float total_ms(int streamsize) // E.B\r
+  {\r
+    return (max_number_of_frames(streamsize) * ms_per_frame());\r
+  }\r
+\r
+  /**\r
+   * Returns synchronized header.\r
+   */\r
+  public int getSyncHeader() // E.B\r
+  {\r
+    return _headerstring;\r
+  }\r
+\r
+  // functions which return header informations as strings:\r
+  /**\r
+   * Return Layer version.\r
+   */\r
+  public String layer_string() {\r
+    switch (h_layer) {\r
+    case 1:\r
+      return "I";\r
+    case 2:\r
+      return "II";\r
+    case 3:\r
+      return "III";\r
+    }\r
+    return null;\r
+  }\r
+\r
+  // E.B -> private to public\r
+  @LOC("T")\r
+  public static final String bitrate_str[][][] = {\r
+      {\r
+          { "free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
+              "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", "176 kbit/s",\r
+              "192 kbit/s", "224 kbit/s", "256 kbit/s", "forbidden" },\r
+          { "free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", "40 kbit/s",\r
+              "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", "96 kbit/s", "112 kbit/s",\r
+              "128 kbit/s", "144 kbit/s", "160 kbit/s", "forbidden" },\r
+          { "free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", "40 kbit/s",\r
+              "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", "96 kbit/s", "112 kbit/s",\r
+              "128 kbit/s", "144 kbit/s", "160 kbit/s", "forbidden" } },\r
+\r
+      {\r
+          { "free format", "32 kbit/s", "64 kbit/s", "96 kbit/s", "128 kbit/s", "160 kbit/s",\r
+              "192 kbit/s", "224 kbit/s", "256 kbit/s", "288 kbit/s", "320 kbit/s", "352 kbit/s",\r
+              "384 kbit/s", "416 kbit/s", "448 kbit/s", "forbidden" },\r
+          { "free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
+              "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s", "192 kbit/s", "224 kbit/s",\r
+              "256 kbit/s", "320 kbit/s", "384 kbit/s", "forbidden" },\r
+          { "free format", "32 kbit/s", "40 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s",\r
+              "80 kbit/s", "96 kbit/s", "112 kbit/s", "128 kbit/s", "160 kbit/s", "192 kbit/s",\r
+              "224 kbit/s", "256 kbit/s", "320 kbit/s", "forbidden" } },\r
+      // SZD: MPEG2.5\r
+      {\r
+          { "free format", "32 kbit/s", "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s",\r
+              "96 kbit/s", "112 kbit/s", "128 kbit/s", "144 kbit/s", "160 kbit/s", "176 kbit/s",\r
+              "192 kbit/s", "224 kbit/s", "256 kbit/s", "forbidden" },\r
+          { "free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", "40 kbit/s",\r
+              "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", "96 kbit/s", "112 kbit/s",\r
+              "128 kbit/s", "144 kbit/s", "160 kbit/s", "forbidden" },\r
+          { "free format", "8 kbit/s", "16 kbit/s", "24 kbit/s", "32 kbit/s", "40 kbit/s",\r
+              "48 kbit/s", "56 kbit/s", "64 kbit/s", "80 kbit/s", "96 kbit/s", "112 kbit/s",\r
+              "128 kbit/s", "144 kbit/s", "160 kbit/s", "forbidden" } }, };\r
+\r
+  /**\r
+   * Return Bitrate.\r
+   * \r
+   * @return bitrate in bps\r
+   */\r
+  public String bitrate_string() {\r
+    if (h_vbr == true) {\r
+      return Integer.toString(bitrate() / 1000) + " kb/s";\r
+    } else\r
+      return bitrate_str[h_version][h_layer - 1][h_bitrate_index];\r
+  }\r
+\r
+  /**\r
+   * Return Bitrate.\r
+   * \r
+   * @return bitrate in bps and average bitrate for VBR header\r
+   */\r
+  public int bitrate() {\r
+    if (h_vbr == true) {\r
+      return ((int) ((h_vbr_bytes * 8) / (ms_per_frame() * h_vbr_frames))) * 1000;\r
+    } else\r
+      return bitrates[h_version][h_layer - 1][h_bitrate_index];\r
+  }\r
+\r
+  /**\r
+   * Return Instant Bitrate. Bitrate for VBR is not constant.\r
+   * \r
+   * @return bitrate in bps\r
+   */\r
+  public int bitrate_instant() {\r
+    return bitrates[h_version][h_layer - 1][h_bitrate_index];\r
+  }\r
+\r
+  /**\r
+   * Returns Frequency\r
+   * \r
+   * @return frequency string in kHz\r
+   */\r
+  public String sample_frequency_string() {\r
+    switch (h_sample_frequency) {\r
+    case THIRTYTWO:\r
+      if (h_version == MPEG1)\r
+        return "32 kHz";\r
+      else if (h_version == MPEG2_LSF)\r
+        return "16 kHz";\r
+      else\r
+        // SZD\r
+        return "8 kHz";\r
+    case FOURTYFOUR_POINT_ONE:\r
+      if (h_version == MPEG1)\r
+        return "44.1 kHz";\r
+      else if (h_version == MPEG2_LSF)\r
+        return "22.05 kHz";\r
+      else\r
+        // SZD\r
+        return "11.025 kHz";\r
+    case FOURTYEIGHT:\r
+      if (h_version == MPEG1)\r
+        return "48 kHz";\r
+      else if (h_version == MPEG2_LSF)\r
+        return "24 kHz";\r
+      else\r
+        // SZD\r
+        return "12 kHz";\r
+    }\r
+    return (null);\r
+  }\r
+\r
+  /**\r
+   * Returns Mode.\r
+   */\r
+  public String mode_string() {\r
+    switch (h_mode) {\r
+    case STEREO:\r
+      return "Stereo";\r
+    case JOINT_STEREO:\r
+      return "Joint stereo";\r
+    case DUAL_CHANNEL:\r
+      return "Dual channel";\r
+    case SINGLE_CHANNEL:\r
+      return "Single channel";\r
+    }\r
+    return null;\r
+  }\r
+\r
+  /**\r
+   * Returns Version.\r
+   * \r
+   * @return MPEG-1 or MPEG-2 LSF or MPEG-2.5 LSF\r
+   */\r
+  public String version_string() {\r
+    switch (h_version) {\r
+    case MPEG1:\r
+      return "MPEG-1";\r
+    case MPEG2_LSF:\r
+      return "MPEG-2 LSF";\r
+    case MPEG25_LSF: // SZD\r
+      return "MPEG-2.5 LSF";\r
+    }\r
+    return (null);\r
+  }\r
+\r
+  /**\r
+   * Returns the number of subbands in the current frame.\r
+   * \r
+   * @return number of subbands\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public int number_of_subbands() {\r
+    return h_number_of_subbands;\r
+  }\r
+\r
+  /**\r
+   * Returns Intensity Stereo. (Layer II joint stereo only). Returns the number\r
+   * of subbands which are in stereo mode, subbands above that limit are in\r
+   * intensity stereo mode.\r
+   * \r
+   * @return intensity\r
+   */\r
+  @RETURNLOC("OUT")\r
+  public int intensity_stereo_bound() {\r
+    return h_intensity_stereo_bound;\r
+  }\r
 }\r
index b895daf..ef79a88 100644 (file)
@@ -161,12 +161,11 @@ class LayerIDecoder implements FrameDecoder {
    * Class for layer I subbands in single channel mode. Used for single channel
    * mode and in derived class for intensity stereo mode
    */
-  @LATTICE("S<L,L<H,H<SH,SH<SH0,SH*,S*")
+  @LATTICE("S<L,L<H,H<SH,SH<SH0,SH*,L*")
   @METHODDEFAULT("OUT<V,V<THIS,THIS<C,C<IN,C*,THISLOC=THIS,RETURNLOC=OUT")
   static class SubbandLayer1 extends Subband {
 
     // Factors and offsets for sample requantization
-    @LOC("H")
     public static final float table_factor[] = { 0.0f, (1.0f / 2.0f) * (4.0f / 3.0f),
         (1.0f / 4.0f) * (8.0f / 7.0f), (1.0f / 8.0f) * (16.0f / 15.0f),
         (1.0f / 16.0f) * (32.0f / 31.0f), (1.0f / 32.0f) * (64.0f / 63.0f),
@@ -176,7 +175,6 @@ class LayerIDecoder implements FrameDecoder {
         (1.0f / 4096.0f) * (8192.0f / 8191.0f), (1.0f / 8192.0f) * (16384.0f / 16383.0f),
         (1.0f / 16384.0f) * (32768.0f / 32767.0f) };
 
-    @LOC("H")
     public static final float table_offset[] = { 0.0f, ((1.0f / 2.0f) - 1.0f) * (4.0f / 3.0f),
         ((1.0f / 4.0f) - 1.0f) * (8.0f / 7.0f), ((1.0f / 8.0f) - 1.0f) * (16.0f / 15.0f),
         ((1.0f / 16.0f) - 1.0f) * (32.0f / 31.0f), ((1.0f / 32.0f) - 1.0f) * (64.0f / 63.0f),
@@ -199,7 +197,7 @@ class LayerIDecoder implements FrameDecoder {
     protected float scalefactor;
     @LOC("L")
     protected int samplelength;
-    @LOC("S")
+    @LOC("L")
     protected float sample;
     @LOC("L")
     protected float factor;
@@ -263,11 +261,14 @@ class LayerIDecoder implements FrameDecoder {
       return false;
     }
 
-    @METHODDEFAULT("OUT<V,V<THIS,THIS<C,C<IN,C*,THISLOC=THIS,RETURNLOC=OUT")
-    public boolean put_next_sample(@LOC("IN") int channels, @LOC("IN") SynthesisFilter filter1,
-        @LOC("IN") SynthesisFilter filter2) {
+    // @METHODDEFAULT("OUT<V,V<THIS,THIS<C,C<IN,C*,THISLOC=THIS,RETURNLOC=OUT")
+    @LATTICE("THIS<IN,OUT,THISLOC=THIS,RETURNLOC=OUT")
+    public boolean put_next_sample(@LOC("IN") int channels,
+        @LOC("THIS,LayerIDecoder$SubbandLayer1.S") SynthesisFilter filter1,
+        @LOC("THIS,LayerIDecoder$SubbandLayer1.S") SynthesisFilter filter2) {
       if ((allocation != 0) && (channels != OutputChannels.RIGHT_CHANNEL)) {
-        @LOC("OUT") float scaled_sample = (sample * factor + offset) * scalefactor;
+        @LOC("THIS,LayerIDecoder$SubbandLayer1.L") float scaled_sample =
+            (sample * factor + offset) * scalefactor;
         filter1.input_sample(scaled_sample, subbandnumber);
       }
       return true;
@@ -400,7 +401,8 @@ class LayerIDecoder implements FrameDecoder {
           */
     @RETURNLOC("THIS,LayerIDecoder$SubbandLayer1Stereo.S")
     public boolean read_sampledata(@LOC("THIS,LayerIDecoder$SubbandLayer1Stereo.S") Bitstream stream) {
-      @LOC("THIS,LayerIDecoder$SubbandLayer1Stereo.S") boolean returnvalue = super.read_sampledata(stream);
+      @LOC("THIS,LayerIDecoder$SubbandLayer1Stereo.S") boolean returnvalue =
+          super.read_sampledata(stream);
       if (channel2_allocation != 0) {
         channel2_sample = (float) (stream.get_bits(channel2_samplelength));
       }
index f4774a2..75d5863 100644 (file)
@@ -68,8 +68,6 @@ public class Player
 \r
        @LOC("B") private int                   lastPosition = 0;\r
        \r
-       @LOC("HE") private Header header;\r
-       \r
        /**\r
         * Creates a new <code>Player</code> instance. \r
         */\r
@@ -84,11 +82,6 @@ public class Player
                bitstream = new Bitstream(stream);              \r
                decoder = new Decoder();\r
                \r
-               // decoder initialization\r
-               // taking out from ssjava loop \r
-               header = bitstream.readFrame();  \r
-               decoder.initialize(header, bitstream);\r
-                               \r
 //             if (device!=null)\r
 //             {               \r
 //                     audio = device;\r
@@ -219,13 +212,13 @@ public class Player
                        //if (out==null)\r
                        //      return false;\r
 \r
-//                     Header h = bitstream.readFrame();       \r
-//                     \r
-//                     if (h==null)\r
-//                             return false;\r
+                       Header h = bitstream.readFrame();       \r
+                       \r
+                       if (h==null)\r
+                               return false;\r
                                \r
                        // sample buffer set when decoder constructed\r
-                       @LOC("O") SampleBuffer output = (SampleBuffer)decoder.decodeFrame(header, bitstream);\r
+                       @LOC("O") SampleBuffer output = (SampleBuffer)decoder.decodeFrame(h, bitstream);\r
                                                                                                                                                                                                                                                                                                        \r
                        //synchronized (this)\r
                        //{\r