/*
 * Copyright 1999-2002 Carnegie Mellon University.  
 * Portions Copyright 2002 Sun Microsystems, Inc.  
 * Portions Copyright 2002 Mitsubishi Electronic Research Laboratories.
 * All Rights Reserved.  Use is subject to license terms.
 * 
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL 
 * WARRANTIES.
 *
 */

package edu.cmu.sphinx.frontend;

import edu.cmu.sphinx.util.SphinxProperties;

import java.io.IOException;


/**
 * A FeatureSource produces Features.
 */
public class FrameDropper extends DataProcessor implements FeatureSource {

    /**
     * The SphinxProperty that specifies dropping one in every
     * Nth frame. If N=2, we drop every other frame. If N=3, we
     * drop every third frame, etc..
     */
    public static final String PROP_DROP_EVERY_NTH_FRAME
        = FrontEnd.PROP_PREFIX + "FrameDropper.dropEveryNthFrame";
    
    /**
     * The default value of PROP_DROP_EVERY_NTH_FRAME.
     */
    public static final int PROP_DROP_EVERY_NTH_FRAME_DEFAULT = -1;

    /**
     * The SphinxProperty that specifies whether to replace the
     * Nth frame with the previous frame.
     */
    public static final String PROP_REPLACE_NTH_WITH_PREVIOUS
        = FrontEnd.PROP_PREFIX + "FrameDropper.replaceNthWithPrevious";

    /**
     * The default value of PROP_REPLACE_NTH_WITH_PREVIOUS.
     */
    public static final boolean PROP_REPLACE_NTH_WITH_PREVIOUS_DEFAULT
        = false;


    private FeatureSource predecessor;
    private Feature lastFeature;
    private boolean replaceNthWithPrevious;
    private int dropEveryNthFrame;
    private int id;


    /**
     * Creates a default FrameDropper.
     *
     * @param name the name of this FrameDropper
     * @param context the context to use
     * @param props the SphinxProperties to use
     * @param predecessor the FeatureSource from which to read Features
     */
    public FrameDropper(String name, String context, 
                        SphinxProperties props,
                        FeatureSource predecessor) {
        super(name, context, props);
        this.predecessor = predecessor;
        this.id = 0;

        dropEveryNthFrame = props.getInt
            (PROP_DROP_EVERY_NTH_FRAME,
             PROP_DROP_EVERY_NTH_FRAME_DEFAULT);

        assert (dropEveryNthFrame > 1);
        
        replaceNthWithPrevious = props.getBoolean
            (PROP_REPLACE_NTH_WITH_PREVIOUS, 
             PROP_REPLACE_NTH_WITH_PREVIOUS_DEFAULT);
    }

    /**
     * Returns the next Feature object from this FrameDropper.
     * The Feature objects belonging to a single Utterance should be
     * preceded by a Feature object with the Signal.UTTERANCE_START, and
     * ended by a Feature object wtih the Signal.UTTERANCE_END.
     *
     * @return the next available Feature object, returns null if no
     *     Feature object is available
     *
     * @throws java.io.IOException
     */
    public Feature getFeature() throws IOException {
        Feature feature = predecessor.getFeature();
        if (feature.hasContent()) {
            if ((feature.getID() % dropEveryNthFrame) == 
                (dropEveryNthFrame - 1)) {
                if (replaceNthWithPrevious) {
                    feature = new Feature
                        (lastFeature.getFeatureData(), id++);
                } else {
                    feature = predecessor.getFeature();
                    if (feature.hasContent()) {
                        feature.setID(id++);
                    }
                }
            } else {
                feature.setID(id++);
            }
        } else if (feature.hasSignal(Signal.UTTERANCE_START)) {
            id = 0;
        }

        if (feature.hasContent()) {
            lastFeature = feature;
        } else {
            lastFeature = null;
        }

        return feature;
    }
}

@@ -3059,32 +3059,67 @@
 r.getFeature();%0A
+        if (feature != null) %7B%0A    
         if (feat
@@ -3130,32 +3130,36 @@
 hasContent()) %7B%0A
+    
             if (
@@ -3216,16 +3216,20 @@
         
+ 
+   
 (dropEve
@@ -3243,24 +3243,28 @@
 ame - 1)) %7B%0A
+    
             
@@ -3309,32 +3309,36 @@
                 
+   
+ 
 feature = new Fe
@@ -3343,16 +3343,20 @@
 Feature%0A
+    
         
@@ -3417,32 +3417,36 @@
                 
+    
 %7D else %7B%0A       
@@ -3450,32 +3450,36 @@
                 
+ 
+   
 feature = predec
@@ -3510,32 +3510,36 @@
                 
+    
 if (feature.hasC
@@ -3525,32 +3525,51 @@
      if (feature
+ != null && feature
 .hasContent()) %7B
@@ -3561,32 +3561,36 @@
 hasContent()) %7B%0A
+    
                 
@@ -3630,34 +3630,42 @@
                 
-%7D%0A
+    %7D%0A    
                 
@@ -3670,32 +3670,36 @@
   %7D%0A            
+  
+  
 %7D else %7B%0A       
@@ -3683,32 +3683,36 @@
        %7D else %7B%0A
+    
                 
@@ -3748,24 +3748,78 @@
     
-%7D%0A        %7D else
+    %7D%0A            %7D%0A            if (feature != null) %7B%0A               
  if 
@@ -3876,16 +3876,24 @@
         
+        
 id = 0;%0A
@@ -3900,27 +3900,54 @@
         
+ 
-%7D%0A%0A
+       %7D%0A                %0A   
         
 if (feat
@@ -3930,32 +3930,37 @@
     %0A           
+     
 if (feature.hasC
@@ -3975,32 +3975,40 @@
 ) %7B%0A            
+     
+   
 lastFeature = fe
@@ -4014,32 +4014,40 @@
 eature;%0A        
+       
+ 
 %7D else %7B%0A       
@@ -4031,32 +4031,40 @@
        %7D else %7B%0A
+        
             last
@@ -4079,16 +4079,105 @@
 = null;%0A
+                %7D%0A            %7D else %7B%0A                lastFeature = null;%0A            %7D%0A
         

Fixes the bug that the first feature in an utterance is sometimes not given an ID of 0. Also check for null features.