sequencer
digitakt_parameter.hpp
Go to the documentation of this file.
1 #pragma once
2 
6 #include <sequencer/midi/lfo.hpp>
9 
10 #include <algorithm>
11 #include <array>
12 #include <cassert>
13 #include <fstream>
14 #include <limits>
15 #include <regex>
16 
18 {
19  inline std::array< double, 128 > create_length_map()
20  {
21  std::array< double, 128 > length_map;
22  using size_type = std::array< double, 128 >::size_type;
23  auto value = 0.125;
24  size_type start = 0;
25  size_type end = 30;
26  const auto add_values = [&]( auto delta ) {
27  for ( size_type i = start; i < end; ++i )
28  {
29  length_map[ i ] = value / 4;
30  value += delta;
31  }
32  start = end;
33  end = start + 16;
34  };
35 
36  add_values( 0.0625 );
37  add_values( 0.125 );
38  add_values( 0.25 );
39  add_values( 0.5 );
40  add_values( 1.0 );
41  add_values( 2.0 );
42  add_values( 4.0 );
43  length_map[ 127 ] = std::numeric_limits< double >::max();
44  return length_map;
45  }
46 
47  inline const std::array< double, 128 >& length_map()
48  {
49  static const auto length_map = create_length_map();
50  return length_map;
51  }
52 
54  {
55  std::vector< std::vector< midi::device_entry_t > > control_parameter;
56  };
57 
58  template < class >
59  class lfo_t;
60 
62  {
63  enum idx
64  {
65  trig = 0,
68  amp,
69  lfo,
72  count
73  };
74 
75  static constexpr auto note_offset_idx = 0u;
76  static constexpr auto velocity_idx = 1u;
77  static constexpr auto length_idx = 2u;
78  enum lfo_idx
79  {
80  speed = 0,
86  mod,
87  depth
88  };
89 
91  {
92  triangular = 0,
95  saw,
96  exp,
98  random
99  };
100 
101  track_parameter_t() : midi::track_parameter_t{idx::count, length_idx + 1}
102  {
103  }
104 
105  auto note_offset() const noexcept
106  {
107  return values[ idx::trig ][ note_offset_idx ].load();
108  }
109 
110  auto velocity() const noexcept
111  {
112  return values[ idx::trig ][ velocity_idx ].load();
113  }
114 
115  void set_velocity( std::uint16_t velocity ) noexcept
116  {
117  values[ idx::trig ][ velocity_idx ] = velocity;
118  }
119 
120  beat_duration note_length() const noexcept
121  {
122  return beat_duration{length_map()[ values[ idx::trig ][ length_idx ].load() ]};
123  }
124 
125  void set_note_length_idx( std::uint16_t idx ) noexcept
126  {
127  values[ idx::trig ][ length_idx ] = idx;
128  }
129 
130  auto lfo_destination() const noexcept
131  {
132  return values[ idx::lfo ][ lfo_idx::destination ];
133  }
134 
135  auto lfo_speed() const noexcept
136  {
137  return values[ idx::lfo ][ lfo_idx::speed ] * values[ idx::lfo ][ lfo_idx::multiplier ];
138  }
139 
140  bool lfo_enabled() const noexcept
141  {
142  return lfo_destination() > 0 && lfo_speed() != 0;
143  }
144 
145  template < class F >
146  auto lfo_func( std::uint8_t min, std::uint8_t max, F f ) const noexcept
147  {
148  return lfo_t< F >{min, max, f, values[ idx::lfo ]};
149  }
150  };
151 
152  template < class F >
153  class lfo_t
154  {
155  public:
156  explicit lfo_t( std::uint8_t min, std::uint8_t max, F f,
157  const midi::track_parameter_t::parameters_type& parameters ) noexcept
158  : min_{min}, max_{max}, f_{f}, parameters_{parameters}
159  {
160  }
161 
162  std::optional< midi::message_t< 3 > > operator()( std::size_t pulses_per_quarter_note,
163  bool restart, bool note_send ) const
164  noexcept
165  {
166  if ( restart || ( lfo_trig_mode() && note_send ) )
167  {
168  pulse_count_ = 0;
169  if ( restart )
170  {
171  return {};
172  }
173  }
174 
175  if ( lfo_hold_mode() && !note_send )
176  {
177  ++pulse_count_;
178  return {};
179  }
180 
181  const auto period_length = 4 * pulses_per_quarter_note * 128 / lfo_speed();
182  if ( ( lfo_one_mode() && pulse_count_ > period_length ) ||
183  ( lfo_half_mode() && pulse_count_ > period_length / 2 ) )
184  {
185  return {};
186  }
187  if ( ( lfo_one_mode() && pulse_count_ == period_length ) ||
188  ( lfo_half_mode() && pulse_count_ == period_length / 2 ) )
189  {
190  ++pulse_count_;
191  return f_( ( min_ + max_ ) / 2 + ( min_ + max_ ) % 2 );
192  }
193 
194  const auto lfo_value = midi::lfo< std::uint8_t >(
195  pulse_count_++, pulses_per_quarter_note, lfo_speed(), lfo_phase(), min_, max_,
196  static_cast< midi::lfo_mode >(
197  parameters_[ track_parameter_t::lfo_idx::wave_form ].load() ) );
198  return f_( lfo_value );
199  }
200 
201  private:
202  bool lfo_trig_mode() const noexcept
203  {
204  return parameters_[ track_parameter_t::lfo_idx::mod ] == 1;
205  }
206 
207  bool lfo_hold_mode() const noexcept
208  {
209  return parameters_[ track_parameter_t::lfo_idx::mod ] == 2;
210  }
211 
212  bool lfo_one_mode() const noexcept
213  {
214  return parameters_[ track_parameter_t::lfo_idx::mod ] == 3;
215  }
216 
217  bool lfo_half_mode() const noexcept
218  {
219  return parameters_[ track_parameter_t::lfo_idx::mod ] == 4;
220  }
221 
222  auto lfo_phase() const noexcept
223  {
224  return parameters_[ track_parameter_t::lfo_idx::phase ];
225  }
226 
227  auto lfo_speed() const noexcept
228  {
229  return parameters_[ track_parameter_t::lfo_idx::speed ] *
230  parameters_[ track_parameter_t::lfo_idx::multiplier ];
231  }
232 
233  std::uint8_t min_;
234  std::uint8_t max_;
235  F f_;
236  const midi::track_parameter_t::parameters_type& parameters_;
237  mutable std::size_t pulse_count_{0};
238  };
239 
240 #define READ_SECTION( section_name ) \
241  if ( section.name == #section_name ) \
242  { \
243  device_spec.control_parameter[ track_parameter_t::idx::section_name ].resize( \
244  section.entries.size() ); \
245  std::copy( \
246  begin( section.entries ), end( section.entries ), \
247  begin( device_spec.control_parameter[ track_parameter_t::idx::section_name ] ) ); \
248  continue; \
249  }
250 
251  inline device_spec_cc_t read_device_spec_cc( std::istream& stream )
252  {
253  const auto sections = midi::read_file( stream );
254 
255  device_spec_cc_t device_spec;
256  device_spec.control_parameter.resize( sections.size() );
257  for ( const auto& section : sections )
258  {
259  READ_SECTION( trig )
262  READ_SECTION( amp )
263  READ_SECTION( lfo )
266  }
267 
268  return device_spec;
269  }
270 #undef READ_SECTION
271 } // namespace sequencer::backend::digitakt
Definition: digitakt_parameter.hpp:96
Definition: digitakt_parameter.hpp:86
Definition: digitakt_parameter.hpp:67
#define READ_SECTION(section_name)
Definition: digitakt_parameter.hpp:240
Definition: digitakt_parameter.hpp:95
std::optional< midi::message_t< 3 > > operator()(std::size_t pulses_per_quarter_note, bool restart, bool note_send) const noexcept
Definition: digitakt_parameter.hpp:162
const auto F
Definition: note.hpp:40
Definition: digitakt_parameter.hpp:70
Definition: digitakt_parameter.hpp:69
auto lfo_destination() const noexcept
Definition: digitakt_parameter.hpp:130
const std::array< double, 128 > & length_map()
Definition: digitakt_parameter.hpp:47
auto lfo_func(std::uint8_t min, std::uint8_t max, F f) const noexcept
Definition: digitakt_parameter.hpp:146
lfo_t(std::uint8_t min, std::uint8_t max, F f, const midi::track_parameter_t::parameters_type &parameters) noexcept
Definition: digitakt_parameter.hpp:156
std::vector< section_t > read_file(std::istream &file)
Definition: device_spec_reader.hpp:96
auto note_offset() const noexcept
Definition: digitakt_parameter.hpp:105
Definition: digitakt_parameter.hpp:61
auto velocity() const noexcept
Definition: digitakt_parameter.hpp:110
Definition: beat_duration.hpp:13
std::vector< std::vector< midi::device_entry_t > > control_parameter
Definition: digitakt_parameter.hpp:55
Definition: digitakt_parameter.hpp:97
void set_note_length_idx(std::uint16_t idx) noexcept
Definition: digitakt_parameter.hpp:125
device_spec_cc_t read_device_spec_cc(std::istream &stream)
Definition: digitakt_parameter.hpp:251
idx
Definition: digitakt_parameter.hpp:63
Definition: digitakt_parameter.hpp:93
bool lfo_enabled() const noexcept
Definition: digitakt_parameter.hpp:140
std::vector< copyable_atomic< std::int16_t > > parameters_type
Definition: track_parameter.hpp:12
lfo_idx
Definition: digitakt_parameter.hpp:78
Definition: digitakt_parameter.hpp:82
auto lfo_speed() const noexcept
Definition: digitakt_parameter.hpp:135
Definition: digitakt_parameter.hpp:66
track_parameter_t()
Definition: digitakt_parameter.hpp:101
Definition: digitakt_parameter.hpp:68
Definition: digitakt_parameter.hpp:85
Definition: digitakt_parameter.hpp:59
Definition: track_parameter.hpp:10
void set_velocity(std::uint16_t velocity) noexcept
Definition: digitakt_parameter.hpp:115
wave_from_idx
Definition: digitakt_parameter.hpp:90
Definition: digitakt_parameter.hpp:94
lfo_mode
Definition: lfo.hpp:11
Definition: digitakt.hpp:18
Definition: digitakt_parameter.hpp:71
beat_duration note_length() const noexcept
Definition: digitakt_parameter.hpp:120
std::array< double, 128 > create_length_map()
Definition: digitakt_parameter.hpp:19
Definition: digitakt_parameter.hpp:53