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 6ab0a6f2dd16fd4faa79bfcd391922224ee58646
parent d267489f9750b47a636345b207843a8041ada4ac
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Sat, 12 Oct 2024 02:47:01 +0200

create helper functions to merge a single + waves + table into a single sysex and vice versa

Diffstat:
Msource/xtLib/xtState.cpp | 94++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msource/xtLib/xtState.h | 21+++++++++++++++------
2 files changed, 108 insertions(+), 7 deletions(-)

diff --git a/source/xtLib/xtState.cpp b/source/xtLib/xtState.cpp @@ -16,7 +16,7 @@ namespace xt { static_assert(std::size(State::Dumps) == static_cast<uint32_t>(State::DumpType::Count), "data definition missing"); - State::State(Xt& _xt, WavePreview& _preview) : m_xt(_xt), m_wavePreview(_preview) + State::State(Xt& _xt, WavePreview& _wavePreview) : m_xt(_xt), m_wavePreview(_wavePreview) { } @@ -825,6 +825,98 @@ namespace xt return sysex; } + void State::splitCombinedPatch(std::vector<SysEx>& _dumps, const SysEx& _combinedSingle) + { + if(getCommand(_combinedSingle) != SysexCommand::SingleDump) + return; + + constexpr auto singleSize = std::tuple_size_v<Single>; + constexpr auto tableSize = std::tuple_size_v<Table>; + constexpr auto waveSize = std::tuple_size_v<Wave>; + + if(_combinedSingle.size() == singleSize) + { + _dumps.push_back(_combinedSingle); + return; + } + + if(_combinedSingle.size() < singleSize + tableSize - 2) + return; + + auto& single = _dumps.emplace_back(); + size_t offBegin = 0; + size_t offEnd = offBegin + singleSize - 1; + single.assign(_combinedSingle.begin() + static_cast<ptrdiff_t>(offBegin), _combinedSingle.begin() + static_cast<ptrdiff_t>(offEnd)); + single.push_back(0xf7); + + auto& table = _dumps.emplace_back(); + + offBegin = offEnd; + offEnd += tableSize - 2; + table.push_back(0xf0); + table.insert(table.end(), _combinedSingle.begin() + static_cast<ptrdiff_t>(offBegin), _combinedSingle.begin() + static_cast<ptrdiff_t>(offEnd)); + table.push_back(0xf7); + + while(_combinedSingle.size() - offEnd >= waveSize - 2) + { + offBegin = offEnd; + offEnd += waveSize - 2; + + auto& wave = _dumps.emplace_back(); + wave.push_back(0xf0); + wave.insert(wave.end(), _combinedSingle.begin() + static_cast<ptrdiff_t>(offBegin), _combinedSingle.begin() + static_cast<ptrdiff_t>(offEnd)); + wave.push_back(0xf7); + } + } + + SysEx State::createCombinedPatch(const std::vector<SysEx>& _dumps) + { + uint32_t singleCount = 0; + uint32_t tableCount = 0; + + std::vector<SysEx> waves; + + SysEx single; + SysEx table; + + for (auto& dump : _dumps) + { + switch(getCommand(dump)) + { + case SysexCommand::SingleDump: + ++singleCount; + single = dump; + break; + case SysexCommand::WaveCtlDump: + ++tableCount; + table = dump; + break; + case SysexCommand::WaveDump: + waves.push_back(dump); + break; + default:; + } + } + + if(!tableCount && waves.empty()) + return single; + + if(tableCount > 1) + return {}; + + // a combined single is a single dump + a table dump + an arbitrary number of wave dumps in one sysex, i.e. f0/f7 are stripped from the individual dumps + single.pop_back(); + + single.insert(single.end(), table.begin()+1, table.end()); + + for (const auto& wave : waves) + single.insert(single.end(), wave.begin()+1, wave.end()-1); + + single.push_back(0xf7); + + return single; + } + void State::onPlayModeChanged() { // if the play mode is changed, force a re-request of the edit buffer for the first single again, because on the device, that edit buffer is shared between multi & single diff --git a/source/xtLib/xtState.h b/source/xtLib/xtState.h @@ -41,6 +41,8 @@ namespace xt Multi, Global, Mode, + Wave, + Table, Count }; @@ -60,16 +62,20 @@ namespace xt static constexpr Dump Dumps[] = { - {DumpType::Single, SysexCommand::SingleRequest, SysexCommand::SingleDump, SysexCommand::SingleParameterChange, IdxSingleParamFirst, IdxSingleParamIndexH, IdxSingleParamIndexL, IdxSingleParamValue, 265}, - {DumpType::Multi , SysexCommand::MultiRequest , SysexCommand::MultiDump , SysexCommand::MultiParameterChange , IdxMultiParamFirst , IdxMultiParamIndexH , IdxMultiParamIndexL , IdxMultiParamValue , 265}, - {DumpType::Global, SysexCommand::GlobalRequest, SysexCommand::GlobalDump, SysexCommand::GlobalParameterChange, IdxGlobalParamFirst, IdxGlobalParamIndexH, IdxGlobalParamIndexL, IdxGlobalParamValue, 39}, - {DumpType::Mode , SysexCommand::ModeRequest , SysexCommand::ModeDump , SysexCommand::ModeParameterChange , IdxModeParamFirst , IdxModeParamIndexH , IdxModeParamIndexL , IdxModeParamValue , 7}, + {DumpType::Single, SysexCommand::SingleRequest , SysexCommand::SingleDump , SysexCommand::SingleParameterChange , IdxSingleParamFirst, IdxSingleParamIndexH, IdxSingleParamIndexL, IdxSingleParamValue, 265}, + {DumpType::Multi , SysexCommand::MultiRequest , SysexCommand::MultiDump , SysexCommand::MultiParameterChange , IdxMultiParamFirst , IdxMultiParamIndexH , IdxMultiParamIndexL , IdxMultiParamValue , 265}, + {DumpType::Global, SysexCommand::GlobalRequest , SysexCommand::GlobalDump , SysexCommand::GlobalParameterChange , IdxGlobalParamFirst, IdxGlobalParamIndexH, IdxGlobalParamIndexL, IdxGlobalParamValue, 39}, + {DumpType::Mode , SysexCommand::ModeRequest , SysexCommand::ModeDump , SysexCommand::ModeParameterChange , IdxModeParamFirst , IdxModeParamIndexH , IdxModeParamIndexL , IdxModeParamValue , 7}, + {DumpType::Wave , SysexCommand::WaveRequest , SysexCommand::WaveDump , SysexCommand::WaveParameterChange , wLib::IdxBuffer , IdxWaveIndexH , IdxWaveIndexL , wLib::IdxBuffer , 137}, + {DumpType::Table , SysexCommand::WaveCtlRequest, SysexCommand::WaveCtlDump, SysexCommand::WaveCtlParameterChange, wLib::IdxBuffer , IdxWaveIndexH , IdxWaveIndexL , wLib::IdxBuffer , 265}, }; using Single = std::array<uint8_t, Dumps[static_cast<uint32_t>(DumpType::Single)].dumpSize>; - using Multi = std::array<uint8_t, Dumps[static_cast<uint32_t>(DumpType::Multi)].dumpSize>; + using Multi = std::array<uint8_t , Dumps[static_cast<uint32_t>(DumpType::Multi) ].dumpSize>; using Global = std::array<uint8_t, Dumps[static_cast<uint32_t>(DumpType::Global)].dumpSize>; - using Mode = std::array<uint8_t, Dumps[static_cast<uint32_t>(DumpType::Mode)].dumpSize>; + using Mode = std::array<uint8_t , Dumps[static_cast<uint32_t>(DumpType::Mode) ].dumpSize>; + using Wave = std::array<uint8_t , Dumps[static_cast<uint32_t>(DumpType::Wave) ].dumpSize>; + using Table = std::array<uint8_t , Dumps[static_cast<uint32_t>(DumpType::Table) ].dumpSize>; State(Xt& _xt, WavePreview& _wavePreview); @@ -91,6 +97,9 @@ namespace xt static void parseTableData(TableData& _table, const SysEx& _sysex); static SysEx createTableData(const TableData& _table, uint32_t _tableIndex, bool _preview); + static SysEx createCombinedPatch(const std::vector<SysEx>& _dumps); + static void splitCombinedPatch(std::vector<SysEx>& _dumps, const SysEx& _combinedSingle); + private: template<size_t Size> static bool append(SysEx& _dst, const std::array<uint8_t, Size>& _src, uint32_t _checksumStartIndex)