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

midiFileToRomData.cpp (3844B)


      1 #include "midiFileToRomData.h"
      2 
      3 #include "dsp56kEmu/logging.h"
      4 
      5 #include "synthLib/midiToSysex.h"
      6 
      7 namespace virusLib
      8 {
      9 	bool MidiFileToRomData::load(const std::string& _filename)
     10 	{
     11 		std::vector<uint8_t> sysex;
     12 
     13 		if(!synthLib::MidiToSysex::readFile(sysex, _filename.c_str()))
     14 			return false;
     15 
     16 		return load(sysex);
     17 	}
     18 
     19 	bool MidiFileToRomData::load(const std::vector<uint8_t>& _fileData, bool _isMidiFileData/* = false*/)
     20 	{
     21 		std::vector<std::vector<uint8_t>> packets;
     22 
     23 		synthLib::MidiToSysex::splitMultipleSysex(packets, _fileData, _isMidiFileData);
     24 
     25 		return add(packets);
     26 	}
     27 
     28 	bool MidiFileToRomData::add(const std::vector<Packet>& _packets)
     29 	{
     30 		for (const auto& packet : _packets)
     31 		{
     32 			if(!add(packet))
     33 				return false;
     34 			if(isComplete())
     35 				return true;
     36 		}
     37 		return false;
     38 	}
     39 
     40 	bool MidiFileToRomData::add(const Packet& _packet)
     41 	{
     42 		if(isComplete())
     43 			return isValid();
     44 
     45 		if(_packet.size() < 11)
     46 			return isValid();
     47 
     48 		const auto cmd = _packet[5];
     49 
     50 		switch (cmd)
     51 		{
     52 		case 0x50:	// Virus A
     53 		case 0x53:	// Virus B OS
     54 		case 0x54:	// Virus Rack Classic (B)
     55 		case 0x55:	// Virus B Demo
     56 		case 0x57:	// Virus C
     57 		case 0x58:	// Virus Rack XL (C)
     58 		case 0x59:	// Virus Classic Demo
     59 			{
     60 				const auto msb = _packet[6];	// packet number MSB
     61 				const auto lsb = _packet[7];	// packet number LSB
     62 
     63 				uint8_t checksum = 0;
     64 				for(size_t i=5; i<_packet.size()-2; ++i)
     65 					checksum += _packet[i];
     66 				checksum &= 0x7f;
     67 
     68 				if(checksum != _packet[_packet.size()-2])
     69 				{
     70 					LOG("Packet MSB " << static_cast<int>(msb) << " LSB " << static_cast<int>(lsb) << " is invalid, wrong checksum");
     71 					m_valid = false;
     72 					return false;
     73 				}
     74 
     75 				if(!processPacket(_packet, msb, lsb))
     76 				{
     77 					m_valid = false;
     78 					return false;
     79 				}
     80 				return isValid();
     81 			}
     82 		default:
     83 			// skip unknown packets
     84 			return true;
     85 		}
     86 	}
     87 
     88 	bool MidiFileToRomData::setCompleted()
     89 	{
     90 		m_complete = true;
     91 		if(!toBinary(m_data))
     92 			m_valid = false;
     93 		return isComplete();
     94 	}
     95 
     96 	bool MidiFileToRomData::toBinary(std::vector<uint8_t>& _binary) const
     97 	{
     98 		if(!isComplete())
     99 			return false;
    100 
    101 		for (const auto& p : m_packets)
    102 		{
    103 			// midi bytes in a sysex frame can only carry 7 bit, not 8. They've chosen the easy way that costs more storage
    104 			// They transfer only one nibble of a ROM byte in one midi byte to ensure that the most significant nibble is
    105 			// always zero. By concating two nibbles together we get one ROM byte
    106 			for(size_t s=8; s<p.size()-2; s += 2)
    107 			{
    108 				const uint8_t a = p[s];
    109 				const uint8_t b = p[s+1];
    110 				if(a > 0xf || b > 0xf)
    111 				{
    112 					LOG("Invalid data, high nibble must be 0");
    113 					return false;
    114 				}
    115 				_binary.push_back(static_cast<uint8_t>(b << 4) | a);
    116 			}
    117 		}
    118 		return true;
    119 	}
    120 	bool MidiFileToRomData::processPacket(const Packet& _packet, uint8_t msb, uint8_t lsb)
    121 	{
    122 //		LOG("Got Packet " << static_cast<int>(msb) << " " << static_cast<int>(lsb) << ", size " << _packet.size());
    123 
    124 		auto packetInvalid = [&]()
    125 		{
    126 			LOG("Packet invalid, expected packet index " << static_cast<int>(m_expectedMSB) << " " << static_cast<int>(m_expectedLSB) << " but got " << static_cast<int>(msb) << " " << static_cast<int>(lsb));
    127 			return false;
    128 		};
    129 
    130 		auto matchExpected = [&]()
    131 		{
    132 			return msb == m_expectedMSB && lsb == m_expectedLSB;
    133 		};
    134 
    135 		if(msb == 127 && m_expectedLSB > 3)
    136 		{
    137 			if(m_expectedSector == 0xff)
    138 			{
    139 				m_firstSector = m_expectedSector = lsb;
    140 			}
    141 
    142 			if(lsb != m_expectedSector)
    143 			{
    144 				if(lsb == 127 || lsb == 126)
    145 					return setCompleted();
    146 				return packetInvalid();
    147 			}
    148 			m_expectedLSB = m_expectedMSB = 0;
    149 			++m_expectedSector;
    150 //			addPacket(_packet);
    151 			return true;
    152 		}
    153 
    154 		if(!matchExpected())
    155 			return packetInvalid();
    156 
    157 		addPacket(_packet);
    158 		++m_expectedLSB;
    159 
    160 		if(m_expectedLSB > 3 && msb != 127)
    161 		{
    162 			m_expectedLSB = 0;
    163 			++m_expectedMSB;
    164 		}
    165 		return true;
    166 	}
    167 }