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 20#include "dsp/core/basic.h" 21 22//#define LOG_NDEBUG 0 23#include <cutils/log.h> 24 25 26namespace le_fx { 27 28namespace sigmod { 29 30template <typename T, class Algorithm> 31InterpolatorBase<T, Algorithm>::InterpolatorBase() { 32 status_ = false; 33 cached_index_ = 0; 34 x_data_ = NULL; 35 y_data_ = NULL; 36 data_length_ = 0; 37 own_x_data_ = false; 38 x_start_offset_ = 0.0; 39 last_element_index_ = -1; 40 x_inverse_sampling_interval_ = 0.0; 41 state_ = NULL; 42} 43 44template <typename T, class Algorithm> 45InterpolatorBase<T, Algorithm>::~InterpolatorBase() { 46 delete [] state_; 47 if (own_x_data_) { 48 delete [] x_data_; 49 } 50} 51 52template <typename T, class Algorithm> 53bool InterpolatorBase<T, Algorithm>::Initialize(const vector<T> &x_data, 54 const vector<T> &y_data) { 55#ifndef NDEBUG 56 if (x_data.size() != y_data.size()) { 57 LoggerError("InterpolatorBase::Initialize: xData size (%d) != yData size" 58 " (%d)", x_data.size(), y_data.size()); 59 } 60#endif 61 return Initialize(&x_data[0], &y_data[0], x_data.size()); 62} 63 64template <typename T, class Algorithm> 65bool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset, 66 double x_sampling_interval, 67 const vector<T> &y_data) { 68 return Initialize(x_start_offset, 69 x_sampling_interval, 70 &y_data[0], 71 y_data.size()); 72} 73 74template <typename T, class Algorithm> 75bool InterpolatorBase<T, Algorithm>::Initialize(double x_start_offset, 76 double x_sampling_interval, 77 const T *y_data, 78 int data_length) { 79 // Constructs and populate x-axis data: `x_data_` 80 T *x_data_tmp = new T[data_length]; 81 float time_offset = x_start_offset; 82 for (int n = 0; n < data_length; n++) { 83 x_data_tmp[n] = time_offset; 84 time_offset += x_sampling_interval; 85 } 86 Initialize(x_data_tmp, y_data, data_length); 87 // Sets-up the regularly sampled interpolation mode 88 x_start_offset_ = x_start_offset; 89 x_inverse_sampling_interval_ = 1.0 / x_sampling_interval; 90 own_x_data_ = true; 91 return status_; 92} 93 94 95template <typename T, class Algorithm> 96bool InterpolatorBase<T, Algorithm>::Initialize( 97 const T *x_data, const T *y_data, int data_length) { 98 // Default settings 99 cached_index_ = 0; 100 data_length_ = 0; 101 x_start_offset_ = 0; 102 x_inverse_sampling_interval_ = 0; 103 state_ = NULL; 104 // Input data is externally owned 105 own_x_data_ = false; 106 x_data_ = x_data; 107 y_data_ = y_data; 108 data_length_ = data_length; 109 last_element_index_ = data_length - 1; 110 // Check input data sanity 111 for (int n = 0; n < last_element_index_; ++n) { 112 if (x_data_[n + 1] <= x_data_[n]) { 113 ALOGE("InterpolatorBase::Initialize: xData are not ordered or " 114 "contain equal values (X[%d] <= X[%d]) (%.5e <= %.5e)", 115 n + 1, n, x_data_[n + 1], x_data_[n]); 116 status_ = false; 117 return false; 118 } 119 } 120 // Pre-compute internal state by calling the corresponding function of the 121 // derived class. 122 status_ = static_cast<Algorithm*>(this)->SetInternalState(); 123 return status_; 124} 125 126template <typename T, class Algorithm> 127T InterpolatorBase<T, Algorithm>::Interpolate(T x) { 128#ifndef NDEBUG 129 if (cached_index_ < 0 || cached_index_ > data_length_ - 2) { 130 LoggerError("InterpolatorBase:Interpolate: CachedIndex_ out of bounds " 131 "[0, %d, %d]", cached_index_, data_length_ - 2); 132 } 133#endif 134 // Search for the containing interval 135 if (x <= x_data_[cached_index_]) { 136 if (cached_index_ <= 0) { 137 cached_index_ = 0; 138 return y_data_[0]; 139 } 140 if (x >= x_data_[cached_index_ - 1]) { 141 cached_index_--; // Fast descending 142 } else { 143 if (x <= x_data_[0]) { 144 cached_index_ = 0; 145 return y_data_[0]; 146 } 147 cached_index_ = SearchIndex(x_data_, x, 0, cached_index_); 148 } 149 } else { 150 if (cached_index_ >= last_element_index_) { 151 cached_index_ = last_element_index_; 152 return y_data_[last_element_index_]; 153 } 154 if (x > x_data_[cached_index_ + 1]) { 155 if (cached_index_ + 2 > last_element_index_) { 156 cached_index_ = last_element_index_ - 1; 157 return y_data_[last_element_index_]; 158 } 159 if (x <= x_data_[cached_index_ + 2]) { 160 cached_index_++; // Fast ascending 161 } else { 162 if (x >= x_data_[last_element_index_]) { 163 cached_index_ = last_element_index_ - 1; 164 return y_data_[last_element_index_]; 165 } 166 cached_index_ = SearchIndex( 167 x_data_, x, cached_index_, last_element_index_); 168 } 169 } 170 } 171 // Compute interpolated value by calling the corresponding function of the 172 // derived class. 173 return static_cast<Algorithm*>(this)->MethodSpecificInterpolation(x); 174} 175 176} // namespace sigmod 177 178} // namespace le_fx 179 180#endif // LE_FX_ENGINE_DSP_CORE_INTERPOLATOR_BASE_INL_H_ 181