Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: add Fuzz plugin for Pedalboard (#402) #403

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

LorenzoMonti
Copy link

@LorenzoMonti LorenzoMonti commented Feb 28, 2025

Problem

Fuzz is a staple effect in many music genres, particularly rock and
experimental electronic music. While distortion and gain effects exist
in Pedalboard, fuzz has a unique aggressive character that cannot be
easily replicated. Adding a fuzz plugin would expand Pedalboard’s
flexibility, providing more options for guitarists and producers
seeking vintage or experimental tones.

This feature request was initially discussed in #402.

Solution

Implemented a new Fuzz effect, emulating a classic fuzz pedal.
The effect consists of:

  • A two-stage clipping process:
    • Hard diode clipping with a threshold of 0.25.
    • Soft clipping using a tanh function.
  • A tone control stage, implemented as a low-pass filter.
  • Unit tests verifying expected behavior.

Result

Pedalboard now includes a fuzz effect, broadening its range of
distortion-based effects. Users can apply fuzz to their audio chains
for a distinctive saturated sound characteristic of classic fuzz pedals.

…d. It features a two-stage clipping process: first a hard diode clipping (threshold=0.25), then a soft clipping via tanh, followed by a tone control stage implemented as a low-pass filter.
Copy link
Member

@psobot psobot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work, thank you @LorenzoMonti! I've left a couple comments inline (mostly about touching the actual DSP parameters directly in the setters/getters rather than copies) - but otherwise, this is virtually a perfect pull request. Great job!

Comment on lines 80 to 81
SampleType driveDecibels;
SampleType toneHz;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don't want to keep a copy of these variables here, as they can differ from the variables set in the ProcessorChain depending on when prepare is called. (And indeed; if you use Fuzz in an AudioStream, it should be possible to call .drive_db = x and the audio should update without needing to stop and start the stream again.)

Comment on lines 41 to 42
void setDriveDecibels(const float f) noexcept { driveDecibels = f; }
float getDriveDecibels() const noexcept { return driveDecibels; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void setDriveDecibels(const float f) noexcept { driveDecibels = f; }
float getDriveDecibels() const noexcept { return driveDecibels; }
void setDriveDecibels(const float f) noexcept { this->getDSP().template get<gainIndex>().setGainDecibels(f); }
float getDriveDecibels() const noexcept { return this->getDSP().template get<gainIndex>().getGainDecibels(f); }

};

// Third stage: Tone control via low-pass filter
auto coeffs = juce::dsp::IIR::Coefficients<SampleType>::makeLowPass(spec.sampleRate, toneHz);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could try using ArrayCoefficients here to allow updating the toneHz parameter without requiring a realloc/extra prepare call here - with the caveat that I haven't worked with that API in a long time and am not sure if it would actually work here.

@LorenzoMonti
Copy link
Author

Excellent work, thank you @LorenzoMonti! I've left a couple comments inline (mostly about touching the actual DSP parameters directly in the setters/getters rather than copies) - but otherwise, this is virtually a perfect pull request. Great job!

Thanks for the thorough and speedy comment! I’m still getting familiar with JUCE, so I really appreciate the guidance. I’ll go through your comments carefully and deepen my understanding of how the ProcessorChain works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants