commit 6143c902d78edbe343dcb8692eac6a78339dc981
parent e72f08bdeebc629c9ea97587d104abfc83b3ee20
Author: jatinchowdhury18 <jatinchowdhury18@users.noreply.github.com>
Date: Wed, 13 May 2020 11:11:52 -0700
Use alpha transform instead of bilinear to allow 1x oversampling
Diffstat:
4 files changed, 17 insertions(+), 22 deletions(-)
diff --git a/Plugin/Source/Processors/Hysteresis/HysteresisProcessing.cpp b/Plugin/Source/Processors/Hysteresis/HysteresisProcessing.cpp
@@ -63,7 +63,8 @@ inline float HysteresisProcessing::langevinD (float x)
inline float HysteresisProcessing::deriv (float x_n, float x_n1, float x_d_n1)
{
- return (twoFs * (x_n - x_n1)) - x_d_n1;
+ constexpr float dAlpha = 0.9f;
+ return (((1.0f + dAlpha) / T) * (x_n - x_n1)) - dAlpha * x_d_n1;
}
inline float HysteresisProcessing::hysteresisFunc (float M, float H, float H_d)
diff --git a/Plugin/Source/Processors/Hysteresis/HysteresisProcessing.h b/Plugin/Source/Processors/Hysteresis/HysteresisProcessing.h
@@ -17,20 +17,20 @@ public:
float process (float H);
void reset();
- void setSampleRate (float newSR) { fs = newSR; T = 1.0f / fs; twoFs = 2.0f * fs; }
+ void setSampleRate (float newSR) { fs = newSR; T = 1.0f / fs; }
void cook (float drive, float width, float sat);
private:
- /* Continued fraction approximation for hyperbolic cotangent */
+ /* DEPRECATED (Continued fraction approximation for hyperbolic cotangent) */
inline float cothApprox (float x);
inline float langevin (float x); // Langevin function
inline float langevinD (float x); // Derivative of Langevin function
- inline float deriv (float x_n, float x_n1, float x_d_n1); // Derivative by trapezoidal rule
+ inline float deriv (float x_n, float x_n1, float x_d_n1); // Derivative by alpha transform
inline float hysteresisFunc (float M, float H, float H_d);
- float M_n (float M_n1, float k1, float k2, float k3, float k4);
+ float M_n (float M_n1, float k1, float k2, float k3, float k4); // DEPRECATED (from RK4 version)
float fs = 48000.0f;
float T = 1.0f / fs;
@@ -41,7 +41,6 @@ private:
float c = (float) 1.7e-1;
// Save calculations
- float twoFs = 2.0f * fs;
float nc = 1-c;
float M_s_oa = M_s / a;
float M_s_oa_tc = c * M_s / a;
diff --git a/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.cpp b/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.cpp
@@ -13,10 +13,9 @@ HysteresisProcessor::HysteresisProcessor (AudioProcessorValueTreeState& vts)
widthParam = vts.getRawParameterValue ("width");
osParam = vts.getRawParameterValue ("os");
- overSample[0].reset (new dsp::Oversampling<float> (2, 1, dsp::Oversampling<float>::filterHalfBandPolyphaseIIR));
- overSample[1].reset (new dsp::Oversampling<float> (2, 2, dsp::Oversampling<float>::filterHalfBandPolyphaseIIR));
- overSample[2].reset (new dsp::Oversampling<float> (2, 3, dsp::Oversampling<float>::filterHalfBandPolyphaseIIR));
- overSample[3].reset (new dsp::Oversampling<float> (2, 4, dsp::Oversampling<float>::filterHalfBandPolyphaseIIR));
+ for (int i = 0; i < 5; ++i)
+ overSample[i] = std::make_unique<dsp::Oversampling<float>>
+ (2, i, dsp::Oversampling<float>::filterHalfBandPolyphaseIIR);
for (int ch = 0; ch < 2; ++ch)
{
@@ -33,7 +32,7 @@ void HysteresisProcessor::createParameterLayout (std::vector<std::unique_ptr<Ran
params.push_back (std::make_unique<AudioParameterFloat> ("sat", "Saturation", 0.0f, 1.0f, 0.5f));
params.push_back (std::make_unique<AudioParameterFloat> ("width", "Bias", 0.0f, 1.0f, 0.5f));
- params.push_back (std::make_unique<AudioParameterChoice> ("os", "Oversampling", StringArray ({"2x", "4x", "8x", "16x"}), 0));
+ params.push_back (std::make_unique<AudioParameterChoice> ("os", "Oversampling", StringArray ({"1x", "2x", "4x", "8x", "16x"}), 1));
}
float HysteresisProcessor::calcMakeup()
@@ -78,7 +77,7 @@ void HysteresisProcessor::toggleOnOff (bool shouldBeOn)
void HysteresisProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
fs = (float) sampleRate;
- overSamplingFactor = (int) powf(2.0f, *osParam + 1);
+ overSamplingFactor = (int) powf(2.0f, *osParam);
for (int ch = 0; ch < 2; ++ch)
{
@@ -92,10 +91,8 @@ void HysteresisProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
hProcs[ch].reset();
}
- overSample[0]->initProcessing (samplesPerBlock);
- overSample[1]->initProcessing (samplesPerBlock);
- overSample[2]->initProcessing (samplesPerBlock);
- overSample[3]->initProcessing (samplesPerBlock);
+ for (int i = 0; i < 5; ++i)
+ overSample[i]->initProcessing (samplesPerBlock);
prevOS = (int) *osParam;
dcBlocker[0].reset (sampleRate);
@@ -116,10 +113,8 @@ void HysteresisProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
void HysteresisProcessor::releaseResources()
{
- overSample[0]->reset();
- overSample[1]->reset();
- overSample[2]->reset();
- overSample[3]->reset();
+ for (int i = 0; i < 5; ++i)
+ overSample[i]->reset();
}
void HysteresisProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& /*midi*/)
@@ -130,7 +125,7 @@ void HysteresisProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer&
if ((int) *osParam != prevOS)
{
- overSamplingFactor = (int) powf(2.0f, *osParam + 1);
+ overSamplingFactor = (int) powf(2.0f, *osParam);
prevOS = (int) *osParam;
for (int ch = 0; ch < 2; ++ch)
diff --git a/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.h b/Plugin/Source/Processors/Hysteresis/HysteresisProcessor.h
@@ -148,7 +148,7 @@ private:
float fs = 44100.0f;
int prevOS = 0;
HysteresisProcessing hProcs[2];
- std::unique_ptr<dsp::Oversampling<float>> overSample[4]; // needs oversampling to avoid aliasing
+ std::unique_ptr<dsp::Oversampling<float>> overSample[5]; // needs oversampling to avoid aliasing
TransformerHPF dcBlocker[2];
// TransformerShelf dcLower[2];