17 halp_meta(name,
"Interpolator")
18 halp_meta(c_name,
"avnd_interpolator")
19 halp_meta(author,
"ossia team")
20 halp_meta(category,
"Control/Data processing")
22 description,
"Linear interpolation of multiple values using weight coefficients")
23 halp_meta(uuid,
"f47ac10b-58cc-4372-a567-0e02b2c3d479")
27 halp::val_port<
"Weights", std::vector<float>> weights;
29 struct : halp::spinbox_i32<
"Input count", halp::range{0, 1024, 2}>
31 static std::function<void(
Interpolator&,
int)> on_controller_interaction()
34 object.inputs.values.request_port_resize(value);
39 halp::dynamic_port<halp::val_port<
"Value {}", ossia::value>> values;
44 halp::val_port<
"Output", ossia::value> output;
48 T interpolate_scalar(
const std::vector<T>& values,
const std::vector<float>& weights)
const
50 if (values.empty() || weights.empty())
54 float total_weight = 0.0f;
56 const int min_size = std::min(values.size(), weights.size());
57 for (
int i = 0; i < min_size; ++i)
59 result += values[i] * weights[i];
60 total_weight += weights[i];
63 if (total_weight != 0.0f)
64 result /= total_weight;
69 template<
typename VecType>
70 VecType interpolate_vector(
const std::vector<VecType>& values,
const std::vector<float>& weights)
const
72 if (values.empty() || weights.empty())
76 float total_weight = 0.0f;
78 const int min_size = std::min(values.size(), weights.size());
79 for (
int i = 0; i < min_size; ++i)
81 for (
int j = 0; j < result.size(); ++j)
83 result[j] += values[i][j] * weights[i];
85 total_weight += weights[i];
88 if (total_weight != 0.0f)
90 for (
auto& component : result)
91 component /= total_weight;
97 std::vector<ossia::value> interpolate_value_vector(
98 const std::vector<std::vector<ossia::value>>& value_vectors,
99 const std::vector<float>& weights)
const
101 if (value_vectors.empty() || weights.empty())
104 const int min_inputs = std::min(value_vectors.size(), weights.size());
108 const int max_size = std::max_element(
109 value_vectors.begin(), value_vectors.begin() + min_inputs,
110 [](
const auto& a,
const auto& b) { return a.size() < b.size(); }
113 std::vector<ossia::value> result;
114 result.reserve(max_size);
116 for (
int elem_idx = 0; elem_idx < max_size; ++elem_idx)
118 std::vector<ossia::value> element_values;
119 std::vector<float> element_weights;
121 for (
int input_idx = 0; input_idx < min_inputs; ++input_idx)
123 if (elem_idx < value_vectors[input_idx].size())
125 element_values.push_back(value_vectors[input_idx][elem_idx]);
126 element_weights.push_back(weights[input_idx]);
130 if (!element_values.empty())
132 result.push_back(interpolate_values(element_values, element_weights));
139 ossia::value interpolate_values(
const std::vector<ossia::value>& values,
const std::vector<float>& weights)
const
141 if (values.empty() || weights.empty())
142 return ossia::value{};
144 const int min_size = std::min(values.size(), weights.size());
146 return ossia::value{};
151 auto first_type = values[0].get_type();
152 bool all_same_type = std::all_of(values.begin(), values.begin() + min_size,
153 [first_type](
const ossia::value& v) { return v.get_type() == first_type; });
162 case ossia::val_type::FLOAT:
164 std::vector<float> float_values;
165 for (
int i = 0; i < min_size; ++i)
166 float_values.push_back(*values[i].target<
float>());
167 return interpolate_scalar(float_values, weights);
169 case ossia::val_type::INT:
171 std::vector<int> int_values;
172 for (
int i = 0; i < min_size; ++i)
173 int_values.push_back(*values[i].target<
int>());
174 float result = interpolate_scalar(
175 std::vector<float>(int_values.begin(), int_values.end()), weights);
176 return static_cast<int>(std::round(result));
178 case ossia::val_type::VEC2F:
180 std::vector<ossia::vec2f> vec_values;
181 for (
int i = 0; i < min_size; ++i)
182 vec_values.push_back(*values[i].target<ossia::vec2f>());
183 return interpolate_vector(vec_values, weights);
185 case ossia::val_type::VEC3F:
187 std::vector<ossia::vec3f> vec_values;
188 for (
int i = 0; i < min_size; ++i)
189 vec_values.push_back(*values[i].target<ossia::vec3f>());
190 return interpolate_vector(vec_values, weights);
192 case ossia::val_type::VEC4F:
194 std::vector<ossia::vec4f> vec_values;
195 for (
int i = 0; i < min_size; ++i)
196 vec_values.push_back(*values[i].target<ossia::vec4f>());
197 return interpolate_vector(vec_values, weights);
199 case ossia::val_type::LIST:
201 std::vector<std::vector<ossia::value>> value_vectors;
202 for (
int i = 0; i < min_size; ++i)
203 value_vectors.push_back(*values[i].target<std::vector<ossia::value>>());
204 return interpolate_value_vector(value_vectors, weights);
206 case ossia::val_type::BOOL:
208 std::vector<float> bool_values;
209 for (
int i = 0; i < min_size; ++i)
210 bool_values.push_back(*values[i].target<
bool>() ? 1.0f : 0.0f);
211 float result = interpolate_scalar(bool_values, weights);
212 return result >= 0.5f;
221 const auto& weights = inputs.weights.value;
223 if (weights.empty() || inputs.values.ports.empty())
225 outputs.output.value = ossia::value{};
229 std::vector<ossia::value> values;
230 for (
const auto& port : inputs.values.ports)
232 values.push_back(port.value);
235 outputs.output.value = interpolate_values(values, weights);