janitor

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

feature-fbank.cc (3965B)


      1 /**
      2  * Copyright (c)  2022  Xiaomi Corporation (authors: Fangjun Kuang)
      3  *
      4  * See LICENSE for clarification regarding multiple authors
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 
     19 // This file is copied/modified from kaldi/src/feat/feature-fbank.cc
     20 //
     21 #include "kaldi-native-fbank/csrc/feature-fbank.h"
     22 
     23 #include <algorithm>
     24 #include <limits>
     25 #include <utility>
     26 #include <vector>
     27 
     28 #include "kaldi-native-fbank/csrc/feature-functions.h"
     29 #include "kaldi-native-fbank/csrc/kaldi-math.h"
     30 #include "kaldi-native-fbank/csrc/log.h"
     31 
     32 namespace knf {
     33 
     34 std::ostream &operator<<(std::ostream &os, const FbankOptions &opts) {
     35   os << opts.ToString();
     36   return os;
     37 }
     38 
     39 FbankComputer::FbankComputer(const FbankOptions &opts)
     40     : opts_(opts), rfft_(opts.frame_opts.PaddedWindowSize()) {
     41   if (opts.energy_floor > 0.0f) {
     42     log_energy_floor_ = logf(opts.energy_floor);
     43   }
     44 
     45   // We'll definitely need the filterbanks info for VTLN warping factor 1.0.
     46   // [note: this call caches it.]
     47   GetMelBanks(1.0f);
     48 }
     49 
     50 FbankComputer::~FbankComputer() {
     51   for (auto iter = mel_banks_.begin(); iter != mel_banks_.end(); ++iter)
     52     delete iter->second;
     53 }
     54 
     55 const MelBanks *FbankComputer::GetMelBanks(float vtln_warp) {
     56   MelBanks *this_mel_banks = nullptr;
     57 
     58   // std::map<float, MelBanks *>::iterator iter = mel_banks_.find(vtln_warp);
     59   auto iter = mel_banks_.find(vtln_warp);
     60   if (iter == mel_banks_.end()) {
     61     this_mel_banks = new MelBanks(opts_.mel_opts, opts_.frame_opts, vtln_warp);
     62     mel_banks_[vtln_warp] = this_mel_banks;
     63   } else {
     64     this_mel_banks = iter->second;
     65   }
     66   return this_mel_banks;
     67 }
     68 
     69 void FbankComputer::Compute(float signal_raw_log_energy, float vtln_warp,
     70                             std::vector<float> *signal_frame, float *feature) {
     71   const MelBanks &mel_banks = *(GetMelBanks(vtln_warp));
     72 
     73   KNF_CHECK_EQ(signal_frame->size(), opts_.frame_opts.PaddedWindowSize());
     74 
     75   // Compute energy after window function (not the raw one).
     76   if (opts_.use_energy && !opts_.raw_energy) {
     77     signal_raw_log_energy = std::log(
     78         std::max<float>(InnerProduct(signal_frame->data(), signal_frame->data(),
     79                                      signal_frame->size()),
     80                         std::numeric_limits<float>::epsilon()));
     81   }
     82   rfft_.Compute(signal_frame->data());  // signal_frame is modified in-place
     83   ComputePowerSpectrum(signal_frame);
     84 
     85   // Use magnitude instead of power if requested.
     86   if (!opts_.use_power) {
     87     Sqrt(signal_frame->data(), signal_frame->size() / 2 + 1);
     88   }
     89 
     90   int32_t mel_offset = ((opts_.use_energy && !opts_.htk_compat) ? 1 : 0);
     91 
     92   // Its length is opts_.mel_opts.num_bins
     93   float *mel_energies = feature + mel_offset;
     94 
     95   // Sum with mel filter banks over the power spectrum
     96   mel_banks.Compute(signal_frame->data(), mel_energies);
     97 
     98   if (opts_.use_log_fbank) {
     99     // Avoid log of zero (which should be prevented anyway by dithering).
    100     for (int32_t i = 0; i != opts_.mel_opts.num_bins; ++i) {
    101       auto t = std::max(mel_energies[i], std::numeric_limits<float>::epsilon());
    102       mel_energies[i] = std::log(t);
    103     }
    104   }
    105 
    106   // Copy energy as first value (or the last, if htk_compat == true).
    107   if (opts_.use_energy) {
    108     if (opts_.energy_floor > 0.0 && signal_raw_log_energy < log_energy_floor_) {
    109       signal_raw_log_energy = log_energy_floor_;
    110     }
    111     int32_t energy_index = opts_.htk_compat ? opts_.mel_opts.num_bins : 0;
    112     feature[energy_index] = signal_raw_log_energy;
    113   }
    114 }
    115 
    116 }  // namespace knf