name: Calculus : public AlgorithmBase
synopsis:

>     g++ [flags ...] file ... -l /isip/tools/lib/$ISIP_BINARY/lib_algo.a

>     #include <Calculus.h>

>     Calculus(ALGORITHM algorithm = DEF_ALGORITHM, IMPLEMENTATION implementation = DEF_IMPLEMENTATION, long order = DEF_ORDER, long delta_win = DEF_DELTAWIN);
>     boolean setAlgorithm(ALGORITHM algorithm);
>     boolean setImplementation(IMPLEMENTATION implementation);
>     boolean compute(VectorFloat& output, const VectorFloat& input,
>                     AlgorithmData::COEF_TYPE input_coef_type);

quick start:

>     VectorFloat input(L"1.0, 2.0, 0.0, -1.0, -2.0");
>     VectorFloat output;
>     Calculus calc;
>     calc.setAlgorithm(Calculus::DIFFERENTIATION);
>     calc.setImplementation(Calculus::REGRESSION);
>     calc.setOrder(1);
>     calc.setDeltaWindow(2);
>     calc.compute(output, input);

description:
The Calculus class computes derivatives, integrals, etc., on vector data. Its most common use is to differentiate features as part of a typical speech recognition front end. As with most classes in the algorithm library, a choice of algorithms and implementations are provided. A good tutorial on the use of this class to approximate derivatives can be found at:

J. Picone, "Signal Processing in Speech Recognition," Proceedings of the Speech Recognition System Training Workshop, Institute for Signal and Information Processing, Mississippi State University, May 2002.

Currently, three forms of derivative computations are supported: regression, central differences, and backward differences. A summary of these algorithms is shown below:
Though the algorithm definitions are the same for FRAME_INTERNAL and CROSS_FRAME, the data on which the algorithm operates is different. In FRAME_INTERNAL mode, the computation is performed directly on the data within the current frame. Note that in this mode the input vector must have the exact dimension required for the calculation. (For example, if a backward difference is used with a delta window of 1, the length of the input vector must be 2, so that there is sufficient data in the vector to perform the computation.)
In CROSS_FRAME mode, the data is treated as a sequence of vectors, as shown below:
The derivative is computed across the sequence consisting of the jth element of each vector. The number of previous and future frames of data used in this computation depends on the algorithm and implementation selection. For example, for a central difference, (2D+1) frames will be required. This form of the derivative computation is what is used in a typical speech recognition front end.
Note that the approximations for integration have not been implemented yet.
dependencies:

- AlgorithmBase

public constants:

- define the class name:

      static const String CLASS_NAME = L"Calculus";

- define the algorithm choices:

      enum ALGORITHM { DIFFERENTIATION = 0, INTEGRATION, DEF_ALGORITHM = DIFFERENTIATION };

- define the implementation choices:

      enum IMPLEMENTATION { REGRESSION = 0, CENTRAL_DIFFERENCE, BACKWARD_DIFFERENCE, DEF_IMPLEMENTATION = REGRESSION };

- define the static NameMap objects

      static const NameMap Calculus::ALGO_MAP(L"DIFFERENTIATION, INTEGRATION");

      static const NameMap Calculus::IMPL_MAP(L"REGRESSION, CENTRAL_DIFFERENCE, BACKWARD_DIFFERENCE");

- define i/o related constants:

      static const String Calculus::DEF_PARAM = L"";

      static const String Calculus::PARAM_ALGORITHM = L"algorithm";

      static const String Calculus::PARAM_IMPLEMENTATION = L"implementation";

      static const String Calculus::PARAM_MODE = L"mode";

      static const String Calculus::PARAM_ORDER = L"order";

      static const String Calculus::PARAM_DELTAWIN = L"delta_win";

- define default value(s) of the class data:

      static const long DEF_ORDER = 1;

      static const long DEF_DELTAWIN = 2;

- define default argument(s):

      static const AlgorithmData::COEF_TYPE DEF_COEF_TYPE = AlgorithmData::GENERIC;

error codes:

- error code indicating a general error:

      static const long ERR = 70200;

      static const long ERR_ZERODENOM = 70201;

protected data:

- data common to all algorithms and implementations:
  - define an algorithm name:

        ALGORITHM algorithm_d;

  - define an implementation name:

        IMPLEMENTATION implementation_d;

  - specify an order for the operation (for example, a 1st order derivative):

        Long order_d;

  - static memory manager:

        static MemoryManager mgr_d;

- algorithm and implementation specific variables:
  - algorithm: differentiation
    implementation: regression/central-difference/backward-difference
    description: window length in frames
    notes: these implementations interpret this variable differently

        Long delta_win_d;

  - algorithm: differentiation
    implementation: regression/central difference/regression
    description: precomputed scaling factor

        double denom_d;

required public methods:

- static methods:

      static const String& name();

      static boolean diagnose(Integral::DEBUG debug_level);

- debug methods: setDebug method is inherited from base class

      boolean debug(const unichar* message) const;

- destructor/constructor(s):

      ~Calculus();

      Calculus(ALGORITHM algorithm = DEF_ALGORITHM, IMPLEMENTATION implementation = DEF_IMPLEMENTATION, long order = DEF_ORDER, long delta_win = DEF_DELTAWIN);

      Calculus(const Calculus& arg);

- assign methods:

      boolean assign(const Calculus& arg);

- operator= methods:

      Calculus& operator= (const Calculus& arg);

- i/o methods:

      long sofSize() const;

      boolean read(Sof& sof, long tag, const String& name = CLASS_NAME);

      boolean write(Sof& sof, long tag, const String& name = CLASS_NAME) const;

      boolean readData(Sof& sof, const String& pname = DEF_PARAM, long size = SofParser::FULL_OBJECT, boolean param = true, boolean nested = false);

      boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

- equality methods:

      boolean eq(const Calculus& arg) const;

- memory management methods:

      static void* operator new(size_t size);

      static void* operator new[](size_t size);

      static void operator delete(void* ptr);

      static void operator delete[](void* ptr);

      static boolean setGrowSize(long grow_size);

      boolean clear(Integral::CMODE ctype = Integral::DEF_CMODE);

class-specific public methods:

- set methods:

      boolean setAlgorithm(ALGORITHM algorithm);

      boolean setImplementation(IMPLEMENTATION implementation);

      boolean setOrder(long order);

      boolean setDeltaWindow(long delta_win);

      boolean set(ALGORITHM algorithm = DEF_ALGORITHM, IMPLEMENTATION implementation = DEF_IMPLEMENTATION, long order = DEF_ORDER, long delta_win = DEF_DELTAWIN);

- get methods:

      ALGORITHM getAlgorithm() const;

      IMPLEMENTATION getImplementation() const;

      long getOrder() const;

      long getDeltaWindow() const;

      boolean get(ALGORITHM& algorithm, IMPLEMENTATION& implementation, long& order, long& delta_win) const;

- computational methods:

      boolean compute(VectorFloat& output, const VectorFloat& input, AlgorithmData::COEF_TYPE coef_type = DEF_COEF_TYPE, long index = DEF_CHANNEL_INDEX);

      boolean compute(VectorComplexFloat& output, const VectorComplexFloat& input, AlgorithmData::COEF_TYPE coef_type = DEF_COEF_TYPE, long index = DEF_CHANNEL_INDEX);

- AlgorithmBase interface contract methods:

      boolean assign(const AlgorithmBase& arg);

      boolean eq(const AlgorithmBase& arg) const;

      const String& className() const;

      boolean init();

      boolean apply(Vector<AlgorithmData>& output, const Vector<AlgorithmData>& input);

      long getLeadingPad() const;

      long getTrailingPad() const;

      boolean setParser(SofParser* parser);

private methods:

- common i/o methods:

      boolean readDataCommon(Sof& sof, const String& pname, long size = SofParser::FULL_OBJECT, boolean param = true, boolean nested = false);

      boolean writeDataCommon(Sof& sof, const String& pname) const;

- general compute methods: since the nature of the computations for FRAME_INTERNAL and CROSS_FRAME are different, we provide separate private compute methods for these modes.

      boolean computeInternal(VectorFloat& output, const CircularBuffer<AlgorithmData>& input, AlgorithmData::COEF_TYPE coef_type = DEF_COEF_TYPE, long channel_index = DEF_CHANNEL_INDEX);

      boolean computeCross(VectorFloat& output, const CircularBuffer<AlgorithmData>& input, AlgorithmData::COEF_TYPE coef_type = DEF_COEF_TYPE, long channel_index = DEF_CHANNEL_INDEX);

- algorithm-specific compute methods: differentiation

      boolean computeDifRegression(VectorFloat& output, const VectorFloat& input);

      boolean computeDifCentral(VectorFloat& output, const VectorFloat& input);

      boolean computeDifBackward(VectorFloat& output, const VectorFloat& input);

examples:

- This example demonstrates how to use the Calculus object to compute the difference of a VectorFloat:

      // configure a Calculus object
      //
      Calculus calc;
      calc.setAlgorithm(Calculus::DIFFERENTIATION);
      calc.setImplementation(Calculus::REGRESSION);
      calc.setOrder(1);
      calc.setDeltaWindow(2);

      // create input and output data
      //
      VectorFloat input(L"1.0, 2.0, 0.0, -1.0, -2.0");
      VectorFloat output;

      // calculate the result
      //
      calc.compute(output, input);
      output.debug(L"output");

- This example shows how to compute a derivative using a backward difference:

      // configure a Calculus object
      //
      Calculus calc;
      calc.setAlgorithm(Calculus::DIFFERENTIATION);
      calc.setImplementation(Calculus::BACKWARD_DIFFERENCE);
      calc.setOrder(1);
      calc.setDeltaWindow(2);

      // create input and output data
      //
      VectorFloat input(L"1.0, 2.0, 0.0");
      VectorFloat output;

      // calculate the result
      //
      calc.compute(output, input);
      output.debug(L"output");

notes:

- Integration has not been implemented yet since it is not used in modern speech recognition systems.
- Currently, only first-order derivatives are supported. Second-order derivatives, also used in speech recognition, are traditionally implemented by cascading two first-order derivatives. This can be realized via the isip_transform utility.