commit ec82e084001d976fc961294e99c9408d666babcd
parent 5a01097c2efbd094feaf7fadd03aa2abc3ca1634
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Thu, 7 Apr 2022 18:30:12 +0200
use separate values for input-to-output latency and midi-to-output latency
Diffstat:
7 files changed, 48 insertions(+), 22 deletions(-)
diff --git a/source/jucePlugin/PluginProcessor.cpp b/source/jucePlugin/PluginProcessor.cpp
@@ -88,7 +88,11 @@ void AudioPluginAudioProcessor::prepareToPlay (double sampleRate, int samplesPer
// initialisation that you need..
m_plugin.setSamplerate(static_cast<float>(sampleRate));
m_plugin.setBlockSize(samplesPerBlock);
- setLatencySamples(m_plugin.getLatencySamples());
+
+ if constexpr(JucePlugin_IsSynth)
+ setLatencySamples(m_plugin.getLatencyMidiToOutput());
+ else
+ setLatencySamples(m_plugin.getLatencyInputToOutput());
}
void AudioPluginAudioProcessor::releaseResources()
diff --git a/source/synthLib/device.cpp b/source/synthLib/device.cpp
@@ -65,17 +65,17 @@ namespace synthLib
for (const auto& ev : _midiIn)
sendMidi(ev, _midiOut);
- m_periph.getEsai().processAudioInterleaved(_inputs, _outputs, _size, 2, 2, m_latency);
+ m_periph.getEsai().processAudioInterleaved(_inputs, _outputs, _size, 2, 2, m_extraLatency);
readMidiOut(_midiOut);
}
- void Device::setLatencySamples(const uint32_t _size)
+ void Device::setExtraLatencySamples(const uint32_t _size)
{
const uint32_t maxLatency = static_cast<uint32_t>(getPeriph().getEsai().getAudioInputs()[0].capacity()) >> 1;
- m_latency = std::min(_size, maxLatency);
+ m_extraLatency = std::min(_size, maxLatency);
- LOG("Latency set to " << m_latency << " samples at " << getSamplerate() << " Hz");
+ LOG("Latency set to " << m_extraLatency << " samples at " << getSamplerate() << " Hz");
if(_size > maxLatency)
{
diff --git a/source/synthLib/device.h b/source/synthLib/device.h
@@ -16,9 +16,12 @@ namespace synthLib
Device(uint32_t _memorySize, uint32_t _externalMemStartAddress);
virtual ~Device();
virtual void process(float** _inputs, float** _outputs, size_t _size, const std::vector<SMidiEvent>& _midiIn, std::vector<SMidiEvent>& _midiOut);
- void setLatencySamples(uint32_t _size);
- uint32_t getLatencySamples() const { return m_latency; }
- virtual uint32_t getInternalLatencySamples() const { return 0; }
+
+ void setExtraLatencySamples(uint32_t _size);
+ uint32_t getExtraLatencySamples() const { return m_extraLatency; }
+
+ virtual uint32_t getInternalLatencyMidiToOutput() const { return 0; }
+ virtual uint32_t getInternalLatencyInputToOutput() const { return 0; }
void startDSPThread();
@@ -50,6 +53,6 @@ namespace synthLib
std::unique_ptr<dsp56k::DSPThread> m_dspThread;
std::vector<SMidiEvent> m_midiIn;
- uint32_t m_latency = 0;
+ uint32_t m_extraLatency = 0;
};
}
diff --git a/source/synthLib/plugin.cpp b/source/synthLib/plugin.cpp
@@ -16,8 +16,9 @@ using namespace synthLib;
namespace synthLib
{
constexpr uint8_t g_stateVersion = 1;
+ constexpr uint32_t g_extraLatencyBlocks = 1;
- Plugin::Plugin(Device* _device) : m_device(_device), m_deviceLatency(0)
+ Plugin::Plugin(Device* _device) : m_device(_device)
{
m_resampler.setDeviceSamplerate(_device->getSamplerate());
}
@@ -213,10 +214,11 @@ namespace synthLib
if(m_blockSize <= 0 || m_hostSamplerate <= 0)
return;
- const auto latency = static_cast<uint32_t>(std::ceil(static_cast<float>(m_blockSize) * m_device->getSamplerate() * m_hostSamplerateInv));
- m_device->setLatencySamples(latency);
+ const auto latency = static_cast<uint32_t>(std::ceil(static_cast<float>(m_blockSize * g_extraLatencyBlocks) * m_device->getSamplerate() * m_hostSamplerateInv));
+ m_device->setExtraLatencySamples(latency);
- m_deviceLatency = static_cast<uint32_t>(m_device->getInternalLatencySamples() * m_hostSamplerate / m_device->getSamplerate());
+ m_deviceLatencyMidiToOutput = static_cast<uint32_t>(static_cast<float>(m_device->getInternalLatencyMidiToOutput()) * m_hostSamplerate / m_device->getSamplerate());
+ m_deviceLatencyInputToOutput = static_cast<uint32_t>(static_cast<float>(m_device->getInternalLatencyInputToOutput()) * m_hostSamplerate / m_device->getSamplerate());
}
void Plugin::processMidiInEvents()
@@ -273,9 +275,15 @@ namespace synthLib
updateDeviceLatency();
}
- uint32_t Plugin::getLatencySamples() const
+ uint32_t Plugin::getLatencyMidiToOutput() const
{
std::lock_guard lock(m_lock);
- return m_blockSize + m_deviceLatency;
+ return m_blockSize * g_extraLatencyBlocks + m_deviceLatencyMidiToOutput;
+ }
+
+ uint32_t Plugin::getLatencyInputToOutput() const
+ {
+ std::lock_guard lock(m_lock);
+ return m_blockSize * g_extraLatencyBlocks + m_deviceLatencyInputToOutput;
}
}
diff --git a/source/synthLib/plugin.h b/source/synthLib/plugin.h
@@ -23,7 +23,8 @@ namespace synthLib
void setSamplerate(float _samplerate);
void setBlockSize(uint32_t _blockSize);
- uint32_t getLatencySamples() const;
+ uint32_t getLatencyMidiToOutput() const;
+ uint32_t getLatencyInputToOutput() const;
void process(float** _inputs, float** _outputs, size_t _count, float _bpm, float _ppqPos, bool _isPlaying);
void getMidiOut(std::vector<SMidiEvent>& _midiOut);
@@ -61,7 +62,8 @@ namespace synthLib
uint32_t m_blockSize = 0;
- uint32_t m_deviceLatency;
+ uint32_t m_deviceLatencyMidiToOutput = 0;
+ uint32_t m_deviceLatencyInputToOutput = 0;
// MIDI Clock
bool m_isPlaying = false;
diff --git a/source/virusLib/device.cpp b/source/virusLib/device.cpp
@@ -58,11 +58,19 @@ namespace virusLib
return m_syx.setState(_state, _type);
}
- uint32_t Device::getInternalLatencySamples() const
+ uint32_t Device::getInternalLatencyMidiToOutput() const
{
-// return 300; // hard to believe but this is what I figured out by measuring with the init patch
+ /*
+ * hard to believe but this is what I figured out by measuring with a customized init patch
+ *
+ * Note that this is an average value, midi latency drifts in a range of roughly +/- 61 samples
+ */
+ return 384 + 28;
+ }
- // more precise, measured by using an input init patch. Sent a click to the input and recorded both the input
+ uint32_t Device::getInternalLatencyInputToOutput() const
+ {
+ // Measured by using an input init patch. Sent a click to the input and recorded both the input
// as direct signal plus the Virus output and checking the resulting latency in a wave editor
return 384;
}
@@ -73,7 +81,7 @@ namespace virusLib
{
// LOG("MIDI: " << std::hex << (int)_ev.a << " " << (int)_ev.b << " " << (int)_ev.c);
auto ev = _ev;
- ev.offset += m_numSamplesProcessed + getLatencySamples();
+ ev.offset += m_numSamplesProcessed + getExtraLatencySamples();
return m_syx.sendMIDI(ev, true);
}
diff --git a/source/virusLib/device.h b/source/virusLib/device.h
@@ -22,7 +22,8 @@ namespace virusLib
bool getState(std::vector<uint8_t>& _state, synthLib::StateType _type) override;
bool setState(const std::vector<uint8_t>& _state, synthLib::StateType _type) override;
- uint32_t getInternalLatencySamples() const override;
+ uint32_t getInternalLatencyMidiToOutput() const override;
+ uint32_t getInternalLatencyInputToOutput() const override;
private:
bool sendMidi(const synthLib::SMidiEvent& _ev, std::vector<synthLib::SMidiEvent>& _response) override;