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

commit a548acbc01e805ce7f213c1a93423c8b43671a48
parent 8b825463e19cb94405a48837e481c51650c2a4f2
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Thu, 25 Jul 2024 19:49:04 +0200

move classes that are not synth specific into new baseLib

Diffstat:
Msource/CMakeLists.txt | 1+
Asource/baseLib/CMakeLists.txt | 23+++++++++++++++++++++++
Asource/baseLib/binarystream.cpp | 24++++++++++++++++++++++++
Asource/baseLib/binarystream.h | 470+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asource/baseLib/configFile.cpp | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asource/baseLib/configFile.h | 20++++++++++++++++++++
Asource/baseLib/hybridcontainer.h | 30++++++++++++++++++++++++++++++
Asource/baseLib/md5.cpp | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asource/baseLib/md5.h | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsource/synthLib/trigger.cpp -> source/baseLib/trigger.cpp | 0
Asource/baseLib/trigger.h | 40++++++++++++++++++++++++++++++++++++++++
Msource/jucePluginEditorLib/pluginProcessor.cpp | 10+++++-----
Msource/jucePluginEditorLib/pluginProcessor.h | 4++--
Msource/jucePluginLib/controller.cpp | 4++--
Msource/jucePluginLib/controller.h | 4++--
Msource/jucePluginLib/parameterlinks.cpp | 8++++----
Msource/jucePluginLib/parameterlinks.h | 4++--
Msource/jucePluginLib/patchdb/datasource.cpp | 8++++----
Msource/jucePluginLib/patchdb/datasource.h | 6+++---
Msource/jucePluginLib/patchdb/db.cpp | 19++++++++++---------
Msource/jucePluginLib/patchdb/patch.cpp | 8++++----
Msource/jucePluginLib/patchdb/patch.h | 6+++---
Msource/jucePluginLib/patchdb/patchmodifications.cpp | 8++++----
Msource/jucePluginLib/patchdb/patchmodifications.h | 4++--
Msource/jucePluginLib/patchdb/tags.cpp | 14+++++++-------
Msource/jucePluginLib/patchdb/tags.h | 10+++++-----
Msource/jucePluginLib/processor.cpp | 33+++++++++++++++++----------------
Msource/jucePluginLib/processor.h | 16++++++++++------
Msource/jucePluginLib/types.h | 4++--
Msource/mqTestConsole/mqTestConsole.cpp | 6+++---
Msource/nord/n2x/n2xLib/n2xdsp.h | 5+++--
Msource/synthLib/CMakeLists.txt | 7+------
Dsource/synthLib/binarystream.cpp | 24------------------------
Dsource/synthLib/binarystream.h | 470-------------------------------------------------------------------------------
Dsource/synthLib/configFile.cpp | 62--------------------------------------------------------------
Dsource/synthLib/configFile.h | 20--------------------
Msource/synthLib/dspMemoryPatch.cpp | 2+-
Msource/synthLib/dspMemoryPatch.h | 7++++---
Dsource/synthLib/hybridcontainer.h | 30------------------------------
Dsource/synthLib/md5.cpp | 145-------------------------------------------------------------------------------
Dsource/synthLib/md5.h | 88-------------------------------------------------------------------------------
Dsource/synthLib/trigger.h | 40----------------------------------------
Msource/virusJucePlugin/VirusProcessor.cpp | 11++++++-----
Msource/virusJucePlugin/VirusProcessor.h | 4++--
Msource/virusLib/dspMemoryPatches.cpp | 2+-
Msource/virusLib/dspMemoryPatches.h | 2+-
Msource/virusLib/romfile.h | 4++--
47 files changed, 1015 insertions(+), 987 deletions(-)

diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt @@ -16,6 +16,7 @@ add_subdirectory(dsp56300/source) # ----------------- Common libraries used by all synths +add_subdirectory(baseLib) add_subdirectory(synthLib) add_subdirectory(libresample) diff --git a/source/baseLib/CMakeLists.txt b/source/baseLib/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.10) +project(baseLib) + +add_library(baseLib STATIC) + +set(SOURCES + binarystream.cpp binarystream.h + configFile.cpp configFile.h + hybridcontainer.h + md5.cpp md5.h + trigger.cpp trigger.h +) + +target_sources(baseLib PRIVATE ${SOURCES}) +source_group("source" FILES ${SOURCES}) + +if(NOT MSVC) + target_link_libraries(baseLib PUBLIC dl) +endif() + +set_property(TARGET baseLib PROPERTY FOLDER "Gearmulator") + +target_include_directories(baseLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..) diff --git a/source/baseLib/binarystream.cpp b/source/baseLib/binarystream.cpp @@ -0,0 +1,24 @@ +#include "binarystream.h" + +namespace baseLib +{ + BinaryStream BinaryStream::readChunk() + { + Chunk chunk; + chunk.read(*this); + return std::move(chunk.data); + } + + BinaryStream BinaryStream::tryReadChunkInternal(const char* _4Cc, const uint32_t _version) + { + Chunk chunk; + chunk.read(*this); + if(chunk.version != _version) + return {}; + if(0 != strcmp(chunk.fourCC, _4Cc)) + return {}; + return std::move(chunk.data); + } + + template BinaryStream BinaryStream::tryReadChunk(char const(& _4Cc)[5], uint32_t _version); +} diff --git a/source/baseLib/binarystream.h b/source/baseLib/binarystream.h @@ -0,0 +1,470 @@ +#pragma once + +#include <cassert> +#include <cstdint> +#include <functional> +#include <sstream> +#include <vector> +#include <cstring> + +namespace baseLib +{ + class StreamBuffer + { + public: + StreamBuffer() = default; + explicit StreamBuffer(std::vector<uint8_t>&& _buffer) : m_vector(std::move(_buffer)) + { + } + explicit StreamBuffer(const size_t _capacity) + { + m_vector.reserve(_capacity); + } + StreamBuffer(uint8_t* _buffer, const size_t _size) : m_buffer(_buffer), m_size(_size), m_fixedSize(true) + { + } + StreamBuffer(StreamBuffer& _parent, const size_t _childSize) : m_buffer(&_parent.buffer()[_parent.tellg()]), m_size(_childSize), m_fixedSize(true) + { + // force eof if range is not valid + if(_parent.tellg() + _childSize > _parent.size()) + { + assert(false && "invalid range"); + m_readPos = _childSize; + } + + // seek parent forward + _parent.seekg(_parent.tellg() + _childSize); + } + StreamBuffer(StreamBuffer&& _source) noexcept + : m_buffer(_source.m_buffer) + , m_size(_source.m_size) + , m_fixedSize(_source.m_fixedSize) + , m_readPos(_source.m_readPos) + , m_writePos(_source.m_writePos) + , m_vector(std::move(_source.m_vector)) + , m_fail(_source.m_fail) + { + _source.destroy(); + } + + StreamBuffer& operator = (StreamBuffer&& _source) noexcept + { + m_buffer = _source.m_buffer; + m_size = _source.m_size; + m_fixedSize = _source.m_fixedSize; + m_readPos = _source.m_readPos; + m_writePos = _source.m_writePos; + m_vector = std::move(_source.m_vector); + + _source.destroy(); + + return *this; + } + + void seekg(const size_t _pos) { m_readPos = _pos; } + size_t tellg() const { return m_readPos; } + void seekp(const size_t _pos) { m_writePos = _pos; } + size_t tellp() const { return m_writePos; } + bool eof() const { return tellg() >= size(); } + bool fail() const { return m_fail; } + + bool read(uint8_t* _dst, size_t _size) + { + const auto remaining = size() - tellg(); + if(remaining < _size) + { + m_fail = true; + return false; + } + ::memcpy(_dst, &buffer()[m_readPos], _size); + m_readPos += _size; + return true; + } + bool write(const uint8_t* _src, size_t _size) + { + const auto remaining = size() - tellp(); + if(remaining < _size) + { + if(m_fixedSize) + { + m_fail = true; + return false; + } + m_vector.resize(tellp() + _size); + } + ::memcpy(&buffer()[m_writePos], _src, _size); + m_writePos += _size; + return true; + } + + explicit operator bool () const + { + return !eof(); + } + + private: + size_t size() const { return m_fixedSize ? m_size : m_vector.size(); } + + uint8_t* buffer() + { + if(m_fixedSize) + return m_buffer; + return m_vector.data(); + } + + void destroy() + { + m_buffer = nullptr; + m_size = 0; + m_fixedSize = false; + m_readPos = 0; + m_writePos = 0; + m_vector.clear(); + m_fail = false; + } + + uint8_t* m_buffer = nullptr; + size_t m_size = 0; + bool m_fixedSize = false; + size_t m_readPos = 0; + size_t m_writePos = 0; + std::vector<uint8_t> m_vector; + bool m_fail = false; + }; + + using StreamSizeType = uint32_t; + + class BinaryStream final : StreamBuffer + { + public: + using Base = StreamBuffer; + using SizeType = StreamSizeType; + + BinaryStream() = default; + + using StreamBuffer::operator bool; + + explicit BinaryStream(BinaryStream& _parent, SizeType _length) : StreamBuffer(_parent, _length) + { + } + + template<typename T> explicit BinaryStream(const std::vector<T>& _data) + { + Base::write(reinterpret_cast<const uint8_t*>(_data.data()), _data.size() * sizeof(T)); + seekg(0); + } + + // ___________________________________ + // tools + // + + void toVector(std::vector<uint8_t>& _buffer, const bool _append = false) + { + const auto size = tellp(); + if(size <= 0) + { + if(!_append) + _buffer.clear(); + return; + } + + seekg(0); + + if(_append) + { + const auto currentSize = _buffer.size(); + _buffer.resize(currentSize + size); + Base::read(&_buffer[currentSize], size); + } + else + { + _buffer.resize(size); + Base::read(_buffer.data(), size); + } + } + + bool checkString(const std::string& _str) + { + const auto pos = tellg(); + + const auto size = read<SizeType>(); + if (size != _str.size()) + { + seekg(pos); + return false; + } + std::string s; + s.resize(size); + Base::read(reinterpret_cast<uint8_t*>(s.data()), size); + const auto result = _str == s; + seekg(pos); + return result; + } + + uint32_t getWritePos() const { return static_cast<uint32_t>(tellp()); } + uint32_t getReadPos() const { return static_cast<uint32_t>(tellg()); } + bool endOfStream() const { return eof(); } + + void setWritePos(const uint32_t _pos) { seekp(_pos); } + void setReadPos(const uint32_t _pos) { seekg(_pos); } + + // ___________________________________ + // write + // + + template<typename T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> void write(const T& _value) + { + Base::write(reinterpret_cast<const uint8_t*>(&_value), sizeof(_value)); + } + + template<typename T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> void write(const std::vector<T>& _vector) + { + const auto size = static_cast<SizeType>(_vector.size()); + write(size); + if(size) + Base::write(reinterpret_cast<const uint8_t*>(_vector.data()), sizeof(T) * size); + } + + void write(const std::string& _string) + { + const auto s = static_cast<SizeType>(_string.size()); + write(s); + Base::write(reinterpret_cast<const uint8_t*>(_string.c_str()), s); + } + + void write(const char* const _value) + { + write(std::string(_value)); + } + + template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> + void write4CC(char const(&_str)[N]) + { + write(_str[0]); + write(_str[1]); + write(_str[2]); + write(_str[3]); + } + + + // ___________________________________ + // read + // + + template<typename T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> T read() + { + T v{}; + Base::read(reinterpret_cast<uint8_t*>(&v), sizeof(v)); + checkFail(); + return v; + } + + template<typename T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> void read(std::vector<T>& _vector) + { + const auto size = read<SizeType>(); + checkFail(); + if (!size) + { + _vector.clear(); + return; + } + _vector.resize(size); + Base::read(reinterpret_cast<uint8_t*>(_vector.data()), sizeof(T) * size); + checkFail(); + } + + std::string readString() + { + const auto size = read<SizeType>(); + std::string s; + s.resize(size); + Base::read(reinterpret_cast<uint8_t*>(s.data()), size); + checkFail(); + return s; + } + + template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> + void read4CC(char const(&_str)[N]) + { + char res[5]; + read4CC(res); + + return strcmp(res, _str) == 0; + } + + template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> + void read4CC(char (&_str)[N]) + { + _str[0] = 'E'; + _str[1] = 'R'; + _str[2] = 'R'; + _str[3] = 'R'; + _str[4] = 0; + + _str[0] = read<char>(); + _str[1] = read<char>(); + _str[2] = read<char>(); + _str[3] = read<char>(); + } + + BinaryStream readChunk(); + template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> + BinaryStream tryReadChunk(char const(&_4Cc)[N], const uint32_t _version = 1) + { + return tryReadChunkInternal(_4Cc, _version); + } + + private: + BinaryStream tryReadChunkInternal(const char* _4Cc, uint32_t _version = 1); + + + // ___________________________________ + // helpers + // + + private: + void checkFail() const + { + if(fail()) + throw std::range_error("end-of-stream"); + } + }; + + struct Chunk + { + using SizeType = BinaryStream::SizeType; + + char fourCC[5]; + uint32_t version; + SizeType length; + BinaryStream data; + + bool read(BinaryStream& _parentStream) + { + _parentStream.read4CC(fourCC); + version = _parentStream.read<uint32_t>(); + length = _parentStream.read<SizeType>(); + data = BinaryStream(_parentStream, length); + return !data.endOfStream(); + } + }; + + class ChunkWriter + { + public: + using SizeType = BinaryStream::SizeType; + + template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> + ChunkWriter(BinaryStream& _stream, char const(&_4Cc)[N], const uint32_t _version = 1) : m_stream(_stream) + { + m_stream.write4CC(_4Cc); + m_stream.write(_version); + m_lengthWritePos = m_stream.getWritePos(); + m_stream.write<SizeType>(0); + } + + ChunkWriter() = delete; + ChunkWriter(ChunkWriter&&) = delete; + ChunkWriter(const ChunkWriter&) = delete; + ChunkWriter& operator = (ChunkWriter&&) = delete; + ChunkWriter& operator = (const ChunkWriter&) = delete; + + ~ChunkWriter() + { + const auto currentWritePos = m_stream.getWritePos(); + const SizeType chunkDataLength = currentWritePos - m_lengthWritePos - sizeof(SizeType); + m_stream.setWritePos(m_lengthWritePos); + m_stream.write(chunkDataLength); + m_stream.setWritePos(currentWritePos); + } + + private: + BinaryStream& m_stream; + SizeType m_lengthWritePos = 0; + }; + + class ChunkReader + { + public: + using SizeType = ChunkWriter::SizeType; + using ChunkCallback = std::function<void(BinaryStream&, uint32_t)>; // data, version + + struct ChunkCallbackData + { + char fourCC[5]; + uint32_t expectedVersion; + ChunkCallback callback; + }; + + explicit ChunkReader(BinaryStream& _stream) : m_stream(_stream) + { + } + + template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> + void add(char const(&_4Cc)[N], const uint32_t _version, const ChunkCallback& _callback) + { + ChunkCallbackData c; + strcpy(c.fourCC, _4Cc); + c.expectedVersion = _version; + c.callback = _callback; + supportedChunks.emplace_back(std::move(c)); + } + + void read(const uint32_t _count = 0) + { + uint32_t count = 0; + + while(!m_stream.endOfStream() && (!_count || ++count <= _count)) + { + Chunk chunk; + chunk.read(m_stream); + + ++m_numChunks; + + for (const auto& chunkData : supportedChunks) + { + if(0 != strcmp(chunkData.fourCC, chunk.fourCC)) + continue; + + if(chunk.version > chunkData.expectedVersion) + break; + + ++m_numRead; + chunkData.callback(chunk.data, chunk.version); + break; + } + } + } + + bool tryRead(const uint32_t _count = 0) + { + const auto pos = m_stream.getReadPos(); + try + { + read(_count); + return true; + } + catch(std::range_error&) + { + m_stream.setReadPos(pos); + return false; + } + } + + uint32_t numRead() const + { + return m_numRead; + } + + uint32_t numChunks() const + { + return m_numChunks; + } + + private: + BinaryStream& m_stream; + std::vector<ChunkCallbackData> supportedChunks; + uint32_t m_numRead = 0; + uint32_t m_numChunks = 0; + }; +} diff --git a/source/baseLib/configFile.cpp b/source/baseLib/configFile.cpp @@ -0,0 +1,59 @@ +#include "configFile.h" + +#include <fstream> + +namespace baseLib +{ + static bool needsTrim(char _c) + { + switch (_c) + { + case ' ': + case '\r': + case '\n': + case '\t': + return true; + default: + return false; + } + } + + static std::string trim(std::string _s) + { + while (!_s.empty() && needsTrim(_s.front())) + _s = _s.substr(1); + while (!_s.empty() && needsTrim(_s.back())) + _s = _s.substr(0, _s.size() - 1); + return _s; + } + + ConfigFile::ConfigFile(const char* _filename) + { + std::ifstream file(_filename, std::ios::in); + + if (!file.is_open()) + throw std::runtime_error("Failed to open config file " + std::string(_filename)); + + std::string line; + + while(std::getline(file, line)) + { + if(line.empty()) + continue; + + // // comment? + if (line.front() == '#' || line.front() == ';') + continue; + + const auto posEq = line.find('='); + + if (posEq == std::string::npos) + continue; + + const auto key = trim(line.substr(0, posEq)); + const auto val = trim(line.substr(posEq + 1)); + + m_values.emplace_back(key, val); + } + } +} +\ No newline at end of file diff --git a/source/baseLib/configFile.h b/source/baseLib/configFile.h @@ -0,0 +1,20 @@ +#pragma once + +#include <string> +#include <vector> + +namespace baseLib +{ + class ConfigFile + { + public: + explicit ConfigFile(const char* _filename); + + const std::vector<std::pair<std::string, std::string>>& getValues() const + { + return m_values; + } + private: + std::vector<std::pair<std::string, std::string>> m_values; + }; +} diff --git a/source/baseLib/hybridcontainer.h b/source/baseLib/hybridcontainer.h @@ -0,0 +1,29 @@ +#pragma once +/* +#include <vector> +#include <memory_resource> +#include <array> + +namespace baseLib +{ + template<typename T, size_t S> class BufferResource + { + public: + auto& getPool() { return m_pool; } + protected: + std::array<T, S> m_buffer; + std::pmr::monotonic_buffer_resource m_pool{ std::data(m_buffer), std::size(m_buffer) }; + }; + + template<typename T, size_t S> + class HybridVector final : public BufferResource<T,S>, public std::pmr::vector<T> + { + public: + using Base = std::pmr::vector<T>; + + HybridVector() : BufferResource<T, S>(), Base(&static_cast<BufferResource<T, S>&>(*this).getPool()) + { + } + }; +} +*/ +\ No newline at end of file diff --git a/source/baseLib/md5.cpp b/source/baseLib/md5.cpp @@ -0,0 +1,147 @@ +#include "md5.h" + +#include <cstring> // memcpy +#include <iomanip> +#include <sstream> + +#define HEXN(S, n) std::hex << std::setfill('0') << std::setw(n) << (uint32_t)S + +namespace baseLib +{ + // leftrotate function definition + uint32_t leftrotate(const uint32_t x, const uint32_t c) + { + return (((x) << (c)) | ((x) >> (32 - (c)))); + } + + // These vars will contain the hash: h0, h1, h2, h3 + void md5(uint32_t& _h0, uint32_t& _h1, uint32_t& _h2, uint32_t& _h3, const uint8_t *_initialMsg, const uint32_t _initialLen) + { + // Note: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating + + // r specifies the per-round shift amounts + + constexpr uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; + + // Use binary integer part of the sines of integers (in radians) as constants// Initialize variables: + constexpr uint32_t k[] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }; + + _h0 = 0x67452301; + _h1 = 0xefcdab89; + _h2 = 0x98badcfe; + _h3 = 0x10325476; + + // Pre-processing: adding a single 1 bit + //append "1" bit to message + /* Notice: the input bytes are considered as bits strings, + where the first bit is the most significant bit of the byte.[37] */ + + // Pre-processing: padding with zeros + //append "0" bit until message length in bit ≡ 448 (mod 512) + //append length mod (2 pow 64) to message + + const uint32_t newLen = ((((_initialLen + 8) / 64) + 1) * 64) - 8; + + std::vector<uint8_t> buffer; + buffer.resize(newLen + 64, 0); + auto* msg = buffer.data(); + memcpy(msg, _initialMsg, _initialLen); + msg[_initialLen] = 128; // write the "1" bit + + const uint32_t bitsLen = 8 * _initialLen; // note, we append the len + memcpy(msg + newLen, &bitsLen, 4); // in bits at the end of the buffer + + // Process the message in successive 512-bit chunks: + //for each 512-bit chunk of message: + for (uint32_t offset = 0; offset < newLen; offset += (512 / 8)) + { + // break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15 + const auto* w = reinterpret_cast<uint32_t*>(msg + offset); + + // Initialize hash value for this chunk: + uint32_t a = _h0; + uint32_t b = _h1; + uint32_t c = _h2; + uint32_t d = _h3; + + // Main loop: + for (uint32_t i = 0; i < 64; i++) + { + uint32_t f, g; + + if (i < 16) { + f = (b & c) | ((~b) & d); + g = i; + } + else if (i < 32) { + f = (d & b) | ((~d) & c); + g = (5 * i + 1) % 16; + } + else if (i < 48) { + f = b ^ c ^ d; + g = (3 * i + 5) % 16; + } + else { + f = c ^ (b | (~d)); + g = (7 * i) % 16; + } + + const uint32_t temp = d; + d = c; + c = b; +// printf("rotateLeft(%x + %x + %x + %x, %d)\n", a, f, k[i], w[g], r[i]); + b = b + leftrotate((a + f + k[i] + w[g]), r[i]); + a = temp; + } + + // Add this chunk's hash to result so far: + + _h0 += a; + _h1 += b; + _h2 += c; + _h3 += d; + + } + + // cleanup + // free(msg); + } + + MD5::MD5(const std::vector<uint8_t>& _data) + { + md5(m_h[0], m_h[1], m_h[2], m_h[3], _data.data(), static_cast<uint32_t>(_data.size())); + } + + std::string MD5::toString() const + { + std::stringstream ss; + + for (const auto& e : m_h) + { + ss << HEXN((e & 0xff), 2); + ss << HEXN(((e>>8u) & 0xff), 2); + ss << HEXN(((e>>16u) & 0xff), 2); + ss << HEXN(((e>>24u) & 0xff), 2); + } + return ss.str(); + } +} diff --git a/source/baseLib/md5.h b/source/baseLib/md5.h @@ -0,0 +1,88 @@ +#pragma once + +#include <array> +#include <cassert> +#include <cstdint> +#include <string> +#include <vector> + +namespace baseLib +{ + class MD5 + { + public: + static constexpr uint32_t parse1(const char _b) + { + if (_b >= '0' && _b <= '9') + return _b - '0'; + if (_b >= 'A' && _b <= 'F') + return _b - 'A' + 10; + if (_b >= 'a' && _b <= 'f') + return _b - 'a' + 10; + assert(false); + return 0; + } + static constexpr uint32_t parse2(const char _b0, const char _b1) + { + return parse1(_b1) << 4 | parse1(_b0); + } + static constexpr uint32_t parse4(const char _b0, const char _b1, const char _b2, const char _b3) + { + return parse2(_b3, _b2) << 8 | parse2(_b1, _b0); + } + static constexpr uint32_t parse8(const char _b0, const char _b1, const char _b2, const char _b3, const char _b4, const char _b5, const char _b6, const char _b7) + { + return parse4(_b4, _b5, _b6, _b7) << 16 | parse4(_b0, _b1, _b2, _b3); + } + + template<size_t N, std::enable_if_t<N == 33, void*> = nullptr> constexpr MD5(char const(&_digest)[N]) + : m_h + { + parse8(_digest[ 0], _digest[ 1], _digest[ 2], _digest[ 3], _digest[ 4], _digest[ 5], _digest[ 6], _digest[ 7]), + parse8(_digest[ 8], _digest[ 9], _digest[10], _digest[11], _digest[12], _digest[13], _digest[14], _digest[15]), + parse8(_digest[16], _digest[17], _digest[18], _digest[19], _digest[20], _digest[21], _digest[22], _digest[23]), + parse8(_digest[24], _digest[25], _digest[26], _digest[27], _digest[28], _digest[29], _digest[30], _digest[31]) + } + { + } + + explicit MD5(const std::vector<uint8_t>& _data); + + MD5() : m_h({0,0,0,0}) {} + + MD5(const MD5& _src) = default; + MD5(MD5&& _src) = default; + + ~MD5() = default; + + MD5& operator = (const MD5&) = default; + MD5& operator = (MD5&&) = default; + + std::string toString() const; + + constexpr bool operator == (const MD5& _md5) const + { + return m_h[0] == _md5.m_h[0] && m_h[1] == _md5.m_h[1] && m_h[2] == _md5.m_h[2] && m_h[3] == _md5.m_h[3]; + } + + constexpr bool operator != (const MD5& _md5) const + { + return !(*this == _md5); + } + + constexpr bool operator < (const MD5& _md5) const + { + if(m_h[0] < _md5.m_h[0]) return true; + if(m_h[0] > _md5.m_h[0]) return false; + if(m_h[1] < _md5.m_h[1]) return true; + if(m_h[1] > _md5.m_h[1]) return false; + if(m_h[2] < _md5.m_h[2]) return true; + if(m_h[2] > _md5.m_h[2]) return false; + if(m_h[3] < _md5.m_h[3]) return true; + /*if(m_h[3] > _md5.m_h[3])*/ return false; + } + + private: + std::array<uint32_t, 4> m_h; + }; +} diff --git a/source/synthLib/trigger.cpp b/source/baseLib/trigger.cpp diff --git a/source/baseLib/trigger.h b/source/baseLib/trigger.h @@ -0,0 +1,40 @@ +#pragma once + +#include <mutex> +#include <condition_variable> +#include <cstdint> + +namespace baseLib +{ + template<typename TCounter = uint32_t> + class Trigger + { + public: + void wait() + { + std::unique_lock uLock(m_haltMutex); + + m_haltcv.wait(uLock, [&] + { + return m_notifyCounter > m_waitCounter; + }); + + ++m_waitCounter; + } + + void notify() + { + { + std::lock_guard uLockHalt(m_haltMutex); + ++m_notifyCounter; + } + m_haltcv.notify_one(); + } + + private: + std::condition_variable m_haltcv; + std::mutex m_haltMutex; + TCounter m_waitCounter = 0; + TCounter m_notifyCounter = 0; + }; +} diff --git a/source/jucePluginEditorLib/pluginProcessor.cpp b/source/jucePluginEditorLib/pluginProcessor.cpp @@ -3,7 +3,7 @@ #include "pluginEditorState.h" #include "pluginEditorWindow.h" -#include "synthLib/binarystream.h" +#include "baseLib/binarystream.h" namespace jucePluginEditorLib { @@ -57,7 +57,7 @@ namespace jucePluginEditorLib m_editorState.reset(); } - void Processor::saveChunkData(synthLib::BinaryStream& s) + void Processor::saveChunkData(baseLib::BinaryStream& s) { pluginLib::Processor::saveChunkData(s); @@ -69,7 +69,7 @@ namespace jucePluginEditorLib if(!m_editorStateData.empty()) { - synthLib::ChunkWriter cw(s, "EDST", 1); + baseLib::ChunkWriter cw(s, "EDST", 1); s.write(m_editorStateData); } @@ -88,11 +88,11 @@ namespace jucePluginEditorLib return true; } - void Processor::loadChunkData(synthLib::ChunkReader& _cr) + void Processor::loadChunkData(baseLib::ChunkReader& _cr) { pluginLib::Processor::loadChunkData(_cr); - _cr.add("EDST", 1, [this](synthLib::BinaryStream& _binaryStream, unsigned _version) + _cr.add("EDST", 1, [this](baseLib::BinaryStream& _binaryStream, unsigned _version) { _binaryStream.read(m_editorStateData); }); diff --git a/source/jucePluginEditorLib/pluginProcessor.h b/source/jucePluginEditorLib/pluginProcessor.h @@ -23,9 +23,9 @@ namespace jucePluginEditorLib virtual PluginEditorState* createEditorState() = 0; void destroyEditorState(); - void saveChunkData(synthLib::BinaryStream& s) override; + void saveChunkData(baseLib::BinaryStream& s) override; bool loadCustomData(const std::vector<uint8_t>& _sourceBuffer) override; - void loadChunkData(synthLib::ChunkReader& _cr) override; + void loadChunkData(baseLib::ChunkReader& _cr) override; private: std::unique_ptr<PluginEditorState> m_editorState; diff --git a/source/jucePluginLib/controller.cpp b/source/jucePluginLib/controller.cpp @@ -497,12 +497,12 @@ namespace pluginLib m_midiMessages.insert(m_midiMessages.end(), _events.begin(), _events.end()); } - void Controller::loadChunkData(synthLib::ChunkReader& _cr) + void Controller::loadChunkData(baseLib::ChunkReader& _cr) { m_parameterLinks.loadChunkData(_cr); } - void Controller::saveChunkData(synthLib::BinaryStream& s) + void Controller::saveChunkData(baseLib::BinaryStream& s) { m_parameterLinks.saveChunkData(s); } diff --git a/source/jucePluginLib/controller.h b/source/jucePluginLib/controller.h @@ -72,8 +72,8 @@ namespace pluginLib // this is called by the plug-in on audio thread! void enqueueMidiMessages(const std::vector<synthLib::SMidiEvent>&); - void loadChunkData(synthLib::ChunkReader& _cr); - void saveChunkData(synthLib::BinaryStream& s); + void loadChunkData(baseLib::ChunkReader& _cr); + void saveChunkData(baseLib::BinaryStream& s); private: void getMidiMessages(std::vector<synthLib::SMidiEvent>&); diff --git a/source/jucePluginLib/parameterlinks.cpp b/source/jucePluginLib/parameterlinks.cpp @@ -130,12 +130,12 @@ namespace pluginLib return m_linkedRegions.find(link) != m_linkedRegions.end(); } - void ParameterLinks::saveChunkData(synthLib::BinaryStream& s) const + void ParameterLinks::saveChunkData(baseLib::BinaryStream& s) const { if(m_linkedRegions.empty()) return; - synthLib::ChunkWriter cw(s, "PLNK", 1); + baseLib::ChunkWriter cw(s, "PLNK", 1); s.write(static_cast<uint32_t>(m_linkedRegions.size())); @@ -147,9 +147,9 @@ namespace pluginLib } } - void ParameterLinks::loadChunkData(synthLib::ChunkReader& _cr) + void ParameterLinks::loadChunkData(baseLib::ChunkReader& _cr) { - _cr.add("PLNK", 1, [this](synthLib::BinaryStream& _binaryStream, unsigned _version) + _cr.add("PLNK", 1, [this](baseLib::BinaryStream& _binaryStream, unsigned _version) { const uint32_t count = _binaryStream.read<uint32_t>(); diff --git a/source/jucePluginLib/parameterlinks.h b/source/jucePluginLib/parameterlinks.h @@ -26,8 +26,8 @@ namespace pluginLib bool unlinkRegion(const std::string& _regionId, uint8_t _partSource, uint8_t _partDest); bool isRegionLinked(const std::string& _regionId, uint8_t _partSource, uint8_t _partDest) const; - void saveChunkData(synthLib::BinaryStream& s) const; - void loadChunkData(synthLib::ChunkReader& _cr); + void saveChunkData(baseLib::BinaryStream& s) const; + void loadChunkData(baseLib::ChunkReader& _cr); private: struct RegionLink diff --git a/source/jucePluginLib/patchdb/datasource.cpp b/source/jucePluginLib/patchdb/datasource.cpp @@ -7,7 +7,7 @@ #include "db.h" #include "patch.h" -#include "synthLib/binarystream.h" +#include "baseLib/binarystream.h" namespace pluginLib::patchDB { @@ -157,9 +157,9 @@ namespace pluginLib::patchDB return ss.str(); } - void DataSource::write(synthLib::BinaryStream& _outStream) const + void DataSource::write(baseLib::BinaryStream& _outStream) const { - synthLib::ChunkWriter cw(_outStream, chunks::g_datasource, 1); + baseLib::ChunkWriter cw(_outStream, chunks::g_datasource, 1); _outStream.write(static_cast<uint8_t>(type)); _outStream.write(static_cast<uint8_t>(origin)); @@ -172,7 +172,7 @@ namespace pluginLib::patchDB patch->write(_outStream); } - bool DataSource::read(synthLib::BinaryStream& _inStream) + bool DataSource::read(baseLib::BinaryStream& _inStream) { auto in = _inStream.tryReadChunk(chunks::g_datasource); if(!in) diff --git a/source/jucePluginLib/patchdb/datasource.h b/source/jucePluginLib/patchdb/datasource.h @@ -4,7 +4,7 @@ #include "patchdbtypes.h" -namespace synthLib +namespace baseLib { class BinaryStream; } @@ -115,8 +115,8 @@ namespace pluginLib::patchDB std::string toString() const; - void write(synthLib::BinaryStream& _outStream) const; - bool read(synthLib::BinaryStream& _inStream); + void write(baseLib::BinaryStream& _outStream) const; + bool read(baseLib::BinaryStream& _inStream); }; struct DataSourceNode final : DataSource, std::enable_shared_from_this<DataSourceNode> diff --git a/source/jucePluginLib/patchdb/db.cpp b/source/jucePluginLib/patchdb/db.cpp @@ -8,8 +8,9 @@ #include "synthLib/os.h" #include "synthLib/midiToSysex.h" -#include "synthLib/hybridcontainer.h" -#include "synthLib/binarystream.h" + +#include "baseLib/hybridcontainer.h" +#include "baseLib/binarystream.h" #include "dsp56kEmu/logging.h" @@ -1733,7 +1734,7 @@ namespace pluginLib::patchDB try { - synthLib::BinaryStream inStream(data); + baseLib::BinaryStream inStream(data); auto stream = inStream.tryReadChunk(chunks::g_patchManager, 2); @@ -1933,14 +1934,14 @@ namespace pluginLib::patchDB if(!m_cacheFileName.hasWriteAccess()) return; - synthLib::BinaryStream outStream; + baseLib::BinaryStream outStream; { std::shared_lock lockDS(m_dataSourcesMutex); std::shared_lock lockP(m_patchesMutex); - synthLib::ChunkWriter cw(outStream, chunks::g_patchManager, 2); + baseLib::ChunkWriter cw(outStream, chunks::g_patchManager, 2); { - synthLib::ChunkWriter cwDS(outStream, chunks::g_patchManagerDataSources, 1); + baseLib::ChunkWriter cwDS(outStream, chunks::g_patchManagerDataSources, 1); outStream.write<uint32_t>(static_cast<uint32_t>(m_dataSources.size())); @@ -1985,7 +1986,7 @@ namespace pluginLib::patchDB { // write tags - synthLib::ChunkWriter cwDS(outStream, chunks::g_patchManagerTags, 1); + baseLib::ChunkWriter cwDS(outStream, chunks::g_patchManagerTags, 1); outStream.write(static_cast<uint32_t>(m_tags.size())); @@ -2004,7 +2005,7 @@ namespace pluginLib::patchDB { // write tag colors - synthLib::ChunkWriter cwDS(outStream, chunks::g_patchManagerTagColors, 1); + baseLib::ChunkWriter cwDS(outStream, chunks::g_patchManagerTagColors, 1); outStream.write(static_cast<uint32_t>(m_tagColors.size())); @@ -2026,7 +2027,7 @@ namespace pluginLib::patchDB { // write patch modifications - synthLib::ChunkWriter cwDS(outStream, chunks::g_patchManagerPatchModifications, 1); + baseLib::ChunkWriter cwDS(outStream, chunks::g_patchManagerPatchModifications, 1); outStream.write(static_cast<uint32_t>(m_patchModifications.size())); diff --git a/source/jucePluginLib/patchdb/patch.cpp b/source/jucePluginLib/patchdb/patch.cpp @@ -9,7 +9,7 @@ #include "juce_core/juce_core.h" -#include "synthLib/binarystream.h" +#include "baseLib/binarystream.h" namespace pluginLib::patchDB { @@ -43,9 +43,9 @@ namespace pluginLib::patchDB sysex = _patch.sysex; } - void Patch::write(synthLib::BinaryStream& _s) const + void Patch::write(baseLib::BinaryStream& _s) const { - synthLib::ChunkWriter chunkWriter(_s, chunks::g_patch, 2); + baseLib::ChunkWriter chunkWriter(_s, chunks::g_patch, 2); _s.write(name); _s.write(bank); @@ -66,7 +66,7 @@ namespace pluginLib::patchDB _s.write(sysex); } - bool Patch::read(synthLib::BinaryStream& _in) + bool Patch::read(baseLib::BinaryStream& _in) { auto in = _in.tryReadChunk(chunks::g_patch, 2); if(!in) diff --git a/source/jucePluginLib/patchdb/patch.h b/source/jucePluginLib/patchdb/patch.h @@ -9,7 +9,7 @@ #include "tags.h" #include "patchdbtypes.h" -namespace synthLib +namespace baseLib { class BinaryStream; } @@ -33,8 +33,8 @@ namespace pluginLib::patchDB void replaceData(const Patch& _patch); - void write(synthLib::BinaryStream& _s) const; - bool read(synthLib::BinaryStream& _in); + void write(baseLib::BinaryStream& _s) const; + bool read(baseLib::BinaryStream& _in); bool operator == (const PatchKey& _key) const; bool operator != (const PatchKey& _key) const diff --git a/source/jucePluginLib/patchdb/patchmodifications.cpp b/source/jucePluginLib/patchdb/patchmodifications.cpp @@ -4,7 +4,7 @@ #include "juce_core/juce_core.h" -#include "synthLib/binarystream.h" +#include "baseLib/binarystream.h" namespace pluginLib::patchDB { @@ -109,14 +109,14 @@ namespace pluginLib::patchDB return name.empty() && tags.empty(); } - void PatchModifications::write(synthLib::BinaryStream& _outStream) const + void PatchModifications::write(baseLib::BinaryStream& _outStream) const { - synthLib::ChunkWriter cw(_outStream, chunks::g_patchModification, 1); + baseLib::ChunkWriter cw(_outStream, chunks::g_patchModification, 1); _outStream.write(name); tags.write(_outStream); } - bool PatchModifications::read(synthLib::BinaryStream& _binaryStream) + bool PatchModifications::read(baseLib::BinaryStream& _binaryStream) { auto in = _binaryStream.tryReadChunk(chunks::g_patchModification, 1); if(!in) diff --git a/source/jucePluginLib/patchdb/patchmodifications.h b/source/jucePluginLib/patchdb/patchmodifications.h @@ -20,8 +20,8 @@ namespace pluginLib::patchDB bool empty() const; - void write(synthLib::BinaryStream& _outStream) const; - bool read(synthLib::BinaryStream& _binaryStream); + void write(baseLib::BinaryStream& _outStream) const; + bool read(baseLib::BinaryStream& _binaryStream); std::weak_ptr<Patch> patch; TypedTags tags; diff --git a/source/jucePluginLib/patchdb/tags.cpp b/source/jucePluginLib/patchdb/tags.cpp @@ -2,13 +2,13 @@ #include "juce_core/juce_core.h" -#include "synthLib/binarystream.h" +#include "baseLib/binarystream.h" namespace pluginLib::patchDB { - void Tags::write(synthLib::BinaryStream& _s) const + void Tags::write(baseLib::BinaryStream& _s) const { - synthLib::ChunkWriter cw(_s, chunks::g_tags, 1); + baseLib::ChunkWriter cw(_s, chunks::g_tags, 1); _s.write(m_added.size()); for (const auto& added : m_added) _s.write(added); @@ -17,7 +17,7 @@ namespace pluginLib::patchDB _s.write(removed); } - bool Tags::read(synthLib::BinaryStream& _stream) + bool Tags::read(baseLib::BinaryStream& _stream) { auto in = _stream.tryReadChunk(chunks::g_tags, 1); if(!in) @@ -253,9 +253,9 @@ namespace pluginLib::patchDB return true; } - void TypedTags::write(synthLib::BinaryStream& _s) const + void TypedTags::write(baseLib::BinaryStream& _s) const { - synthLib::ChunkWriter cw(_s, chunks::g_typedTags, 1); + baseLib::ChunkWriter cw(_s, chunks::g_typedTags, 1); _s.write(m_tags.size()); for (const auto& t : m_tags) @@ -265,7 +265,7 @@ namespace pluginLib::patchDB } } - bool TypedTags::read(synthLib::BinaryStream& _stream) + bool TypedTags::read(baseLib::BinaryStream& _stream) { auto in = _stream.tryReadChunk(chunks::g_typedTags, 1); diff --git a/source/jucePluginLib/patchdb/tags.h b/source/jucePluginLib/patchdb/tags.h @@ -6,7 +6,7 @@ #include "patchdbtypes.h" -namespace synthLib +namespace baseLib { class BinaryStream; } @@ -77,8 +77,8 @@ namespace pluginLib::patchDB return m_added.empty() && m_removed.empty(); } - void write(synthLib::BinaryStream& _s) const; - bool read(synthLib::BinaryStream& _stream); + void write(baseLib::BinaryStream& _s) const; + bool read(baseLib::BinaryStream& _stream); bool operator == (const Tags& _t) const; @@ -105,8 +105,8 @@ namespace pluginLib::patchDB void deserialize(juce::DynamicObject* _obj); bool operator == (const TypedTags& _tags) const; - void write(synthLib::BinaryStream& _s) const; - bool read(synthLib::BinaryStream& _stream); + void write(baseLib::BinaryStream& _s) const; + bool read(baseLib::BinaryStream& _stream); private: std::unordered_map<TagType, Tags> m_tags; diff --git a/source/jucePluginLib/processor.cpp b/source/jucePluginLib/processor.cpp @@ -2,9 +2,10 @@ #include "dummydevice.h" #include "types.h" +#include "baseLib/binarystream.h" + #include "synthLib/deviceException.h" #include "synthLib/os.h" -#include "synthLib/binarystream.h" #include "synthLib/midiBufferParser.h" #include "dsp56kEmu/fastmath.h" @@ -193,22 +194,22 @@ namespace pluginLib void Processor::saveCustomData(std::vector<uint8_t>& _targetBuffer) { - synthLib::BinaryStream s; + baseLib::BinaryStream s; saveChunkData(s); s.toVector(_targetBuffer, true); } - void Processor::saveChunkData(synthLib::BinaryStream& s) + void Processor::saveChunkData(baseLib::BinaryStream& s) { { std::vector<uint8_t> buffer; getPlugin().getState(buffer, synthLib::StateTypeGlobal); - synthLib::ChunkWriter cw(s, "MIDI", 1); + baseLib::ChunkWriter cw(s, "MIDI", 1); s.write(buffer); } { - synthLib::ChunkWriter cw(s, "GAIN", 1); + baseLib::ChunkWriter cw(s, "GAIN", 1); s.write<uint32_t>(1); // version s.write(m_inputGain); s.write(m_outputGain); @@ -216,13 +217,13 @@ namespace pluginLib if(m_dspClockPercent != 100) { - synthLib::ChunkWriter cw(s, "DSPC", 1); + baseLib::ChunkWriter cw(s, "DSPC", 1); s.write(m_dspClockPercent); } if(m_preferredDeviceSamplerate > 0) { - synthLib::ChunkWriter cw(s, "DSSR", 1); + baseLib::ChunkWriter cw(s, "DSSR", 1); s.write(m_preferredDeviceSamplerate); } } @@ -235,48 +236,48 @@ namespace pluginLib // In Vavra, the only data we had was the gain parameters if(_sourceBuffer.size() == sizeof(float) * 2 + sizeof(uint32_t)) { - synthLib::BinaryStream ss(_sourceBuffer); + baseLib::BinaryStream ss(_sourceBuffer); readGain(ss); return true; } - synthLib::BinaryStream s(_sourceBuffer); - synthLib::ChunkReader cr(s); + baseLib::BinaryStream s(_sourceBuffer); + baseLib::ChunkReader cr(s); loadChunkData(cr); return _sourceBuffer.empty() || (cr.tryRead() && cr.numRead() > 0); } - void Processor::loadChunkData(synthLib::ChunkReader& _cr) + void Processor::loadChunkData(baseLib::ChunkReader& _cr) { - _cr.add("MIDI", 1, [this](synthLib::BinaryStream& _binaryStream, uint32_t _version) + _cr.add("MIDI", 1, [this](baseLib::BinaryStream& _binaryStream, uint32_t _version) { std::vector<uint8_t> buffer; _binaryStream.read(buffer); getPlugin().setState(buffer); }); - _cr.add("GAIN", 1, [this](synthLib::BinaryStream& _binaryStream, uint32_t _version) + _cr.add("GAIN", 1, [this](baseLib::BinaryStream& _binaryStream, uint32_t _version) { readGain(_binaryStream); }); - _cr.add("DSPC", 1, [this](synthLib::BinaryStream& _binaryStream, uint32_t _version) + _cr.add("DSPC", 1, [this](baseLib::BinaryStream& _binaryStream, uint32_t _version) { auto p = _binaryStream.read<uint32_t>(); p = dsp56k::clamp<uint32_t>(p, 50, 200); setDspClockPercent(p); }); - _cr.add("DSSR", 1, [this](synthLib::BinaryStream& _binaryStream, uint32_t _version) + _cr.add("DSSR", 1, [this](baseLib::BinaryStream& _binaryStream, uint32_t _version) { const auto sr = _binaryStream.read<float>(); setPreferredDeviceSamplerate(sr); }); } - void Processor::readGain(synthLib::BinaryStream& _s) + void Processor::readGain(baseLib::BinaryStream& _s) { const auto version = _s.read<uint32_t>(); if (version != 1) diff --git a/source/jucePluginLib/processor.h b/source/jucePluginLib/processor.h @@ -7,10 +7,14 @@ #include "synthLib/plugin.h" -namespace synthLib +namespace baseLib { class BinaryStream; class ChunkReader; +} + +namespace synthLib +{ class Plugin; struct SMidiEvent; } @@ -57,11 +61,11 @@ namespace pluginLib virtual void updateLatencySamples(); virtual void saveCustomData(std::vector<uint8_t>& _targetBuffer); - virtual void saveChunkData(synthLib::BinaryStream& s); + virtual void saveChunkData(baseLib::BinaryStream& s); virtual bool loadCustomData(const std::vector<uint8_t>& _sourceBuffer); - virtual void loadChunkData(synthLib::ChunkReader& _cr); + virtual void loadChunkData(baseLib::ChunkReader& _cr); - void readGain(synthLib::BinaryStream& _s); + void readGain(baseLib::BinaryStream& _s); template<size_t N> void applyOutputGain(std::array<float*, N>& _buffers, const size_t _numSamples) { @@ -80,7 +84,7 @@ namespace pluginLib { if (buf) { - for (int i = 0; i < _numSamples; ++i) + for (size_t i = 0; i < _numSamples; ++i) buf[i] *= _gain; } } @@ -102,7 +106,7 @@ namespace pluginLib const Properties& getProperties() const { return m_properties; } - virtual void processBpm(float _bpm) {}; + virtual void processBpm(float _bpm) {} bool rebootDevice(); diff --git a/source/jucePluginLib/types.h b/source/jucePluginLib/types.h @@ -1,10 +1,10 @@ #pragma once -#include "synthLib/binarystream.h" +#include "baseLib/binarystream.h" namespace pluginLib { - using PluginStream = synthLib::BinaryStream; + using PluginStream = baseLib::BinaryStream; enum ParameterLinkType : uint32_t { diff --git a/source/mqTestConsole/mqTestConsole.cpp b/source/mqTestConsole/mqTestConsole.cpp @@ -2,14 +2,14 @@ #include <iostream> #include <memory> +#include "baseLib/configFile.h" + #include "synthLib/os.h" #include "synthLib/wavWriter.h" #include "synthLib/midiTypes.h" -#include "synthLib/configFile.h" #include "mqLib/microq.h" #include "mqLib/mqhardware.h" -#include "mqLib/rom.h" #include "dsp56kEmu/threadtools.h" @@ -78,7 +78,7 @@ int main(int _argc, char* _argv[]) try { - synthLib::ConfigFile cfg((synthLib::getModulePath() + "config.cfg").c_str()); + baseLib::ConfigFile cfg((synthLib::getModulePath() + "config.cfg").c_str()); for (const auto& v : cfg.getValues()) { if(v.first == "MidiIn") diff --git a/source/nord/n2x/n2xLib/n2xdsp.h b/source/nord/n2x/n2xLib/n2xdsp.h @@ -5,7 +5,8 @@ #include "dsp56kEmu/dsp.h" #include "dsp56kEmu/dspthread.h" -#include "synthLib/trigger.h" + +#include "baseLib/trigger.h" namespace mc68k { @@ -79,7 +80,7 @@ namespace n2x std::condition_variable m_haltDSPcv; std::mutex m_haltDSPmutex; - synthLib::Trigger<> m_triggerInterruptDone; + baseLib::Trigger<> m_triggerInterruptDone; uint32_t m_vbaInterruptDone = 0; }; } diff --git a/source/synthLib/CMakeLists.txt b/source/synthLib/CMakeLists.txt @@ -10,15 +10,11 @@ add_library(synthLib STATIC) set(SOURCES audiobuffer.cpp audiobuffer.h audioTypes.h - binarystream.cpp binarystream.h buildconfig.h buildconfig.h.in - configFile.cpp configFile.h device.cpp device.h deviceException.cpp deviceException.h deviceTypes.h dspMemoryPatch.cpp dspMemoryPatch.h - hybridcontainer.h - md5.cpp md5.h midiBufferParser.cpp midiBufferParser.h midiToSysex.cpp midiToSysex.h midiTypes.h @@ -28,7 +24,6 @@ set(SOURCES resamplerInOut.cpp resamplerInOut.h romLoader.cpp romLoader.h sysexToMidi.cpp sysexToMidi.h - trigger.cpp trigger.h wavReader.cpp wavReader.h wavTypes.h wavWriter.cpp wavWriter.h @@ -37,7 +32,7 @@ set(SOURCES target_sources(synthLib PRIVATE ${SOURCES}) source_group("source" FILES ${SOURCES}) -target_link_libraries(synthLib PUBLIC resample dsp56kEmu) +target_link_libraries(synthLib PUBLIC resample dsp56kEmu baseLib) if(NOT MSVC) target_link_libraries(synthLib PUBLIC dl) diff --git a/source/synthLib/binarystream.cpp b/source/synthLib/binarystream.cpp @@ -1,24 +0,0 @@ -#include "binarystream.h" - -namespace synthLib -{ - BinaryStream BinaryStream::readChunk() - { - Chunk chunk; - chunk.read(*this); - return std::move(chunk.data); - } - - BinaryStream BinaryStream::tryReadChunkInternal(const char* _4Cc, const uint32_t _version) - { - Chunk chunk; - chunk.read(*this); - if(chunk.version != _version) - return {}; - if(0 != strcmp(chunk.fourCC, _4Cc)) - return {}; - return std::move(chunk.data); - } - - template BinaryStream BinaryStream::tryReadChunk(char const(& _4Cc)[5], uint32_t _version); -} diff --git a/source/synthLib/binarystream.h b/source/synthLib/binarystream.h @@ -1,470 +0,0 @@ -#pragma once - -#include <cassert> -#include <cstdint> -#include <functional> -#include <sstream> -#include <vector> -#include <cstring> - -namespace synthLib -{ - class StreamBuffer - { - public: - StreamBuffer() = default; - explicit StreamBuffer(std::vector<uint8_t>&& _buffer) : m_vector(std::move(_buffer)) - { - } - explicit StreamBuffer(const size_t _capacity) - { - m_vector.reserve(_capacity); - } - StreamBuffer(uint8_t* _buffer, const size_t _size) : m_buffer(_buffer), m_size(_size), m_fixedSize(true) - { - } - StreamBuffer(StreamBuffer& _parent, const size_t _childSize) : m_buffer(&_parent.buffer()[_parent.tellg()]), m_size(_childSize), m_fixedSize(true) - { - // force eof if range is not valid - if(_parent.tellg() + _childSize > _parent.size()) - { - assert(false && "invalid range"); - m_readPos = _childSize; - } - - // seek parent forward - _parent.seekg(_parent.tellg() + _childSize); - } - StreamBuffer(StreamBuffer&& _source) noexcept - : m_buffer(_source.m_buffer) - , m_size(_source.m_size) - , m_fixedSize(_source.m_fixedSize) - , m_readPos(_source.m_readPos) - , m_writePos(_source.m_writePos) - , m_vector(std::move(_source.m_vector)) - , m_fail(_source.m_fail) - { - _source.destroy(); - } - - StreamBuffer& operator = (StreamBuffer&& _source) noexcept - { - m_buffer = _source.m_buffer; - m_size = _source.m_size; - m_fixedSize = _source.m_fixedSize; - m_readPos = _source.m_readPos; - m_writePos = _source.m_writePos; - m_vector = std::move(_source.m_vector); - - _source.destroy(); - - return *this; - } - - void seekg(const size_t _pos) { m_readPos = _pos; } - size_t tellg() const { return m_readPos; } - void seekp(const size_t _pos) { m_writePos = _pos; } - size_t tellp() const { return m_writePos; } - bool eof() const { return tellg() >= size(); } - bool fail() const { return m_fail; } - - bool read(uint8_t* _dst, size_t _size) - { - const auto remaining = size() - tellg(); - if(remaining < _size) - { - m_fail = true; - return false; - } - ::memcpy(_dst, &buffer()[m_readPos], _size); - m_readPos += _size; - return true; - } - bool write(const uint8_t* _src, size_t _size) - { - const auto remaining = size() - tellp(); - if(remaining < _size) - { - if(m_fixedSize) - { - m_fail = true; - return false; - } - m_vector.resize(tellp() + _size); - } - ::memcpy(&buffer()[m_writePos], _src, _size); - m_writePos += _size; - return true; - } - - explicit operator bool () const - { - return !eof(); - } - - private: - size_t size() const { return m_fixedSize ? m_size : m_vector.size(); } - - uint8_t* buffer() - { - if(m_fixedSize) - return m_buffer; - return m_vector.data(); - } - - void destroy() - { - m_buffer = nullptr; - m_size = 0; - m_fixedSize = false; - m_readPos = 0; - m_writePos = 0; - m_vector.clear(); - m_fail = false; - } - - uint8_t* m_buffer = nullptr; - size_t m_size = 0; - bool m_fixedSize = false; - size_t m_readPos = 0; - size_t m_writePos = 0; - std::vector<uint8_t> m_vector; - bool m_fail = false; - }; - - using StreamSizeType = uint32_t; - - class BinaryStream final : StreamBuffer - { - public: - using Base = StreamBuffer; - using SizeType = StreamSizeType; - - BinaryStream() = default; - - using StreamBuffer::operator bool; - - explicit BinaryStream(BinaryStream& _parent, SizeType _length) : StreamBuffer(_parent, _length) - { - } - - template<typename T> explicit BinaryStream(const std::vector<T>& _data) - { - Base::write(reinterpret_cast<const uint8_t*>(_data.data()), _data.size() * sizeof(T)); - seekg(0); - } - - // ___________________________________ - // tools - // - - void toVector(std::vector<uint8_t>& _buffer, const bool _append = false) - { - const auto size = tellp(); - if(size <= 0) - { - if(!_append) - _buffer.clear(); - return; - } - - seekg(0); - - if(_append) - { - const auto currentSize = _buffer.size(); - _buffer.resize(currentSize + size); - Base::read(&_buffer[currentSize], size); - } - else - { - _buffer.resize(size); - Base::read(_buffer.data(), size); - } - } - - bool checkString(const std::string& _str) - { - const auto pos = tellg(); - - const auto size = read<SizeType>(); - if (size != _str.size()) - { - seekg(pos); - return false; - } - std::string s; - s.resize(size); - Base::read(reinterpret_cast<uint8_t*>(s.data()), size); - const auto result = _str == s; - seekg(pos); - return result; - } - - uint32_t getWritePos() const { return static_cast<uint32_t>(tellp()); } - uint32_t getReadPos() const { return static_cast<uint32_t>(tellg()); } - bool endOfStream() const { return eof(); } - - void setWritePos(const uint32_t _pos) { seekp(_pos); } - void setReadPos(const uint32_t _pos) { seekg(_pos); } - - // ___________________________________ - // write - // - - template<typename T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> void write(const T& _value) - { - Base::write(reinterpret_cast<const uint8_t*>(&_value), sizeof(_value)); - } - - template<typename T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> void write(const std::vector<T>& _vector) - { - const auto size = static_cast<SizeType>(_vector.size()); - write(size); - if(size) - Base::write(reinterpret_cast<const uint8_t*>(_vector.data()), sizeof(T) * size); - } - - void write(const std::string& _string) - { - const auto s = static_cast<SizeType>(_string.size()); - write(s); - Base::write(reinterpret_cast<const uint8_t*>(_string.c_str()), s); - } - - void write(const char* const _value) - { - write(std::string(_value)); - } - - template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> - void write4CC(char const(&_str)[N]) - { - write(_str[0]); - write(_str[1]); - write(_str[2]); - write(_str[3]); - } - - - // ___________________________________ - // read - // - - template<typename T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> T read() - { - T v{}; - Base::read(reinterpret_cast<uint8_t*>(&v), sizeof(v)); - checkFail(); - return v; - } - - template<typename T, typename = std::enable_if_t<std::is_trivially_copyable_v<T>>> void read(std::vector<T>& _vector) - { - const auto size = read<SizeType>(); - checkFail(); - if (!size) - { - _vector.clear(); - return; - } - _vector.resize(size); - Base::read(reinterpret_cast<uint8_t*>(_vector.data()), sizeof(T) * size); - checkFail(); - } - - std::string readString() - { - const auto size = read<SizeType>(); - std::string s; - s.resize(size); - Base::read(reinterpret_cast<uint8_t*>(s.data()), size); - checkFail(); - return s; - } - - template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> - void read4CC(char const(&_str)[N]) - { - char res[5]; - read4CC(res); - - return strcmp(res, _str) == 0; - } - - template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> - void read4CC(char (&_str)[N]) - { - _str[0] = 'E'; - _str[1] = 'R'; - _str[2] = 'R'; - _str[3] = 'R'; - _str[4] = 0; - - _str[0] = read<char>(); - _str[1] = read<char>(); - _str[2] = read<char>(); - _str[3] = read<char>(); - } - - BinaryStream readChunk(); - template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> - BinaryStream tryReadChunk(char const(&_4Cc)[N], const uint32_t _version = 1) - { - return tryReadChunkInternal(_4Cc, _version); - } - - private: - BinaryStream tryReadChunkInternal(const char* _4Cc, uint32_t _version = 1); - - - // ___________________________________ - // helpers - // - - private: - void checkFail() const - { - if(fail()) - throw std::range_error("end-of-stream"); - } - }; - - struct Chunk - { - using SizeType = BinaryStream::SizeType; - - char fourCC[5]; - uint32_t version; - SizeType length; - BinaryStream data; - - bool read(BinaryStream& _parentStream) - { - _parentStream.read4CC(fourCC); - version = _parentStream.read<uint32_t>(); - length = _parentStream.read<SizeType>(); - data = BinaryStream(_parentStream, length); - return !data.endOfStream(); - } - }; - - class ChunkWriter - { - public: - using SizeType = BinaryStream::SizeType; - - template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> - ChunkWriter(BinaryStream& _stream, char const(&_4Cc)[N], const uint32_t _version = 1) : m_stream(_stream) - { - m_stream.write4CC(_4Cc); - m_stream.write(_version); - m_lengthWritePos = m_stream.getWritePos(); - m_stream.write<SizeType>(0); - } - - ChunkWriter() = delete; - ChunkWriter(ChunkWriter&&) = delete; - ChunkWriter(const ChunkWriter&) = delete; - ChunkWriter& operator = (ChunkWriter&&) = delete; - ChunkWriter& operator = (const ChunkWriter&) = delete; - - ~ChunkWriter() - { - const auto currentWritePos = m_stream.getWritePos(); - const SizeType chunkDataLength = currentWritePos - m_lengthWritePos - sizeof(SizeType); - m_stream.setWritePos(m_lengthWritePos); - m_stream.write(chunkDataLength); - m_stream.setWritePos(currentWritePos); - } - - private: - BinaryStream& m_stream; - SizeType m_lengthWritePos = 0; - }; - - class ChunkReader - { - public: - using SizeType = ChunkWriter::SizeType; - using ChunkCallback = std::function<void(BinaryStream&, uint32_t)>; // data, version - - struct ChunkCallbackData - { - char fourCC[5]; - uint32_t expectedVersion; - ChunkCallback callback; - }; - - explicit ChunkReader(BinaryStream& _stream) : m_stream(_stream) - { - } - - template<size_t N, std::enable_if_t<N == 5, void*> = nullptr> - void add(char const(&_4Cc)[N], const uint32_t _version, const ChunkCallback& _callback) - { - ChunkCallbackData c; - strcpy(c.fourCC, _4Cc); - c.expectedVersion = _version; - c.callback = _callback; - supportedChunks.emplace_back(std::move(c)); - } - - void read(const uint32_t _count = 0) - { - uint32_t count = 0; - - while(!m_stream.endOfStream() && (!_count || ++count <= _count)) - { - Chunk chunk; - chunk.read(m_stream); - - ++m_numChunks; - - for (const auto& chunkData : supportedChunks) - { - if(0 != strcmp(chunkData.fourCC, chunk.fourCC)) - continue; - - if(chunk.version > chunkData.expectedVersion) - break; - - ++m_numRead; - chunkData.callback(chunk.data, chunk.version); - break; - } - } - } - - bool tryRead(const uint32_t _count = 0) - { - const auto pos = m_stream.getReadPos(); - try - { - read(_count); - return true; - } - catch(std::range_error&) - { - m_stream.setReadPos(pos); - return false; - } - } - - uint32_t numRead() const - { - return m_numRead; - } - - uint32_t numChunks() const - { - return m_numChunks; - } - - private: - BinaryStream& m_stream; - std::vector<ChunkCallbackData> supportedChunks; - uint32_t m_numRead = 0; - uint32_t m_numChunks = 0; - }; -} diff --git a/source/synthLib/configFile.cpp b/source/synthLib/configFile.cpp @@ -1,61 +0,0 @@ -#include "configFile.h" - -#include <fstream> - -#include "dsp56kEmu/logging.h" - -namespace synthLib -{ - static bool needsTrim(char _c) - { - switch (_c) - { - case ' ': - case '\r': - case '\n': - case '\t': - return true; - default: - return false; - } - } - - static std::string trim(std::string _s) - { - while (!_s.empty() && needsTrim(_s.front())) - _s = _s.substr(1); - while (!_s.empty() && needsTrim(_s.back())) - _s = _s.substr(0, _s.size() - 1); - return _s; - } - - ConfigFile::ConfigFile(const char* _filename) - { - std::ifstream file(_filename, std::ios::in); - - if (!file.is_open()) - throw std::runtime_error("Failed to open config file " + std::string(_filename)); - - std::string line; - - while(std::getline(file, line)) - { - if(line.empty()) - continue; - - // // comment? - if (line.front() == '#' || line.front() == ';') - continue; - - const auto posEq = line.find('='); - - if (posEq == std::string::npos) - continue; - - const auto key = trim(line.substr(0, posEq)); - const auto val = trim(line.substr(posEq + 1)); - - m_values.emplace_back(key, val); - } - } -} -\ No newline at end of file diff --git a/source/synthLib/configFile.h b/source/synthLib/configFile.h @@ -1,20 +0,0 @@ -#pragma once - -#include <string> -#include <vector> - -namespace synthLib -{ - class ConfigFile - { - public: - explicit ConfigFile(const char* _filename); - - const std::vector<std::pair<std::string, std::string>>& getValues() const - { - return m_values; - } - private: - std::vector<std::pair<std::string, std::string>> m_values; - }; -} diff --git a/source/synthLib/dspMemoryPatch.cpp b/source/synthLib/dspMemoryPatch.cpp @@ -65,7 +65,7 @@ namespace synthLib return true; } - bool DspMemoryPatches::apply(dsp56k::DSP& _dsp, const MD5& _md5) const + bool DspMemoryPatches::apply(dsp56k::DSP& _dsp, const baseLib::MD5& _md5) const { for (const auto& e : allowedTargets) { diff --git a/source/synthLib/dspMemoryPatch.h b/source/synthLib/dspMemoryPatch.h @@ -1,6 +1,7 @@ #pragma once -#include "md5.h" +#include "baseLib/md5.h" + #include "dsp56kEmu/types.h" namespace dsp56k @@ -50,10 +51,10 @@ namespace synthLib struct DspMemoryPatches { - std::initializer_list<MD5> allowedTargets; + std::initializer_list<baseLib::MD5> allowedTargets; std::initializer_list<DspMemoryPatch> patches; - bool apply(dsp56k::DSP& _dsp, const MD5& _md5) const; + bool apply(dsp56k::DSP& _dsp, const baseLib::MD5& _md5) const; private: static bool apply(dsp56k::DSP& _dsp, const std::initializer_list<DspMemoryPatch>& _patches); diff --git a/source/synthLib/hybridcontainer.h b/source/synthLib/hybridcontainer.h @@ -1,29 +0,0 @@ -#pragma once -/* -#include <vector> -#include <memory_resource> -#include <array> - -namespace synthLib -{ - template<typename T, size_t S> class BufferResource - { - public: - auto& getPool() { return m_pool; } - protected: - std::array<T, S> m_buffer; - std::pmr::monotonic_buffer_resource m_pool{ std::data(m_buffer), std::size(m_buffer) }; - }; - - template<typename T, size_t S> - class HybridVector final : public BufferResource<T,S>, public std::pmr::vector<T> - { - public: - using Base = std::pmr::vector<T>; - - HybridVector() : BufferResource<T, S>(), Base(&static_cast<BufferResource<T, S>&>(*this).getPool()) - { - } - }; -} -*/ -\ No newline at end of file diff --git a/source/synthLib/md5.cpp b/source/synthLib/md5.cpp @@ -1,145 +0,0 @@ -#include "md5.h" - -#include "dsp56kEmu/logging.h" - -#include <cstring> // memcpy - -namespace synthLib -{ - // leftrotate function definition - uint32_t leftrotate(const uint32_t x, const uint32_t c) - { - return (((x) << (c)) | ((x) >> (32 - (c)))); - } - - // These vars will contain the hash: h0, h1, h2, h3 - void md5(uint32_t& _h0, uint32_t& _h1, uint32_t& _h2, uint32_t& _h3, const uint8_t *_initialMsg, const uint32_t _initialLen) - { - // Note: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating - - // r specifies the per-round shift amounts - - constexpr uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, - 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, - 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, - 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; - - // Use binary integer part of the sines of integers (in radians) as constants// Initialize variables: - constexpr uint32_t k[] = { - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, - 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }; - - _h0 = 0x67452301; - _h1 = 0xefcdab89; - _h2 = 0x98badcfe; - _h3 = 0x10325476; - - // Pre-processing: adding a single 1 bit - //append "1" bit to message - /* Notice: the input bytes are considered as bits strings, - where the first bit is the most significant bit of the byte.[37] */ - - // Pre-processing: padding with zeros - //append "0" bit until message length in bit ≡ 448 (mod 512) - //append length mod (2 pow 64) to message - - const uint32_t newLen = ((((_initialLen + 8) / 64) + 1) * 64) - 8; - - std::vector<uint8_t> buffer; - buffer.resize(newLen + 64, 0); - auto* msg = buffer.data(); - memcpy(msg, _initialMsg, _initialLen); - msg[_initialLen] = 128; // write the "1" bit - - const uint32_t bitsLen = 8 * _initialLen; // note, we append the len - memcpy(msg + newLen, &bitsLen, 4); // in bits at the end of the buffer - - // Process the message in successive 512-bit chunks: - //for each 512-bit chunk of message: - for (uint32_t offset = 0; offset < newLen; offset += (512 / 8)) - { - // break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15 - const auto* w = reinterpret_cast<uint32_t*>(msg + offset); - - // Initialize hash value for this chunk: - uint32_t a = _h0; - uint32_t b = _h1; - uint32_t c = _h2; - uint32_t d = _h3; - - // Main loop: - for (uint32_t i = 0; i < 64; i++) - { - uint32_t f, g; - - if (i < 16) { - f = (b & c) | ((~b) & d); - g = i; - } - else if (i < 32) { - f = (d & b) | ((~d) & c); - g = (5 * i + 1) % 16; - } - else if (i < 48) { - f = b ^ c ^ d; - g = (3 * i + 5) % 16; - } - else { - f = c ^ (b | (~d)); - g = (7 * i) % 16; - } - - const uint32_t temp = d; - d = c; - c = b; -// printf("rotateLeft(%x + %x + %x + %x, %d)\n", a, f, k[i], w[g], r[i]); - b = b + leftrotate((a + f + k[i] + w[g]), r[i]); - a = temp; - } - - // Add this chunk's hash to result so far: - - _h0 += a; - _h1 += b; - _h2 += c; - _h3 += d; - - } - - // cleanup - // free(msg); - } - - MD5::MD5(const std::vector<uint8_t>& _data) - { - md5(m_h[0], m_h[1], m_h[2], m_h[3], _data.data(), static_cast<uint32_t>(_data.size())); - } - - std::string MD5::toString() const - { - std::stringstream ss; - - for (const auto& e : m_h) - { - ss << HEXN((e & 0xff), 2); - ss << HEXN(((e>>8u) & 0xff), 2); - ss << HEXN(((e>>16u) & 0xff), 2); - ss << HEXN(((e>>24u) & 0xff), 2); - } - return ss.str(); - } -} diff --git a/source/synthLib/md5.h b/source/synthLib/md5.h @@ -1,88 +0,0 @@ -#pragma once - -#include <array> -#include <cassert> -#include <cstdint> -#include <string> -#include <vector> - -namespace synthLib -{ - class MD5 - { - public: - static constexpr uint32_t parse1(const char _b) - { - if (_b >= '0' && _b <= '9') - return _b - '0'; - if (_b >= 'A' && _b <= 'F') - return _b - 'A' + 10; - if (_b >= 'a' && _b <= 'f') - return _b - 'a' + 10; - assert(false); - return 0; - } - static constexpr uint32_t parse2(const char _b0, const char _b1) - { - return parse1(_b1) << 4 | parse1(_b0); - } - static constexpr uint32_t parse4(const char _b0, const char _b1, const char _b2, const char _b3) - { - return parse2(_b3, _b2) << 8 | parse2(_b1, _b0); - } - static constexpr uint32_t parse8(const char _b0, const char _b1, const char _b2, const char _b3, const char _b4, const char _b5, const char _b6, const char _b7) - { - return parse4(_b4, _b5, _b6, _b7) << 16 | parse4(_b0, _b1, _b2, _b3); - } - - template<size_t N, std::enable_if_t<N == 33, void*> = nullptr> constexpr MD5(char const(&_digest)[N]) - : m_h - { - parse8(_digest[ 0], _digest[ 1], _digest[ 2], _digest[ 3], _digest[ 4], _digest[ 5], _digest[ 6], _digest[ 7]), - parse8(_digest[ 8], _digest[ 9], _digest[10], _digest[11], _digest[12], _digest[13], _digest[14], _digest[15]), - parse8(_digest[16], _digest[17], _digest[18], _digest[19], _digest[20], _digest[21], _digest[22], _digest[23]), - parse8(_digest[24], _digest[25], _digest[26], _digest[27], _digest[28], _digest[29], _digest[30], _digest[31]) - } - { - } - - explicit MD5(const std::vector<uint8_t>& _data); - - MD5() : m_h({0,0,0,0}) {} - - MD5(const MD5& _src) = default; - MD5(MD5&& _src) = default; - - ~MD5() = default; - - MD5& operator = (const MD5&) = default; - MD5& operator = (MD5&&) = default; - - std::string toString() const; - - constexpr bool operator == (const MD5& _md5) const - { - return m_h[0] == _md5.m_h[0] && m_h[1] == _md5.m_h[1] && m_h[2] == _md5.m_h[2] && m_h[3] == _md5.m_h[3]; - } - - constexpr bool operator != (const MD5& _md5) const - { - return !(*this == _md5); - } - - constexpr bool operator < (const MD5& _md5) const - { - if(m_h[0] < _md5.m_h[0]) return true; - if(m_h[0] > _md5.m_h[0]) return false; - if(m_h[1] < _md5.m_h[1]) return true; - if(m_h[1] > _md5.m_h[1]) return false; - if(m_h[2] < _md5.m_h[2]) return true; - if(m_h[2] > _md5.m_h[2]) return false; - if(m_h[3] < _md5.m_h[3]) return true; - /*if(m_h[3] > _md5.m_h[3])*/ return false; - } - - private: - std::array<uint32_t, 4> m_h; - }; -} diff --git a/source/synthLib/trigger.h b/source/synthLib/trigger.h @@ -1,40 +0,0 @@ -#pragma once - -#include <mutex> -#include <condition_variable> -#include <cstdint> - -namespace synthLib -{ - template<typename TCounter = uint32_t> - class Trigger - { - public: - void wait() - { - std::unique_lock uLock(m_haltMutex); - - m_haltcv.wait(uLock, [&] - { - return m_notifyCounter > m_waitCounter; - }); - - ++m_waitCounter; - } - - void notify() - { - { - std::lock_guard uLockHalt(m_haltMutex); - ++m_notifyCounter; - } - m_haltcv.notify_one(); - } - - private: - std::condition_variable m_haltcv; - std::mutex m_haltMutex; - TCounter m_waitCounter = 0; - TCounter m_notifyCounter = 0; - }; -} diff --git a/source/virusJucePlugin/VirusProcessor.cpp b/source/virusJucePlugin/VirusProcessor.cpp @@ -4,8 +4,9 @@ #include "virusLib/romloader.h" +#include "baseLib/binarystream.h" + #include "synthLib/deviceException.h" -#include "synthLib/binarystream.h" #include "synthLib/os.h" //============================================================================== @@ -97,12 +98,12 @@ pluginLib::Controller* VirusProcessor::createController() return new Virus::Controller(*this, m_defaultModel); } -void VirusProcessor::saveChunkData(synthLib::BinaryStream& s) +void VirusProcessor::saveChunkData(baseLib::BinaryStream& s) { auto* rom = getSelectedRom(); if(rom) { - synthLib::ChunkWriter cw(s, "ROM ", 2); + baseLib::ChunkWriter cw(s, "ROM ", 2); const auto romName = synthLib::getFilenameWithoutPath(rom->getFilename()); s.write<uint8_t>(static_cast<uint8_t>(rom->getModel())); s.write(romName); @@ -110,9 +111,9 @@ void VirusProcessor::saveChunkData(synthLib::BinaryStream& s) Processor::saveChunkData(s); } -void VirusProcessor::loadChunkData(synthLib::ChunkReader& _cr) +void VirusProcessor::loadChunkData(baseLib::ChunkReader& _cr) { - _cr.add("ROM ", 2, [this](synthLib::BinaryStream& _binaryStream, unsigned _version) + _cr.add("ROM ", 2, [this](baseLib::BinaryStream& _binaryStream, unsigned _version) { auto model = virusLib::DeviceModel::ABC; diff --git a/source/virusJucePlugin/VirusProcessor.h b/source/virusJucePlugin/VirusProcessor.h @@ -64,8 +64,8 @@ private: pluginLib::Controller* createController() override; - void saveChunkData(synthLib::BinaryStream& s) override; - void loadChunkData(synthLib::ChunkReader& _cr) override; + void saveChunkData(baseLib::BinaryStream& s) override; + void loadChunkData(baseLib::ChunkReader& _cr) override; //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VirusProcessor) diff --git a/source/virusLib/dspMemoryPatches.cpp b/source/virusLib/dspMemoryPatches.cpp @@ -8,7 +8,7 @@ namespace virusLib { }; - void DspMemoryPatches::apply(const DspSingle* _dsp, const synthLib::MD5& _romChecksum) + void DspMemoryPatches::apply(const DspSingle* _dsp, const baseLib::MD5& _romChecksum) { if(!_dsp) return; diff --git a/source/virusLib/dspMemoryPatches.h b/source/virusLib/dspMemoryPatches.h @@ -9,6 +9,6 @@ namespace virusLib class DspMemoryPatches { public: - static void apply(const DspSingle* _dsp, const synthLib::MD5& _romChecksum); + static void apply(const DspSingle* _dsp, const baseLib::MD5& _romChecksum); }; } diff --git a/source/virusLib/romfile.h b/source/virusLib/romfile.h @@ -6,7 +6,7 @@ #include "dsp56kEmu/types.h" -#include "synthLib/md5.h" +#include "baseLib/md5.h" #include "deviceModel.h" @@ -137,7 +137,7 @@ private: std::string m_romFileName; std::vector<uint8_t> m_romFileData; - synthLib::MD5 m_romDataHash; + baseLib::MD5 m_romDataHash; }; }