FactorOracle2MIDI.hpp
1 #pragma once
2 #include <Engine/Node/SimpleApi.hpp>
3 
4 #include <ossia/detail/hash_map.hpp>
5 #include <ossia/detail/math.hpp>
6 #include <ossia/detail/ssize.hpp>
7 
8 #include <random>
9 #if !defined(NDEBUG) && !defined(_MSC_VER) && !defined(__clang__)
10 #include <debug/vector>
11 #define debug_vector_t __gnu_debug::vector
12 #else
13 #define debug_vector_t std::vector
14 #endif
15 
53 namespace FactorOracle2MIDI
54 {
57 class Notes
58 {
59 public:
60  int note;
61  int pitch;
62  double startTime;
63  double endTime;
64 };
65 template <class T>
67 {
68 public:
71  T symbol_;
72 };
73 
80 template <class T>
81 class State
82 {
83 public:
84  int state_;
85  std::vector<SingleTransition<T>> transition_;
86  int suffix_transition_;
87  int lrs_ = 0;
88  void singleTransitionResize() { transition_.resize(10); }
89 };
90 
91 template <class T>
93 {
94 public:
95  int phi, k, fo_iter, current_state = 1;
96  std::vector<T> input_values;
97  std::vector<State<T>> states_;
98  std::vector<std::vector<int>>
101  {
102  this->states_.resize(2);
103  this->states_[0].state_ = 0;
104  this->states_[0].lrs_ = 0;
105  this->states_[0].suffix_transition_ = -1;
106  this->RevSuffix.resize(2);
107  }
108  void AddLetter(int i, std::vector<T> word)
109  {
111 
115  if(i != 0)
116  {
117  this->states_.resize(i + 1);
118  this->RevSuffix.resize(i + 1);
119  T alpha = word[i - 1];
120  this->AddState(i - 1);
121  int state_m_plus_one = i;
122  this->AddTransition(i - 1, i, alpha);
123  k = this->states_[i - 1].suffix_transition_;
124  phi = i - 1;
125  int flag = 0, iter = 0;
132  while(k > -1 && flag == 0)
133  {
134  while(iter < this->states_[k].transition_.size())
135  {
136  if(this->states_[k].transition_[iter].symbol_ == alpha)
137  {
138  flag = 1;
139  }
140  iter++;
141  }
142  if(flag == 0)
143  {
144  this->AddTransition(k, state_m_plus_one, alpha);
145  phi = k;
146  k = this->states_[k].suffix_transition_;
147  iter = 0;
148  }
149  }
150  if(k == -1)
151  {
152  this->states_[state_m_plus_one].suffix_transition_ = 0;
153  this->states_[state_m_plus_one].lrs_ = 0;
154  }
155  else
156  {
157  flag = 0, iter = 0;
158  if(this->states_[k].transition_[iter].symbol_ == alpha)
159  {
160  flag = 1;
161  this->states_[state_m_plus_one].suffix_transition_
162  = this->states_[k].transition_[iter].last_state_;
163  this->states_[state_m_plus_one].lrs_
164  = this->LengthCommonSuffix(
165  phi, this->states_[state_m_plus_one].suffix_transition_ - 1)
166  + 1;
167  }
168  while(iter < this->states_[k].transition_.size() && flag == 0)
169  {
170  if(this->states_[k].transition_[iter].symbol_ == alpha)
171  {
172 
173  this->states_[state_m_plus_one].suffix_transition_
174  = this->states_[k].transition_[iter].last_state_;
175  this->states_[state_m_plus_one].lrs_
176  = this->LengthCommonSuffix(
177  phi, this->states_[state_m_plus_one].suffix_transition_ - 1)
178  + 1;
179  flag = 1;
180  }
181 
182  iter++;
183  }
184  }
185  T temp_word = word[state_m_plus_one - this->states_[state_m_plus_one].lrs_ - 1];
186  k = this->FindBetter(state_m_plus_one, temp_word, word);
187  if(k != 0)
188  {
189  this->states_[state_m_plus_one].lrs_ = this->states_[state_m_plus_one].lrs_ + 1;
190  this->states_[state_m_plus_one].suffix_transition_ = k;
191  }
192  RevSuffix[this->states_[state_m_plus_one].suffix_transition_].push_back(
193  state_m_plus_one);
194  }
195  };
196  int LengthCommonSuffix(int phi_one, int phi_two)
197  {
198  if(phi_two == this->states_[phi_one].suffix_transition_)
199  return this->states_[phi_one].lrs_;
200  else
201  {
202  while(this->states_[phi_one].suffix_transition_
203  != this->states_[phi_two].suffix_transition_)
204  phi_two = this->states_[phi_two].suffix_transition_;
205  }
206  if(this->states_[phi_one].lrs_ <= this->states_[phi_two].lrs_)
207  return this->states_[phi_one].lrs_;
208  else
209  return this->states_[phi_two].lrs_;
210  };
211  int FindBetter(int i, T alpha, std::vector<T> word)
212  {
214 
221  int len_t = this->RevSuffix[this->states_[i].suffix_transition_].size();
222  int statei = this->states_[i].suffix_transition_;
223  if(len_t == 0)
224  return 0;
225  sort(this->RevSuffix[statei].begin(), this->RevSuffix[statei].end());
226  for(int j = 0; j < len_t; j++)
227  {
228  if(this->states_[this->RevSuffix[this->states_[i].suffix_transition_][j]].lrs_
229  == this->states_[i].lrs_
230  && word
231  [this->RevSuffix[this->states_[i].suffix_transition_][j]
232  - this->states_[i].lrs_ - 1]
233  == alpha)
234  {
235  int output_midi = RevSuffix[this->states_[i].suffix_transition_][j];
236  return output_midi;
237  }
238  }
239  return 0;
240  };
241  std::vector<T> FOGenerate(int& i, std::vector<T> v, float q)
242  {
244 
250  std::random_device rd;
251  std::mt19937 gen(rd());
252  std::uniform_real_distribution<> dis(0.0, 1.0);
253  float u = dis(gen);
254  if(this->states_.size() == 2 || this->states_.size() == 1)
255  {
256  v.push_back(this->states_[0].transition_[0].symbol_);
257  }
258  else
259  {
260  if(u < q)
261  {
262  i = i + 1;
263  int len = this->states_.size();
264  if(i >= len)
265  i = len - 1;
266  T w = this->states_[i].transition_[0].symbol_;
267  v.push_back(w);
268  }
269  else
270  {
271  int lenSuffix
272  = this->states_[this->states_[i].suffix_transition_].transition_.size() - 1;
273  std::random_device rd;
274  std::mt19937 gen(rd());
275  std::uniform_int_distribution<> dis_int(0, lenSuffix);
276  int rand_alpha = dis_int(gen);
277  T alpha = this->states_[this->states_[i].suffix_transition_]
278  .transition_[rand_alpha]
279  .symbol_;
280  i = this->states_[this->states_[i].suffix_transition_]
281  .transition_[rand_alpha]
282  .last_state_;
283  if(i == -1)
284  {
285  i = 0;
286  }
287  v.push_back(alpha);
288  }
289  }
290  return v;
291  };
292  void FactorOracleStart(std::vector<T> word)
293  {
295 
298  int len = std::ssize(word);
299  this->states_.resize(2);
300  this->states_[0].state_ = 0;
301  this->states_[0].lrs_ = 0;
302  this->states_[0].suffix_transition_ = -1;
303  this->RevSuffix.resize(2);
304  };
305  void AddState(int first_state) { this->states_[first_state].state_ = first_state; };
306  void AddTransition(int first_state, int last_state, T symbol)
307  {
308  SingleTransition<T> transition_i;
309  transition_i.first_state_ = first_state;
310  transition_i.last_state_ = last_state;
311  transition_i.symbol_ = symbol;
312  this->states_[first_state].transition_.push_back(transition_i);
313  };
314  std::vector<T> CallGenerate(int len, float q)
315  {
316 
317  std::vector<T> oracle = {};
318  fo_iter = 1;
319  for(int x = 0; x < len; x++)
320  {
321  oracle = this->FOGenerate(fo_iter, oracle, q);
322  if(fo_iter == len)
323  fo_iter = len - 1;
324  }
325  return oracle;
326  };
327 };
328 }
329 namespace Nodes::FactorOracle2MIDI
330 {
331 struct Node
332 {
334  {
335  static const constexpr auto prettyName = "New Factor Oracle MIDI";
336  static const constexpr auto objectKey = "New Factor Oracle MIDI";
337  static const constexpr auto category = "Control/Impro";
338  static const constexpr auto author = "Maria Paula Carrero Rivas";
339  static const constexpr auto kind = Process::ProcessCategory::Mapping;
340  static const constexpr auto description = "Factor Oracle algorithm ."; // TODO cite
341  static const constexpr auto tags = std::array<const char*, 0>{};
342  static const uuid_constexpr auto uuid
343  = make_uuid("C87B5326-56C2-4489-8E08-AA9E1EF27359");
344 
345  static const constexpr auto controls
346  = tuplet::make_tuple(Control::IntSlider{"Sequence length", 1, 64, 8});
347  static const constexpr midi_in midi_ins[]{"input_midi"};
348  static const constexpr midi_out midi_outs[]{"output_midi"};
349  static const constexpr value_in value_ins[]{"regen", "bang"};
350  };
351 
352  struct State
353  {
355  int i = 0;
356  debug_vector_t<libremidi::midi_bytes> sequence;
357  debug_vector_t<libremidi::midi_bytes> midi_bytes;
358  std::size_t sequence_idx{};
359  };
360 
361  using control_policy = ossia::safe_nodes::last_tick;
362  static void
363  run(const ossia::midi_port& input_midi, const ossia::value_port& regen,
364  const ossia::value_port& bangs, int seq_len, ossia::midi_port& output_midi,
365  ossia::token_request, ossia::exec_state_facade, State& self)
366  {
367 
368  // EntrĂ©es sont dans p1
369  for(auto val : input_midi.messages)
370  {
372  temp.pitch = val.bytes[1];
373  self.oracle.input_values.push_back(val.bytes[1]);
374  self.oracle.AddLetter(self.oracle.current_state, self.oracle.input_values);
375  self.oracle.current_state = self.oracle.current_state + 1;
376  }
377 
378  if(!regen.get_data().empty())
379  {
380  if(!self.oracle.input_values.empty())
381  {
382  std::vector<int> temp_vec = self.oracle.CallGenerate(seq_len, 0.6);
383  //self.sequence = self.oracle.CallGenerate(seq_len, 0.6);
384  self.midi_bytes.push_back({144, 0, 40});
385  self.midi_bytes[seq_len][1] = temp_vec[seq_len];
386  self.sequence = self.midi_bytes;
387  }
388  }
389 
390  if(!self.sequence.empty() && !self.oracle.input_values.empty())
391  {
392  for(auto& bang : bangs.get_data())
393  {
394  self.sequence_idx = ossia::clamp<int64_t>(
395  (int64_t)self.sequence_idx, 0, (int64_t)self.sequence.size() - 1);
396  libremidi::message tmp;
397  tmp.bytes = self.sequence[self.sequence_idx];
398  tmp.timestamp = bang.timestamp;
399  output_midi.messages.push_back(tmp);
400  self.sequence_idx = (self.sequence_idx + 1) % self.sequence.size();
401  }
402  }
403  }
404 };
405 #undef debug_vector_t
406 }
Definition: FactorOracle2MIDI.hpp:93
std::vector< State< T > > states_
Definition: FactorOracle2MIDI.hpp:97
int FindBetter(int i, T alpha, std::vector< T > word)
Definition: FactorOracle2MIDI.hpp:211
FactorOracle2MIDI()
Definition: FactorOracle2MIDI.hpp:100
void FactorOracleStart(std::vector< T > word)
Definition: FactorOracle2MIDI.hpp:292
std::vector< std::vector< int > > RevSuffix
Definition: FactorOracle2MIDI.hpp:99
void AddLetter(int i, std::vector< T > word)
Definition: FactorOracle2MIDI.hpp:108
std::vector< T > FOGenerate(int &i, std::vector< T > v, float q)
Definition: FactorOracle2MIDI.hpp:241
Definition: FactorOracle2MIDI.hpp:58
Definition: FactorOracle2MIDI.hpp:67
int first_state_
Definition: FactorOracle2MIDI.hpp:69
T symbol_
Definition: FactorOracle2MIDI.hpp:71
int last_state_
Definition: FactorOracle2MIDI.hpp:70
std::vector< SingleTransition< T > > transition_
denotes the number of the state
Definition: FactorOracle2MIDI.hpp:85
int state_
denotes the number of the state
Definition: FactorOracle2MIDI.hpp:84
Utilities for OSSIA data structures.
Definition: DeviceInterface.hpp:33
Definition: score-lib-process/Control/Widgets.hpp:178
Definition: SimpleApi.hpp:32
Definition: FactorOracle2MIDI.hpp:334
Definition: FactorOracle2MIDI.hpp:332