diff --git a/include/boo/audiodev/MIDIEncoder.hpp b/include/boo/audiodev/MIDIEncoder.hpp index 693152e..42f3741 100644 --- a/include/boo/audiodev/MIDIEncoder.hpp +++ b/include/boo/audiodev/MIDIEncoder.hpp @@ -1,5 +1,8 @@ #pragma once +#include +#include + #include "boo/audiodev/IMIDIReader.hpp" namespace boo { @@ -8,7 +11,14 @@ template class MIDIEncoder : public IMIDIReader { Sender& m_sender; uint8_t m_status = 0; + void _sendMessage(const uint8_t* data, size_t len); + + template + void _sendMessage(const ContiguousContainer& container) { + _sendMessage(std::data(container), std::size(container)); + } + void _sendContinuedValue(uint32_t val); public: diff --git a/lib/audiodev/MIDIEncoder.cpp b/lib/audiodev/MIDIEncoder.cpp index 925026c..c1df082 100644 --- a/lib/audiodev/MIDIEncoder.cpp +++ b/lib/audiodev/MIDIEncoder.cpp @@ -1,9 +1,17 @@ #include "boo/audiodev/MIDIEncoder.hpp" +#include + #include "boo/audiodev/IMIDIPort.hpp" #include "lib/audiodev/MIDICommon.hpp" namespace boo { +namespace { +template +constexpr auto MakeCommand(Args&&... args) -> std::array { + return {std::forward(args)...}; +} +} // Anonymous namespace template void MIDIEncoder::_sendMessage(const uint8_t* data, size_t len) { @@ -18,7 +26,7 @@ void MIDIEncoder::_sendMessage(const uint8_t* data, size_t len) { template void MIDIEncoder::_sendContinuedValue(uint32_t val) { - uint8_t send[3] = {}; + std::array send{}; uint8_t* ptr = nullptr; if (val >= 0x4000) { ptr = &send[0]; @@ -28,154 +36,164 @@ void MIDIEncoder::_sendContinuedValue(uint32_t val) { } if (val >= 0x80) { - if (!ptr) + if (ptr == nullptr) { ptr = &send[1]; + } send[1] = 0x80 | ((val / 0x80) & 0x7f); } - if (!ptr) + if (ptr == nullptr) { ptr = &send[2]; + } send[2] = val & 0x7f; - m_sender.send(ptr, 3 - (ptr - send)); + const size_t sendLength = send.size() - (ptr - send.data()); + m_sender.send(ptr, sendLength); } template void MIDIEncoder::noteOff(uint8_t chan, uint8_t key, uint8_t velocity) { - uint8_t cmd[3] = {uint8_t(int(Status::NoteOff) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)}; - _sendMessage(cmd, 3); + const auto cmd = + MakeCommand(uint8_t(int(Status::NoteOff) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::noteOn(uint8_t chan, uint8_t key, uint8_t velocity) { - uint8_t cmd[3] = {uint8_t(int(Status::NoteOn) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)}; - _sendMessage(cmd, 3); + const auto cmd = + MakeCommand(uint8_t(int(Status::NoteOn) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(velocity & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::notePressure(uint8_t chan, uint8_t key, uint8_t pressure) { - uint8_t cmd[3] = {uint8_t(int(Status::NotePressure) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(pressure & 0x7f)}; - _sendMessage(cmd, 3); + const auto cmd = + MakeCommand(uint8_t(int(Status::NotePressure) | (chan & 0xf)), uint8_t(key & 0x7f), uint8_t(pressure & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::controlChange(uint8_t chan, uint8_t control, uint8_t value) { - uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(control & 0x7f), uint8_t(value & 0x7f)}; - _sendMessage(cmd, 3); + const auto cmd = + MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(control & 0x7f), uint8_t(value & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::programChange(uint8_t chan, uint8_t program) { - uint8_t cmd[2] = {uint8_t(int(Status::ProgramChange) | (chan & 0xf)), uint8_t(program & 0x7f)}; - _sendMessage(cmd, 2); + const auto cmd = MakeCommand(uint8_t(int(Status::ProgramChange) | (chan & 0xf)), uint8_t(program & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::channelPressure(uint8_t chan, uint8_t pressure) { - uint8_t cmd[2] = {uint8_t(int(Status::ChannelPressure) | (chan & 0xf)), uint8_t(pressure & 0x7f)}; - _sendMessage(cmd, 2); + const auto cmd = MakeCommand(uint8_t(int(Status::ChannelPressure) | (chan & 0xf)), uint8_t(pressure & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::pitchBend(uint8_t chan, int16_t pitch) { - uint8_t cmd[3] = {uint8_t(int(Status::PitchBend) | (chan & 0xf)), uint8_t((pitch % 128) & 0x7f), - uint8_t((pitch / 128) & 0x7f)}; - _sendMessage(cmd, 3); + const auto cmd = MakeCommand(uint8_t(int(Status::PitchBend) | (chan & 0xf)), uint8_t((pitch % 128) & 0x7f), + uint8_t((pitch / 128) & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::allSoundOff(uint8_t chan) { - uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 120, 0}; - _sendMessage(cmd, 3); + const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t{120}, uint8_t{0}); + _sendMessage(cmd); } template void MIDIEncoder::resetAllControllers(uint8_t chan) { - uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 121, 0}; - _sendMessage(cmd, 3); + const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t{121}, uint8_t{0}); + _sendMessage(cmd); } template void MIDIEncoder::localControl(uint8_t chan, bool on) { - uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 122, uint8_t(on ? 127 : 0)}; - _sendMessage(cmd, 3); + const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t{122}, uint8_t(on ? 127 : 0)); + _sendMessage(cmd); } template void MIDIEncoder::allNotesOff(uint8_t chan) { - uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), 123, 0}; - _sendMessage(cmd, 3); + const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t{123}, uint8_t{0}); + _sendMessage(cmd); } template void MIDIEncoder::omniMode(uint8_t chan, bool on) { - uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 125 : 124), 0}; - _sendMessage(cmd, 3); + const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 125 : 124), uint8_t{0}); + _sendMessage(cmd); } template void MIDIEncoder::polyMode(uint8_t chan, bool on) { - uint8_t cmd[3] = {uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 127 : 126), 0}; - _sendMessage(cmd, 3); + const auto cmd = MakeCommand(uint8_t(int(Status::ControlChange) | (chan & 0xf)), uint8_t(on ? 127 : 126), uint8_t{0}); + _sendMessage(cmd); } template void MIDIEncoder::sysex(const void* data, size_t len) { - uint8_t cmd = uint8_t(Status::SysEx); - _sendMessage(&cmd, 1); + constexpr auto sysexCmd = MakeCommand(uint8_t(Status::SysEx)); + _sendMessage(sysexCmd); + _sendContinuedValue(len); m_sender.send(data, len); - cmd = uint8_t(Status::SysExTerm); - _sendMessage(&cmd, 1); + + constexpr auto sysexTermCmd = MakeCommand(uint8_t(Status::SysExTerm)); + _sendMessage(sysexTermCmd); } template void MIDIEncoder::timeCodeQuarterFrame(uint8_t message, uint8_t value) { - uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t((message & 0x7 << 4) | (value & 0xf))}; - _sendMessage(cmd, 2); + const auto cmd = + MakeCommand(uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t((message & 0x7 << 4) | (value & 0xf))); + _sendMessage(cmd); } template void MIDIEncoder::songPositionPointer(uint16_t pointer) { - uint8_t cmd[3] = {uint8_t(int(Status::SongPositionPointer)), uint8_t((pointer % 128) & 0x7f), - uint8_t((pointer / 128) & 0x7f)}; - _sendMessage(cmd, 3); + const auto cmd = MakeCommand(uint8_t(int(Status::SongPositionPointer)), uint8_t((pointer % 128) & 0x7f), + uint8_t((pointer / 128) & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::songSelect(uint8_t song) { - uint8_t cmd[2] = {uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t(song & 0x7f)}; - _sendMessage(cmd, 2); + const auto cmd = MakeCommand(uint8_t(int(Status::TimecodeQuarterFrame)), uint8_t(song & 0x7f)); + _sendMessage(cmd); } template void MIDIEncoder::tuneRequest() { - uint8_t cmd = uint8_t(Status::TuneRequest); - _sendMessage(&cmd, 1); + constexpr auto cmd = MakeCommand(uint8_t(Status::TuneRequest)); + _sendMessage(cmd); } template void MIDIEncoder::startSeq() { - uint8_t cmd = uint8_t(Status::Start); - _sendMessage(&cmd, 1); + constexpr auto cmd = MakeCommand(uint8_t(Status::Start)); + _sendMessage(cmd); } template void MIDIEncoder::continueSeq() { - uint8_t cmd = uint8_t(Status::Continue); - _sendMessage(&cmd, 1); + constexpr auto cmd = MakeCommand(uint8_t(Status::Continue)); + _sendMessage(cmd); } template void MIDIEncoder::stopSeq() { - uint8_t cmd = uint8_t(Status::Stop); - _sendMessage(&cmd, 1); + constexpr auto cmd = MakeCommand(uint8_t(Status::Stop)); + _sendMessage(cmd); } template void MIDIEncoder::reset() { - uint8_t cmd = uint8_t(Status::Reset); - _sendMessage(&cmd, 1); + constexpr auto cmd = MakeCommand(uint8_t(Status::Reset)); + _sendMessage(cmd); } template class MIDIEncoder;