commit 4726aa34a9db4934b8b917e221a91146dfda058c
parent 76ac813f6f56cbc2acce5f143cf4afd6138c536c
Author: jatinchowdhury18 <[email protected]>
Date: Sun, 16 Aug 2020 14:56:57 -0700
Fixing loss filter sliders and tooltip labels (#70)
* Fix loss filter slider ranges and labels
* Fix tooltip names not always showing up
Co-authored-by: jatinchowdhury18 <[email protected]>
Diffstat:
6 files changed, 195 insertions(+), 158 deletions(-)
diff --git a/Plugin/CHOWTapeModel.jucer b/Plugin/CHOWTapeModel.jucer
@@ -71,6 +71,7 @@
</GROUP>
<GROUP id="{37F4BCFA-28D3-CD4D-17AF-3C696E7EC8DA}" name="Loss_Effects">
<FILE id="gJA2Gi" name="FIRFilter.h" compile="0" resource="0" file="Source/Processors/Loss_Effects/FIRFilter.h"/>
+ <FILE id="gjr7ub" name="LossFilter.cpp" compile="1" resource="0" file="Source/Processors/Loss_Effects/LossFilter.cpp"/>
<FILE id="ZNErgZ" name="LossFilter.h" compile="0" resource="0" file="Source/Processors/Loss_Effects/LossFilter.h"/>
</GROUP>
<GROUP id="{0C000F30-53FD-3EFB-FAEA-6321B08AE56A}" name="Timing_Effects">
diff --git a/Plugin/Source/GUI/Assets/gui.xml b/Plugin/Source/GUI/Assets/gui.xml
@@ -65,17 +65,17 @@
<View flex-direction="column" tab-caption="Loss" tab-color="" background-color="FF31323A"
padding="0" margin="0">
<View flex-grow="0.1" background-color="00000000"/>
- <Slider caption="Gap [mm]" parameter="gap" slider-type="linear-horizontal"
+ <Slider caption="Gap [cm]" parameter="gap" slider-type="linear-horizontal"
class="Slider" padding="0" slider-background="ff595c6b" slider-track="ff9cbcbd"
name="Gap" tooltip="Sets the width of the playhead gap. Certain frequencies that resonate with the gap width will be emphasized."
slidertext-height="18" caption-placement="top-left"/>
<View flex-grow="0.2" background-color="00000000"/>
- <Slider caption="Thickness [mm]" parameter="thick" class="Slider" slider-type="linear-horizontal"
+ <Slider caption="Thickness [cm]" parameter="thick" class="Slider" slider-type="linear-horizontal"
padding="0" slider-background="ff595c6b" slider-track="ff9cbcbd"
name="Thickness" tooltip="Sets the thickness of the tape. Thicker tape has a more muted high-frequency response."
caption-placement="top-left"/>
<View flex-grow="0.2" background-color="00000000"/>
- <Slider caption="Spacing [mm]" parameter="spacing" slider-type="linear-horizontal"
+ <Slider caption="Spacing [cm]" parameter="spacing" slider-type="linear-horizontal"
class="Slider" padding="0" slider-background="ff595c6b" slider-track="ff9cbcbd"
name="Spacing" tooltip="Sets the spacing between the tape and the playhead. A larger spacing means more high frequency signal is lost during playback."
caption-placement="top-left"/>
diff --git a/Plugin/Source/GUI/TooltipComp.cpp b/Plugin/Source/GUI/TooltipComp.cpp
@@ -36,17 +36,20 @@ void TooltipComponent::paint (Graphics& g)
}
}
-String TooltipComponent::getTipFor (Component& c)
+void TooltipComponent::getTipFor (Component& c, String& newTip, String& newName)
{
if (Process::isForegroundProcess()
&& ! ModifierKeys::currentModifiers.isAnyMouseButtonDown())
{
if (auto* ttc = dynamic_cast<TooltipClient*> (&c))
+ {
if (! c.isCurrentlyBlockedByAnotherModalComponent())
- return ttc->getTooltip();
+ {
+ newTip = ttc->getTooltip();
+ newName = c.getName();
+ }
+ }
}
-
- return {};
}
void TooltipComponent::timerCallback()
@@ -59,11 +62,18 @@ void TooltipComponent::timerCallback()
bool needsRepaint = false;
if (newComp != nullptr)
{
- auto newTip = getTipFor (*newComp);
+ String newTip, newName;
+ getTipFor (*newComp, newTip, newName);
needsRepaint = newTip != tip;
+ if (newTip.isNotEmpty() && newName.isEmpty())
+ {
+ if (auto parent = newComp->getParentComponent())
+ newName = parent->getName();
+ }
+
tip = newTip;
- name = newComp->getName();
+ name = newName;
if (! showTip.load())
{
diff --git a/Plugin/Source/GUI/TooltipComp.h b/Plugin/Source/GUI/TooltipComp.h
@@ -18,7 +18,7 @@ public:
void paint (Graphics& g) override;
void timerCallback() override;
- String getTipFor (Component& c);
+ void getTipFor (Component& c, String& newTip, String& newName);
private:
String name, tip;
diff --git a/Plugin/Source/Processors/Loss_Effects/LossFilter.cpp b/Plugin/Source/Processors/Loss_Effects/LossFilter.cpp
@@ -0,0 +1,169 @@
+#include "LossFilter.h"
+
+LossFilter::LossFilter (AudioProcessorValueTreeState& vts, int order) :
+ order (order)
+{
+ speed = vts.getRawParameterValue ("speed");
+ spacing = vts.getRawParameterValue ("spacing");
+ thickness = vts.getRawParameterValue ("thick");
+ gap = vts.getRawParameterValue ("gap");
+
+ filters.add (new FIRFilter (order));
+ filters.add (new FIRFilter (order));
+
+ currentCoefs.resize (order);
+}
+
+void LossFilter::createParameterLayout (std::vector<std::unique_ptr<RangedAudioParameter>>& params)
+{
+ constexpr float minDist = (float) 1.0e-6;
+ constexpr float centreSkew = 5.0f;
+
+ auto valueToString = [] (float value, int) { return String (10.0f * value, 5); };
+ auto stringToValue = [] (const String& text) { return text.getFloatValue() / 10.0f; };
+
+ NormalisableRange<float> speedRange (1.0f, 100.0f); // meters per second
+ speedRange.setSkewForCentre (15.0f);
+
+ NormalisableRange<float> spaceRange (minDist, 100.0f);
+ spaceRange.setSkewForCentre (centreSkew);
+
+ NormalisableRange<float> thickRange (minDist, 10.0f);
+ thickRange.setSkewForCentre (centreSkew);
+
+ NormalisableRange<float> gapRange (minDist, 100.0f);
+ gapRange.setSkewForCentre (centreSkew);
+
+ params.push_back (std::make_unique<AudioParameterFloat> ("speed", "Speed [ips]",
+ speedRange, 15.0f, String(), AudioProcessorParameter::genericParameter,
+ [] (float value, int) { return String (value, 4); }));
+
+ params.push_back (std::make_unique<AudioParameterFloat> ("spacing", "Spacing [cm]",
+ spaceRange, minDist, String(), AudioProcessorParameter::genericParameter,
+ valueToString, stringToValue));
+
+ params.push_back (std::make_unique<AudioParameterFloat> ("thick", "Thickness [cm]",
+ thickRange, minDist, String(), AudioProcessorParameter::genericParameter,
+ valueToString, stringToValue));
+
+ params.push_back (std::make_unique<AudioParameterFloat> ("gap", "Gap",
+ gapRange, minDist, String(), AudioProcessorParameter::genericParameter,
+ valueToString, stringToValue));
+}
+
+void LossFilter::prepare (float sampleRate, int samplesPerBlock)
+{
+ fs = sampleRate;
+ fadeBuffer.setSize (1, samplesPerBlock);
+
+ fsFactor = (float) fs / 44100.0f;
+ const int curOrder = int (order * fsFactor);
+ filters.clear();
+ filters.add (new FIRFilter (curOrder));
+ filters.add (new FIRFilter (curOrder));
+ currentCoefs.resize (curOrder);
+
+ filters[0]->reset();
+ filters[1]->reset();
+
+ calcCoefs();
+ filters[0]->setCoefs (currentCoefs.getRawDataPointer());
+ filters[1]->setCoefs (currentCoefs.getRawDataPointer());
+
+ prevSpeed = *speed;
+ prevSpacing = *spacing;
+ prevThickness = *thickness;
+ prevGap = *gap;
+
+ starting = true;
+}
+
+void LossFilter::calcCoefs()
+{
+ // Set freq domain multipliers
+ const int curOrder = int (order * fsFactor);
+ binWidth = fs / (float) curOrder;
+ std::unique_ptr<float[]> H (new float[curOrder]);
+ for (int k = 0; k < curOrder / 2; k++)
+ {
+ const auto freq = ((float) k * binWidth); // + (binWidth / 2.0f);
+ const auto waveNumber = MathConstants<float>::twoPi * jmax (freq, 20.0f) / (*speed * 0.0254f);
+ const auto thickTimesK = waveNumber * (*thickness * (float) 1.0e-3);
+ const auto kGapOverTwo = waveNumber * (*gap * (float) 1.0e-3) / 2.0f;
+
+ H[k] = expf (-1.0f * waveNumber * (*spacing * (float) 1.0e-3)); // Spacing loss formula
+ H[k] *= (1.0f - expf (-thickTimesK)) / thickTimesK;
+ H[k] *= sinf (kGapOverTwo) / kGapOverTwo;
+ H[curOrder - k - 1] = H[k];
+ }
+
+ // Create time domain filter signals
+ auto h = currentCoefs.getRawDataPointer();
+ for (int n = 0; n < curOrder; n++)
+ {
+ for (int k = 0; k < curOrder; k++)
+ h[n] += H[k] * cosf (MathConstants<float>::twoPi * (float) k * (float) n / (float) curOrder);
+
+ h[n] /= (float) curOrder;
+ }
+}
+
+void LossFilter::processBlock (float* buffer, const int numSamples)
+{
+ if (*spacing == (float) 1.0e-6 && *thickness == (float) 1.0e-6 && *gap == (float) 1.0e-6
+ && *spacing == prevSpacing && *thickness == prevThickness && *gap == prevGap)
+ {
+ filters[activeFilter]->processBypassed (buffer, numSamples);
+ return;
+ }
+
+ if ((*speed != prevSpeed || *spacing != prevSpacing ||
+ *thickness != prevThickness || *gap != prevGap) && fadeCount == 0)
+ {
+ calcCoefs();
+ filters[! activeFilter]->setCoefs (currentCoefs.getRawDataPointer());
+
+ fadeCount = fadeLength;
+ prevSpeed = *speed;
+ prevSpacing = *spacing;
+ prevThickness = *thickness;
+ prevGap = *gap;
+ }
+
+ if (fadeCount > 0)
+ {
+ fadeBuffer.setSize (1, numSamples, false, false, true);
+ fadeBuffer.copyFrom (0, 0, buffer, numSamples);
+ }
+ else
+ {
+ filters[! activeFilter]->processBypassed (buffer, numSamples);
+ }
+
+ if (! starting)
+ filters[activeFilter]->process (buffer, numSamples);
+ else
+ {
+ starting = false;
+ filters[activeFilter]->processBypassed (buffer, numSamples);
+ }
+
+ if (fadeCount > 0)
+ {
+ auto* fadePtr = fadeBuffer.getWritePointer (0);
+ filters[! activeFilter]->process (fadePtr, numSamples);
+
+ for (int n = 0; n < numSamples; ++n)
+ {
+ float mult = (float) fadeCount / (float) fadeLength;
+ buffer[n] = buffer[n] * mult + fadePtr[n] * (1.0f - mult);
+
+ fadeCount--;
+ if (fadeCount == 0)
+ break;
+ }
+
+ if (fadeCount == 0)
+ activeFilter = ! activeFilter;
+ }
+}
diff --git a/Plugin/Source/Processors/Loss_Effects/LossFilter.h b/Plugin/Source/Processors/Loss_Effects/LossFilter.h
@@ -6,157 +6,14 @@
class LossFilter
{
public:
- LossFilter (AudioProcessorValueTreeState& vts, int order = 100) :
- order (order)
- {
- speed = vts.getRawParameterValue ("speed");
- spacing = vts.getRawParameterValue ("spacing");
- thickness = vts.getRawParameterValue ("thick");
- gap = vts.getRawParameterValue ("gap");
-
- filters.add (new FIRFilter (order));
- filters.add (new FIRFilter (order));
-
- currentCoefs.resize (order);
- }
+ LossFilter (AudioProcessorValueTreeState& vts, int order = 100);
~LossFilter() {}
- static void createParameterLayout (std::vector<std::unique_ptr<RangedAudioParameter>>& params)
- {
- NormalisableRange<float> speedRange (1.0f, 100.0f); // meters per second
- speedRange.setSkewForCentre (15.0f);
-
- NormalisableRange<float> spaceRange ((float) 1.0e-6, 100.0f);
- spaceRange.setSkewForCentre ((float) 1.0);
-
- NormalisableRange<float> thickRange ((float) 1.0e-6, 10.0f);
- thickRange.setSkewForCentre (0.0001f);
-
- NormalisableRange<float> gapRange ((float) 1.0e-6, 100.0f);
- gapRange.setSkewForCentre ((float) 1.0e-3);
-
- params.push_back (std::make_unique<AudioParameterFloat> ("speed", "Speed [ips]", speedRange, 15.0f));
- params.push_back (std::make_unique<AudioParameterFloat> ("spacing", "Spacing [mm]", spaceRange, (float) 1.0e-9));
- params.push_back (std::make_unique<AudioParameterFloat> ("thick", "Thickness [mm]", thickRange, (float) 1.0e-9));
- params.push_back (std::make_unique<AudioParameterFloat> ("gap", "Gap", gapRange, (float) 1.0e-9));
- }
-
- void prepare (float sampleRate, int samplesPerBlock)
- {
- fs = sampleRate;
- fadeBuffer.setSize (1, samplesPerBlock);
-
- fsFactor = (float) fs / 44100.0f;
- const int curOrder = int (order * fsFactor);
- filters.clear();
- filters.add (new FIRFilter (curOrder));
- filters.add (new FIRFilter (curOrder));
- currentCoefs.resize (curOrder);
-
- filters[0]->reset();
- filters[1]->reset();
-
- calcCoefs();
- filters[0]->setCoefs (currentCoefs.getRawDataPointer());
- filters[1]->setCoefs (currentCoefs.getRawDataPointer());
-
- prevSpeed = *speed;
- prevSpacing = *spacing;
- prevThickness = *thickness;
- prevGap = *gap;
-
- starting = true;
- }
-
- void calcCoefs()
- {
- // Set freq domain multipliers
- const int curOrder = int (order * fsFactor);
- binWidth = fs / (float) curOrder;
- std::unique_ptr<float[]> H (new float[curOrder]);
- for (int k = 0; k < curOrder / 2; k++)
- {
- const auto freq = ((float) k * binWidth); // + (binWidth / 2.0f);
- const auto waveNumber = MathConstants<float>::twoPi * jmax (freq, 20.0f) / (*speed * 0.0254f);
- const auto thickTimesK = waveNumber * (*thickness * (float) 1.0e-3);
- const auto kGapOverTwo = waveNumber * (*gap * (float) 1.0e-3) / 2.0f;
-
- H[k] = expf (-1.0f * waveNumber * (*spacing * (float) 1.0e-3)); // Spacing loss formula
- H[k] *= (1.0f - expf (-thickTimesK)) / thickTimesK;
- H[k] *= sinf (kGapOverTwo) / kGapOverTwo;
- H[curOrder - k - 1] = H[k];
- }
-
- // Create time domain filter signals
- auto h = currentCoefs.getRawDataPointer();
- for (int n = 0; n < curOrder; n++)
- {
- for (int k = 0; k < curOrder; k++)
- h[n] += H[k] * cosf (MathConstants<float>::twoPi * (float) k * (float) n / (float) curOrder);
-
- h[n] /= (float) curOrder;
- }
- }
-
- inline void processBlock (float* buffer, const int numSamples)
- {
- if (*spacing == (float) 1.0e-6 && *thickness == (float) 1.0e-6 && *gap == (float) 1.0e-6
- && *spacing == prevSpacing && *thickness == prevThickness && *gap == prevGap)
- {
- filters[activeFilter]->processBypassed (buffer, numSamples);
- return;
- }
-
- if ((*speed != prevSpeed || *spacing != prevSpacing ||
- *thickness != prevThickness || *gap != prevGap) && fadeCount == 0)
- {
- calcCoefs();
- filters[! activeFilter]->setCoefs (currentCoefs.getRawDataPointer());
-
- fadeCount = fadeLength;
- prevSpeed = *speed;
- prevSpacing = *spacing;
- prevThickness = *thickness;
- prevGap = *gap;
- }
+ static void createParameterLayout (std::vector<std::unique_ptr<RangedAudioParameter>>& params);
- if (fadeCount > 0)
- {
- fadeBuffer.setSize (1, numSamples, false, false, true);
- fadeBuffer.copyFrom (0, 0, buffer, numSamples);
- }
- else
- {
- filters[! activeFilter]->processBypassed (buffer, numSamples);
- }
-
- if (! starting)
- filters[activeFilter]->process (buffer, numSamples);
- else
- {
- starting = false;
- filters[activeFilter]->processBypassed (buffer, numSamples);
- }
-
- if (fadeCount > 0)
- {
- auto* fadePtr = fadeBuffer.getWritePointer (0);
- filters[! activeFilter]->process (fadePtr, numSamples);
-
- for (int n = 0; n < numSamples; ++n)
- {
- float mult = (float) fadeCount / (float) fadeLength;
- buffer[n] = buffer[n] * mult + fadePtr[n] * (1.0f - mult);
-
- fadeCount--;
- if (fadeCount == 0)
- break;
- }
-
- if (fadeCount == 0)
- activeFilter = ! activeFilter;
- }
- }
+ void prepare (float sampleRate, int samplesPerBlock);
+ void calcCoefs();
+ void processBlock (float* buffer, const int numSamples);
private:
OwnedArray<FIRFilter> filters;