commit bc46fe6d5ef285377a7be9e6a8a2c69ac8a8025d
parent a787f4ae03dea7ac1c405d93e54a73533c1b3225
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Sun, 22 May 2022 16:31:36 +0200
add ability to adjust plugin latency
Diffstat:
6 files changed, 58 insertions(+), 9 deletions(-)
diff --git a/source/jucePlugin/PluginEditor.cpp b/source/jucePlugin/PluginEditor.cpp
@@ -28,8 +28,10 @@ AudioPluginAudioProcessorEditor::AudioPluginAudioProcessorEditor(AudioPluginAudi
}
loadSkin(skin);
-
setGuiScale(scale);
+
+ const auto latencyBlocks = config->getIntValue("latencyBlocks", static_cast<int>(processorRef.getPlugin().getLatencyBlocks()));
+ setLatencyBlocks(latencyBlocks);
}
void AudioPluginAudioProcessorEditor::loadSkin(const Skin& _skin)
@@ -150,8 +152,17 @@ void AudioPluginAudioProcessorEditor::openMenu()
scaleMenu.addItem("200%", true, scale == 200, [this] { setGuiScale(200); });
scaleMenu.addItem("300%", true, scale == 300, [this] { setGuiScale(300); });
+ const auto latency = processorRef.getPlugin().getLatencyBlocks();
+ juce::PopupMenu latencyMenu;
+ latencyMenu.addItem("0 (DAW will report proper CPU usage)", true, latency == 0, [this] { setLatencyBlocks(0); });
+ latencyMenu.addItem("1 (default)", true, latency == 1, [this] { setLatencyBlocks(1); });
+ latencyMenu.addItem("2", true, latency == 2, [this] { setLatencyBlocks(2); });
+ latencyMenu.addItem("4", true, latency == 4, [this] { setLatencyBlocks(4); });
+ latencyMenu.addItem("8", true, latency == 8, [this] { setLatencyBlocks(8); });
+
menu.addSubMenu("GUI Skin", skinMenu);
menu.addSubMenu("GUI Scale", scaleMenu);
+ menu.addSubMenu("Latency (blocks)", latencyMenu);
menu.showMenuAsync(juce::PopupMenu::Options());
}
@@ -198,6 +209,20 @@ void AudioPluginAudioProcessorEditor::writeSkinToConfig(const Skin& _skin) const
config->setValue("skinFolder", _skin.folder.c_str());
}
+void AudioPluginAudioProcessorEditor::setLatencyBlocks(uint32_t _blocks) const
+{
+ auto& p = processorRef.getPlugin();
+
+ if(p.setLatencyBlocks(_blocks))
+ {
+ processorRef.updateLatencySamples();
+
+ auto* config = processorRef.getController().getConfig();
+ config->setValue("latencyBlocks", static_cast<int>(_blocks));
+ config->saveIfNeeded();
+ }
+}
+
AudioPluginAudioProcessorEditor::~AudioPluginAudioProcessorEditor()
{
m_virusEditor.reset();
diff --git a/source/jucePlugin/PluginEditor.h b/source/jucePlugin/PluginEditor.h
@@ -35,6 +35,7 @@ private:
void exportCurrentSkin() const;
Skin readSkinFromConfig() const;
void writeSkinToConfig(const Skin& _skin) const;
+ void setLatencyBlocks(uint32_t _blocks) const;
// This reference is provided as a quick way for your editor to
// access the processor object that created it.
diff --git a/source/jucePlugin/PluginProcessor.cpp b/source/jucePlugin/PluginProcessor.cpp
@@ -93,10 +93,7 @@ void AudioPluginAudioProcessor::prepareToPlay (double sampleRate, int samplesPer
m_plugin.setSamplerate(static_cast<float>(sampleRate));
m_plugin.setBlockSize(samplesPerBlock);
- if constexpr(JucePlugin_IsSynth)
- setLatencySamples(m_plugin.getLatencyMidiToOutput());
- else
- setLatencySamples(m_plugin.getLatencyInputToOutput());
+ updateLatencySamples();
}
void AudioPluginAudioProcessor::releaseResources()
@@ -403,6 +400,14 @@ void AudioPluginAudioProcessor::handleIncomingMidiMessage(juce::MidiInput *sourc
}
}
+void AudioPluginAudioProcessor::updateLatencySamples()
+{
+ if constexpr(JucePlugin_IsSynth)
+ setLatencySamples(m_plugin.getLatencyMidiToOutput());
+ else
+ setLatencySamples(m_plugin.getLatencyInputToOutput());
+}
+
Virus::Controller &AudioPluginAudioProcessor::getController()
{
if (m_controller == nullptr)
diff --git a/source/jucePlugin/PluginProcessor.h b/source/jucePlugin/PluginProcessor.h
@@ -63,6 +63,9 @@ public:
std::string getRomName() {
return juce::File(juce::String(m_romName)).getFileNameWithoutExtension().toStdString();
}
+
+ void updateLatencySamples();
+
// _____________
//
private:
diff --git a/source/synthLib/plugin.cpp b/source/synthLib/plugin.cpp
@@ -16,7 +16,6 @@ using namespace synthLib;
namespace synthLib
{
constexpr uint8_t g_stateVersion = 1;
- constexpr uint32_t g_extraLatencyBlocks = 1;
Plugin::Plugin(Device* _device) : m_device(_device)
{
@@ -137,6 +136,18 @@ namespace synthLib
m_midiIn.push_back(_ev);
}
+ bool Plugin::setLatencyBlocks(uint32_t _latencyBlocks)
+ {
+ std::lock_guard lock(m_lock);
+
+ if(m_extraLatencyBlocks == _latencyBlocks)
+ return false;
+
+ m_extraLatencyBlocks = _latencyBlocks;
+ updateDeviceLatency();
+ return true;
+ }
+
void Plugin::processMidiClock(float _bpm, float _ppqPos, bool _isPlaying, size_t _sampleCount)
{
if(_bpm < 1.0f)
@@ -214,7 +225,7 @@ namespace synthLib
if(m_blockSize <= 0 || m_hostSamplerate <= 0)
return;
- const auto latency = static_cast<uint32_t>(std::ceil(static_cast<float>(m_blockSize * g_extraLatencyBlocks) * m_device->getSamplerate() * m_hostSamplerateInv));
+ const auto latency = static_cast<uint32_t>(std::ceil(static_cast<float>(m_blockSize * m_extraLatencyBlocks) * m_device->getSamplerate() * m_hostSamplerateInv));
m_device->setExtraLatencySamples(latency);
m_deviceLatencyMidiToOutput = static_cast<uint32_t>(static_cast<float>(m_device->getInternalLatencyMidiToOutput()) * m_hostSamplerate / m_device->getSamplerate());
@@ -278,12 +289,12 @@ namespace synthLib
uint32_t Plugin::getLatencyMidiToOutput() const
{
std::lock_guard lock(m_lock);
- return m_blockSize * g_extraLatencyBlocks + m_deviceLatencyMidiToOutput + m_resampler.getOutputLatency();
+ return m_blockSize * m_extraLatencyBlocks + m_deviceLatencyMidiToOutput + m_resampler.getOutputLatency();
}
uint32_t Plugin::getLatencyInputToOutput() const
{
std::lock_guard lock(m_lock);
- return m_blockSize * g_extraLatencyBlocks + m_deviceLatencyInputToOutput + m_resampler.getOutputLatency() + m_resampler.getInputLatency();
+ return m_blockSize * m_extraLatencyBlocks + m_deviceLatencyInputToOutput + m_resampler.getOutputLatency() + m_resampler.getInputLatency();
}
}
diff --git a/source/synthLib/plugin.h b/source/synthLib/plugin.h
@@ -36,6 +36,9 @@ namespace synthLib
void insertMidiEvent(const SMidiEvent& _ev);
+ bool setLatencyBlocks(uint32_t _latencyBlocks);
+ uint32_t getLatencyBlocks() const { return m_extraLatencyBlocks; }
+
private:
void processMidiClock(float _bpm, float _ppqPos, bool _isPlaying, size_t _sampleCount);
float* getDummyBuffer(size_t _minimumSize);
@@ -69,5 +72,6 @@ namespace synthLib
bool m_isPlaying = false;
bool m_needsStart = false;
double m_clockTickPos = 0.0;
+ uint32_t m_extraLatencyBlocks = 1;
};
}