Program Listing for File PDJE_MIDI.cpp

Return to documentation for file (include\input\midi\PDJE_MIDI.cpp)

#include "PDJE_MIDI.hpp"

namespace PDJE_MIDI {

MIDI::MIDI(const int buffer_size) : evlog(buffer_size)
{
}

void
MIDI::Run(const bool CC_LSB_ON)
{
    for (const auto &i : configed_devices) {
        std::string pname = i.port_name;

        libremidi::input_configuration input_config{

            .on_message =
                [this, CC_LSB_ON, pname](const libremidi::message &m) {
                    try {
                        const auto &b = m.bytes;
                        if (b.empty()) {
                            return;
                        }
                        auto       type = m.get_message_type();
                        const auto ch   = static_cast<uint8_t>(m.get_channel() &
                                                             0x0F); // 0 ~ 15
                        uint8_t    pos  = 0;
                        uint16_t   value = 0;

                        switch (m.get_message_type()) {
                        case libremidi::message_type::NOTE_ON: {
                            B_GUARD(b, 3)

                            pos   = PDJE_BIT_PARSE_7(b[1]);
                            value = PDJE_BIT_PARSE_7(b[2]);
                            if (value == 0) {
                                type = libremidi::message_type::NOTE_OFF;
                            }
                        } break;
                        case libremidi::message_type::NOTE_OFF: // ch - note -
                                                                // velocity
                        {
                            B_GUARD(b, 3)

                            pos   = PDJE_BIT_PARSE_7(b[1]);
                            value = PDJE_BIT_PARSE_7(b[2]);
                        } break;
                        case libremidi::message_type::
                            CONTROL_CHANGE: // status, data num, value or MSB,
                                            // LSB
                        {
                            B_GUARD(b, 3)

                            pos           = PDJE_BIT_PARSE_7(b[1]);
                            value         = PDJE_BIT_PARSE_7(b[2]);
                            auto &CC_stat = __CC_stat[pname];
                            if (pos < 32 && CC_LSB_ON) { // msb

                                CC_stat[ch][pos] =
                                    (CC_stat[ch][pos] & 0x007F) | (value << 7);
                                value = CC_stat[ch][pos];
                            } else if (pos < 64 && CC_LSB_ON) { // lsb
                                CC_stat[ch][pos - 32] &= 0x3F80;
                                CC_stat[ch][pos - 32] |= value;
                                value = CC_stat[ch][pos - 32];

                            } else {
                                value = value << 7;
                            }
                        } break;
                        case libremidi::message_type::PITCH_BEND: // ch - LSB -
                                                                  // MSB
                        {
                            B_GUARD(b, 3)

                            value =
                                (static_cast<uint16_t>(
                                    PDJE_BIT_PARSE_7(b[1]))) |
                                (static_cast<uint16_t>(PDJE_BIT_PARSE_7(b[2]))
                                 << 7);
                        } break;

                        case libremidi::message_type::AFTERTOUCH: // ch -
                                                                  // pressure
                        {
                            B_GUARD(b, 2)

                            value = PDJE_BIT_PARSE_7(b[1]);
                        } break;
                        case libremidi::message_type::POLY_PRESSURE: // ch -
                                                                     // note -
                                                                     // pressure
                        {
                            B_GUARD(b, 3)

                            pos   = PDJE_BIT_PARSE_7(b[1]);
                            value = PDJE_BIT_PARSE_7(b[2]);
                        } break;
                        default: {

                            return;
                        }
                        }
                        MIDI_EV evres{ .type  = static_cast<uint8_t>(type),
                                       .ch    = ch,
                                       .pos   = pos,
                                       .value = value,
                                       .highres_time =
                                           clock.Get_MicroSecond() };
                        evres.port_name_len =
                            pname.size() > 256 ? 256 : pname.size();
                        std::memcpy(evres.port_name,
                                    pname.data(),
                                    sizeof(char) * (evres.port_name_len));

                        evlog.Write(evres);
                    } catch (const std::exception &e) {
                        critlog("runtime error on midi input loop. What: ");
                        critlog(e.what());
                        return;
                    }
                },

            .timestamps = libremidi::NoTimestamp
        };
        __CC_stat.try_emplace(pname,
                              std::array<std::array<uint16_t, 32>, 16>{});

        midiin.emplace_back(std::pair(libremidi::midi_in{ input_config }, i));

        auto err = midiin.back().first.open_port(i);
        if (err != stdx::error{}) {
            throw std::runtime_error(
                std::string(err.message().data(), err.message().size()));
        }
    }
}

} // namespace PDJE_MIDI