name: FilterBank : public AlgorithmBase
synopsis:

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

>     #include <FilterBank.h>

>     FilterBank();
>     FilterBank(const FilterBank& arg);
>     boolean eq(const FilterBank& arg);
>     boolean setAlgorithm(ALGORITHM algorithm);
>     boolean setImplementation(IMPLEMENTATION implementation);
>     boolean set(long order, float sample_freq, ALGORITHM algo, IMPLEMENTATION impl, SCALE scale);
>     boolean set(float width, float sample_freq, ALGORITHM algo, IMPLEMENTATION impl, SCALE scale);

quick start:

>     VectorFloat input;
>     VectorFloat output;
>     FilterBank fb;
>     fb.set(24, 8000, FilterBank::FREQUENCY_SAMPLED, FilterBank::TRIANGULAR, Warp::MEL);
>     fb.compute(output, input);

description:
A filter bank is an important part of the feature extraction process for speech recognition, because it allows the signal to be decomposed into its frequency components in a manner similar to the way the human ear operates. In terms of basic digital signal processing theory, a filter bank performs a time frequency analysis of the signal, much like a wavelet analysis. A filter bank is a useful tool because it can be used to simulate a nonlinear warping of the frequency axis. A good reference for the analysis and implementation of such filter banks is:

J. Picone, "Signal Modeling Techniques in Speech Recognition", IEEE Proceedings, vol. 81, no. 9, pp. 1215-1247, September 1993.

This class currently supports two algorithm choices: TIME and FREQUENCY. The TIME algorithm is essentially a bank of digital filters that operate in the time domain to generate a multi-channel output corresponding to each digital filter. The Filter class is used to implement this bank of filters, using the constant coefficient difference equation (CCDE) implementation. Please note that the coefficients of these digital filters are set using a standard Sof-formatted parameter file. The parameter file can be set using the setFiltersParamFile method in this class.
The second algorithm type supported in this class is FREQUENCY. This mode is used to implement a popular approach in speech recognition in which the frequency scale is nonlinearly warped and oversampled to produce cepstral coefficients. The input spectrum is separated in a series of bins, and the frequency samples within these bins are averaged together using an appropriate weighting function. The input spectrum must be a log magnitude spectrum, and can be supplied as either a symmetric spectrum (SYMMETRIC - used for real signals) or a or an asymmetric spectrum (FULL - used for complex signals).
An overview of the options available for this class is given below:
A filter bank is best understood using the follow diagram:
which depicts how the spectrum is sampled in the case of the triangularly weighting option (e.g., algorithm = FREQUENCY, implementation = TRIANGULAR). For most of the frequency sampling methods, overlapping filters are used to produce a smoother estimate of the spectrum. Also, the frequency scale is typically nonlinearly warped (e.g., scale = MEL) to better match human perception. More details on these techniques can be found in our Fundamentals of Speech Recognition course, or our speech recognition workshop notes.
dependencies:

- AlgorithmBase
- Filter
- Vector
- String
- Long
- Float
- VectorFloat
- MemoryManager

public constants:

- define the class name:

      static const String CLASS_NAME = L"FilterBank";

- define the algorithm choices:

      enum ALGORITHM { FREQUENCY = 0, TIME, DEF_ALGORITHM = FREQUENCY };

- define the implementation choices:

      enum IMPLEMENTATION { UNIFORM = 0, TRIANGULAR, RAISED_COSINE, CCDE, DEF_IMPLEMENTATION = UNIFORM };

- define the scale choices:

      enum SCALE { LINEAR = 0, MEL, BARK, DEF_SCALE = LINEAR };

- define the frequency sampling method:

      enum FREQUENCY_SAMPLING { ORDER = 0, BANDWIDTH, DEF_FREQUENCY_SAMPLING = ORDER };

- define the input mode choices:

      enum INPUT_MODE { FULL = 0, SYMMETRIC, DEF_INPUT_MODE = FULL };

- define the static NameMap objects:

      static const NameMap ALGO_MAP(L"TIME, FREQUENCY");

      static const NameMap IMPL_MAP(L"UNIFORM, TRIANGULAR, RAISED_COSINE, CCDE");

      static const NameMap SCALE_MAP(L"LINEAR, MEL, BARK");

      const NameMap FilterBank::FREQUENCY_SAMPLING_MAP(L"ORDER, BANDWIDTH");

      const NameMap FilterBank::INPUT_MODE_MAP(L"FULL, SYMMETRIC");

- define i/o related constants:

      static const String DEF_PARAM = L"";

      static const String PARAM_ALGORITHM = L"algorithm";

      static const String PARAM_IMPLEMENTATION = L"implementation";

      static const String PARAM_FILTERS_PFILE = L"filters_pfile";

      static const String PARAM_SCALE = L"scale";

      static const String PARAM_FREQUENCY_SAMPLING = L"frequency_sampling";

      static const String PARAM_INPUT_MODE = L"input_mode";

      static const String PARAM_ORDER = L"order";

      static const String PARAM_BANDWIDTH = L"bandwidth";

      static const String PARAM_CMODE = L"compute_mode_d";

      static const String PARAM_DMODE = L"data_mode_d";

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

      static const String DEF_FILTERS_PFILE = L"filters.sof";

      static const long DEF_ORDER = (long)24;

      static const float DEF_BANDWIDTH = (float)85.8426;

      static const float DEF_NUM_FILTERS = (long)1;

- define default argument(s):

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

      static const long DEF_CHANNEL_INDEX = 0;

error codes:

- general error codes:

      static const long ERR = 70700;

protected data:

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

        ALGORITHM algorithm_d;

  - implementation name:

        IMPLEMENTATION implementation_d;

  - static memory manager:

        static MemoryManager mgr_d;

- algorithm and implementation specific variables:
  - algorithm: TIME
    implementation: CCDE
    - define parameters used to describe a multichannel digital filter bank:

          Vector<Filter> filters_d;

          String filters_pfile_d;

  - algorithm: FREQUENCY
    implementation: all
    - define a parameter that describes the methods used for frequency scaling and sampling:

          SCALE scale_d;

          FREQUENCY_SAMPLING fsmp_d;

    - define a parameter that describes how the spectrum is represented:

          INPUT_MODE input_mode_d;

    - the number of filter banks specified by the user:

          Long order_d;

    - the filter bank spacing specified by the user: note that the units of this are dependent on the technique selected (e.g, FREQUENCY/MEL means the units of this constant are mel)

          Float bandwidth_d;

    - define temporary buffers used to describe the filter bank:

          VectorFloat warp_freq_d;

          VectorFloat lin_freq_d;

          VectorFloat cen_freq_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):

      ~FilterBank();

      FilterBank();

      FilterBank(const FilterBank& arg);

- assign methods:

      boolean assign(const FilterBank& arg);

- operator= methods:

      FilterBank& operator= (const FilterBank& 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 FilterBank& 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 setScale(SCALE scale);

      boolean setFrequencySampling(FREQUENCY_SAMPLING fsmp);

      boolean setInputMode(INPUT_MODE input_mode);

      boolean setOrder(long order);

      boolean setBandwidth(long order);

      boolean set(ALGORITHM algo, IMPLEMENTATION impl, INPUT_MODE input_mode, SCALE scale, long order, float sample_freq);

      boolean set(ALGORITHM algo, IMPLEMENTATION impl, INPUT_MODE input_mode, SCALE scale, float bandwidth, float sample_freq);

      boolean setFiltersParamFile(String filters_pfile);

- get methods:

      ALGORITHM getAlgorithm() const;

      IMPLEMENTATION getImplementation() const;

      SCALE getScale() const;

      FREQUENCY_SAMPLING getFrequencySampling();

      INPUT_MODE getInputMode() const;

      long getOrder() const;

      long getBandwidth() const;

      boolean get(ALGORITHM& algo, IMPLEMENTATION& impl, INPUT_MODE& input_mode, SCALE& scale, long& order, float& sample_freq) const;

      boolean get(ALGORITHM& algo, IMPLEMENTATION& impl, INPUT_MODE& input_mode, SCALE& scale, float& bandwidth, float& sample_freq) const;

      long getFiltersParamFile(String& filters_param_file) const;

- compute methods: TIME algorithm (multichannel output)

      boolean compute(Vector<VectorFloat>& output, const Vector<VectorFloat>& input, AlgorithmData::COEF_TYPE input_coef_type = DEF_COEF_TYPE, long index = DEF_CHANNEL_INDEX);

- compute methods: FREQUENCY algorithm (vector output)

      boolean compute(VectorFloat& output, const VectorFloat& input, AlgorithmData::COEF_TYPE input_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);

      boolean setParser(SofParser* parser);

      boolean getLeadingPad() const;

      boolean getTrailingPad() const;

private methods:

- TIME algorithm i/o methods:

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

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

- FREQUENCY algorithm i/o methods:

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

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

- TIME algorithm computational methods:

      boolean computeTimeCommon(Vector<VectorFloat>& output, const CircularBuffer<AlgorithmData>& input, long index = DEF_CHANNEL_INDEX);

      boolean computeTimeCcde(Vector<VectorFloat>& output, const VectorFloat& input, long index = DEF_CHANNEL_INDEX);

- FREQUENCY algorithm computational methods:

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

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

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

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

examples:

- This example demonstrates how to compute filter bank values using an algorithm choice of FREQUENCY:

      // declare a FilterBank object
      //
      FilterBank fb;

      // set the parameters
      //
      long order = 4;
      float sf = 8000;
      FilterBank::ALGORITHM algo = FilterBank::FREQUENCY;
      FilterBank::IMPLEMENTATION impl = FilterBank::TRIANGULAR;
      FilterBank::INPUT_MODE input_mode = FilterBank::FULL;
      SCALE scale = MEL;

      if (!fb.set(order, sf, algo, impl, input_mode, scale)) {
        Error::handle(fb.name(), L"set", Error::TEST, __FILE__, __LINE__);
        Integral::exit();
      }

      // generate a signal of VectorFloat
      //
      VectorFloat input;
      input.assign(L"58.682139, 27.352428, 40.681365, 119.681669, 392.449627, 432.773435, 345.984134, 175.399777, 97.606844");

      // compute filter bank to the signal
      //
      VectorFloat output;
      fb.compute(output, input);

notes:

- There is a discrepancy between the read and the write methods for the TIME algorithm type. While the read method first reads the filters parameter filename, and then proceeds to read the filter coefficients from this file, the write method just writes the filter parameter filename.