Home | History | Annotate | Download | only in micro_features
      1 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 #include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_scale.h"
     16 
     17 #include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/bits.h"
     18 #include "tensorflow/lite/experimental/micro/examples/micro_speech/micro_features/log_lut.h"
     19 
     20 #define kuint16max 0x0000FFFF
     21 
     22 // The following functions implement integer logarithms of various sizes. The
     23 // approximation is calculated according to method described in
     24 //       www.inti.gob.ar/electronicaeinformatica/instrumentacion/utic/
     25 //       publicaciones/SPL2007/Log10-spl07.pdf
     26 // It first calculates log2 of the input and then converts it to natural
     27 // logarithm.
     28 
     29 static uint32_t Log2FractionPart(const uint32_t x, const uint32_t log2x) {
     30   // Part 1
     31   int32_t frac = x - (1LL << log2x);
     32   if (log2x < kLogScaleLog2) {
     33     frac <<= kLogScaleLog2 - log2x;
     34   } else {
     35     frac >>= log2x - kLogScaleLog2;
     36   }
     37   // Part 2
     38   const uint32_t base_seg = frac >> (kLogScaleLog2 - kLogSegmentsLog2);
     39   const uint32_t seg_unit =
     40       ((static_cast<uint32_t>(1)) << kLogScaleLog2) >> kLogSegmentsLog2;
     41 
     42   const int32_t c0 = kLogLut[base_seg];
     43   const int32_t c1 = kLogLut[base_seg + 1];
     44   const int32_t seg_base = seg_unit * base_seg;
     45   const int32_t rel_pos = ((c1 - c0) * (frac - seg_base)) >> kLogScaleLog2;
     46   return frac + c0 + rel_pos;
     47 }
     48 
     49 static uint32_t Log(const uint32_t x, const uint32_t scale_shift) {
     50   const uint32_t integer = MostSignificantBit32(x) - 1;
     51   const uint32_t fraction = Log2FractionPart(x, integer);
     52   const uint32_t log2 = (integer << kLogScaleLog2) + fraction;
     53   const uint32_t round = kLogScale / 2;
     54   const uint32_t loge =
     55       ((static_cast<uint64_t>(kLogCoeff)) * log2 + round) >> kLogScaleLog2;
     56   // Finally scale to our output scale
     57   const uint32_t loge_scaled = ((loge << scale_shift) + round) >> kLogScaleLog2;
     58   return loge_scaled;
     59 }
     60 
     61 uint16_t* LogScaleApply(struct LogScaleState* state, uint32_t* signal,
     62                         int signal_size, int correction_bits) {
     63   const int scale_shift = state->scale_shift;
     64   uint16_t* output = reinterpret_cast<uint16_t*>(signal);
     65   uint16_t* ret = output;
     66   int i;
     67   for (i = 0; i < signal_size; ++i) {
     68     uint32_t value = *signal++;
     69     if (state->enable_log) {
     70       if (correction_bits < 0) {
     71         value >>= -correction_bits;
     72       } else {
     73         value <<= correction_bits;
     74       }
     75       if (value > 1) {
     76         value = Log(value, scale_shift);
     77       } else {
     78         value = 0;
     79       }
     80     }
     81     *output++ = (value < kuint16max) ? value : kuint16max;
     82   }
     83   return ret;
     84 }
     85