commit 754aa7fda42a6e99cdf7f447996ebb2bf045f79a
parent 13c8960f3b786cd83c6f8a249b2379e390739ade
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Thu, 30 Dec 2021 22:48:03 +0100
Merge branch 'dsp56300' into dsp56300_ui
Diffstat:
11 files changed, 228 insertions(+), 134 deletions(-)
diff --git a/source/jucePlugin/PluginEditor.cpp b/source/jucePlugin/PluginEditor.cpp
@@ -51,19 +51,20 @@ AudioPluginAudioProcessorEditor::AudioPluginAudioProcessorEditor(AudioPluginAudi
loadFile();
};
- for (auto pt = 0; pt < 16; pt++)
+ for (uint8_t pt = 0; pt < 16; pt++)
{
m_partSelectors[pt].onClick = [this, pt]() {
juce::PopupMenu selector;
- for(auto b=0; b<processorRef.getController().getBankCount(); ++b)
+ for(uint8_t b=0; b<processorRef.getController().getBankCount(); ++b)
{
- auto bank = processorRef.getController().getSinglePresetNames(b);
+ const auto bank = virusLib::fromArrayIndex(b);
+ auto presetNames = processorRef.getController().getSinglePresetNames(bank);
juce::PopupMenu p;
- for (auto i = 0; i < 128; i++)
+ for (uint8_t i = 0; i < 128; i++)
{
- p.addItem(bank[i], [this, b, i, pt] { processorRef.getController().setCurrentPartPreset(pt, b, i); });
+ p.addItem(presetNames[i], [this, bank, i, pt] { processorRef.getController().setCurrentPartPreset(pt, bank, i); });
}
std::stringstream bankName;
bankName << "Bank " << static_cast<char>('A' + b);
@@ -280,63 +281,70 @@ void AudioPluginAudioProcessorEditor::loadFile() {
m_previousPath.isEmpty() ? juce::File::getSpecialLocation(juce::File::currentApplicationFile).getParentDirectory() : m_previousPath,
"*.syx,*.mid,*.midi",
true);
- const bool result = chooser.browseForFileToOpen();
- if (result)
+
+ if (!chooser.browseForFileToOpen())
+ return;
+ bool sentData = false;
+ const auto result = chooser.getResult();
+ m_previousPath = result.getParentDirectory().getFullPathName();
+ const auto ext = result.getFileExtension().toLowerCase();
+ if (ext == ".syx")
{
- const auto result = chooser.getResult();
- m_previousPath = result.getParentDirectory().getFullPathName();
- const auto ext = result.getFileExtension().toLowerCase();
- if (ext == ".syx")
+ juce::MemoryBlock data;
+ result.loadFileAsData(data);
+ for (auto it = data.begin(); it != data.end(); it += 267)
{
- juce::MemoryBlock data;
- result.loadFileAsData(data);
- for (auto it = data.begin(); it != data.end(); it += 267)
+ if ((it + 267) < data.end())
{
- if ((it + 267) < data.end())
- {
- processorRef.getController().parseMessage(Virus::SysEx(it, it + 267));
- }
+ processorRef.getController().sendSysEx(Virus::SysEx(it, it + 267));
+ sentData = true;
}
- m_btLoadFile.setButtonText("Loaded");
}
- else if (ext == ".mid" || ext == ".midi")
+ m_btLoadFile.setButtonText("Loaded");
+ }
+ else if (ext == ".mid" || ext == ".midi")
+ {
+ juce::MemoryBlock data;
+ if (!result.loadFileAsData(data))
{
- juce::MemoryBlock data;
- if (!result.loadFileAsData(data))
- {
- return;
- }
- const uint8_t *ptr = (uint8_t *)data.getData();
- const auto end = ptr + data.getSize();
+ return;
+ }
+ const uint8_t *ptr = (uint8_t *)data.getData();
+ const auto end = ptr + data.getSize();
- for (auto it = ptr; it < end; it += 1)
+ for (auto it = ptr; it < end; it += 1)
+ {
+ if ((uint8_t)*it == (uint8_t)0xf0 && (it+267) < end)
{
- if ((uint8_t)*it == (uint8_t)0xf0 && (it+267) < end)
+ if ((uint8_t) *(it + 1) == (uint8_t)0x00)
{
- if ((uint8_t) *(it + 1) == (uint8_t)0x00)
- {
- auto syx = Virus::SysEx(it, it + 267);
- syx[7] = 0x01; // force to bank a
- syx[266] = 0xf7;
- processorRef.getController().parseMessage(syx);
-
- it += 266;
- }
- else // some midi files have two bytes after the 0xf0
+ auto syx = Virus::SysEx(it, it + 267);
+ syx[7] = 0x01; // force to bank a
+ syx[266] = 0xf7;
+
+ processorRef.getController().sendSysEx(syx);
+
+ it += 266;
+ }
+ else // some midi files have two bytes after the 0xf0
+ {
+ auto syx = Virus::SysEx();
+ syx.push_back(0xf0);
+ for (auto i = it + 3; i < it + 3 + 266; i++)
{
- auto syx = Virus::SysEx();
- syx.push_back(0xf0);
- for (auto i = it + 3; i < it + 3 + 266; i++)
- {
- syx.push_back((uint8_t)*i);
- }
- syx[7] = 0x01; // force to bank a
- syx[266] = 0xf7;
- processorRef.getController().parseMessage(syx);
- it += 266;
+ syx.push_back((uint8_t)*i);
}
+ syx[7] = 0x01; // force to bank a
+ syx[266] = 0xf7;
+ processorRef.getController().sendSysEx(syx);
+ it += 266;
}
+
+ sentData = true;
}
}
- }
-}
-\ No newline at end of file
+ }
+
+ if (sentData)
+ processorRef.getController().onStateLoaded();
+}
diff --git a/source/jucePlugin/PluginProcessor.cpp b/source/jucePlugin/PluginProcessor.cpp
@@ -398,6 +398,8 @@ void AudioPluginAudioProcessor::setState(const void* _data, size_t _sizeInBytes)
state.resize(_sizeInBytes);
memcpy(&state[0], _data, _sizeInBytes);
m_plugin.setState(state);
+ if (m_controller)
+ m_controller->onStateLoaded();
}
//==============================================================================
diff --git a/source/jucePlugin/VirusController.cpp b/source/jucePlugin/VirusController.cpp
@@ -216,8 +216,16 @@ namespace Virus
*/
}
- juce::StringArray Controller::getSinglePresetNames(int bank) const
+ juce::StringArray Controller::getSinglePresetNames(virusLib::BankNumber _bank) const
{
+ if (_bank == virusLib::BankNumber::EditBuffer)
+ {
+ jassertfalse;
+ return {};
+ }
+
+ const auto bank = virusLib::toArrayIndex(_bank);
+
if (bank >= m_singles.size() || bank < 0)
{
jassertfalse;
@@ -248,9 +256,17 @@ namespace Virus
return juce::String(text);
}
- void Controller::setCurrentPartPreset(uint8_t part, uint8_t bank, uint8_t prg)
+ void Controller::setCurrentPartPreset(uint8_t part, virusLib::BankNumber _bank, uint8_t prg)
{
- if (bank < 0 || bank >= m_singles.size() || prg < 0 || prg > 127)
+ if(_bank == virusLib::BankNumber::EditBuffer || prg < 0 || prg > 127)
+ {
+ jassertfalse;
+ return;
+ }
+
+ const auto bank = virusLib::toArrayIndex(_bank);
+
+ if (bank >= m_singles.size())
{
jassertfalse;
return;
@@ -263,11 +279,11 @@ namespace Virus
patch.push_back(preset.data[i]);
sendSysEx(constructMessage(patch));
sendSysEx(constructMessage({MessageType::REQUEST_ARRANGEMENT}));
- m_currentBank[part] = bank;
+ m_currentBank[part] = _bank;
m_currentProgram[part] = prg;
}
- uint8_t Controller::getCurrentPartBank(uint8_t part) { return m_currentBank[part]; }
+ virusLib::BankNumber Controller::getCurrentPartBank(uint8_t part) { return m_currentBank[part]; }
uint8_t Controller::getCurrentPartProgram(uint8_t part) { return m_currentProgram[part]; }
void Controller::parseSingle(const SysEx &msg)
{
@@ -279,7 +295,7 @@ namespace Virus
assert(hasChecksum || dataSize == expectedDataSize);
SinglePatch patch;
- patch.bankNumber = msg[kHeaderWithMsgCodeLen];
+ patch.bankNumber = virusLib::fromMidiByte(msg[kHeaderWithMsgCodeLen]);
patch.progNumber = msg[kHeaderWithMsgCodeLen + 1];
[[maybe_unused]] const auto dataSum = copyData(msg, kHeaderWithMsgCodeLen + 2, patch.data);
@@ -287,16 +303,15 @@ namespace Virus
{
const auto checksum = msg[msg.size() - 2];
const auto deviceId = msg[5];
- [[maybe_unused]] const auto expectedSum =
- (deviceId + 0x10 + patch.bankNumber + patch.progNumber + dataSum) & 0x7f;
+ [[maybe_unused]] const auto expectedSum = (deviceId + 0x10 + virusLib::toMidiByte(patch.bankNumber) + patch.progNumber + dataSum) & 0x7f;
assert(expectedSum == checksum);
}
- if (patch.bankNumber == 0)
+ if (patch.bankNumber == virusLib::BankNumber::EditBuffer)
{
// virus sends also the single buffer not matter what's the mode.
// instead of keeping both, we 'encapsulate' this into first channel.
// the logic to maintain this is done by listening the global single/multi param.
- if (isMultiMode() && patch.progNumber == 0x40)
+ if (isMultiMode() && patch.progNumber == virusLib::SINGLE)
return;
else if (!isMultiMode() && patch.progNumber == 0x0)
return;
@@ -310,7 +325,7 @@ namespace Virus
}
}
else
- m_singles[patch.bankNumber - 1][patch.progNumber] = patch;
+ m_singles[virusLib::toArrayIndex(patch.bankNumber)][patch.progNumber] = patch;
const auto namePos = kHeaderWithMsgCodeLen + 2 + 128 + 112;
assert(namePos < msg.size());
@@ -1679,6 +1694,11 @@ namespace Virus
m_processor.addMidiEvent(ev);
}
+ void Controller::onStateLoaded()
+ {
+ sendSysEx(constructMessage({ MessageType::REQUEST_TOTAL }));
+ }
+
std::vector<uint8_t> Controller::constructMessage(SysEx msg)
{
const uint8_t start[] = {0xf0, 0x00, 0x20, 0x33, 0x01, static_cast<uint8_t>(m_deviceId)};
diff --git a/source/jucePlugin/VirusController.h b/source/jucePlugin/VirusController.h
@@ -4,6 +4,11 @@
#include "../synthLib/plugin.h"
#include "VirusParameter.h"
+namespace virusLib
+{
+ enum class BankNumber : uint8_t;
+}
+
class AudioPluginAudioProcessor;
namespace Virus
@@ -399,18 +404,19 @@ namespace Virus
Parameter* getParameter(ParameterType _param);
// bank - 0-1 (AB)
- juce::StringArray getSinglePresetNames(int bank) const;
+ juce::StringArray getSinglePresetNames(virusLib::BankNumber bank) const;
juce::StringArray getMultiPresetsName() const;
bool isMultiMode() { return getParamValue(0, 2, 0x7a)->getValue(); }
// part 0 - 15 (ignored when single! 0x40...)
- void setCurrentPartPreset(uint8_t part, uint8_t bank, uint8_t prg);
- uint8_t getCurrentPartBank(uint8_t part);
+ void setCurrentPartPreset(uint8_t part, virusLib::BankNumber bank, uint8_t prg);
+ virusLib::BankNumber getCurrentPartBank(uint8_t part);
uint8_t getCurrentPartProgram(uint8_t part);
juce::String getCurrentPartPresetName(uint8_t part);
uint32_t getBankCount() const { return static_cast<uint32_t>(m_singles.size()); }
void parseMessage(const SysEx &);
void sendSysEx(const SysEx &);
- private:
+ void onStateLoaded();
+ private:
void timerCallback() override;
static constexpr size_t kDataSizeInBytes = 256; // same for multi and single
@@ -423,7 +429,7 @@ namespace Virus
struct SinglePatch
{
- uint8_t bankNumber;
+ virusLib::BankNumber bankNumber;
uint8_t progNumber;
uint8_t data[kDataSizeInBytes];
};
@@ -475,7 +481,7 @@ namespace Virus
juce::CriticalSection m_eventQueueLock;
std::vector<synthLib::SMidiEvent> m_virusOut;
unsigned char m_deviceId;
- uint8_t m_currentBank[16];
+ virusLib::BankNumber m_currentBank[16];
uint8_t m_currentProgram[16];
};
}; // namespace Virus
diff --git a/source/jucePlugin/VirusParameter.h b/source/jucePlugin/VirusParameter.h
@@ -68,8 +68,8 @@ namespace Virus
{
// brute force but this should be O(1) of 128...
for (auto i = 0; i < 128; i++)
- if (m_desc.valueToTextFunction(i, m_desc) == text)
- return convertTo0to1(i);
+ if (m_desc.valueToTextFunction(static_cast<float>(i), m_desc) == text)
+ return convertTo0to1(static_cast<float>(i));
}
return convertTo0to1(text.getFloatValue());
}
diff --git a/source/virusLib/CMakeLists.txt b/source/virusLib/CMakeLists.txt
@@ -8,7 +8,7 @@ set(SOURCES
midiOutParser.cpp midiOutParser.h
romfile.cpp romfile.h
microcontroller.cpp microcontroller.h
- microcontrollerTypes.h
+ microcontrollerTypes.cpp microcontrollerTypes.h
)
target_sources(virusLib PRIVATE ${SOURCES})
diff --git a/source/virusLib/microcontroller.cpp b/source/virusLib/microcontroller.cpp
@@ -96,7 +96,7 @@ void Microcontroller::createDefaultState()
sendControlCommand(PLAY_MODE, g_defaultPlayMode);
if constexpr (g_defaultPlayMode == PlayModeSingle)
- writeSingle(0, SINGLE, m_singleEditBuffer);
+ writeSingle(BankNumber::EditBuffer, SINGLE, m_singleEditBuffer);
else
loadMulti(0, m_multiEditBuffer);
}
@@ -196,10 +196,10 @@ bool Microcontroller::sendMIDI(const SMidiEvent& _ev, bool cancelIfFull/* = fals
if(singleMode)
{
- if(getSingle(m_currentBank, _ev.b, single))
+ if(getSingle(fromArrayIndex(m_currentBank), _ev.b, single))
{
m_currentSingle = _ev.b;
- return writeSingle(0, SINGLE, single);
+ return writeSingle(BankNumber::EditBuffer, SINGLE, single);
}
}
else
@@ -262,7 +262,7 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
response.push_back(deviceId);
};
- auto buildPresetResponse = [&](const uint8_t _type, const uint8_t _bank, const uint8_t _program, const TPreset& _dump)
+ auto buildPresetResponse = [&](const uint8_t _type, const BankNumber _bank, const uint8_t _program, const TPreset& _dump)
{
SMidiEvent ev;
ev.source = _source;
@@ -272,7 +272,7 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
buildResponseHeader(ev);
response.push_back(_type);
- response.push_back(_bank);
+ response.push_back(toMidiByte(_bank));
response.push_back(_program);
for(const auto value : _dump)
@@ -293,7 +293,7 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
_responses.emplace_back(std::move(ev));
};
- auto buildSingleResponse = [&](const uint8_t _bank, const uint8_t _program)
+ auto buildSingleResponse = [&](const BankNumber _bank, const uint8_t _program)
{
TPreset dump;
const auto res = requestSingle(_bank, _program, dump);
@@ -301,7 +301,7 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
buildPresetResponse(DUMP_SINGLE, _bank, _program, dump);
};
- auto buildMultiResponse = [&](const uint8_t _bank, const uint8_t _program)
+ auto buildMultiResponse = [&](const BankNumber _bank, const uint8_t _program)
{
TPreset dump;
const auto res = requestMulti(_bank, _program, dump);
@@ -309,12 +309,17 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
buildPresetResponse(DUMP_MULTI, _bank, _program, dump);
};
- auto buildSingleBankResponse = [&](const uint8_t _bank)
+ auto buildSingleBankResponse = [&](const BankNumber _bank)
{
- if(_bank > 0 && _bank <= m_singles.size())
+ if (_bank == BankNumber::EditBuffer)
+ return;
+
+ const auto bankIndex = toArrayIndex(_bank);
+
+ if(bankIndex < m_singles.size())
{
// eat this, host, whoever you are. 128 single packets
- for(uint8_t i=0; i<m_singles[_bank-1].size(); ++i)
+ for(uint8_t i=0; i<m_singles[bankIndex].size(); ++i)
{
TPreset data;
const auto res = requestSingle(_bank, i, data);
@@ -323,9 +328,9 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
}
};
- auto buildMultiBankResponse = [&](const uint8_t _bank)
+ auto buildMultiBankResponse = [&](const BankNumber _bank)
{
- if(_bank == 1)
+ if(_bank == BankNumber::A)
{
// eat this, host, whoever you are. 128 multi packets
for(uint8_t i=0; i<g_presetsPerBank; ++i)
@@ -363,9 +368,9 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
auto buildTotalResponse = [&]()
{
buildGlobalResponses();
- buildSingleBankResponse(1);
- buildSingleBankResponse(2);
- buildMultiBankResponse(1);
+ buildSingleBankResponse(BankNumber::A);
+ buildSingleBankResponse(BankNumber::B);
+ buildMultiBankResponse(BankNumber::A);
};
auto buildArrangementResponse = [&]()
@@ -375,22 +380,22 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
const bool isMultiMode = m_globalSettings[PLAY_MODE] == PlayModeMulti;
if(isMultiMode)
- buildSingleResponse(0, SINGLE);
+ buildSingleResponse(BankNumber::EditBuffer, SINGLE);
- buildMultiResponse(0, 0);
+ buildMultiResponse(BankNumber::EditBuffer, 0);
for(uint8_t p=0; p<16; ++p)
- buildPresetResponse(DUMP_SINGLE, 0, p, m_singleEditBuffers[p]);
+ buildPresetResponse(DUMP_SINGLE, BankNumber::EditBuffer, p, m_singleEditBuffers[p]);
if(!isMultiMode)
- buildSingleResponse(0, SINGLE);
+ buildSingleResponse(BankNumber::EditBuffer, SINGLE);
};
auto buildControllerDumpResponse = [&](uint8_t _part)
{
TPreset _dump, _multi;
- const auto res = requestSingle(0, _part, _dump);
- const auto resm = requestMulti(0, 0, _multi);
+ const auto res = requestSingle(BankNumber::EditBuffer, _part, _dump);
+ const auto resm = requestMulti(BankNumber::EditBuffer, 0, _multi);
const uint8_t channel = _part == SINGLE ? m_globalSettings[GLOBAL_CHANNEL] : _multi[static_cast<size_t>(MD_PART_MIDI_CHANNEL) + _part];
for (const auto cc : g_pageA)
{
@@ -417,33 +422,33 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
{
case DUMP_SINGLE:
{
- const uint8_t bank = _data[7];
+ const auto bank = fromMidiByte(_data[7]);
const uint8_t program = _data[8];
- LOG("Received Single dump, Bank " << (int)bank << ", program " << (int)program);
+ LOG("Received Single dump, Bank " << (int)toMidiByte(bank) << ", program " << (int)program);
TPreset dump;
std::copy_n(_data.data() + g_sysexPresetHeaderSize, dump.size(), dump.begin());
return writeSingle(bank, program, dump);
}
case DUMP_MULTI:
{
- const uint8_t bank = _data[7];
+ const auto bank = fromMidiByte(_data[7]);
const uint8_t program = _data[8];
- LOG("Received Multi dump, Bank " << (int)bank << ", program " << (int)program);
+ LOG("Received Multi dump, Bank " << (int)toMidiByte(bank) << ", program " << (int)program);
TPreset dump;
std::copy_n(_data.data() + g_sysexPresetHeaderSize, dump.size(), dump.begin());
return writeMulti(bank, program, dump);
}
case REQUEST_SINGLE:
{
- const uint8_t bank = _data[7];
+ const auto bank = fromMidiByte(_data[7]);
const uint8_t program = _data[8];
- LOG("Request Single, Bank " << (int)bank << ", program " << (int)program);
+ LOG("Request Single, Bank " << (int)toMidiByte(bank) << ", program " << (int)program);
buildSingleResponse(bank, program);
break;
}
case REQUEST_MULTI:
{
- const uint8_t bank = _data[7];
+ const auto bank = fromMidiByte(_data[7]);
const uint8_t program = _data[8];
LOG("Request Multi, Bank " << (int)bank << ", program " << (int)program);
buildMultiResponse(bank, program);
@@ -451,19 +456,19 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
}
case REQUEST_BANK_SINGLE:
{
- const uint8_t bank = _data[7];
+ const auto bank = fromMidiByte(_data[7]);
buildSingleBankResponse(bank);
break;
}
case REQUEST_BANK_MULTI:
{
- const uint8_t bank = _data[7];
+ const auto bank = fromMidiByte(_data[7]);
buildMultiBankResponse(bank);
break;
}
case REQUEST_CONTROLLER_DUMP:
{
- const uint8_t part = _data[8];
+ const auto part = _data[8];
if (part < 16 || part == SINGLE)
buildControllerDumpResponse(part);
break;
@@ -506,15 +511,15 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelI
m_globalSettings[PLAY_MODE] = playMode;
LOG("Switch to Single mode");
- return writeSingle(0, SINGLE, m_singleEditBuffer);
+ return writeSingle(BankNumber::EditBuffer, SINGLE, m_singleEditBuffer);
}
case PlayModeMultiSingle:
case PlayModeMulti:
{
m_globalSettings[PLAY_MODE] = PlayModeMulti;
- writeMulti(0, 0, m_multiEditBuffer);
+ writeMulti(BankNumber::EditBuffer, 0, m_multiEditBuffer);
for(uint8_t i=0; i<16; ++i)
- writeSingle(0, i, m_singleEditBuffers[i]);
+ writeSingle(BankNumber::EditBuffer, i, m_singleEditBuffers[i]);
return true;
}
default:
@@ -588,11 +593,17 @@ std::vector<TWord> Microcontroller::presetToDSPWords(const TPreset& _preset)
return preset;
}
-bool Microcontroller::getSingle(uint32_t _bank, uint32_t _preset, TPreset& _result) const
+bool Microcontroller::getSingle(BankNumber _bank, uint32_t _preset, TPreset& _result) const
{
- if(_bank >= m_singles.size())
+ if (_bank == BankNumber::EditBuffer)
return false;
- const auto& s = m_singles[_bank];
+
+ const auto bank = toArrayIndex(_bank);
+
+ if(bank >= m_singles.size())
+ return false;
+
+ const auto& s = m_singles[bank];
if(_preset >= s.size())
return false;
@@ -610,25 +621,25 @@ void Microcontroller::waitUntilReady() const
}
}
-bool Microcontroller::requestMulti(uint8_t _bank, uint8_t _program, TPreset& _data) const
+bool Microcontroller::requestMulti(BankNumber _bank, uint8_t _program, TPreset& _data) const
{
- if (_bank == 0)
+ if (_bank == BankNumber::EditBuffer)
{
// Use multi-edit buffer
_data = m_multiEditBuffer;
return true;
}
- if (_bank != 1)
+ if (_bank != BankNumber::A)
return false;
// Load from flash
return m_rom.getMulti(_program, _data);
}
-bool Microcontroller::requestSingle(uint8_t _bank, uint8_t _program, TPreset& _data) const
+bool Microcontroller::requestSingle(BankNumber _bank, uint8_t _program, TPreset& _data) const
{
- if (_bank == 0)
+ if (_bank == BankNumber::EditBuffer)
{
// Use single-edit buffer
if(_program == SINGLE)
@@ -640,20 +651,22 @@ bool Microcontroller::requestSingle(uint8_t _bank, uint8_t _program, TPreset& _d
}
// Load from flash
- return getSingle(_bank - 1, _program, _data);
+ return getSingle(_bank, _program, _data);
}
-bool Microcontroller::writeSingle(uint8_t _bank, uint8_t _program, const TPreset& _data)
+bool Microcontroller::writeSingle(BankNumber _bank, uint8_t _program, const TPreset& _data)
{
- if (_bank > 0)
+ if (_bank != BankNumber::EditBuffer)
{
- if(_bank >= m_singles.size() || _bank >= g_singleRamBankCount)
+ const auto bank = toArrayIndex(_bank);
+
+ if(bank >= m_singles.size() || bank >= g_singleRamBankCount)
return true; // out of range
- if(_program >= m_singles[_bank].size())
+ if(_program >= m_singles[bank].size())
return true; // out of range
- m_singles[_bank][_program] = _data;
+ m_singles[bank][_program] = _data;
return true;
}
@@ -669,11 +682,11 @@ bool Microcontroller::writeSingle(uint8_t _bank, uint8_t _program, const TPreset
return sendPreset(_program, presetToDSPWords(_data), false);
}
-bool Microcontroller::writeMulti(uint8_t _bank, uint8_t _program, const TPreset& _data)
+bool Microcontroller::writeMulti(BankNumber _bank, uint8_t _program, const TPreset& _data)
{
- if (_bank != 0)
+ if (_bank != BankNumber::EditBuffer)
{
- LOG("We do not support writing to flash, attempt to write multi to bank " << _bank << ", program " << _program);
+ LOG("We do not support writing to RAM or ROM, attempt to write multi to bank " << static_cast<int>(toMidiByte(_bank)) << ", program " << static_cast<int>(_program));
return true;
}
@@ -699,12 +712,12 @@ bool Microcontroller::partProgramChange(const uint8_t _part, const uint8_t _valu
{
TPreset single;
- const auto bank = m_multiEditBuffer[MD_PART_BANK_NUMBER + _part];
+ const auto bank = fromMidiByte(m_multiEditBuffer[MD_PART_BANK_NUMBER + _part]);
if(getSingle(bank, _value, single))
{
m_multiEditBuffer[MD_PART_PROGRAM_NUMBER + _part] = _value;
- return writeSingle(0, _part, single);
+ return writeSingle(BankNumber::EditBuffer, _part, single);
}
return true;
@@ -722,7 +735,7 @@ bool Microcontroller::multiProgramChange(uint8_t _value)
bool Microcontroller::loadMulti(uint8_t _program, const TPreset& _multi)
{
- if(!writeMulti(0, _program, _multi))
+ if(!writeMulti(BankNumber::EditBuffer, _program, _multi))
return false;
for (uint8_t p = 0; p < 16; ++p)
diff --git a/source/virusLib/microcontroller.h b/source/virusLib/microcontroller.h
@@ -25,10 +25,10 @@ public:
bool sendMIDI(const synthLib::SMidiEvent& _ev, bool cancelIfFull = false);
bool sendSysex(const std::vector<uint8_t>& _data, bool _cancelIfFull, std::vector<synthLib::SMidiEvent>& _responses, synthLib::MidiEventSource _source);
- bool writeSingle(uint8_t _bank, uint8_t _program, const TPreset& _data);
- bool writeMulti(uint8_t _bank, uint8_t _program, const TPreset& _data);
- bool requestMulti(uint8_t _bank, uint8_t _program, TPreset& _data) const;
- bool requestSingle(uint8_t _bank, uint8_t _program, TPreset& _data) const;
+ bool writeSingle(BankNumber _bank, uint8_t _program, const TPreset& _data);
+ bool writeMulti(BankNumber _bank, uint8_t _program, const TPreset& _data);
+ bool requestMulti(BankNumber _bank, uint8_t _program, TPreset& _data) const;
+ bool requestSingle(BankNumber _bank, uint8_t _program, TPreset& _data) const;
void sendInitControlCommands();
@@ -51,7 +51,7 @@ private:
void waitUntilReady() const;
void waitUntilBufferEmpty() const;
static std::vector<dsp56k::TWord> presetToDSPWords(const TPreset& _preset);
- bool getSingle(uint32_t _bank, uint32_t _preset, TPreset& _result) const;
+ bool getSingle(BankNumber _bank, uint32_t _preset, TPreset& _result) const;
bool partBankSelect(uint8_t _part, uint8_t _value, bool _immediatelySelectSingle);
bool partProgramChange(uint8_t _part, uint8_t _value);
diff --git a/source/virusLib/microcontrollerTypes.cpp b/source/virusLib/microcontrollerTypes.cpp
@@ -0,0 +1,26 @@
+#include "microcontrollerTypes.h"
+
+#include <cassert>
+
+namespace virusLib
+{
+ uint8_t toMidiByte(BankNumber _bank)
+ {
+ return static_cast<uint8_t>(_bank);
+ }
+ BankNumber fromMidiByte(uint8_t _byte)
+ {
+ return static_cast<BankNumber>(_byte);
+ }
+ uint32_t toArrayIndex(BankNumber _bank)
+ {
+ const auto bank = static_cast<uint8_t>(_bank);
+ assert(bank > 0);
+ return bank - 1;
+ }
+
+ BankNumber fromArrayIndex(uint8_t _bank)
+ {
+ return static_cast<BankNumber>(_bank + 1);
+ }
+}
diff --git a/source/virusLib/microcontrollerTypes.h b/source/virusLib/microcontrollerTypes.h
@@ -1,5 +1,7 @@
#pragma once
+#include <cstdint>
+
namespace virusLib
{
enum SysexMessageType : uint8_t
@@ -158,4 +160,23 @@ namespace virusLib
};
static constexpr uint8_t OMNI_DEVICE_ID = 0x10;
-}
-\ No newline at end of file
+
+ enum class BankNumber : uint8_t
+ {
+ EditBuffer,
+ A,
+ B,
+ C,
+ D,
+ E,
+ F,
+ G,
+ H,
+ Count
+ };
+
+ uint8_t toMidiByte(BankNumber _bank);
+ BankNumber fromMidiByte(uint8_t _byte);
+ uint32_t toArrayIndex(BankNumber _bank);
+ BankNumber fromArrayIndex(uint8_t _bank);
+}
diff --git a/source/virusTestConsole/virusTestConsole.cpp b/source/virusTestConsole/virusTestConsole.cpp
@@ -51,7 +51,7 @@ void audioCallback(dsp56k::Audio* audio)
break;
case 64:
LOG("Sending Preset");
- microcontroller->writeSingle(0, SINGLE, preset);
+ microcontroller->writeSingle(BankNumber::EditBuffer, SINGLE, preset);
break;
case 128:
LOG("Sending Note On");