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();