gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

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 }