janitor

janitor
git clone https://git.prime8.dev/janitor.git
Log | Files | Refs | README | LICENSE

feature-window.h (7023B)


      1 // kaldi-native-fbank/csrc/feature-window.h
      2 //
      3 // Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)
      4 
      5 // This file is copied/modified from kaldi/src/feat/feature-window.h
      6 
      7 #ifndef KALDI_NATIVE_FBANK_CSRC_FEATURE_WINDOW_H_
      8 #define KALDI_NATIVE_FBANK_CSRC_FEATURE_WINDOW_H_
      9 
     10 #include <sstream>
     11 #include <string>
     12 #include <vector>
     13 #include <cstdint>
     14 
     15 #include "kaldi-native-fbank/csrc/log.h"
     16 
     17 namespace knf {
     18 
     19 inline int32_t RoundUpToNearestPowerOfTwo(int32_t n) {
     20   // copied from kaldi/src/base/kaldi-math.cc
     21   KNF_CHECK_GT(n, 0);
     22   n--;
     23   n |= n >> 1;
     24   n |= n >> 2;
     25   n |= n >> 4;
     26   n |= n >> 8;
     27   n |= n >> 16;
     28   return n + 1;
     29 }
     30 
     31 struct FrameExtractionOptions {
     32   float samp_freq = 16000;
     33   float frame_shift_ms = 10.0f;   // in milliseconds.
     34   float frame_length_ms = 25.0f;  // in milliseconds.
     35 
     36   float dither = 0.00003f;  // Amount of dithering, 0.0 means no dither.
     37                             // Value 0.00003f is equivalent to 1.0 in kaldi.
     38 
     39   float preemph_coeff = 0.97f;        // Preemphasis coefficient.
     40   bool remove_dc_offset = true;       // Subtract mean of wave before FFT.
     41   std::string window_type = "povey";  // e.g. Hamming window
     42   // May be "hamming", "rectangular", "povey", "hanning", "hann", "sine",
     43   // "blackman".
     44   // "povey" is a window I made to be similar to Hamming but to go to zero at
     45   // the edges, it's pow((0.5 - 0.5*cos(n/N*2*pi)), 0.85) I just don't think the
     46   // Hamming window makes sense as a windowing function.
     47   bool round_to_power_of_two = true;
     48   float blackman_coeff = 0.42f;
     49   bool snip_edges = true;
     50   // bool allow_downsample = false;
     51   // bool allow_upsample = false;
     52 
     53   int32_t WindowShift() const {
     54     return static_cast<int32_t>(samp_freq * 0.001f * frame_shift_ms);
     55   }
     56   int32_t WindowSize() const {
     57     return static_cast<int32_t>(samp_freq * 0.001f * frame_length_ms);
     58   }
     59   int32_t PaddedWindowSize() const {
     60     return (round_to_power_of_two ? RoundUpToNearestPowerOfTwo(WindowSize())
     61                                   : WindowSize());
     62   }
     63   std::string ToString() const {
     64     std::ostringstream os;
     65 #define KNF_PRINT(x) os << #x << ": " << x << "\n"
     66     KNF_PRINT(samp_freq);
     67     KNF_PRINT(frame_shift_ms);
     68     KNF_PRINT(frame_length_ms);
     69     KNF_PRINT(dither);
     70     KNF_PRINT(preemph_coeff);
     71     KNF_PRINT(remove_dc_offset);
     72     KNF_PRINT(window_type);
     73     KNF_PRINT(round_to_power_of_two);
     74     KNF_PRINT(blackman_coeff);
     75     KNF_PRINT(snip_edges);
     76     // KNF_PRINT(allow_downsample);
     77     // KNF_PRINT(allow_upsample);
     78 #undef KNF_PRINT
     79     return os.str();
     80   }
     81 };
     82 
     83 std::ostream &operator<<(std::ostream &os, const FrameExtractionOptions &opts);
     84 
     85 class FeatureWindowFunction {
     86  public:
     87   FeatureWindowFunction() = default;
     88   explicit FeatureWindowFunction(const FrameExtractionOptions &opts);
     89   /**
     90    * @param wave Pointer to a 1-D array of shape [window_size].
     91    *             It is modified in-place: wave[i] = wave[i] * window_[i].
     92    * @param
     93    */
     94   void Apply(float *wave) const;
     95   const std::vector<float> &GetWindow() const { return window_; }
     96 
     97  private:
     98   std::vector<float> window_;  // of size opts.WindowSize()
     99 };
    100 
    101 int64_t FirstSampleOfFrame(int32_t frame, const FrameExtractionOptions &opts);
    102 
    103 /**
    104    This function returns the number of frames that we can extract from a wave
    105    file with the given number of samples in it (assumed to have the same
    106    sampling rate as specified in 'opts').
    107 
    108       @param [in] num_samples  The number of samples in the wave file.
    109       @param [in] opts     The frame-extraction options class
    110 
    111       @param [in] flush   True if we are asserting that this number of samples
    112    is 'all there is', false if we expecting more data to possibly come in.  This
    113    only makes a difference to the answer
    114    if opts.snip_edges== false.  For offline feature extraction you always want
    115    flush == true.  In an online-decoding context, once you know (or decide) that
    116    no more data is coming in, you'd call it with flush == true at the end to
    117    flush out any remaining data.
    118 */
    119 int32_t NumFrames(int64_t num_samples, const FrameExtractionOptions &opts,
    120                   bool flush = true);
    121 
    122 /*
    123   ExtractWindow() extracts a windowed frame of waveform (possibly with a
    124   power-of-two, padded size, depending on the config), including all the
    125   processing done by ProcessWindow().
    126 
    127   @param [in] sample_offset  If 'wave' is not the entire waveform, but
    128                    part of it to the left has been discarded, then the
    129                    number of samples prior to 'wave' that we have
    130                    already discarded.  Set this to zero if you are
    131                    processing the entire waveform in one piece, or
    132                    if you get 'no matching function' compilation
    133                    errors when updating the code.
    134   @param [in] wave  The waveform
    135   @param [in] f     The frame index to be extracted, with
    136                     0 <= f < NumFrames(sample_offset + wave.Dim(), opts, true)
    137   @param [in] opts  The options class to be used
    138   @param [in] window_function  The windowing function, as derived from the
    139                     options class.
    140   @param [out] window  The windowed, possibly-padded waveform to be
    141                      extracted.  Will be resized as needed.
    142   @param [out] log_energy_pre_window  If non-NULL, the log-energy of
    143                    the signal prior to pre-emphasis and multiplying by
    144                    the windowing function will be written to here.
    145 */
    146 void ExtractWindow(int64_t sample_offset, const std::vector<float> &wave,
    147                    int32_t f, const FrameExtractionOptions &opts,
    148                    const FeatureWindowFunction &window_function,
    149                    std::vector<float> *window,
    150                    float *log_energy_pre_window = nullptr);
    151 
    152 /**
    153   This function does all the windowing steps after actually
    154   extracting the windowed signal: depending on the
    155   configuration, it does dithering, dc offset removal,
    156   preemphasis, and multiplication by the windowing function.
    157    @param [in] opts  The options class to be used
    158    @param [in] window_function  The windowing function-- should have
    159                     been initialized using 'opts'.
    160    @param [in,out] window  A vector of size opts.WindowSize().  Note:
    161       it will typically be a sub-vector of a larger vector of size
    162       opts.PaddedWindowSize(), with the remaining samples zero,
    163       as the FFT code is more efficient if it operates on data with
    164       power-of-two size.
    165    @param [out]   log_energy_pre_window If non-NULL, then after dithering and
    166       DC offset removal, this function will write to this pointer the log of
    167       the total energy (i.e. sum-squared) of the frame.
    168  */
    169 void ProcessWindow(const FrameExtractionOptions &opts,
    170                    const FeatureWindowFunction &window_function, float *window,
    171                    float *log_energy_pre_window = nullptr);
    172 
    173 // Compute the inner product of two vectors
    174 float InnerProduct(const float *a, const float *b, int32_t n);
    175 
    176 }  // namespace knf
    177 
    178 #endif  // KALDI_NATIVE_FBANK_CSRC_FEATURE_WINDOW_H_