2 #include <ossia/detail/hash_map.hpp>
3 #include <ossia/detail/math.hpp>
4 #include <ossia/detail/ssize.hpp>
8 #include <halp/controls.hpp>
9 #include <halp/meta.hpp>
10 #include <halp/midi.hpp>
11 #include <rnd/random.hpp>
12 #if !defined(NDEBUG) && !defined(_MSC_VER) && !defined(__clang__)
13 #include <debug/vector>
14 #define debug_vector_t __gnu_debug::vector
16 #define debug_vector_t std::vector
18 namespace Nodes::FactorOracle
21 template <
typename T, T default_value>
25 debug_vector_t<T> impl;
27 T& operator[](
int i_) {
return (*
this)[
static_cast<std::size_t
>(i_)]; }
28 T& operator[](std::size_t i_)
30 auto i =
static_cast<std::size_t
>(i_);
31 if(i < impl.size() && impl.size() != 0)
35 impl.resize((i + 1) * 2, default_value);
39 const T& operator[](
int i_)
const {
return (*
this)[
static_cast<std::size_t
>(i_)]; }
40 const T& operator[](std::size_t i_)
const
42 auto i =
static_cast<std::size_t
>(i_);
43 if(i < impl.size() && impl.size() != 0)
47 static constexpr
auto dval = default_value;
55 debug_vector_t<T> impl;
57 T& operator[](
int i_) {
return (*
this)[
static_cast<std::size_t
>(i_)]; }
58 T& operator[](std::size_t i_)
60 auto i =
static_cast<std::size_t
>(i_);
61 if(i < impl.size() && impl.size() != 0)
65 impl.resize((i + 1) * 2);
73 int cur_alphabet_size = 0;
74 debug_vector_t<std::pair<int, ossia::value>> value_map;
76 : m_forwardLink(sz + 1, debug_vector_t<int>{-1})
79 m_sp.impl.resize(1000);
80 m_lrs.impl.resize(1000);
86 int LCS(
int p1,
int p2)
91 while(m_sp[p2] != m_sp[p1])
94 return std::min(m_lrs[p1], m_lrs[p2]);
97 void add_char(ossia::value c)
99 if(n < std::ssize(m_forwardLink) - 1)
101 m_sequence.push_back(std::move(c));
102 auto it = ossia::find_if(value_map, [&](
const auto& pair) {
return pair.second == c; });
103 if(it != value_map.end())
105 add_state(it->first);
109 value_map.push_back({cur_alphabet_size, m_sequence.back()});
110 add_state(cur_alphabet_size);
116 void add_state(
int c)
118 m_trans[n][c] = n + 1;
122 while(j != -1 && m_trans[j][c] == -1)
124 int& m_trans_j_c = m_trans[j][c];
126 if(m_forwardLink[j][0] == -1)
128 m_forwardLink[j][0] = m_trans_j_c;
132 m_forwardLink[j].push_back(m_trans_j_c);
137 int& m_sp_n = m_sp[n];
138 m_sp_n = (j == -1 ? 0 : m_trans[j][c]);
139 m_lrs[n] = (m_sp_n == 0 ? 0 :
LCS(p1, m_sp_n - 1) + 1);
142 debug_vector_t<ossia::value> make_rand_sequence(
float continuity,
int seqSize)
const
144 auto start = std::uniform_int_distribution<std::size_t>{0, m_sequence.size()}(m_rand_engine);
145 return make_sequence(continuity, start, seqSize);
148 debug_vector_t<ossia::value> make_sequence(
float continuity, std::size_t curState, std::size_t seqSize)
const
150 if(curState > m_sequence.size())
152 qDebug() <<
"Le point initial de l'improvisation doit être comprise "
157 debug_vector_t<ossia::value> v;
159 for(std::size_t i = 0; i < seqSize; i++)
161 auto f = std::uniform_real_distribution<float>{}(m_rand_engine);
162 if(f <= continuity && curState < m_sequence.size() - 1)
165 v.push_back(m_sequence[curState]);
171 int links = (curState == 0 ? 0 : 1);
172 if(m_forwardLink[curState][0] != -1)
174 links += m_forwardLink[curState].size();
177 auto linkToFollow = std::uniform_int_distribution<int>{0, links - 1}(m_rand_engine);
178 if(linkToFollow == links - 1)
182 curState = m_sp[curState];
187 curState = m_forwardLink[curState][linkToFollow];
189 }
while(curState >= m_sequence.size());
191 v.push_back(m_sequence[curState]);
199 safe_vector<int, 0> m_sp;
200 safe_vector<int, 0> m_lrs;
201 safe_vector_simple<safe_vector<int, -1>> m_trans;
202 debug_vector_t<ossia::value> m_sequence;
203 debug_vector_t<debug_vector_t<int>> m_forwardLink;
205 mutable rnd::pcg m_rand_engine;
210 halp_meta(name,
"Factor Oracle")
211 halp_meta(c_name,
"Factor Oracle")
212 halp_meta(category,
"Control/Impro")
213 halp_meta(manual_url,
"")
214 halp_meta(author,
"Shlomo Dubnov, Ge Wang, Éric Meaux, Jean-Michaël Celerier")
215 halp_meta(description,
"Factor Oracle algorithm .")
216 halp_meta(uuid,
"d90284c0-4196-47e0-802d-7e07342029ec")
226 static const constexpr
auto controls = tuplet::make_tuple(Control::IntSlider{
"Sequence length", 1, 64, 8});
228 static const constexpr value_in value_ins[]{
"in",
"regen",
"bang"};
229 static const constexpr value_out value_outs[]{
"out"};
234 debug_vector_t<ossia::value> sequence;
235 std::size_t sequence_idx{};
238 using control_policy = ossia::safe_nodes::last_tick;
239 static void run(
const ossia::value_port& in,
const ossia::value_port& regen,
const ossia::value_port& bangs,
int seq_len, ossia::value_port& out, ossia::token_request, ossia::exec_state_facade,
State&
self)
242 for(
auto val : in.get_data())
244 self.oracle.add_char(val.value);
247 if(!regen.get_data().empty())
249 self.sequence =
self.oracle.make_rand_sequence(0.4, seq_len);
252 if(!
self.sequence.empty())
254 for(
auto& bang : bangs.get_data())
256 self.sequence_idx = ossia::clamp<int64_t>((int64_t)
self.sequence_idx, 0, (int64_t)
self.sequence.size() - 1);
257 out.write_value(
self.sequence[
self.sequence_idx], bang.timestamp);
258 self.sequence_idx = (
self.sequence_idx + 1) %
self.sequence.size();
263 #undef debug_vector_t
Definition: FactorOracle.hpp:71
int LCS(int p1, int p2)
Function LCS (longest common suffix)
Definition: FactorOracle.hpp:86
Utilities for OSSIA data structures.
Definition: DeviceInterface.hpp:33
Definition: FactorOracle.hpp:209
Definition: FactorOracle.hpp:53
Definition: FactorOracle.hpp:23