sequencer
system_exclusive.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <sequencer/assert.hpp>
7 
8 #include <cstdint>
9 
11 {
12  constexpr message_t< 1 > end_system_exclusive() noexcept
13  {
14  return {byte::sysex_end};
15  }
16 
17  template < class... Data >
18  constexpr message_t< sizeof...( Data ) + 3u > system_exclusive( std::byte manufacturer_id,
19  Data&&... data ) noexcept
20  {
21  return {byte::sysex_start, manufacturer_id, std::byte( std::forward< Data >( data ) )...,
23  }
24 
25  template < class... Data >
26  constexpr message_t< sizeof...( Data ) + 3u > system_exclusive( std::uint8_t manufacturer_id,
27  Data&&... data ) noexcept
28  {
29  return system_exclusive( std::byte{manufacturer_id}, std::forward< Data >( data )... );
30  }
31 
32  template < class... Data >
33  constexpr message_t< sizeof...( Data ) + 5u > system_exclusive( message_t< 3 > manufacturer_id,
34  Data&&... data ) noexcept
35  {
36  return {byte::sysex_start,
37  manufacturer_id[ 0 ],
38  manufacturer_id[ 1 ],
39  manufacturer_id[ 2 ],
40  std::byte( std::forward< Data >( data ) )...,
42  }
43 
44  template < class... Data >
45  constexpr message_t< sizeof...( Data ) + 5u >
46  system_exclusive( std::array< std::uint8_t, 3 > manufacturer_id, Data&&... data ) noexcept
47  {
48  return system_exclusive( std::byte{manufacturer_id[ 0 ]}, std::byte{manufacturer_id[ 1 ]},
49  std::byte{manufacturer_id[ 2 ]}, std::forward< Data >( data )... );
50  }
51 
52  namespace realtime
53  {
54  constexpr auto id_byte = std::byte{0x7F};
55 
56  template < class... Data >
57  constexpr message_t< sizeof...( Data ) + 4u >
58  system_exclusive( std::uint8_t manufacturer_id, Data&&... data ) noexcept
59  {
60  return exclusive::system_exclusive( id_byte, manufacturer_id,
61  std::forward< Data >( data )... );
62  }
63 
64  constexpr message_t< 8 > device_control( std::uint8_t manufacturer_id, std::uint8_t key,
65  std::uint16_t value ) noexcept
66  {
67  const auto hex_value = uint16_to_lsb_msb( value );
68  return system_exclusive( manufacturer_id, byte::sysex::device_control, key,
69  hex_value.first, hex_value.second );
70  }
71 
72  constexpr message_t< 8 > master_volume( std::uint8_t manufacturer_id,
73  std::uint16_t value ) noexcept
74  {
75  return device_control( manufacturer_id, 0x01, value );
76  }
77 
78  constexpr message_t< 8 > master_balance( std::uint8_t manufacturer_id,
79  std::uint16_t value ) noexcept
80  {
81  return device_control( manufacturer_id, 0x02, value );
82  }
83 
84  constexpr message_t< 8 > master_fine_tuning( std::uint8_t manufacturer_id,
85  std::uint16_t value ) noexcept
86  {
87  return device_control( manufacturer_id, 0x03, value );
88  }
89 
90  constexpr message_t< 8 > master_coarse_tuning( std::uint8_t manufacturer_id,
91  std::uint16_t value ) noexcept
92  {
93  return device_control( manufacturer_id, 0x04, value );
94  }
95 
96  template < std::size_t... index >
97  constexpr message_t< 4 + sizeof...( index ) >
98  make_sysex( std::uint8_t manufacturer_id, const message_t< sizeof...( index ) >& data,
99  std::index_sequence< index... > )
100  {
101  return system_exclusive( manufacturer_id, data[ index ]... );
102  }
103 
104  template < class Id, class Value, std::size_t number_of_values,
105  std::size_t number_of_slots = 0 >
106  constexpr message_t< 9 + ( sizeof( Id ) + sizeof( Value ) ) * number_of_values +
107  2 * number_of_slots >
109  std::uint8_t manufacturer_id,
110  const std::array< std::pair< Id, Value >, number_of_values >& id_value_pairs,
111  const std::array< std::uint16_t, number_of_slots >& slots = {} ) noexcept
112  {
113  constexpr auto pair_size = sizeof( Id ) + sizeof( Value );
114  constexpr auto user_data_size = pair_size * number_of_values + 2 * number_of_slots;
116  data[ 0 ] = byte::sysex::device_control;
117  data[ 1 ] = std::byte{0x05}; // global parameter control
118  data[ 2 ] = std::byte{number_of_slots};
119  data[ 3 ] = std::byte{sizeof( Id )};
120  data[ 4 ] = std::byte{sizeof( Value )};
121 
122  for ( auto i = std::size_t{0}; i < number_of_slots; ++i )
123  {
124  const auto [ lsb, msb ] = uint16_to_lsb_msb( slots[ i ] );
125  data[ 5 + 2 * i ] = std::byte{msb};
126  data[ 5 + 2 * i + 1 ] = std::byte{lsb};
127  }
128 
129  const auto offset = 5 + 2 * number_of_slots;
130  for ( auto i = std::size_t{0}; i < number_of_values; ++i )
131  {
132  if constexpr ( sizeof( Id ) == 1 && sizeof( Value ) == 1 )
133  {
134  data[ offset + pair_size * i ] = std::byte{id_value_pairs[ i ].first};
135  data[ offset + pair_size * i + 1 ] = std::byte{id_value_pairs[ i ].second};
136  }
137 
138  if constexpr ( sizeof( Id ) == 2 && sizeof( Value ) == 1 )
139  {
140  const auto [ id_lsb, id_msb ] = uint16_to_lsb_msb( id_value_pairs[ i ].first );
141  data[ offset + pair_size * i ] = std::byte{id_msb};
142  data[ offset + pair_size * i + 1 ] = std::byte{id_lsb};
143  data[ offset + pair_size * i + 2 ] = std::byte{id_value_pairs[ i ].second};
144  }
145 
146  if constexpr ( sizeof( Id ) == 1 && sizeof( Value ) == 2 )
147  {
148  const auto [ value_lsb, value_msb ] =
149  uint16_to_lsb_msb( id_value_pairs[ i ].second );
150  data[ offset + pair_size * i ] = std::byte{id_value_pairs[ i ].first};
151  data[ offset + pair_size * i + 1 ] = std::byte{value_lsb};
152  data[ offset + pair_size * i + 2 ] = std::byte{value_msb};
153  }
154 
155  if constexpr ( sizeof( Id ) == 2 && sizeof( Value ) == 2 )
156  {
157  const auto [ id_lsb, id_msb ] = uint16_to_lsb_msb( id_value_pairs[ i ].first );
158  data[ offset + pair_size * i ] = std::byte{id_msb};
159  data[ offset + pair_size * i + 1 ] = std::byte{id_lsb};
160  const auto [ value_lsb, value_msb ] =
161  uint16_to_lsb_msb( id_value_pairs[ i ].second );
162  data[ offset + pair_size * i + 2 ] = std::byte{value_lsb};
163  data[ offset + pair_size * i + 3 ] = std::byte{value_msb};
164  }
165  }
166 
167  return make_sysex( manufacturer_id, data,
168  std::make_index_sequence< 5 + user_data_size >() );
169  }
170 
171  enum class key_based_instrument_control_type : std::uint8_t
172  {
173  note_volume = 0x07,
174  pan = 0x0A,
176  release_time = 0x48,
177  attack_time = 0x49,
178  brightness = 0x4A,
179  decay_time = 0x4B,
180  vibrato_rate = 0x4C,
181  vibrato_depth = 0x4D,
182  vibrato_delay = 0x4E,
183  reverb_send = 0x5B,
184  chorus_send = 0x5D,
185  fine_tuning = 0x78,
186  coarse_tuning = 0x79
187  };
188 
189  constexpr std::uint8_t to_uint8( key_based_instrument_control_type type ) noexcept
190  {
191  return static_cast< std::uint8_t >( type );
192  }
193 
194  template < std::size_t number_of_entries >
196  std::uint8_t manufacturer_id, std::uint8_t channel, std::uint8_t key,
197  const std::array< std::pair< std::uint8_t, std::uint8_t >, number_of_entries >&
198  number_value_pairs ) noexcept
199  {
200  SEQUENCER_ASSERT( channel < 16 );
201  constexpr auto fixed_entry_offset = 4u;
202  constexpr auto data_size = fixed_entry_offset + 2 * number_of_entries;
204  data[ 0 ] = std::byte{0x0A};
205  data[ 1 ] = std::byte{0x01};
206  data[ 2 ] = std::byte{channel};
207  data[ 3 ] = std::byte{key};
208  for ( auto i = std::size_t{0}; i < number_of_entries; ++i )
209  {
210  const auto id = number_value_pairs[ i ].first;
211  const auto value = number_value_pairs[ i ].second;
212  data[ fixed_entry_offset + 2 * i ] = std::byte{id};
215  ( value <= 0x40 ) );
217  !( id ==
219  ( value <= 0x40 ) );
222  ( value <= 0x40 ) );
225  ( value <= 0x40 ) );
228  ( value <= 0x40 ) );
231  ( value <= 0x40 ) );
234  ( value <= 0x40 ) );
237  ( value <= 0x40 ) );
240  ( value <= 0x40 ) );
243  ( value <= 0x40 ) );
246  ( value <= 0x40 ) );
247  data[ fixed_entry_offset + 2 * i + 1 ] = std::byte{value};
248  }
249 
250  return make_sysex( manufacturer_id, data, std::make_index_sequence< data_size >() );
251  }
252  } // namespace realtime
253 
254  namespace non_realtime
255  {
256  static constexpr auto id_byte = std::byte{0x7E};
257  static constexpr auto gm_byte = std::byte{0x09};
258  static constexpr auto dls_byte = std::byte{0x0A};
259 
260  template < class... Data >
261  constexpr message_t< sizeof...( Data ) + 4u >
262  system_exclusive( std::uint8_t manufacturer_id, Data&&... data ) noexcept
263  {
264  return exclusive::system_exclusive( id_byte, manufacturer_id,
265  std::forward< Data >( data )... );
266  }
267 
268  constexpr message_t< 6 > general_midi_system( std::uint8_t manufacturer_id,
269  std::uint8_t value ) noexcept
270  {
271  return system_exclusive( manufacturer_id, gm_byte, value );
272  }
273 
274  constexpr message_t< 6 >
275  general_midi_system_disable( std::uint8_t manufacturer_id ) noexcept
276  {
277  return general_midi_system( manufacturer_id, 0x02 );
278  }
279 
280  constexpr message_t< 6 >
281  general_midi_1_system_enable( std::uint8_t manufacturer_id ) noexcept
282  {
283  return general_midi_system( manufacturer_id, 0x01 );
284  }
285 
286  constexpr message_t< 6 >
287  general_midi_2_system_enable( std::uint8_t manufacturer_id ) noexcept
288  {
289  return general_midi_system( manufacturer_id, 0x03 );
290  }
291 
292  constexpr message_t< 6 > downloadable_sounds( std::uint8_t manufacturer_id,
293  std::byte value ) noexcept
294  {
295  return system_exclusive( manufacturer_id, dls_byte, value );
296  }
297 
298  constexpr message_t< 6 > downloadable_sounds( std::uint8_t manufacturer_id,
299  bool on ) noexcept
300  {
301  const std::uint8_t value = on ? 0x01 : 0x02;
302  return downloadable_sounds( manufacturer_id, std::byte{value} );
303  }
304 
305  constexpr message_t< 6 > downloadable_sounds_voice_allocation( std::uint8_t manufacturer_id,
306  bool on ) noexcept
307  {
308  const std::uint8_t value = on ? 0x04 : 0x03;
309  return downloadable_sounds( manufacturer_id, std::byte{value} );
310  }
311  } // namespace non_realtime
312 } // namespace sequencer::midi::system::exclusive
constexpr message_t< 4+sizeof...(index) > make_sysex(std::uint8_t manufacturer_id, const message_t< sizeof...(index) > &data, std::index_sequence< index... >)
Definition: system_exclusive.hpp:98
constexpr auto sysex_end
Definition: byte.hpp:24
constexpr message_t< 6 > general_midi_system_disable(std::uint8_t manufacturer_id) noexcept
Definition: system_exclusive.hpp:275
constexpr message_t< 8 > master_balance(std::uint8_t manufacturer_id, std::uint16_t value) noexcept
Definition: system_exclusive.hpp:78
constexpr message_t< 8 > master_volume(std::uint8_t manufacturer_id, std::uint16_t value) noexcept
Definition: system_exclusive.hpp:72
std::conditional_t< greater_than< number_of_bytes, 0 >::value, std::array< std::byte, number_of_bytes >, std::vector< std::byte > > message_t
Definition: message_type.hpp:18
#define SEQUENCER_ASSERT(cond)
Definition: assert.hpp:8
constexpr message_t< 6 > general_midi_1_system_enable(std::uint8_t manufacturer_id) noexcept
Definition: system_exclusive.hpp:281
constexpr auto sysex_start
Definition: byte.hpp:23
constexpr auto lsb(std::byte msb)
Definition: byte.hpp:37
constexpr message_t< 8 > master_fine_tuning(std::uint8_t manufacturer_id, std::uint16_t value) noexcept
Definition: system_exclusive.hpp:84
constexpr message_t< 1 > end_system_exclusive() noexcept
Definition: system_exclusive.hpp:12
constexpr auto id_byte
Definition: system_exclusive.hpp:54
key_based_instrument_control_type
Definition: system_exclusive.hpp:171
constexpr message_t< 8+2 *number_of_entries > key_based_instrument_control(std::uint8_t manufacturer_id, std::uint8_t channel, std::uint8_t key, const std::array< std::pair< std::uint8_t, std::uint8_t >, number_of_entries > &number_value_pairs) noexcept
Definition: system_exclusive.hpp:195
constexpr std::uint8_t to_uint8(key_based_instrument_control_type type) noexcept
Definition: system_exclusive.hpp:189
constexpr auto device_control
Definition: byte.hpp:102
constexpr message_t< sizeof...(Data)+3u > system_exclusive(std::byte manufacturer_id, Data &&... data) noexcept
Definition: system_exclusive.hpp:18
constexpr message_t< 9+(sizeof(Id)+sizeof(Value)) *number_of_values+2 *number_of_slots > global_parameter_control(std::uint8_t manufacturer_id, const std::array< std::pair< Id, Value >, number_of_values > &id_value_pairs, const std::array< std::uint16_t, number_of_slots > &slots={}) noexcept
Definition: system_exclusive.hpp:108
Definition: system_exclusive.hpp:10
constexpr message_t< 8 > device_control(std::uint8_t manufacturer_id, std::uint8_t key, std::uint16_t value) noexcept
Definition: system_exclusive.hpp:64
constexpr std::pair< std::byte, std::byte > uint16_to_lsb_msb(std::uint16_t value) noexcept
Definition: util.hpp:34
constexpr message_t< sizeof...(Data)+4u > system_exclusive(std::uint8_t manufacturer_id, Data &&... data) noexcept
Definition: system_exclusive.hpp:58
constexpr message_t< 8 > master_coarse_tuning(std::uint8_t manufacturer_id, std::uint16_t value) noexcept
Definition: system_exclusive.hpp:90
constexpr message_t< 6 > downloadable_sounds_voice_allocation(std::uint8_t manufacturer_id, bool on) noexcept
Definition: system_exclusive.hpp:305
constexpr message_t< 6 > general_midi_system(std::uint8_t manufacturer_id, std::uint8_t value) noexcept
Definition: system_exclusive.hpp:268
constexpr message_t< 6 > general_midi_2_system_enable(std::uint8_t manufacturer_id) noexcept
Definition: system_exclusive.hpp:287
constexpr message_t< 6 > downloadable_sounds(std::uint8_t manufacturer_id, bool on) noexcept
Definition: system_exclusive.hpp:298