sciMidi.cpp (2564B)
1 #include "sciMidi.h" 2 3 #include <deque> 4 5 #include "mc68k/qsm.h" 6 7 #include "synthLib/midiBufferParser.h" 8 9 namespace hwLib 10 { 11 // pause 0.1 seconds for a sysex size of 500, delay is calculated for other sysex sizes accordingly 12 static constexpr float g_sysexSendDelaySeconds = 0.1f; 13 static constexpr uint32_t g_sysexSendDelaySize = 500; 14 15 SciMidi::SciMidi(mc68k::Qsm& _qsm, const float _samplerate) : m_qsm(_qsm), m_samplerate(_samplerate), m_sysexDelaySeconds(g_sysexSendDelaySeconds), m_sysexDelaySize(g_sysexSendDelaySize) 16 { 17 } 18 19 void SciMidi::process(const uint32_t _numSamples) 20 { 21 std::unique_lock lock(m_mutex); 22 23 if(m_readingSysex) 24 return; 25 26 auto remainingSamples = _numSamples; 27 28 while(!m_pendingSysexBuffers.empty()) 29 { 30 if(m_remainingSysexDelay > 0) 31 { 32 const auto sub = std::min(m_remainingSysexDelay, remainingSamples); 33 remainingSamples -= sub; 34 35 m_remainingSysexDelay -= sub; 36 } 37 38 if(m_remainingSysexDelay) 39 break; 40 41 const auto& msg = m_pendingSysexBuffers.front(); 42 43 for (const auto b : msg) 44 m_qsm.writeSciRX(b); 45 46 m_remainingSysexDelay = static_cast<uint32_t>(static_cast<float>(msg.size()) * m_samplerate * m_sysexDelaySeconds / static_cast<float>(m_sysexDelaySize)); 47 48 m_pendingSysexBuffers.pop_front(); 49 } 50 } 51 52 void SciMidi::write(const uint8_t _byte) 53 { 54 std::unique_lock lock(m_mutex); 55 56 if(_byte == 0xf0) 57 { 58 m_writingSysex = true; 59 } 60 61 if(m_writingSysex) 62 { 63 m_pendingSysexMessage.push_back(_byte); 64 } 65 else 66 { 67 m_qsm.writeSciRX(_byte); 68 } 69 70 if (_byte == 0xf7) 71 { 72 m_writingSysex = false; 73 74 if (!m_pendingSysexMessage.empty()) 75 m_pendingSysexBuffers.push_back(std::move(m_pendingSysexMessage)); 76 77 m_pendingSysexMessage.clear(); 78 } 79 } 80 81 void SciMidi::write(const synthLib::SMidiEvent& _e) 82 { 83 if(!_e.sysex.empty()) 84 { 85 write(_e.sysex); 86 } 87 else 88 { 89 write(_e.a); 90 const auto len = synthLib::MidiBufferParser::lengthFromStatusByte(_e.a); 91 if (len > 1) 92 write(_e.b); 93 if (len > 2) 94 write(_e.c); 95 } 96 } 97 98 void SciMidi::read(std::vector<uint8_t>& _result) 99 { 100 std::deque<uint16_t> midiData; 101 m_qsm.readSciTX(midiData); 102 if (midiData.empty()) 103 return; 104 105 _result.clear(); 106 _result.reserve(midiData.size()); 107 108 for (const auto data : midiData) 109 { 110 const uint8_t d = data & 0xff; 111 112 if(d == 0xf0) 113 m_readingSysex = true; 114 else if(d == 0xf7) 115 m_readingSysex = false; 116 117 _result.push_back(d); 118 } 119 } 120 121 void SciMidi::setSysexDelay(const float _seconds, const uint32_t _size) 122 { 123 m_sysexDelaySeconds = _seconds; 124 m_sysexDelaySize = _size; 125 } 126 }