commit bd2b4277108ab74f2a858b8bd749bc6f0912b07c
parent 61af621d66f231b51077efca839cccfb1e4bbca7
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Mon, 19 Jul 2021 23:57:58 +0200
completely rework midi timing
Diffstat:
6 files changed, 71 insertions(+), 73 deletions(-)
diff --git a/source/synthLib/device.cpp b/source/synthLib/device.cpp
@@ -19,7 +19,12 @@ namespace synthLib
auto* bufDSP = buf;
auto* bufMem = bufDSP + alignedSize<DSP>();
auto* bufBuf = bufMem + alignedSize<Memory>();
-
+
+ m_periph.getEsai().setCallback([this](Audio* _audio)
+ {
+ onAudioWritten();
+ }, 0, 1);
+
m_memory = new (bufMem)Memory(m_memoryValidator, _memorySize, reinterpret_cast<TWord*>(bufBuf));
m_dsp = new (buf)DSP(*m_memory, &m_periph, &m_periph);
@@ -57,67 +62,12 @@ namespace synthLib
void Device::process(float** _inputs, float** _outputs, const size_t _size, const std::vector<SMidiEvent>& _midiIn, std::vector<SMidiEvent>& _midiOut)
{
- m_midiIn.insert(m_midiIn.end(), _midiIn.begin(), _midiIn.end());
+ for(size_t i=0; i<_midiIn.size(); ++i)
+ sendMidi(_midiIn[i], _midiOut);
- if(!m_midiIn.empty())
- {
- size_t i = 0;
-
- uint32_t end = 0;
- uint32_t begin = 0;
-
- bool sendMidiFailed = false;
-
- while(i < m_midiIn.size() && !sendMidiFailed)
- {
- end = m_midiIn[i].offset;
-
- const auto size = end - begin;
-
- m_periph.getEsai().processAudioInterleaved(_inputs, _outputs, size, 2, 2, m_latency);
- readMidiOut(_midiOut);
-
- _inputs[0] += size;
- _inputs[1] += size;
- _outputs[0] += size;
- _outputs[1] += size;
-
- for(size_t j=i; j<m_midiIn.size() && !sendMidiFailed; j++)
- {
- if(m_midiIn[j].offset <= static_cast<int>(end))
- {
- if(!sendMidi(m_midiIn[j], _midiOut))
- {
- if(j > 0)
- {
- m_midiIn.erase(m_midiIn.begin(), m_midiIn.begin() + j);
-
- for (auto& event : m_midiIn)
- event.offset = 0;
- }
- sendMidiFailed = true;
- }
- ++i;
- }
- }
-
- begin = end;
- }
-
- if(end < _size)
- {
- m_periph.getEsai().processAudioInterleaved(_inputs, _outputs, _size - end, 2, 2, m_latency);
- readMidiOut(_midiOut);
- }
-
- if(!sendMidiFailed)
- m_midiIn.clear();
- }
- else
- {
- m_periph.getEsai().processAudioInterleaved(_inputs, _outputs, _size, 2, 2, m_latency);
- readMidiOut(_midiOut);
- }
+ m_periph.getEsai().processAudioInterleaved(_inputs, _outputs, _size, 2, 2, m_latency);
+
+ readMidiOut(_midiOut);
}
void Device::setLatencySamples(const uint32_t _size)
diff --git a/source/synthLib/device.h b/source/synthLib/device.h
@@ -29,6 +29,7 @@ namespace synthLib
protected:
virtual void readMidiOut(std::vector<SMidiEvent>& _midiOut) = 0;
virtual bool sendMidi(const SMidiEvent& _ev, std::vector<SMidiEvent>& _response) = 0;
+ virtual void onAudioWritten() {}
void dummyProcess(uint32_t _numSamples);
diff --git a/source/virusLib/device.cpp b/source/virusLib/device.cpp
@@ -42,6 +42,8 @@ namespace virusLib
void Device::process(float** _inputs, float** _outputs, size_t _size, const std::vector<synthLib::SMidiEvent>& _midiIn, std::vector<synthLib::SMidiEvent>& _midiOut)
{
+ m_numSamplesProcessed += static_cast<uint32_t>(_size);
+
synthLib::Device::process(_inputs, _outputs, _size, _midiIn, _midiOut);
m_syx.process(_size);
}
@@ -61,7 +63,9 @@ namespace virusLib
if(_ev.sysex.empty())
{
// LOG("MIDI: " << std::hex << (int)_ev.a << " " << (int)_ev.b << " " << (int)_ev.c);
- return m_syx.sendMIDI(_ev, true);
+ auto ev = _ev;
+ ev.offset += m_numSamplesProcessed;
+ return m_syx.sendMIDI(ev, true);
}
std::vector<synthLib::SMidiEvent> responses;
@@ -87,4 +91,12 @@ namespace virusLib
}
}
}
+
+ void Device::onAudioWritten()
+ {
+ m_numSamplesWritten += 1;
+
+ if(m_numSamplesWritten >= 0)
+ m_syx.sendPendingMidiEvents(m_numSamplesWritten >> 1);
+ }
}
diff --git a/source/virusLib/device.h b/source/virusLib/device.h
@@ -25,9 +25,12 @@ namespace virusLib
private:
bool sendMidi(const synthLib::SMidiEvent& _ev, std::vector<synthLib::SMidiEvent>& _response) override;
void readMidiOut(std::vector<synthLib::SMidiEvent>& _midiOut) override;
+ void onAudioWritten() override;
ROMFile m_rom;
Microcontroller m_syx;
MidiOutParser m_midiOutParser;
+ uint32_t m_numSamplesWritten = 0;
+ uint32_t m_numSamplesProcessed = 0;
};
}
diff --git a/source/virusLib/microcontroller.cpp b/source/virusLib/microcontroller.cpp
@@ -106,6 +106,8 @@ bool Microcontroller::needsToWaitForHostBits(char flag1, char flag2) const
void Microcontroller::writeHostBitsWithWait(const char flag1, const char flag2) const
{
+ std::lock_guard lock(m_mutex);
+
const int hsr=m_hdi08.readStatusRegister();
const int target=(flag1?1:0)|(flag2?2:0);
if (((hsr>>3)&3)==target) return;
@@ -115,6 +117,8 @@ void Microcontroller::writeHostBitsWithWait(const char flag1, const char flag2)
bool Microcontroller::sendPreset(uint8_t program, const std::vector<TWord>& preset, bool isMulti)
{
+ std::lock_guard lock(m_mutex);
+
if(m_hdi08.hasDataToSend() || needsToWaitForHostBits(0,1))
{
m_pendingPresetWrites.emplace_back(SPendingPresetWrite{program, isMulti, preset});
@@ -139,7 +143,10 @@ void Microcontroller::sendControlCommand(const ControlCommand _command, const ui
bool Microcontroller::send(const Page _page, const uint8_t _part, const uint8_t _param, const uint8_t _value, bool cancelIfFull/* = false*/)
{
+ std::lock_guard lock(m_mutex);
+
waitUntilReady();
+
if(cancelIfFull && needsToWaitForHostBits(0,1))
return false;
writeHostBitsWithWait(0,1);
@@ -206,7 +213,8 @@ bool Microcontroller::sendMIDI(const SMidiEvent& _ev, bool cancelIfFull/* = fals
break;
}
- return sendMIDItoDSP(_ev.a,_ev.b,_ev.c, cancelIfFull);
+ m_pendingMidiEvents.push_back(_ev);
+ return true;
}
bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, bool _cancelIfFull, std::vector<SMidiEvent>& _responses)
@@ -707,6 +715,8 @@ bool Microcontroller::loadMultiSingle(uint8_t _part, const TPreset& _multi)
void Microcontroller::process(size_t _size)
{
+ std::lock_guard lock(m_mutex);
+
if(!m_pendingPresetWrites.empty() && !m_hdi08.hasDataToSend())
{
const auto preset = m_pendingPresetWrites.front();
@@ -779,6 +789,8 @@ bool Microcontroller::setState(const std::vector<unsigned char>& _state, const S
bool Microcontroller::sendMIDItoDSP(uint8_t _a, uint8_t _b, uint8_t _c, bool cancelIfFull)
{
+ std::lock_guard lock(m_mutex);
+
if(cancelIfFull && (needsToWaitForHostBits(1,1) || m_hdi08.dataRXFull()))
return false;
writeHostBitsWithWait(1,1);
@@ -787,6 +799,25 @@ bool Microcontroller::sendMIDItoDSP(uint8_t _a, uint8_t _b, uint8_t _c, bool can
return true;
}
+void Microcontroller::sendPendingMidiEvents(uint32_t _maxOffset)
+{
+ auto size = m_pendingMidiEvents.size();
+
+ if(!size)
+ return;
+
+ while(!m_pendingMidiEvents.empty() && static_cast<uint32_t>(m_pendingMidiEvents.front().offset) <= _maxOffset)
+ {
+ const auto& ev = m_pendingMidiEvents.front();
+
+ if(!sendMIDItoDSP(ev.a,ev.b,ev.c, true))
+ break;
+
+ m_pendingMidiEvents.pop_front();
+ --size;
+ }
+}
+
void Microcontroller::applyToSingleEditBuffer(const Page _page, const uint8_t _part, const uint8_t _param, const uint8_t _value)
{
if(_part == SINGLE)
diff --git a/source/virusLib/microcontroller.h b/source/virusLib/microcontroller.h
@@ -6,13 +6,10 @@
#include "romfile.h"
#include "../synthLib/deviceTypes.h"
+#include "../synthLib/midiTypes.h"
#include <list>
-
-namespace synthLib
-{
- struct SMidiEvent;
-}
+#include <mutex>
namespace virusLib
{
@@ -180,10 +177,7 @@ public:
explicit Microcontroller(dsp56k::HDI08& hdi08, ROMFile& romFile);
- bool sendPreset(uint8_t program, const std::vector<dsp56k::TWord>& preset, bool isMulti = false);
- void sendControlCommand(ControlCommand command, uint8_t value);
bool sendMIDI(const synthLib::SMidiEvent& _ev, bool cancelIfFull = false);
- bool send(Page page, uint8_t part, uint8_t param, uint8_t value, bool cancelIfFull = false);
bool sendSysex(const std::vector<uint8_t>& _data, bool _cancelIfFull, std::vector<synthLib::SMidiEvent>& _responses);
bool writeSingle(uint8_t _bank, uint8_t _program, const TPreset& _data);
@@ -191,7 +185,6 @@ public:
bool requestMulti(uint8_t _bank, uint8_t _program, TPreset& _data) const;
bool requestSingle(uint8_t _bank, uint8_t _program, TPreset& _data) const;
- bool needsToWaitForHostBits(char flag1,char flag2) const;
void sendInitControlCommands();
void createDefaultState();
@@ -202,7 +195,13 @@ public:
bool sendMIDItoDSP(uint8_t _a, uint8_t _b, uint8_t _c, bool cancelIfFull);
+ void sendPendingMidiEvents(uint32_t _maxOffset);
+
private:
+ bool send(Page page, uint8_t part, uint8_t param, uint8_t value, bool cancelIfFull = false);
+ void sendControlCommand(ControlCommand command, uint8_t value);
+ bool sendPreset(uint8_t program, const std::vector<dsp56k::TWord>& preset, bool isMulti = false);
+ bool needsToWaitForHostBits(char flag1,char flag2) const;
void writeHostBitsWithWait(char flag1,char flag2) const;
void waitUntilReady() const;
void waitUntilBufferEmpty() const;
@@ -245,7 +244,9 @@ private:
};
std::list<SPendingPresetWrite> m_pendingPresetWrites;
- uint32_t m_presetWriteCount = 0;
+
+ dsp56k::RingBuffer<synthLib::SMidiEvent, 1024, false> m_pendingMidiEvents;
+ mutable std::recursive_mutex m_mutex;
};
}