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_ 196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include "dsp/core/basic.h" 216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi//#define LOG_NDEBUG 0 236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#include <cutils/log.h> 246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace le_fx { 276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivinamespace sigmod { 296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm> 316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviInterpolatorBase<T, Algorithm>::InterpolatorBase() { 326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi status_ = false; 336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = 0; 346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_data_ = NULL; 356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi y_data_ = NULL; 366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi data_length_ = 0; 376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi own_x_data_ = false; 386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_start_offset_ = 0.0; 396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi last_element_index_ = -1; 406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_inverse_sampling_interval_ = 0.0; 416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi state_ = NULL; 426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm> 456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviInterpolatorBase<T, Algorithm>::~InterpolatorBase() { 466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi delete [] state_; 476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (own_x_data_) { 486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi delete [] x_data_; 496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm> 536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(const vector<T> &x_data, 546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi const vector<T> &y_data) { 556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#ifndef NDEBUG 566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (x_data.size() != y_data.size()) { 576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LoggerError("InterpolatorBase::Initialize: xData size (%d) != yData size" 586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi " (%d)", x_data.size(), y_data.size()); 596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif 616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return Initialize(&x_data[0], &y_data[0], x_data.size()); 626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm> 656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset, 666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi double x_sampling_interval, 676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi const vector<T> &y_data) { 686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return Initialize(x_start_offset, 696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_sampling_interval, 706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi &y_data[0], 716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi y_data.size()); 726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm> 756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset, 766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi double x_sampling_interval, 776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi const T *y_data, 786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi int data_length) { 796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // Constructs and populate x-axis data: `x_data_` 806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi T *x_data_tmp = new T[data_length]; 816cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi float time_offset = x_start_offset; 826cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi for (int n = 0; n < data_length; n++) { 836cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_data_tmp[n] = time_offset; 846cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi time_offset += x_sampling_interval; 856cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 866cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi Initialize(x_data_tmp, y_data, data_length); 876cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // Sets-up the regularly sampled interpolation mode 886cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_start_offset_ = x_start_offset; 896cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_inverse_sampling_interval_ = 1.0 / x_sampling_interval; 906cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi own_x_data_ = true; 916cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return status_; 926cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 936cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 946cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 956cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm> 966cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivibool InterpolatorBase<T, Algorithm>::Initialize( 976cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi const T *x_data, const T *y_data, int data_length) { 986cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // Default settings 996cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = 0; 1006cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi data_length_ = 0; 1016cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_start_offset_ = 0; 1026cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_inverse_sampling_interval_ = 0; 1036cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi state_ = NULL; 1046cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // Input data is externally owned 1056cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi own_x_data_ = false; 1066cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_data_ = x_data; 1076cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi y_data_ = y_data; 1086cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi data_length_ = data_length; 1096cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi last_element_index_ = data_length - 1; 1106cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // Check input data sanity 1116cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi for (int n = 0; n < last_element_index_; ++n) { 1126cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (x_data_[n + 1] <= x_data_[n]) { 1136cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi ALOGE("InterpolatorBase::Initialize: xData are not ordered or " 1146cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi "contain equal values (X[%d] <= X[%d]) (%.5e <= %.5e)", 1156cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi n + 1, n, x_data_[n + 1], x_data_[n]); 1166cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi status_ = false; 1176cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return false; 1186cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1196cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1206cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // Pre-compute internal state by calling the corresponding function of the 1216cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // derived class. 1226cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi status_ = static_cast<Algorithm*>(this)->SetInternalState(); 1236cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return status_; 1246cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 1256cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1266cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivitemplate <typename T, class Algorithm> 1276cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel TriviT InterpolatorBase<T, Algorithm>::Interpolate(T x) { 1286cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#ifndef NDEBUG 1296cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (cached_index_ < 0 || cached_index_ > data_length_ - 2) { 1306cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi LoggerError("InterpolatorBase:Interpolate: CachedIndex_ out of bounds " 1316cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi "[0, %d, %d]", cached_index_, data_length_ - 2); 1326cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1336cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif 1346cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // Search for the containing interval 1356cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (x <= x_data_[cached_index_]) { 1366cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (cached_index_ <= 0) { 1376cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = 0; 1386cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return y_data_[0]; 1396cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1406cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (x >= x_data_[cached_index_ - 1]) { 1416cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_--; // Fast descending 1426cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } else { 1436cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (x <= x_data_[0]) { 1446cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = 0; 1456cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return y_data_[0]; 1466cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1476cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = SearchIndex(x_data_, x, 0, cached_index_); 1486cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1496cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } else { 1506cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (cached_index_ >= last_element_index_) { 1516cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = last_element_index_; 1526cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return y_data_[last_element_index_]; 1536cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1546cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (x > x_data_[cached_index_ + 1]) { 1556cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (cached_index_ + 2 > last_element_index_) { 1566cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = last_element_index_ - 1; 1576cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return y_data_[last_element_index_]; 1586cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1596cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (x <= x_data_[cached_index_ + 2]) { 1606cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_++; // Fast ascending 1616cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } else { 1626cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi if (x >= x_data_[last_element_index_]) { 1636cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = last_element_index_ - 1; 1646cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return y_data_[last_element_index_]; 1656cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1666cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi cached_index_ = SearchIndex( 1676cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi x_data_, x, cached_index_, last_element_index_); 1686cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1696cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1706cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi } 1716cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // Compute interpolated value by calling the corresponding function of the 1726cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi // derived class. 1736cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi return static_cast<Algorithm*>(this)->MethodSpecificInterpolation(x); 1746cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} 1756cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1766cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} // namespace sigmod 1776cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1786cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi} // namespace le_fx 1796cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi 1806cc3a9948b51193dfdcb0c3527d7f3d1ca38aa3cJean-Michel Trivi#endif // LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_ 181