1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_ 18#define LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_ 19#ifndef LOG_TAG 20#define LOG_TAG NULL 21#endif 22//#define LOG_NDEBUG 0 23 24#include <log/log.h> 25 26#include "dsp/core/basic.h" 27 28namespace le_fx { 29 30namespace sigmod { 31 32template <typename T, class Algorithm> 33InterpolatorBase<T, Algorithm>::InterpolatorBase() { 34 status_ = false; 35 cached_index_ = 0; 36 x_data_ = NULL; 37 y_data_ = NULL; 38 data_length_ = 0; 39 own_x_data_ = false; 40 x_start_offset_ = 0.0; 41 last_element_index_ = -1; 42 x_inverse_sampling_interval_ = 0.0; 43 state_ = NULL; 44} 45 46template <typename T, class Algorithm> 47InterpolatorBase<T, Algorithm>::~InterpolatorBase() { 48 delete [] state_; 49 if (own_x_data_) { 50 delete [] x_data_; 51 } 52} 53 54template <typename T, class Algorithm> 55bool InterpolatorBase<T, Algorithm>::Initialize(const vector<T> &x_data, 56 const vector<T> &y_data) { 57#ifndef NDEBUG 58 if (x_data.size() != y_data.size()) { 59 LoggerError("InterpolatorBase::Initialize: xData size (%d) != yData size" 60 " (%d)", x_data.size(), y_data.size()); 61 } 62#endif 63 return Initialize(&x_data[0], &y_data[0], x_data.size()); 64} 65 66template <typename T, class Algorithm> 67bool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset, 68 double x_sampling_interval, 69 const vector<T> &y_data) { 70 return Initialize(x_start_offset, 71 x_sampling_interval, 72 &y_data[0], 73 y_data.size()); 74} 75 76template <typename T, class Algorithm> 77bool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset, 78 double x_sampling_interval, 79 const T *y_data, 80 int data_length) { 81 // Constructs and populate x-axis data: `x_data_` 82 T *x_data_tmp = new T[data_length]; 83 float time_offset = x_start_offset; 84 for (int n = 0; n < data_length; n++) { 85 x_data_tmp[n] = time_offset; 86 time_offset += x_sampling_interval; 87 } 88 Initialize(x_data_tmp, y_data, data_length); 89 // Sets-up the regularly sampled interpolation mode 90 x_start_offset_ = x_start_offset; 91 x_inverse_sampling_interval_ = 1.0 / x_sampling_interval; 92 own_x_data_ = true; 93 return status_; 94} 95 96 97template <typename T, class Algorithm> 98bool InterpolatorBase<T, Algorithm>::Initialize( 99 const T *x_data, const T *y_data, int data_length) { 100 // Default settings 101 cached_index_ = 0; 102 data_length_ = 0; 103 x_start_offset_ = 0; 104 x_inverse_sampling_interval_ = 0; 105 state_ = NULL; 106 // Input data is externally owned 107 own_x_data_ = false; 108 x_data_ = x_data; 109 y_data_ = y_data; 110 data_length_ = data_length; 111 last_element_index_ = data_length - 1; 112 // Check input data sanity 113 for (int n = 0; n < last_element_index_; ++n) { 114 if (x_data_[n + 1] <= x_data_[n]) { 115 ALOGE("InterpolatorBase::Initialize: xData are not ordered or " 116 "contain equal values (X[%d] <= X[%d]) (%.5e <= %.5e)", 117 n + 1, n, x_data_[n + 1], x_data_[n]); 118 status_ = false; 119 return false; 120 } 121 } 122 // Pre-compute internal state by calling the corresponding function of the 123 // derived class. 124 status_ = static_cast<Algorithm*>(this)->SetInternalState(); 125 return status_; 126} 127 128template <typename T, class Algorithm> 129T InterpolatorBase<T, Algorithm>::Interpolate(T x) { 130#ifndef NDEBUG 131 if (cached_index_ < 0 || cached_index_ > data_length_ - 2) { 132 LoggerError("InterpolatorBase:Interpolate: CachedIndex_ out of bounds " 133 "[0, %d, %d]", cached_index_, data_length_ - 2); 134 } 135#endif 136 // Search for the containing interval 137 if (x <= x_data_[cached_index_]) { 138 if (cached_index_ <= 0) { 139 cached_index_ = 0; 140 return y_data_[0]; 141 } 142 if (x >= x_data_[cached_index_ - 1]) { 143 cached_index_--; // Fast descending 144 } else { 145 if (x <= x_data_[0]) { 146 cached_index_ = 0; 147 return y_data_[0]; 148 } 149 cached_index_ = SearchIndex(x_data_, x, 0, cached_index_); 150 } 151 } else { 152 if (cached_index_ >= last_element_index_) { 153 cached_index_ = last_element_index_; 154 return y_data_[last_element_index_]; 155 } 156 if (x > x_data_[cached_index_ + 1]) { 157 if (cached_index_ + 2 > last_element_index_) { 158 cached_index_ = last_element_index_ - 1; 159 return y_data_[last_element_index_]; 160 } 161 if (x <= x_data_[cached_index_ + 2]) { 162 cached_index_++; // Fast ascending 163 } else { 164 if (x >= x_data_[last_element_index_]) { 165 cached_index_ = last_element_index_ - 1; 166 return y_data_[last_element_index_]; 167 } 168 cached_index_ = SearchIndex( 169 x_data_, x, cached_index_, last_element_index_); 170 } 171 } 172 } 173 // Compute interpolated value by calling the corresponding function of the 174 // derived class. 175 return static_cast<Algorithm*>(this)->MethodSpecificInterpolation(x); 176} 177 178} // namespace sigmod 179 180} // namespace le_fx 181 182#endif // LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_ 183