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

midiTranslator.cpp (2415B)


      1 #include "midiTranslator.h"
      2 
      3 #include "midiTypes.h"
      4 
      5 #include <cstddef>
      6 
      7 namespace synthLib
      8 {
      9 	MidiTranslator::MidiTranslator()
     10 	{
     11 		reset();
     12 	}
     13 
     14 	void MidiTranslator::process(std::vector<SMidiEvent>& _results, const SMidiEvent& _source)
     15 	{
     16 		const size_t size = _source.sysex.size();
     17 
     18 		if (!size)
     19 		{
     20 			if (_source.a < 0xf0)
     21 			{
     22 				auto& targets = m_targetChannels[_source.a & 0x0f];
     23 
     24 				for (auto target : targets)
     25 				{
     26 					auto& result = _results.emplace_back(_source);
     27 					result.a = static_cast<uint8_t>((_source.a & 0xf0) | target);
     28 				}
     29 			}
     30 			else
     31 			{
     32 				_results.push_back(_source);
     33 			}
     34 
     35 			return;
     36 		}
     37 
     38 		if (size < 4 || _source.sysex.front() != 0xf0 || _source.sysex.back() != 0xf7 || _source.sysex[1] != ManufacturerId)
     39 		{
     40 			_results.push_back(_source);
     41 			return;
     42 		}
     43 
     44 		switch (_source.sysex[2])
     45 		{
     46 		case CmdSkipTranslation:
     47 			if (size == 7)
     48 			{
     49 				auto& result = _results.emplace_back(_source);
     50 				result.a = _source.sysex[3];
     51 				result.b = _source.sysex[4];
     52 				result.c = _source.sysex[5];
     53 				result.sysex.clear();
     54 			}
     55 			break;
     56 		case CmdAddTargetChannel:
     57 			if (size == 6)
     58 			{
     59 				const auto sourceChannel = _source.sysex[3];
     60 				const auto targetChannel = _source.sysex[4];
     61 				addTargetChannel(sourceChannel, targetChannel);
     62 			}
     63 			break;
     64 		case CmdResetTargetChannels:
     65 			reset();
     66 			break;
     67 		case CmdClearTargetChannels:
     68 			clear();
     69 			break;
     70 		default:;
     71 		}
     72 	}
     73 
     74 	bool MidiTranslator::addTargetChannel(const uint8_t _sourceChannel, const uint8_t _targetChannel)
     75 	{
     76 		if (_sourceChannel >= 16 || _targetChannel >= 16)
     77 			return false;
     78 		m_targetChannels[_sourceChannel].insert(_targetChannel);
     79 		return true;
     80 	}
     81 
     82 	void MidiTranslator::reset()
     83 	{
     84 		for (uint8_t i = 0; i < static_cast<uint8_t>(m_targetChannels.size()); ++i)
     85 			m_targetChannels[i].insert(i);
     86 	}
     87 
     88 	void MidiTranslator::clear()
     89 	{
     90 		for (uint8_t i = 0; i < static_cast<uint8_t>(m_targetChannels.size()); ++i)
     91 			m_targetChannels[i].clear();
     92 	}
     93 
     94 	SMidiEvent& MidiTranslator::createPacketSkipTranslation(SMidiEvent& _ev)
     95 	{
     96 		if (_ev.sysex.empty())
     97 			_ev.sysex = { 0xf0, ManufacturerId, CmdSkipTranslation, _ev.a, _ev.b, _ev.c, 0xf7 };
     98 		return _ev;
     99 	}
    100 
    101 	SMidiEvent MidiTranslator::createPacketSetTargetChannel(const uint8_t _sourceChannel, const uint8_t _targetChannel)
    102 	{
    103 		SMidiEvent e;
    104 		e.sysex = { 0xf0, ManufacturerId, CmdAddTargetChannel, _sourceChannel, _targetChannel, 0xf7 };
    105 		return e;
    106 	}
    107 }