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
28 namespace le_fx {
29
30 namespace sigmod {
31
32 template <typename T, class Algorithm>
InterpolatorBase()33 InterpolatorBase<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
46 template <typename T, class Algorithm>
~InterpolatorBase()47 InterpolatorBase<T, Algorithm>::~InterpolatorBase() {
48 delete [] state_;
49 if (own_x_data_) {
50 delete [] x_data_;
51 }
52 }
53
54 template <typename T, class Algorithm>
Initialize(const vector<T> & x_data,const vector<T> & y_data)55 bool 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
66 template <typename T, class Algorithm>
Initialize(double x_start_offset,double x_sampling_interval,const vector<T> & y_data)67 bool 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
76 template <typename T, class Algorithm>
Initialize(double x_start_offset,double x_sampling_interval,const T * y_data,int data_length)77 bool 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
97 template <typename T, class Algorithm>
Initialize(const T * x_data,const T * y_data,int data_length)98 bool 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
128 template <typename T, class Algorithm>
Interpolate(T x)129 T 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