16cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi/*
26cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Copyright (C) 2013 The Android Open Source Project
36cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *
46cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
56cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * you may not use this file except in compliance with the License.
66cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * You may obtain a copy of the License at
76cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *
86cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
96cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi *
106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * See the License for the specific language governing permissions and
146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi * limitations under the License.
156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi */
166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#ifndef LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#define LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
1960d02077d86d2d1092443519290101f503aa6f7aMark Salyzyn#ifndef LOG_TAG
2060d02077d86d2d1092443519290101f503aa6f7aMark Salyzyn#define LOG_TAG NULL
2160d02077d86d2d1092443519290101f503aa6f7aMark Salyzyn#endif
226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//#define LOG_NDEBUG 0
236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
24eb16561336e6445f7edae047998f2459e046cdfeMark Salyzyn#include <log/log.h>
2560d02077d86d2d1092443519290101f503aa6f7aMark Salyzyn
2660d02077d86d2d1092443519290101f503aa6f7aMark Salyzyn#include "dsp/core/basic.h"
276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace le_fx {
296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace sigmod {
316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviInterpolatorBase<T, Algorithm>::InterpolatorBase() {
346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  status_ = false;
356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  cached_index_ = 0;
366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_data_ = NULL;
376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  y_data_ = NULL;
386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  data_length_ = 0;
396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  own_x_data_ = false;
406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_start_offset_ = 0.0;
416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  last_element_index_ = -1;
426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_inverse_sampling_interval_ = 0.0;
436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  state_ = NULL;
446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviInterpolatorBase<T, Algorithm>::~InterpolatorBase() {
486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  delete [] state_;
496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  if (own_x_data_) {
506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    delete [] x_data_;
516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(const vector<T> &x_data,
566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                const vector<T> &y_data) {
576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#ifndef NDEBUG
586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  if (x_data.size() != y_data.size()) {
596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    LoggerError("InterpolatorBase::Initialize: xData size (%d) != yData size"
606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                  " (%d)", x_data.size(), y_data.size());
616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif
636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return Initialize(&x_data[0], &y_data[0], x_data.size());
646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset,
686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                double x_sampling_interval,
696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                const vector<T> &y_data) {
706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return Initialize(x_start_offset,
716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                    x_sampling_interval,
726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                    &y_data[0],
736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                    y_data.size());
746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset,
786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                double x_sampling_interval,
796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                const T *y_data,
806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                                                int data_length) {
816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Constructs and populate x-axis data: `x_data_`
826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  T *x_data_tmp = new T[data_length];
836cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  float time_offset = x_start_offset;
846cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  for (int n = 0; n < data_length; n++) {
856cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    x_data_tmp[n] = time_offset;
866cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    time_offset += x_sampling_interval;
876cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
886cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  Initialize(x_data_tmp, y_data, data_length);
896cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Sets-up the regularly sampled interpolation mode
906cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_start_offset_ = x_start_offset;
916cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_inverse_sampling_interval_ = 1.0 / x_sampling_interval;
926cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  own_x_data_ = true;
936cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return status_;
946cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
956cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
966cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
976cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
986cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(
996cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    const T *x_data, const T *y_data, int data_length) {
1006cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Default settings
1016cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  cached_index_ = 0;
1026cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  data_length_ = 0;
1036cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_start_offset_ = 0;
1046cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_inverse_sampling_interval_ = 0;
1056cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  state_ = NULL;
1066cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Input data is externally owned
1076cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  own_x_data_ = false;
1086cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  x_data_ = x_data;
1096cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  y_data_ = y_data;
1106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  data_length_ = data_length;
1116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  last_element_index_ = data_length - 1;
1126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Check input data sanity
1136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  for (int n = 0; n < last_element_index_; ++n) {
1146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (x_data_[n + 1] <= x_data_[n]) {
1156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      ALOGE("InterpolatorBase::Initialize: xData are not ordered or "
1166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi              "contain equal values (X[%d] <= X[%d]) (%.5e <= %.5e)",
11760d02077d86d2d1092443519290101f503aa6f7aMark Salyzyn            n + 1, n, x_data_[n + 1], x_data_[n]);
1186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      status_ = false;
1196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      return false;
1206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
1226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Pre-compute internal state by calling the corresponding function of the
1236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // derived class.
1246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  status_ = static_cast<Algorithm*>(this)->SetInternalState();
1256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return status_;
1266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
1276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
1286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm>
1296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviT InterpolatorBase<T, Algorithm>::Interpolate(T x) {
1306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#ifndef NDEBUG
1316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  if (cached_index_ < 0 || cached_index_ > data_length_ - 2) {
1326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    LoggerError("InterpolatorBase:Interpolate: CachedIndex_ out of bounds "
1336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi                  "[0, %d, %d]", cached_index_, data_length_ - 2);
1346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
1356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif
1366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Search for the containing interval
1376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  if (x <= x_data_[cached_index_]) {
1386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (cached_index_ <= 0) {
1396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      cached_index_ = 0;
1406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      return y_data_[0];
1416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (x >= x_data_[cached_index_ - 1]) {
1436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      cached_index_--;  // Fast descending
1446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    } else {
1456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      if (x <= x_data_[0]) {
1466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        cached_index_ = 0;
1476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        return y_data_[0];
1486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      }
1496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      cached_index_ = SearchIndex(x_data_, x, 0, cached_index_);
1506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  } else {
1526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (cached_index_ >= last_element_index_) {
1536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      cached_index_ = last_element_index_;
1546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      return y_data_[last_element_index_];
1556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    if (x > x_data_[cached_index_ + 1]) {
1576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      if (cached_index_ + 2 > last_element_index_) {
1586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        cached_index_ = last_element_index_ - 1;
1596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        return y_data_[last_element_index_];
1606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      }
1616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      if (x <= x_data_[cached_index_ + 2]) {
1626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        cached_index_++;  // Fast ascending
1636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      } else {
1646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        if (x >= x_data_[last_element_index_]) {
1656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi          cached_index_ = last_element_index_ - 1;
1666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi          return y_data_[last_element_index_];
1676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        }
1686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi        cached_index_ = SearchIndex(
1696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi            x_data_, x, cached_index_, last_element_index_);
1706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi      }
1716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi    }
1726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  }
1736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // Compute interpolated value by calling the corresponding function of the
1746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  // derived class.
1756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi  return static_cast<Algorithm*>(this)->MethodSpecificInterpolation(x);
1766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}
1776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
1786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}  // namespace sigmod
1796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
1806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi}  // namespace le_fx
1816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi
1826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif  // LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_
183