-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Copied the BigMuffDrive with a new name * Register the new drive * Rename without the drive * Make the MuffClipper single-stage * Optimistically add parameters * Implement asymmetric clipping * Rescaled the smoothing parameter * cosh as true derivative of sinh * Add myself to the authors for this module * Added a preset with the new module * make the metadata more like the things already there * Listed a Violet Mist in the preset manager * Another preset * Metadata for the new new preset * Small cleanup and optimizations * Fixed +/- clips for the signal getting inverted * rebrand the new presets Co-authored-by: Jatin Chowdhury <[email protected]>
- Loading branch information
1 parent
f8f673e
commit d369246
Showing
10 changed files
with
534 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<Preset name="Gainful Clipper" plugin="BYOD" vendor="x31eq" category="Pedals" | ||
version="1.1.0"> | ||
<proc_chain state_plugin_version="1.1.0"> | ||
<Muff_Tone> | ||
<Parameters x_pos="0.6112957000732422" y_pos="0.2140151560306549"> | ||
<PARAM id="mids" value="0.3120000660419464"/> | ||
<PARAM id="on_off" value="1.0"/> | ||
<PARAM id="tone" value="0.5560000538825989"/> | ||
<PARAM id="type" value="8.0"/> | ||
</Parameters> | ||
<port_0 connection_0="-1" connection_end_0="0"/> | ||
</Muff_Tone> | ||
<Muff_Clipper> | ||
<Parameters x_pos="0.1436877101659775" y_pos="0.5151515007019043"> | ||
<PARAM id="clip1" value="0.355555534362793"/> | ||
<PARAM id="clip2" value="0.644444465637207"/> | ||
<PARAM id="harmonics" value="0.7555555701255798"/> | ||
<PARAM id="high_q" value="1.0"/> | ||
<PARAM id="level" value="0.6499999761581421"/> | ||
<PARAM id="on_off" value="1.0"/> | ||
<PARAM id="scream" value="0.0"/> | ||
<PARAM id="smoothing" value="-0.199999988079071"/> | ||
<PARAM id="sustain" value="0.7888888716697693"/> | ||
</Parameters> | ||
<port_0 connection_0="2" connection_end_0="0"/> | ||
</Muff_Clipper> | ||
<Muff_Clipper> | ||
<Parameters x_pos="0.3554817140102386" y_pos="0.07196969538927078"> | ||
<PARAM id="clip1" value="0.2666666507720947"/> | ||
<PARAM id="clip2" value="0.08888888359069824"/> | ||
<PARAM id="harmonics" value="0.6555555462837219"/> | ||
<PARAM id="high_q" value="1.0"/> | ||
<PARAM id="level" value="0.7222222089767456"/> | ||
<PARAM id="on_off" value="1.0"/> | ||
<PARAM id="scream" value="0.0"/> | ||
<PARAM id="smoothing" value="0.4666666984558105"/> | ||
<PARAM id="sustain" value="0.8333333134651184"/> | ||
</Parameters> | ||
<port_0 connection_0="0" connection_end_0="0"/> | ||
</Muff_Clipper> | ||
<Input> | ||
<Parameters x_pos="0.01197604835033417" y_pos="0.1228070184588432"> | ||
<PARAM id="on_off" value="1.0"/> | ||
</Parameters> | ||
<port_0 connection_0="1" connection_end_0="0"/> | ||
</Input> | ||
<Output> | ||
<Parameters x_pos="0.8999999761581421" y_pos="0.112648218870163"> | ||
<PARAM id="on_off" value="1.0"/> | ||
</Parameters> | ||
</Output> | ||
</proc_chain> | ||
<extra_info/> | ||
</Preset> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<Preset name="Violet Mist" plugin="BYOD" vendor="x31eq" category="Pedals" | ||
version="1.1.0"> | ||
<proc_chain state_plugin_version="1.1.0"> | ||
<Muff_Tone> | ||
<Parameters x_pos="0.579734206199646" y_pos="0.3162878751754761"> | ||
<PARAM id="mids" value="0.5"/> | ||
<PARAM id="on_off" value="1.0"/> | ||
<PARAM id="tone" value="0.5"/> | ||
<PARAM id="type" value="1.0"/> | ||
</Parameters> | ||
<port_0 connection_0="-1" connection_end_0="0"/> | ||
</Muff_Tone> | ||
<Muff_Clipper> | ||
<Parameters x_pos="0.1644518226385117" y_pos="0.1780302971601486"> | ||
<PARAM id="clip1" value="-0.3777777552604675"/> | ||
<PARAM id="clip2" value="-0.3111110925674438"/> | ||
<PARAM id="harmonics" value="0.8888888955116272"/> | ||
<PARAM id="high_q" value="1.0"/> | ||
<PARAM id="level" value="0.4888888895511627"/> | ||
<PARAM id="on_off" value="1.0"/> | ||
<PARAM id="smoothing" value="-0.04444444179534912"/> | ||
<PARAM id="sustain" value="0.5"/> | ||
</Parameters> | ||
<port_0 connection_0="2" connection_end_0="0"/> | ||
</Muff_Clipper> | ||
<Muff_Clipper> | ||
<Parameters x_pos="0.3197674453258514" y_pos="0.564393937587738"> | ||
<PARAM id="clip1" value="0.4444444179534912"/> | ||
<PARAM id="clip2" value="0.2666666507720947"/> | ||
<PARAM id="harmonics" value="0.2666666805744171"/> | ||
<PARAM id="high_q" value="1.0"/> | ||
<PARAM id="level" value="0.7444444298744202"/> | ||
<PARAM id="on_off" value="1.0"/> | ||
<PARAM id="smoothing" value="0.355555534362793"/> | ||
<PARAM id="sustain" value="0.4777777791023254"/> | ||
</Parameters> | ||
<port_0 connection_0="0" connection_end_0="0"/> | ||
</Muff_Clipper> | ||
<Input> | ||
<Parameters x_pos="0.005020080134272575" y_pos="0.3221343755722046"> | ||
<PARAM id="on_off" value="1.0"/> | ||
</Parameters> | ||
<port_0 connection_0="1" connection_end_0="0"/> | ||
</Input> | ||
<Output> | ||
<Parameters x_pos="0.8594377636909485" y_pos="0.3221343755722046"> | ||
<PARAM id="on_off" value="1.0"/> | ||
</Parameters> | ||
</Output> | ||
</proc_chain> | ||
<extra_info/> | ||
</Preset> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
#include "MuffClipper.h" | ||
#include "../../ParameterHelpers.h" | ||
|
||
namespace | ||
{ | ||
const auto cutoffRange = ParameterHelpers::createNormalisableRange (500.0f, 22000.0f, 1200.0f); | ||
float harmParamToCutoffHz (float harmParam) | ||
{ | ||
return cutoffRange.convertFrom0to1 (harmParam); | ||
} | ||
|
||
const auto sustainRange = ParameterHelpers::createNormalisableRange (0.4f, 2.0f, 1.0f); | ||
const auto levelRange = ParameterHelpers::createNormalisableRange (-60.0f, 0.0f, -9.0f); | ||
} // namespace | ||
|
||
MuffClipper::MuffClipper (UndoManager* um) : BaseProcessor ("Muff Clipper", createParameterLayout(), um) | ||
{ | ||
using namespace ParameterHelpers; | ||
loadParameterPointer (sustainParam, vts, "sustain"); | ||
loadParameterPointer (harmParam, vts, "harmonics"); | ||
loadParameterPointer (levelParam, vts, "level"); | ||
clip1Param.setParameterHandle (getParameterPointer<chowdsp::FloatParameter*> (vts, "clip1")); | ||
clip2Param.setParameterHandle (getParameterPointer<chowdsp::FloatParameter*> (vts, "clip2")); | ||
smoothingParam.setParameterHandle (getParameterPointer<chowdsp::FloatParameter*> (vts, "smoothing")); | ||
hiQParam = vts.getRawParameterValue ("high_q"); | ||
|
||
addPopupMenuParameter ("high_q"); | ||
|
||
uiOptions.backgroundColour = Colours::darkgrey.brighter (0.3f).withRotatedHue (0.2f); | ||
uiOptions.powerColour = Colours::red.brighter (0.15f); | ||
uiOptions.info.description = "Fuzz effect based on a single drive stage from the Electro-Harmonix Big Muff Pi."; | ||
uiOptions.info.authors = StringArray { "Jatin Chowdhury", "Graham Breed" }; | ||
} | ||
|
||
ParamLayout MuffClipper::createParameterLayout() | ||
{ | ||
using namespace ParameterHelpers; | ||
|
||
auto params = createBaseParams(); | ||
|
||
createPercentParameter (params, "sustain", "Gain", 0.5f); | ||
createPercentParameter (params, "harmonics", "Harm.", 0.65f); | ||
createBipolarPercentParameter (params, "smoothing", "Smooth", 0.0f); | ||
createBipolarPercentParameter (params, "clip2", "+Clip", 0.0f); | ||
createBipolarPercentParameter (params, "clip1", "-Clip", 0.0f); | ||
createPercentParameter (params, "level", "Level", 0.65f); | ||
|
||
emplace_param<AudioParameterBool> (params, "high_q", "High Quality", true); | ||
|
||
return { params.begin(), params.end() }; | ||
} | ||
|
||
void MuffClipper::prepare (double sampleRate, int samplesPerBlock) | ||
{ | ||
fs = (float) sampleRate; | ||
|
||
cutoffSmooth.reset (sampleRate, 0.02); | ||
cutoffSmooth.setCurrentAndTargetValue (harmParamToCutoffHz (*harmParam)); | ||
for (auto& filt : inputFilter) | ||
{ | ||
filt.calcCoefs (cutoffSmooth.getTargetValue(), fs); | ||
filt.reset(); | ||
} | ||
|
||
clip1Param.setRampLength (0.05); | ||
clip1Param.mappingFunction = [] (float val) | ||
{ | ||
return MuffClipperStage::getClipV (val); | ||
}; | ||
clip1Param.prepare (sampleRate, samplesPerBlock); | ||
|
||
clip2Param.setRampLength (0.05); | ||
clip2Param.mappingFunction = [] (float val) | ||
{ | ||
return MuffClipperStage::getClipV (val); | ||
}; | ||
clip2Param.prepare (sampleRate, samplesPerBlock); | ||
|
||
smoothingParam.setRampLength (0.05); | ||
smoothingParam.mappingFunction = [fs = this->fs] (float val) | ||
{ | ||
return MuffClipperStage::getGC12 (fs, val); | ||
}; | ||
smoothingParam.prepare (sampleRate, samplesPerBlock); | ||
|
||
stage.prepare (sampleRate); | ||
|
||
auto spec = dsp::ProcessSpec { sampleRate, (uint32) samplesPerBlock, 2 }; | ||
|
||
sustainGain.prepare (spec); | ||
sustainGain.setRampDurationSeconds (0.02); | ||
|
||
outLevel.prepare (spec); | ||
outLevel.setRampDurationSeconds (0.02); | ||
|
||
for (auto& filt : dcBlocker) | ||
{ | ||
filt.calcCoefs (16.0f, fs); | ||
filt.reset(); | ||
} | ||
|
||
maxBlockSize = samplesPerBlock; | ||
doPrebuffering(); | ||
} | ||
|
||
void MuffClipper::doPrebuffering() | ||
{ | ||
AudioBuffer<float> buffer (2, maxBlockSize); | ||
for (int i = 0; i < 10000; i += maxBlockSize) | ||
{ | ||
buffer.clear(); | ||
processAudio (buffer); | ||
} | ||
} | ||
|
||
void MuffClipper::processInputStage (AudioBuffer<float>& buffer) | ||
{ | ||
const auto numChannels = buffer.getNumChannels(); | ||
const auto numSamples = buffer.getNumSamples(); | ||
|
||
cutoffSmooth.setTargetValue (harmParamToCutoffHz (*harmParam)); | ||
if (cutoffSmooth.isSmoothing()) | ||
{ | ||
if (numChannels == 1) | ||
{ | ||
auto* x = buffer.getWritePointer (0); | ||
for (int n = 0; n < numSamples; ++n) | ||
{ | ||
inputFilter[0].calcCoefs (cutoffSmooth.getNextValue(), fs); | ||
x[n] = inputFilter[0].processSample (x[n]); | ||
} | ||
} | ||
else if (numChannels == 2) | ||
{ | ||
auto* xL = buffer.getWritePointer (0); | ||
auto* xR = buffer.getWritePointer (1); | ||
for (int n = 0; n < numSamples; ++n) | ||
{ | ||
auto cutoffHz = cutoffSmooth.getNextValue(); | ||
|
||
inputFilter[0].calcCoefs (cutoffHz, fs); | ||
xL[n] = inputFilter[0].processSample (xL[n]); | ||
|
||
inputFilter[1].calcCoefs (cutoffHz, fs); | ||
xR[n] = inputFilter[1].processSample (xR[n]); | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
for (int ch = 0; ch < numChannels; ++ch) | ||
{ | ||
inputFilter[ch].calcCoefs (cutoffSmooth.getNextValue(), fs); | ||
inputFilter[ch].processBlock (buffer.getWritePointer (ch), numSamples); | ||
} | ||
} | ||
|
||
sustainGain.setGainLinear (sustainRange.convertFrom0to1 (*sustainParam)); | ||
dsp::AudioBlock<float> block { buffer }; | ||
sustainGain.process (dsp::ProcessContextReplacing<float> { block }); | ||
} | ||
|
||
void MuffClipper::processAudio (AudioBuffer<float>& buffer) | ||
{ | ||
const auto numChannels = buffer.getNumChannels(); | ||
const auto numSamples = buffer.getNumSamples(); | ||
|
||
processInputStage (buffer); | ||
|
||
clip1Param.process (numSamples); | ||
clip2Param.process (numSamples); | ||
smoothingParam.process (numSamples); | ||
const auto useHighQualityMode = hiQParam->load() == 1.0f; | ||
if (useHighQualityMode) | ||
{ | ||
stage.processBlock<true> (buffer, clip1Param, clip2Param, smoothingParam); | ||
} | ||
else | ||
{ | ||
stage.processBlock<false> (buffer, clip1Param, clip2Param, smoothingParam); | ||
} | ||
|
||
for (int ch = 0; ch < numChannels; ++ch) | ||
dcBlocker[ch].processBlock (buffer.getWritePointer (ch), numSamples); | ||
|
||
auto outGain = Decibels::decibelsToGain (levelRange.convertFrom0to1 (*levelParam), levelRange.start); | ||
outGain *= Decibels::decibelsToGain (13.0f); // makeup from level lost in clipping stage | ||
outGain *= -1.0f; | ||
outLevel.setGainLinear (outGain); | ||
dsp::AudioBlock<float> block { buffer }; | ||
outLevel.process (dsp::ProcessContextReplacing<float> { block }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#pragma once | ||
|
||
#include "../../BaseProcessor.h" | ||
#include "MuffClipperStage.h" | ||
|
||
class MuffClipper : public BaseProcessor | ||
{ | ||
public: | ||
explicit MuffClipper (UndoManager* um); | ||
|
||
ProcessorType getProcessorType() const override { return Drive; } | ||
static ParamLayout createParameterLayout(); | ||
|
||
void prepare (double sampleRate, int samplesPerBlock) override; | ||
void processAudio (AudioBuffer<float>& buffer) override; | ||
|
||
private: | ||
void doPrebuffering(); | ||
void processInputStage (AudioBuffer<float>& buffer); | ||
|
||
chowdsp::FloatParameter* sustainParam = nullptr; | ||
chowdsp::FloatParameter* harmParam = nullptr; | ||
chowdsp::FloatParameter* levelParam = nullptr; | ||
chowdsp::SmoothedBufferValue<float> clip1Param; | ||
chowdsp::SmoothedBufferValue<float> clip2Param; | ||
chowdsp::SmoothedBufferValue<float> smoothingParam; | ||
std::atomic<float>* hiQParam = nullptr; | ||
|
||
chowdsp::FirstOrderLPF<float> inputFilter[2]; | ||
SmoothedValue<float, ValueSmoothingTypes::Multiplicative> cutoffSmooth; | ||
dsp::Gain<float> sustainGain; | ||
|
||
MuffClipperStage stage; | ||
|
||
chowdsp::FirstOrderHPF<float> dcBlocker[2]; | ||
dsp::Gain<float> outLevel; | ||
|
||
float fs = 48000.0f; | ||
int maxBlockSize = 0; | ||
|
||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MuffClipper) | ||
}; |
Oops, something went wrong.