Skip to content

Commit

Permalink
Smooth muff (#244)
Browse files Browse the repository at this point in the history
* added instructions to at least compile

* set triangle capacitors

* Add parameter for the smoothing

* Take out the "Stages" heading

* Move the admittance to the process function

* Use the smoothing

* Use the smoothing

* Put smoothing before level

* Give the smoothing a wider range

* Change the build hint

* Revert "set triangle capacitors"

No need for this any more: it's a parameter

This reverts commit 927cb8b070f8e1c5f08e0f724178d08a25653038.

* Add parameter smoothing

* Revert expremental thing I was trying out (whoops)

* Added Big Muff variant presets and fixed smoother initialization bug

Co-authored-by: Jatin Chowdhury <jatinchowdhury18@gmail.com>
  • Loading branch information
x31eq and jatinchowdhury18 committed Dec 3, 2022
1 parent 961c088 commit daa1f2c
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 24 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,11 @@

All notable changes to this project will be documented in this file.

## [UNRELEASED]
- Added "Smoothing" parameter for "Muff Drive" module.
- Added new factory presets.
- Fixed parameter name changes not showing up in some CLAP hosts.

## [1.1.0] 2022-11-21
- Added support for the CLAP plugin format (with parameter modulation).
- Added modulation ports so modules with internal modulation can share modulation signals.
Expand Down
40 changes: 40 additions & 0 deletions res/presets/Big Muff (Ram's Head 56).chowpreset
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>

<Preset name="Big Muff (Ram's Head 56)" plugin="BYOD" vendor="CHOW" category="Pedals"
version="1.1.0">
<proc_chain state_plugin_version="1.1.0">
<Muff_Drive>
<Parameters x_pos="0.2234146296977997" y_pos="0.3075657784938812">
<PARAM id="harmonics" value="0.8799999952316284"/>
<PARAM id="level" value="0.6499999761581421"/>
<PARAM id="n_stages" value="1.0"/>
<PARAM id="on_off" value="1.0"/>
<PARAM id="sustain" value="0.5"/>
<PARAM id="high_q"/>
<PARAM id="smoothing" value="0.4550000429153442"/>
</Parameters>
<port_0 connection_0="1" connection_end_0="0"/>
</Muff_Drive>
<Muff_Tone>
<Parameters x_pos="0.5463414788246155" y_pos="0.320723682641983">
<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>
<Input>
<Parameters x_pos="0.005020080134272575" y_pos="0.3221343755722046">
<PARAM id="on_off" value="1.0"/>
</Parameters>
<port_0 connection_0="0" 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>
40 changes: 40 additions & 0 deletions res/presets/Big Muff (Russian).chowpreset
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>

<Preset name="Big Muff (Russian)" plugin="BYOD" vendor="CHOW" category="Pedals"
version="1.1.0">
<proc_chain state_plugin_version="1.1.0">
<Muff_Drive>
<Parameters x_pos="0.2234146296977997" y_pos="0.3075657784938812">
<PARAM id="harmonics" value="0.8799999952316284"/>
<PARAM id="level" value="0.6499999761581421"/>
<PARAM id="n_stages" value="1.0"/>
<PARAM id="on_off" value="1.0"/>
<PARAM id="sustain" value="0.5"/>
<PARAM id="high_q"/>
<PARAM id="smoothing" value="-0.2049999833106995"/>
</Parameters>
<port_0 connection_0="1" connection_end_0="0"/>
</Muff_Drive>
<Muff_Tone>
<Parameters x_pos="0.5463414788246155" y_pos="0.320723682641983">
<PARAM id="mids" value="0.5"/>
<PARAM id="on_off" value="1.0"/>
<PARAM id="tone" value="0.5"/>
<PARAM id="type" value="3.0"/>
</Parameters>
<port_0 connection_0="-1" connection_end_0="0"/>
</Muff_Tone>
<Input>
<Parameters x_pos="0.005020080134272575" y_pos="0.3221343755722046">
<PARAM id="on_off" value="1.0"/>
</Parameters>
<port_0 connection_0="0" 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>
40 changes: 40 additions & 0 deletions res/presets/Big Muff (Triangle).chowpreset
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>

<Preset name="Big Muff (Triangle)" plugin="BYOD" vendor="CHOW" category="Pedals"
version="1.1.0">
<proc_chain state_plugin_version="1.1.0">
<Muff_Drive>
<Parameters x_pos="0.2234146296977997" y_pos="0.3075657784938812">
<PARAM id="harmonics" value="0.5699999928474426"/>
<PARAM id="level" value="0.6499999761581421"/>
<PARAM id="n_stages" value="1.0"/>
<PARAM id="on_off" value="1.0"/>
<PARAM id="sustain" value="0.5"/>
<PARAM id="high_q"/>
<PARAM id="smoothing" value="0.1549999713897705"/>
</Parameters>
<port_0 connection_0="1" connection_end_0="0"/>
</Muff_Drive>
<Muff_Tone>
<Parameters x_pos="0.5463414788246155" y_pos="0.320723682641983">
<PARAM id="mids" value="0.5"/>
<PARAM id="on_off" value="1.0"/>
<PARAM id="tone" value="0.5"/>
<PARAM id="type" value="0.0"/>
</Parameters>
<port_0 connection_0="-1" connection_end_0="0"/>
</Muff_Tone>
<Input>
<Parameters x_pos="0.005020080134272575" y_pos="0.3221343755722046">
<PARAM id="on_off" value="1.0"/>
</Parameters>
<port_0 connection_0="0" 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>
51 changes: 34 additions & 17 deletions src/processors/drive/big_muff/BigMuffClippingStage.cpp
Expand Up @@ -62,8 +62,6 @@ void BigMuffClippingStage::prepare (double sampleRate)
{
fs = (float) sampleRate;

G_C_12 = (2.0f * C12 * fs);

// set coefficients for input filter
float b_s[] = { C5 * R20, 0.0f };
float a_s[] = { C5 * (R19 + R20), 1.0f };
Expand All @@ -87,32 +85,51 @@ void BigMuffClippingStage::reset()
}
}

float BigMuffClippingStage::getGC12 (float fs, float smoothing)
{
// capacitor C12 admittance, smoothing adds or removes 200 pF
return 2.0f * (C12 + smoothing * 200.0e-12f) * fs;
}

template <bool highQuality>
void BigMuffClippingStage::processBlock (AudioBuffer<float>& buffer) noexcept
void BigMuffClippingStage::processBlock (AudioBuffer<float>& buffer, const chowdsp::SmoothedBufferValue<float>& gc12Smoothed) noexcept
{
const auto numChannels = buffer.getNumChannels();
const auto numSamples = buffer.getNumSamples();

for (int ch = 0; ch < numChannels; ++ch)
const auto processSample = [this] (int ch, float x, float G_C_12)
{
auto* x = buffer.getWritePointer (ch);
// input filter
auto u_n = inputFilter[ch].processSample (x);

for (int n = 0; n < numSamples; ++n)
{
// input filter
auto u_n = inputFilter[ch].processSample (x[n]);
// newton-raphson
float y_k = newton_raphson<(highQuality ? 8 : 4)> (u_n, y_1[ch], C_12_1[ch], G_C_12);

// newton-raphson
float y_k = newton_raphson<(highQuality ? 8 : 4)> (u_n, y_1[ch], C_12_1[ch], G_C_12);
// update state
C_12_1[ch] = 2.0f * (y_k - VbiasA) * G_C_12 - C_12_1[ch];
y_1[ch] = y_k;

// update state
C_12_1[ch] = 2.0f * (y_k - VbiasA) * G_C_12 - C_12_1[ch];
y_1[ch] = y_k;
return y_k;
};

x[n] = y_k;
for (int ch = 0; ch < numChannels; ++ch)
{
auto* x = buffer.getWritePointer (ch);

if (gc12Smoothed.isSmoothing())
{
const auto G_C_12_data = gc12Smoothed.getSmoothedBuffer();
for (int n = 0; n < numSamples; ++n)
x[n] = processSample (ch, x[n], G_C_12_data[n]);
}
else
{
const auto G_C_12 = gc12Smoothed.getCurrentValue();
for (int n = 0; n < numSamples; ++n)
x[n] = processSample (ch, x[n], G_C_12);
}
}
}

template void BigMuffClippingStage::processBlock<true> (AudioBuffer<float>& buffer) noexcept;
template void BigMuffClippingStage::processBlock<false> (AudioBuffer<float>& buffer) noexcept;
template void BigMuffClippingStage::processBlock<true> (AudioBuffer<float>&, const chowdsp::SmoothedBufferValue<float>&) noexcept;
template void BigMuffClippingStage::processBlock<false> (AudioBuffer<float>&, const chowdsp::SmoothedBufferValue<float>&) noexcept;
6 changes: 3 additions & 3 deletions src/processors/drive/big_muff/BigMuffClippingStage.h
Expand Up @@ -11,15 +11,15 @@ class BigMuffClippingStage
void reset();

template <bool highQuality>
void processBlock (AudioBuffer<float>& buffer) noexcept;
void processBlock (AudioBuffer<float>& buffer, const chowdsp::SmoothedBufferValue<float>& gc12Smoothed) noexcept;

static float getGC12 (float fs, float smoothing);

private:
chowdsp::IIRFilter<1, float> inputFilter[2];

float fs = 48000.0f;
float y_1[2] {}; // newton-raphson state

float G_C_12 = 1.0f; // capacitor C12 admittance
float C_12_1[2] {}; // capacitor C12 state

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BigMuffClippingStage)
Expand Down
16 changes: 13 additions & 3 deletions src/processors/drive/big_muff/BigMuffDrive.cpp
Expand Up @@ -19,6 +19,7 @@ BigMuffDrive::BigMuffDrive (UndoManager* um) : BaseProcessor ("Muff Drive", crea
loadParameterPointer (sustainParam, vts, "sustain");
loadParameterPointer (harmParam, vts, "harmonics");
loadParameterPointer (levelParam, vts, "level");
smoothingParam.setParameterHandle (getParameterPointer<chowdsp::FloatParameter*> (vts, "smoothing"));
nStagesParam = vts.getRawParameterValue ("n_stages");
hiQParam = vts.getRawParameterValue ("high_q");

Expand All @@ -38,9 +39,10 @@ ParamLayout BigMuffDrive::createParameterLayout()

createPercentParameter (params, "sustain", "Sustain", 0.5f);
createPercentParameter (params, "harmonics", "Harmonics", 0.65f);
createBipolarPercentParameter (params, "smoothing", "Smoothing", 0.0f);
createPercentParameter (params, "level", "Level", 0.65f);

emplace_param<AudioParameterChoice> (params, "n_stages", "Stages", StringArray { "1 Stage", "2 Stages", "3 Stages", "4 Stages" }, 1);
emplace_param<AudioParameterChoice> (params, "n_stages", "", StringArray { "1 Stage", "2 Stages", "3 Stages", "4 Stages" }, 1);
emplace_param<AudioParameterBool> (params, "high_q", "High Quality", false);

return { params.begin(), params.end() };
Expand All @@ -58,6 +60,13 @@ void BigMuffDrive::prepare (double sampleRate, int samplesPerBlock)
filt.reset();
}

smoothingParam.setRampLength (0.05);
smoothingParam.mappingFunction = [fs = this->fs] (float val)
{
return BigMuffClippingStage::getGC12 (fs, val);
};
smoothingParam.prepare (sampleRate, samplesPerBlock);

for (auto& stage : stages)
stage.prepare (sampleRate);

Expand Down Expand Up @@ -151,16 +160,17 @@ void BigMuffDrive::processAudio (AudioBuffer<float>& buffer)

processInputStage (buffer);

smoothingParam.process (numSamples);
const auto useHighQualityMode = hiQParam->load() == 1.0f;
if (useHighQualityMode)
{
for (int i = 0; i < numStages; ++i)
stages[i].processBlock<true> (buffer);
stages[i].processBlock<true> (buffer, smoothingParam);
}
else
{
for (int i = 0; i < numStages; ++i)
stages[i].processBlock<false> (buffer);
stages[i].processBlock<false> (buffer, smoothingParam);
}

for (int ch = 0; ch < numChannels; ++ch)
Expand Down
3 changes: 2 additions & 1 deletion src/processors/drive/big_muff/BigMuffDrive.h
Expand Up @@ -17,10 +17,11 @@ class BigMuffDrive : public BaseProcessor
private:
void doPrebuffering();
void processInputStage (AudioBuffer<float>& buffer);

chowdsp::FloatParameter* sustainParam = nullptr;
chowdsp::FloatParameter* harmParam = nullptr;
chowdsp::FloatParameter* levelParam = nullptr;
chowdsp::SmoothedBufferValue<float> smoothingParam;
std::atomic<float>* nStagesParam = nullptr;
std::atomic<float>* hiQParam = nullptr;

Expand Down
3 changes: 3 additions & 0 deletions src/state/presets/PresetManager.cpp
Expand Up @@ -109,6 +109,9 @@ void PresetManager::loadBYODFactoryPresets()
// pedals
factoryPresets.emplace_back (BinaryData::American_Sound_chowpreset, BinaryData::American_Sound_chowpresetSize);
factoryPresets.emplace_back (BinaryData::Big_Muff_chowpreset, BinaryData::Big_Muff_chowpresetSize);
factoryPresets.emplace_back (BinaryData::Big_Muff_Triangle_chowpreset, BinaryData::Big_Muff_Triangle_chowpresetSize);
factoryPresets.emplace_back (BinaryData::Big_Muff_Rams_Head_56_chowpreset, BinaryData::Big_Muff_Rams_Head_56_chowpresetSize);
factoryPresets.emplace_back (BinaryData::Big_Muff_Russian_chowpreset, BinaryData::Big_Muff_Russian_chowpresetSize);
factoryPresets.emplace_back (BinaryData::Centaur_chowpreset, BinaryData::Centaur_chowpresetSize);
factoryPresets.emplace_back (BinaryData::King_Of_Tone_chowpreset, BinaryData::King_Of_Tone_chowpresetSize);
factoryPresets.emplace_back (BinaryData::MXR_Distortion_chowpreset, BinaryData::MXR_Distortion_chowpresetSize);
Expand Down

0 comments on commit daa1f2c

Please sign in to comment.