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