Skip to content

Commit 19e8c48

Browse files
committed
examples: add a multichoice object
1 parent 15d12bd commit 19e8c48

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#pragma once
2+
3+
#include <ossia/network/value/value.hpp>
4+
5+
#include <halp/audio.hpp>
6+
#include <halp/controls.hpp>
7+
#include <halp/meta.hpp>
8+
#include <halp/sample_accurate_controls.hpp>
9+
10+
#include <cmath>
11+
#include <algorithm>
12+
#include <limits>
13+
#include <variant>
14+
#include <vector>
15+
16+
namespace ao
17+
{
18+
19+
class MultiChoice
20+
{
21+
public:
22+
halp_meta(name, "Multi-choice")
23+
halp_meta(c_name, "multi_choice")
24+
halp_meta(category, "Control/Mappings")
25+
halp_meta(uuid, "2c1d4578-7ef7-48b1-bbb8-c2b1c41063c9")
26+
halp_meta(author, "ossia score")
27+
halp_meta(description, "Choose a value according to multiple inputs")
28+
halp_meta(manual_url, "https://ossia.io/score-docs/processes/multi-choice.html")
29+
30+
struct ins
31+
{
32+
struct : halp::val_port<"Inputs", std::vector<float>>
33+
{
34+
} nodes;
35+
36+
halp::knob_f32<"Smooth", halp::range{.min = 0.01, .max = 1.0, .init = 0.1}> smooth;
37+
halp::knob_f32<"Threshold", halp::range{.min = 0.0, .max = 1.0, .init = 0.8}> threshold;
38+
halp::knob_f32<"Margin", halp::range{.min = 0.0, .max = 1.0, .init = 0.15}> margin;
39+
} inputs;
40+
41+
struct outs
42+
{
43+
halp::val_port<"Output index", std::optional<int>> index;
44+
halp::val_port<"Current Weights", std::vector<float>> weights;
45+
} outputs;
46+
47+
std::vector<float> m_state;
48+
std::optional<int> m_last_index;
49+
50+
using tick = halp::tick;
51+
void operator()(halp::tick t)
52+
{
53+
const float alpha = this->inputs.smooth.value;
54+
const float threshold = 0.8f;
55+
const float margin = 0.15f;
56+
57+
const std::vector<float>& input = this->inputs.nodes.value;
58+
if(input.empty())
59+
{
60+
m_last_index = std::nullopt;
61+
outputs.index = std::nullopt;
62+
outputs.weights.value.clear();
63+
return;
64+
}
65+
66+
if(m_state.size() != input.size())
67+
{
68+
m_state.resize(input.size(), 0.0f);
69+
outputs.weights.value.resize(input.size(), 0.0f);
70+
}
71+
72+
for(size_t i = 0; i < input.size(); ++i)
73+
{
74+
m_state[i] += (input[i] - m_state[i]) * alpha;
75+
outputs.weights.value[i] = m_state[i];
76+
}
77+
78+
auto max_it = std::max_element(m_state.begin(), m_state.end());
79+
int winner_idx = std::distance(m_state.begin(), max_it);
80+
float winner_val = *max_it;
81+
82+
float runner_up_val = 0.0f;
83+
for(size_t i = 0; i < m_state.size(); ++i)
84+
{
85+
if((int)i != winner_idx)
86+
{
87+
if(m_state[i] > runner_up_val)
88+
runner_up_val = m_state[i];
89+
}
90+
}
91+
92+
if(winner_val > threshold && (winner_val - runner_up_val) > margin)
93+
{
94+
if(m_last_index != winner_idx)
95+
outputs.index = winner_idx;
96+
m_last_index = winner_idx;
97+
}
98+
else
99+
{
100+
outputs.index = std::nullopt;
101+
m_last_index = std::nullopt;
102+
}
103+
}
104+
};
105+
106+
}

0 commit comments

Comments
 (0)