MIDI2LR 6.3.0.1
MIDI2LR is an application that interfaces MIDI controllers with Lightroom 6+/CC Classic. It processes MIDI input into develop parameter updates and photo actions, and sends MIDI output when parameters are changed for motorized feedback (on controllers that have motorized faders). A listing of available LightRoom commands is in the Wiki. Assistance on the code and design is welcome.
Loading...
Searching...
No Matches
ChannelModel Class Reference

#include <ControlsModel.h>

Public Member Functions

 ChannelModel () noexcept
double ControllerToPlugin (rsj::MessageType controltype, int controlnumber, int value, bool wrap)
int GetCcMax (int controlnumber) const
rsj::CCmethod GetCcMethod (int controlnumber) const
int GetCcMin (int controlnumber) const
int GetPwMax () const noexcept
int GetPwMin () const noexcept
int MeasureChange (rsj::MessageType controltype, int controlnumber, int value)
int PluginToController (rsj::MessageType controltype, int controlnumber, double value)
void SetCc (int controlnumber, int min, int max, rsj::CCmethod controltype)
void SetCcAll (int controlnumber, int min, int max, rsj::CCmethod controltype)
void SetCcMax (int controlnumber, int value)
void SetCcMethod (int controlnumber, rsj::CCmethod value)
void SetCcMin (int controlnumber, int value)
void SetPwMax (int value) noexcept
void SetPwMin (int value) noexcept
int SetToCenter (rsj::MessageType controltype, int controlnumber)

Private Member Functions

void ActiveToSaved () const
void CcDefaults () noexcept
int CenterCc (int controlnumber) const noexcept
int CenterPw () const noexcept
bool IsNrpn (int controlnumber) const noexcept
template<class Archive>
void load (Archive &archive, const uint32_t version)
double OffsetResult (int diff, int controlnumber, bool wrap)
template<class Archive>
void save (Archive &archive, const uint32_t version) const
void SavedToActive ()
void SaveSettings (int start, int end, int maxVal) const

Private Attributes

std::array< int, kMaxControlscc_high_ {}
std::array< int, kMaxControlscc_low_ {}
std::array< rsj::CCmethod, kMaxControlscc_method_ {}
std::array< std::atomic< int >, kMaxControlscurrent_v_ {}
std::atomic< int > pitch_wheel_current_ {kMaxNrpnHalf}
int pitch_wheel_max_ {kMaxNrpn}
int pitch_wheel_min_ {0}
std::vector< rsj::SettingsStructsettings_to_save_ {}

Static Private Attributes

static constexpr int kBit14 {0x2000}
static constexpr int kBit7 {0x40}
static constexpr int kLow13Bits {0x1FFF}
static constexpr int kLow6Bits {0x3F}
static constexpr size_t kMaxControls {0x4000}
static constexpr int kMaxMidi {0x7F}
static constexpr int kMaxMidiHalf {kMaxMidi / 2}
static constexpr int kMaxNrpn {0x3FFF}
static constexpr int kMaxNrpnHalf {kMaxNrpn / 2}

Friends

class cereal::access

Constructor & Destructor Documentation

◆ ChannelModel()

ChannelModel::ChannelModel ( )
inlinenoexcept
145{ CcDefaults(); }
void CcDefaults() noexcept
Definition ControlsModel.cpp:405

References CcDefaults().

Member Function Documentation

◆ ActiveToSaved()

void ChannelModel::ActiveToSaved ( ) const
private
393{
394 try {
395 settings_to_save_.clear();
398 }
399 catch (const std::exception& e) {
400 rsj::ExceptionResponse(e, std::source_location::current());
401 throw;
402 }
403}
void SaveSettings(int start, int end, int maxVal) const
Definition ControlsModel.cpp:382
std::vector< rsj::SettingsStruct > settings_to_save_
Definition ControlsModel.h:212
static constexpr int kMaxMidi
Definition ControlsModel.h:138
static constexpr int kMaxNrpn
Definition ControlsModel.h:140
void ExceptionResponse(gsl::czstring id, gsl::czstring fu, const std::exception &e) noexcept

References kMaxMidi, kMaxNrpn, and SaveSettings().

◆ CcDefaults()

void ChannelModel::CcDefaults ( )
privatenoexcept
406{
407 cc_low_.fill(0);
408 cc_high_.fill(kMaxNrpn);
410#ifdef __cpp_lib_atomic_ref
412 std::fill_n(cc_high_.begin(), kMaxMidi + 1, kMaxMidi);
413 std::fill_n(current_v_.begin(), kMaxMidi + 1, kMaxMidiHalf);
414#else
415 for (auto&& a : current_v_) { a.store(kMaxNrpnHalf, std::memory_order_relaxed); }
416 std::fill_n(cc_high_.begin(), kMaxMidi + 1, kMaxMidi);
417 for (size_t a {0}; a <= kMaxMidi; ++a) {
418 current_v_.at(a).store(kMaxMidiHalf, std::memory_order_relaxed);
419 }
420#endif
421}
std::array< int, kMaxControls > cc_low_
Definition ControlsModel.h:218
std::array< rsj::CCmethod, kMaxControls > cc_method_
Definition ControlsModel.h:216
static constexpr int kMaxNrpnHalf
Definition ControlsModel.h:141
std::array< int, kMaxControls > cc_high_
Definition ControlsModel.h:217
static constexpr int kMaxMidiHalf
Definition ControlsModel.h:139
std::array< std::atomic< int >, kMaxControls > current_v_
Definition ControlsModel.h:222
@ kAbsolute
Definition ControlsModel.h:33

References kMaxMidi.

Referenced by ChannelModel(), and SavedToActive().

◆ CenterCc()

int ChannelModel::CenterCc ( int controlnumber) const
inlinenodiscardprivatenoexcept
182 {
183 auto diff {cc_high_.at(controlnumber) - cc_low_.at(controlnumber)};
184 MIDI2LR_ASSUME(diff >= 0);
185 return diff / 2 + cc_low_.at(controlnumber) + diff % 2;
186 }

Referenced by SetToCenter().

◆ CenterPw()

int ChannelModel::CenterPw ( ) const
inlinenodiscardprivatenoexcept
189 {
191 MIDI2LR_ASSUME(diff >= 0);
192 return diff / 2 + pitch_wheel_min_ + diff % 2;
193 }
int pitch_wheel_min_
Definition ControlsModel.h:214
int pitch_wheel_max_
Definition ControlsModel.h:213

References pitch_wheel_max_, and pitch_wheel_min_.

Referenced by SetToCenter().

◆ ControllerToPlugin()

double ChannelModel::ControllerToPlugin ( rsj::MessageType controltype,
int controlnumber,
int value,
bool wrap )
59{
60 try {
61 const auto cc_method {cc_method_.at(controlnumber)};
62 const auto cc_low {cc_low_.at(controlnumber)};
63 const auto cc_high {cc_high_.at(controlnumber)};
64 // clearer precondition checks instead of ternary expressions
65 if (controltype == rsj::MessageType::kCc && cc_method == rsj::CCmethod::kAbsolute) {
66 Expects(cc_low < cc_high);
67 }
68 if (controltype == rsj::MessageType::kPw) {
70 Expects(value >= pitch_wheel_min_ && value <= pitch_wheel_max_);
71 }
72 /* note that the value is not msb,lsb, but rather the calculated value. Since lsb is only 7
73 * bits, high bits are shifted one right when placed into int. */
74 switch (controltype) {
76 pitch_wheel_current_.store(value, std::memory_order_release);
77#pragma warning(suppress : 26451) /* int subtraction won't overflow 4 bytes here */
78 return static_cast<double>(value - pitch_wheel_min_)
79 / static_cast<double>(pitch_wheel_max_ - pitch_wheel_min_);
81 switch (cc_method) {
83#ifdef __cpp_lib_atomic_ref
84 std::atomic_ref(current_v_.at(controlnumber)).store(value, std::memory_order_release);
85#else
86 current_v_.at(controlnumber).store(value, std::memory_order_release);
87#endif
88#pragma warning(suppress : 26451) /* int subtraction won't overflow 4 bytes here */
89 return static_cast<double>(value - cc_low) / static_cast<double>(cc_high - cc_low);
91 if (IsNrpn(controlnumber)) { return OffsetResult(value - kBit14, controlnumber, wrap); }
92 return OffsetResult(value - kBit7, controlnumber, wrap);
94 if (IsNrpn(controlnumber)) {
95 return OffsetResult(value & kBit14 ? -(value & kLow13Bits) : value, controlnumber,
96 wrap);
97 }
98 return OffsetResult(value & kBit7 ? -(value & kLow6Bits) : value, controlnumber, wrap);
100 /* SEE:https://en.wikipedia.org/wiki/Signed_number_representations#Two.27s_complement
101 * flip twos comp and subtract--independent of processor architecture */
102 if (IsNrpn(controlnumber)) {
103 return OffsetResult(value & kBit14 ? -((value ^ kMaxNrpn) + 1) : value,
104 controlnumber, wrap);
105 }
106 return OffsetResult(value & kBit7 ? -((value ^ kMaxMidi) + 1) : value, controlnumber,
107 wrap);
108 }
110 return static_cast<double>(value)
111 / static_cast<double>((IsNrpn(controlnumber) ? kMaxNrpn : kMaxMidi));
113 return 0.0;
118 throw std::invalid_argument(fmt::format("ChannelModel::ControllerToPlugin unexpected "
119 "control type. Controltype {}, controlnumber {}, "
120 "value {}, wrap {}.",
121 controltype, controlnumber, value, wrap));
122 }
123 throw std::domain_error(fmt::format("Undefined control type in "
124 "ChannelModel::PluginToController. Control type {}.",
125 controltype));
126 }
127 catch (const std::exception& e) {
128 rsj::ExceptionResponse(e, std::source_location::current());
129 throw;
130 }
131}
double OffsetResult(int diff, int controlnumber, bool wrap)
Definition ControlsModel.cpp:21
static constexpr int kLow6Bits
Definition ControlsModel.h:137
static constexpr int kBit14
Definition ControlsModel.h:134
static constexpr int kBit7
Definition ControlsModel.h:135
static constexpr int kLow13Bits
Definition ControlsModel.h:136
std::atomic< int > pitch_wheel_current_
Definition ControlsModel.h:215
bool IsNrpn(int controlnumber) const noexcept
Definition ControlsModel.h:196
@ kBinaryOffset
Definition ControlsModel.h:33
@ kTwosComplement
Definition ControlsModel.h:33
@ kSignMagnitude
Definition ControlsModel.h:33
@ kChanPressure
Definition MidiUtilities.h:47
@ kSystem
Definition MidiUtilities.h:49
@ kCc
Definition MidiUtilities.h:45
@ kKeyPressure
Definition MidiUtilities.h:44
@ kNoteOff
Definition MidiUtilities.h:42
@ kNoteOn
Definition MidiUtilities.h:43
@ kPgmChange
Definition MidiUtilities.h:46
@ kPw
Definition MidiUtilities.h:48

References IsNrpn(), rsj::kAbsolute, rsj::kBinaryOffset, kBit14, kBit7, rsj::kCc, rsj::kChanPressure, rsj::kKeyPressure, kLow13Bits, kLow6Bits, kMaxMidi, kMaxNrpn, rsj::kNoteOff, rsj::kNoteOn, rsj::kPgmChange, rsj::kPw, rsj::kSignMagnitude, rsj::kSystem, rsj::kTwosComplement, pitch_wheel_max_, and pitch_wheel_min_.

◆ GetCcMax()

int ChannelModel::GetCcMax ( int controlnumber) const
inlinenodiscard
156{ return cc_high_.at(controlnumber); }

◆ GetCcMethod()

rsj::CCmethod ChannelModel::GetCcMethod ( int controlnumber) const
inlinenodiscard
152 {
153 return cc_method_.at(controlnumber);
154 }

◆ GetCcMin()

int ChannelModel::GetCcMin ( int controlnumber) const
inlinenodiscard
158{ return cc_low_.at(controlnumber); }

◆ GetPwMax()

int ChannelModel::GetPwMax ( ) const
inlinenodiscardnoexcept
160{ return pitch_wheel_max_; }

References pitch_wheel_max_.

◆ GetPwMin()

int ChannelModel::GetPwMin ( ) const
inlinenodiscardnoexcept
162{ return pitch_wheel_min_; }

References pitch_wheel_min_.

◆ IsNrpn()

bool ChannelModel::IsNrpn ( int controlnumber) const
inlinenodiscardprivatenoexcept
197 {
198 Expects(controlnumber <= kMaxNrpn && controlnumber >= 0);
199 return controlnumber > kMaxMidi;
200 }

References kMaxMidi.

Referenced by ControllerToPlugin(), MeasureChange(), SetCcAll(), and SetCcMax().

◆ load()

template<class Archive>
void ChannelModel::load ( Archive & archive,
const uint32_t version )
private
332{
333 try {
334 switch (version) {
335 case 1:
337 break;
338 case 2:
339 archive(settings_to_save_);
341 break;
342 case 3:
343 archive(settings_to_save_, cereal::make_nvp("PWmax", pitch_wheel_max_),
344 cereal::make_nvp("PWmin", pitch_wheel_min_));
346 break;
347 default:
348 {
349 constexpr auto msg {
350 "The file, 'settings.xml', is marked as a version not supported by the current "
351 "version of MIDI2LR ChannelModel, and won't be loaded. File version: {}."};
352 rsj::LogAndAlertError(fmt::format(fmt::runtime(juce::translate(msg).toStdString()),
353 version),
354 fmt::format(fmt::runtime(msg), version), std::source_location::current());
355 }
356 break;
357 }
358 }
359 catch (const std::exception& e) {
360 rsj::ExceptionResponse(e, std::source_location::current());
361 throw;
362 }
363}
void SavedToActive()
Definition ControlsModel.cpp:423
void LogAndAlertError(const juce::String &error_text, const std::source_location &location=std::source_location::current()) noexcept
Definition Misc.cpp:141

◆ MeasureChange()

int ChannelModel::MeasureChange ( rsj::MessageType controltype,
int controlnumber,
int value )
172{
173 try {
174 if (controltype == rsj::MessageType::kCc
175 && cc_method_.at(controlnumber) == rsj::CCmethod::kAbsolute) {
176 Expects(cc_low_.at(controlnumber) < cc_high_.at(controlnumber));
177 }
178 if (controltype == rsj::MessageType::kPw) {
180 Expects(value >= pitch_wheel_min_ && value <= pitch_wheel_max_);
181 }
182 /* note that the value is not msb,lsb, but rather the calculated value. Since lsb is only 7
183 * bits, high bits are shifted one right when placed into int. */
184 switch (controltype) {
186 return value - pitch_wheel_current_.exchange(value, std::memory_order_acq_rel);
188 switch (cc_method_.at(controlnumber)) {
190#ifdef __cpp_lib_atomic_ref
191 return value
192 - std::atomic_ref(current_v_.at(controlnumber))
193 .exchange(value, std::memory_order_acq_rel);
194#else
195 return value - current_v_.at(controlnumber).exchange(value, std::memory_order_acq_rel);
196#endif
198 if (IsNrpn(controlnumber)) { return value - kBit14; }
199 return value - kBit7;
201 if (IsNrpn(controlnumber)) { return value & kBit14 ? -(value & kLow13Bits) : value; }
202 return value & kBit7 ? -(value & kLow6Bits) : value;
204 /* SEE:https://en.wikipedia.org/wiki/Signed_number_representations#Two.27s_complement
205 * flip twos comp and subtract--independent of processor architecture */
206 if (IsNrpn(controlnumber)) {
207 return value & kBit14 ? -((value ^ kMaxNrpn) + 1) : value;
208 }
209 return value & kBit7 ? -((value ^ kMaxMidi) + 1) : value;
210 }
213 return int {0};
218 throw std::invalid_argument(fmt::format("ChannelModel::MeasureChange unexpected control "
219 "type. Controltype {}, controlnumber {}, value "
220 "{}.",
221 controltype, controlnumber, value));
222 }
223 throw std::domain_error(fmt::format("Undefined control type in "
224 "ChannelModel::PluginToController. Control type {}.",
225 controltype));
226 }
227 catch (const std::exception& e) {
228 rsj::ExceptionResponse(e, std::source_location::current());
229 throw;
230 }
231}

References IsNrpn(), kBit14, kBit7, rsj::kCc, rsj::kChanPressure, rsj::kKeyPressure, kLow13Bits, kLow6Bits, kMaxMidi, kMaxNrpn, rsj::kNoteOff, rsj::kNoteOn, rsj::kPgmChange, rsj::kPw, rsj::kSystem, pitch_wheel_max_, and pitch_wheel_min_.

◆ OffsetResult()

double ChannelModel::OffsetResult ( int diff,
int controlnumber,
bool wrap )
private
22{
23 try {
24 const auto high_limit {cc_high_.at(controlnumber)};
25 Expects(high_limit > 0); // guard against divide/modulo by zero
26 Expects(diff <= high_limit && diff >= -high_limit);
27#ifdef __cpp_lib_atomic_ref
28 std::atomic_ref cv {current_v_.at(controlnumber)};
29#else
30 auto& cv {current_v_.at(controlnumber)};
31#endif
32 auto old_v {cv.load(std::memory_order_relaxed)};
33 int new_v {};
34 if (wrap) {
35 const auto mod {high_limit + 1}; // inclusive range 0..high_limit
36 do {
37 auto old_diff_mod {old_v + diff + mod};
38 MIDI2LR_ASSUME(old_diff_mod >= 0);
39 new_v = old_diff_mod % mod;
40 } while (!cv.compare_exchange_weak(old_v, new_v, std::memory_order_release,
41 std::memory_order_relaxed));
42 }
43 else [[likely]] {
44 do {
45 new_v = std::clamp(old_v + diff, 0, high_limit);
46 } while (!cv.compare_exchange_weak(old_v, new_v, std::memory_order_release,
47 std::memory_order_relaxed));
48 }
49 return static_cast<double>(new_v) / static_cast<double>(high_limit);
50 }
51 catch (const std::exception& e) {
52 rsj::ExceptionResponse(e, std::source_location::current());
53 throw;
54 }
55}

◆ PluginToController()

int ChannelModel::PluginToController ( rsj::MessageType controltype,
int controlnumber,
double value )
238{
239 try {
240 /* value effectively clamped to 0-1 by clamp calls below */
241 switch (controltype) {
243 {
244 /* TODO(C26451): int subtraction: can it overflow? */
245 const auto newv {
246 std::clamp(gsl::narrow<int>(std::lrint(
247 value * static_cast<double>(pitch_wheel_max_ - pitch_wheel_min_)))
250 pitch_wheel_current_.store(newv, std::memory_order_release);
251 return newv;
252 }
254 {
255 /* TODO(C26451): int subtraction: can it overflow? */
256 const auto clow {cc_low_.at(controlnumber)};
257 const auto chigh {cc_high_.at(controlnumber)};
258 const auto newv {std::clamp(
259 gsl::narrow_cast<int>(std::lrint(value * static_cast<double>(chigh - clow))) + clow,
260 clow, chigh)};
261#ifdef __cpp_lib_atomic_ref
262 std::atomic_ref(current_v_.at(controlnumber)).store(newv, std::memory_order_release);
263#else
264 current_v_.at(controlnumber).store(newv, std::memory_order_release);
265#endif
266 return newv;
267 }
269 return kMaxMidi;
275 throw std::invalid_argument(fmt::format(
276 "Unexpected control type in ChannelModel::PluginToController. Control type {}.",
277 controltype));
278 }
279 throw std::domain_error(fmt::format("Undefined control type in "
280 "ChannelModel::PluginToController. Control type {}.",
281 controltype));
282 }
283 catch (const std::exception& e) {
284 rsj::ExceptionResponse(e, std::source_location::current());
285 throw;
286 }
287}

References rsj::kCc, rsj::kChanPressure, rsj::kKeyPressure, kMaxMidi, rsj::kNoteOff, rsj::kNoteOn, rsj::kPgmChange, rsj::kPw, and rsj::kSystem.

◆ save()

template<class Archive>
void ChannelModel::save ( Archive & archive,
const uint32_t version ) const
private
366{
367 try {
368 switch (version) {
369 case 1:
371 break;
372 case 2:
374 archive(settings_to_save_);
375 break;
376 case 3:
378 archive(settings_to_save_, cereal::make_nvp("PWmax", pitch_wheel_max_),
379 cereal::make_nvp("PWmin", pitch_wheel_min_));
380 break;
381 default:
382 {
383 constexpr auto msg {
384 "The file, 'settings.xml', is marked as a version not supported by the current "
385 "version of MIDI2LR ChannelModel, and won't be loaded. File version: {}."};
386 rsj::LogAndAlertError(fmt::format(fmt::runtime(juce::translate(msg).toStdString()),
387 version),
388 fmt::format(fmt::runtime(msg), version), std::source_location::current());
389 }
390 break;
391 }
392 }
393 catch (const std::exception& e) {
394 rsj::ExceptionResponse(e, std::source_location::current());
395 throw;
396 }
397}
void ActiveToSaved() const
Definition ControlsModel.cpp:392

◆ SavedToActive()

void ChannelModel::SavedToActive ( )
private
424{
425 try {
426 CcDefaults();
427 for (const auto& set : settings_to_save_) {
428 SetCc(set.control_number, set.low, set.high, set.method);
429 }
430 }
431 catch (const std::exception& e) {
432 rsj::ExceptionResponse(e, std::source_location::current());
433 throw;
434 }
435}
void SetCc(int controlnumber, int min, int max, rsj::CCmethod controltype)
Definition ControlsModel.cpp:291

References CcDefaults().

◆ SaveSettings()

void ChannelModel::SaveSettings ( int start,
int end,
int maxVal ) const
private
383{
384 for (auto i {start}; i <= end; ++i) {
385 if (cc_method_.at(i) != rsj::CCmethod::kAbsolute || cc_high_.at(i) != maxVal
386 || cc_low_.at(i) != 0) {
387 settings_to_save_.emplace_back(i, cc_low_.at(i), cc_high_.at(i), cc_method_.at(i));
388 }
389 }
390}

Referenced by ActiveToSaved().

◆ SetCc()

void ChannelModel::SetCc ( int controlnumber,
int min,
int max,
rsj::CCmethod controltype )
293{
294 try {
295 /* CcMethod has to be set before others or ranges won't be correct */
296 SetCcMethod(controlnumber, controltype);
297 SetCcMin(controlnumber, min);
298 SetCcMax(controlnumber, max);
299 }
300 catch (const std::exception& e) {
301 rsj::ExceptionResponse(e, std::source_location::current());
302 throw;
303 }
304}
void SetCcMethod(int controlnumber, rsj::CCmethod value)
Definition ControlsModel.h:169
void SetCcMax(int controlnumber, int value)
Definition ControlsModel.cpp:323
void SetCcMin(int controlnumber, int value)
Definition ControlsModel.cpp:348

References SetCcMax(), SetCcMethod(), and SetCcMin().

◆ SetCcAll()

void ChannelModel::SetCcAll ( int controlnumber,
int min,
int max,
rsj::CCmethod controltype )
308{
309 try {
310 if (IsNrpn(controlnumber)) {
311 for (auto a {kMaxMidi + 1}; a <= kMaxNrpn; ++a) { SetCc(a, min, max, controltype); }
312 }
313 else {
314 for (auto a {0}; a <= kMaxMidi; ++a) { SetCc(a, min, max, controltype); }
315 }
316 }
317 catch (const std::exception& e) {
318 rsj::ExceptionResponse(e, std::source_location::current());
319 throw;
320 }
321}

References IsNrpn(), kMaxMidi, and kMaxNrpn.

◆ SetCcMax()

void ChannelModel::SetCcMax ( int controlnumber,
int value )
324{
325 try {
326 Expects(value <= kMaxNrpn && value >= 0);
327 if (cc_method_.at(controlnumber) != rsj::CCmethod::kAbsolute) {
328 cc_high_.at(controlnumber) = value < 0 ? 1000 : value;
329 }
330 else {
331 const auto max {IsNrpn(controlnumber) ? kMaxNrpn : kMaxMidi};
332 cc_high_.at(controlnumber) =
333 value <= cc_low_.at(controlnumber) || value > max ? max : value;
334 }
335#ifdef __cpp_lib_atomic_ref
336 std::atomic_ref(current_v_.at(controlnumber))
337 .store(CenterCc(controlnumber), std::memory_order_release);
338#else
339 current_v_.at(controlnumber).store(CenterCc(controlnumber), std::memory_order_release);
340#endif
341 }
342 catch (const std::exception& e) {
343 rsj::ExceptionResponse(e, std::source_location::current());
344 throw;
345 }
346}
int CenterCc(int controlnumber) const noexcept
Definition ControlsModel.h:181

References IsNrpn(), kMaxMidi, and kMaxNrpn.

Referenced by SetCc().

◆ SetCcMethod()

void ChannelModel::SetCcMethod ( int controlnumber,
rsj::CCmethod value )
inline
170 {
171 cc_method_.at(controlnumber) = value;
172 }

Referenced by SetCc().

◆ SetCcMin()

void ChannelModel::SetCcMin ( int controlnumber,
int value )
349{
350 try {
351 if (cc_method_.at(controlnumber) != rsj::CCmethod::kAbsolute) {
352 cc_low_.at(controlnumber) = 0;
353 }
354 else {
355 cc_low_.at(controlnumber) = value < 0 || value >= cc_high_.at(controlnumber) ? 0 : value;
356 }
357#ifdef __cpp_lib_atomic_ref
358 std::atomic_ref(current_v_.at(controlnumber))
359 .store(CenterCc(controlnumber), std::memory_order_release);
360#else
361 current_v_.at(controlnumber).store(CenterCc(controlnumber), std::memory_order_release);
362#endif
363 }
364 catch (const std::exception& e) {
365 rsj::ExceptionResponse(e, std::source_location::current());
366 throw;
367 }
368}

Referenced by SetCc().

◆ SetPwMax()

void ChannelModel::SetPwMax ( int value)
noexcept
371{
372 pitch_wheel_max_ = value > kMaxNrpn || value <= pitch_wheel_min_ ? kMaxNrpn : value;
373 pitch_wheel_current_.store(CenterPw(), std::memory_order_release);
374}
int CenterPw() const noexcept
Definition ControlsModel.h:188

References kMaxNrpn, pitch_wheel_max_, and pitch_wheel_min_.

◆ SetPwMin()

void ChannelModel::SetPwMin ( int value)
noexcept
377{
378 pitch_wheel_min_ = value < 0 || value >= pitch_wheel_max_ ? 0 : value;
379 pitch_wheel_current_.store(CenterPw(), std::memory_order_release);
380}

References pitch_wheel_max_, and pitch_wheel_min_.

◆ SetToCenter()

int ChannelModel::SetToCenter ( rsj::MessageType controltype,
int controlnumber )
136{
137 try {
138 auto retval {0};
139 switch (controltype) {
141 retval = CenterPw();
142 pitch_wheel_current_.store(retval, std::memory_order_release);
143 break;
145 if (cc_method_.at(controlnumber) == rsj::CCmethod::kAbsolute) {
146 retval = CenterCc(controlnumber);
147#ifdef __cpp_lib_atomic_ref
148 std::atomic_ref(current_v_.at(controlnumber)).store(retval, std::memory_order_release);
149#else
150 current_v_.at(controlnumber).store(retval, std::memory_order_release);
151#endif
152 }
153 break;
160 break;
161 }
162 return retval;
163 }
164 catch (const std::exception& e) {
165 rsj::ExceptionResponse(e, std::source_location::current());
166 throw;
167 }
168}

References CenterCc(), CenterPw(), rsj::kCc, rsj::kChanPressure, rsj::kKeyPressure, rsj::kNoteOff, rsj::kNoteOn, rsj::kPgmChange, rsj::kPw, and rsj::kSystem.

◆ cereal::access

friend class cereal::access
friend

Member Data Documentation

◆ cc_high_

std::array<int, kMaxControls> ChannelModel::cc_high_ {}
private
217{};

◆ cc_low_

std::array<int, kMaxControls> ChannelModel::cc_low_ {}
private
218{};

◆ cc_method_

std::array<rsj::CCmethod, kMaxControls> ChannelModel::cc_method_ {}
private
216{};

◆ current_v_

std::array<std::atomic<int>, kMaxControls> ChannelModel::current_v_ {}
private
222{};

◆ kBit14

int ChannelModel::kBit14 {0x2000}
staticconstexprprivate
134{0x2000};

Referenced by ControllerToPlugin(), and MeasureChange().

◆ kBit7

int ChannelModel::kBit7 {0x40}
staticconstexprprivate
135{0x40};

Referenced by ControllerToPlugin(), and MeasureChange().

◆ kLow13Bits

int ChannelModel::kLow13Bits {0x1FFF}
staticconstexprprivate
136{0x1FFF};

Referenced by ControllerToPlugin(), and MeasureChange().

◆ kLow6Bits

int ChannelModel::kLow6Bits {0x3F}
staticconstexprprivate
137{0x3F};

Referenced by ControllerToPlugin(), and MeasureChange().

◆ kMaxControls

size_t ChannelModel::kMaxControls {0x4000}
staticconstexprprivate
142{0x4000};

◆ kMaxMidi

int ChannelModel::kMaxMidi {0x7F}
staticconstexprprivate

◆ kMaxMidiHalf

int ChannelModel::kMaxMidiHalf {kMaxMidi / 2}
staticconstexprprivate
139{kMaxMidi / 2};

◆ kMaxNrpn

int ChannelModel::kMaxNrpn {0x3FFF}
staticconstexprprivate

◆ kMaxNrpnHalf

int ChannelModel::kMaxNrpnHalf {kMaxNrpn / 2}
staticconstexprprivate
141{kMaxNrpn / 2};

◆ pitch_wheel_current_

std::atomic<int> ChannelModel::pitch_wheel_current_ {kMaxNrpnHalf}
private

◆ pitch_wheel_max_

int ChannelModel::pitch_wheel_max_ {kMaxNrpn}
private

◆ pitch_wheel_min_

int ChannelModel::pitch_wheel_min_ {0}
private

◆ settings_to_save_

std::vector<rsj::SettingsStruct> ChannelModel::settings_to_save_ {}
mutableprivate
212{};

The documentation for this class was generated from the following files:
  • C:/Users/rsjaf/source/repos/MIDI2LR/src/application/ControlsModel.h
  • C:/Users/rsjaf/source/repos/MIDI2LR/src/application/ControlsModel.cpp