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 26 namespace le_fx { 27 28 namespace sigmod { 29 30 template <typename T, class Algorithm> 31 InterpolatorBase<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 44 template <typename T, class Algorithm> 45 InterpolatorBase<T, Algorithm>::~InterpolatorBase() { 46 delete [] state_; 47 if (own_x_data_) { 48 delete [] x_data_; 49 } 50 } 51 52 template <typename T, class Algorithm> 53 bool 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 64 template <typename T, class Algorithm> 65 bool 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 74 template <typename T, class Algorithm> 75 bool 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 95 template <typename T, class Algorithm> 96 bool 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 126 template <typename T, class Algorithm> 127 T 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