commit 59a2d201641f483153fa03041a28e7d2569bc22a
parent 07f07589865992ced56c7322658fbe5f7a20a510
Author: jatinchowdhury18 <jatinchowdhury18@gmail.com>
Date: Sun, 23 Aug 2020 17:54:50 -0700
Adjust dry/wet signal flow (#73)
* Adjust dry/wet signal flow
* Update Mac builds
* Add simple auto-update checking (#74)
* Add simple auto-update checking
* Update changelog
Co-authored-by: jatinchowdhury18 <jatinchowdhury18@users.noreply.github.com>
* Update latency compensation for dry/wet processing
* Update Mac builds
* Final tweaks to latency compensation
Co-authored-by: jatinchowdhury18 <jatinchowdhury18@users.noreply.github.com>
Co-authored-by: Travis CI <travis@Traviss-Mac-6.local>
Diffstat:
4 files changed, 31 insertions(+), 32 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
@@ -6,6 +6,7 @@ this file.
- Updated delay lines in wow/flutter processing to use 3-point
Lagrange interpolation.
- Change Newton-Raphson solver to use 4 or 8 iterations, in unrolled loop.
+- Adjust signal flow so that input/output gains apply only to the wet signal.
- Added simple behavior to automatically check for updates.
- Improved loss filter sliders.
- Fixed tooltip name sometimes not appearing.
diff --git a/Plugin/Source/PluginProcessor.cpp b/Plugin/Source/PluginProcessor.cpp
@@ -144,14 +144,12 @@ void ChowtapeModelAudioProcessor::prepareToPlay (double sampleRate, int samplesP
hysteresis.prepareToPlay (sampleRate, samplesPerBlock);
degrade.prepareToPlay (sampleRate, samplesPerBlock);
chewer.prepare (sampleRate);
+
+ dryDelay.prepare ({ sampleRate, (uint32) samplesPerBlock, 2 });
+ dryDelay.setDelay (calcLatencySamples());
for (int ch = 0; ch < 2; ++ch)
- {
- dryDelay[ch].prepareToPlay (sampleRate, samplesPerBlock);
- dryDelay[ch].setLengthMs (1000.0f * calcLatencySamples() / (float) sampleRate, true);
-
lossFilter[ch]->prepare ((float) sampleRate, samplesPerBlock);
- }
flutter.prepareToPlay (sampleRate, samplesPerBlock);
outGain.prepareToPlay (sampleRate, samplesPerBlock);
@@ -207,9 +205,8 @@ void ChowtapeModelAudioProcessor::processBlock (AudioBuffer<float>& buffer, Midi
outGain.setGain (Decibels::decibelsToGain (vts.getRawParameterValue ("outgain")->load()));
dryWet.setDryWet (*vts.getRawParameterValue ("drywet") / 100.0f);
- inGain.processBlock (buffer, midiMessages);
-
dryBuffer.makeCopyOf (buffer, true);
+ inGain.processBlock (buffer, midiMessages);
hysteresis.processBlock (buffer, midiMessages);
chewer.processBlock (buffer);
@@ -220,30 +217,31 @@ void ChowtapeModelAudioProcessor::processBlock (AudioBuffer<float>& buffer, Midi
for (int ch = 0; ch < buffer.getNumChannels(); ++ch)
lossFilter[ch]->processBlock (buffer.getWritePointer (ch), buffer.getNumSamples());
- // delay dry buffer to avoid phase issues
- const auto latencySamp = roundToInt (calcLatencySamples());
- setLatencySamples (latencySamp);
- for (int ch = 0; ch < buffer.getNumChannels(); ++ch)
- {
- auto* dryPtr = dryBuffer.getWritePointer (ch);
-
- // For "true bypass" use integer sample delay to avoid delay
- // line interpolation freq. response issues
- if (dryWet.getDryWet() < 0.2f)
- dryDelay[ch].setLengthMs (1000.0f * latencySamp / (float) getSampleRate());
- else
- dryDelay[ch].setLengthMs (1000.0f * calcLatencySamples() / (float) getSampleRate());
-
- for (int n = 0; n < dryBuffer.getNumSamples(); ++n)
- dryPtr[n] = dryDelay[ch].delay (dryPtr[n]);
- }
+ latencyCompensation();
- dryWet.processBlock (dryBuffer, buffer);
outGain.processBlock (buffer, midiMessages);
+ dryWet.processBlock (dryBuffer, buffer);
scope->pushSamples (buffer);
}
+void ChowtapeModelAudioProcessor::latencyCompensation()
+{
+ // delay dry buffer to avoid phase issues
+ const auto latencySamp = roundToInt (calcLatencySamples());
+ setLatencySamples (latencySamp);
+
+ // For "true bypass" use integer sample delay to avoid delay
+ // line interpolation freq. response issues
+ if (dryWet.getDryWet() < 0.15f)
+ dryDelay.setDelay ((float) latencySamp);
+ else
+ dryDelay.setDelay (calcLatencySamples());
+
+ dsp::AudioBlock<float> block { dryBuffer };
+ dryDelay.process (dsp::ProcessContextReplacing<float> { block });
+}
+
//==============================================================================
bool ChowtapeModelAudioProcessor::hasEditor() const
{
diff --git a/Plugin/Source/PluginProcessor.h b/Plugin/Source/PluginProcessor.h
@@ -67,12 +67,12 @@ public:
void getStateInformation (MemoryBlock& destData) override;
void setStateInformation (const void* data, int sizeInBytes) override;
- AudioProcessorValueTreeState::ParameterLayout createParameterLayout();
- AudioProcessorValueTreeState& getVTS() { return vts; }
-
PresetManager& getPresetManager() { return presetManager; }
-
+
private:
+ AudioProcessorValueTreeState::ParameterLayout createParameterLayout();
+ void latencyCompensation();
+
AudioProcessorValueTreeState vts;
GainProcessor inGain;
@@ -82,7 +82,7 @@ private:
std::unique_ptr<LossFilter> lossFilter[2];
Flutter flutter;
DryWetProcessor dryWet;
- DelayProcessor dryDelay[2];
+ dsp::DelayLine<float, dsp::DelayLineInterpolationTypes::Lagrange3rd> dryDelay { 1 << 21 };
GainProcessor outGain;
AudioBuffer<float> dryBuffer;
diff --git a/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.cpp b/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.cpp
@@ -151,8 +151,8 @@ void HysteresisProcessor::releaseResources()
float HysteresisProcessor::getLatencySamples() const noexcept
{
- // latency of oversampling + fudge factor for Runge-Kutta and hysteresis
- return overSample[curOS]->getLatencyInSamples() + 1.65f;
+ // latency of oversampling + fudge factor for hysteresis
+ return overSample[curOS]->getLatencyInSamples() + 1.4f;
}
void HysteresisProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& /*midi*/)