diff --git a/AudioTracks/LetsAllLoveLain.mp3 b/AudioTracks/LetsAllLoveLain.mp3 deleted file mode 100644 index 670bf90..0000000 Binary files a/AudioTracks/LetsAllLoveLain.mp3 and /dev/null differ diff --git a/AudioTracks/drumLoop120BPM.wav b/AudioTracks/drumLoop120BPM.wav new file mode 100644 index 0000000..9b03f5e Binary files /dev/null and b/AudioTracks/drumLoop120BPM.wav differ diff --git a/QuasoCompressor.jucer b/QuasoCompressor.jucer index d3a31d7..b787c15 100644 --- a/QuasoCompressor.jucer +++ b/QuasoCompressor.jucer @@ -4,14 +4,26 @@ displaySplashScreen="1" jucerFormatVersion="1" companyName="sadmemelord"> + + + + + + + + + + diff --git a/Source/DSP/CustomCompressor.cpp b/Source/DSP/CustomCompressor.cpp new file mode 100644 index 0000000..64b11ea --- /dev/null +++ b/Source/DSP/CustomCompressor.cpp @@ -0,0 +1,50 @@ +/* + ============================================================================== + + CustomCompressor.cpp + Created: 7 Feb 2023 4:07:01pm + Author: Utente + + ============================================================================== +*/ + +#include "CustomCompressor.h" + +CustomCompressor::CustomCompressor() +{ + +} + + +void CustomCompressor::prepare(juce::dsp::ProcessSpec& spec) noexcept +{ + _sampleRate = spec.sampleRate; +} + + +void CustomCompressor::setThreshold(float newThresh) +{ + _thresh = newThresh; +} + + +void CustomCompressor::setRatio(float newRatio) +{ + _ratio = newRatio; +} + + +void CustomCompressor::setAttack(float newAttack) +{ + _attack = newAttack / 1000.0f; +} + +void CustomCompressor::setRelease(float newRelease) +{ + _release = newRelease / 1000.0f; +} + +void CustomCompressor::setBypass(bool newBypass) +{ + _isBypassed = newBypass; +} \ No newline at end of file diff --git a/Source/DSP/CustomCompressor.h b/Source/DSP/CustomCompressor.h new file mode 100644 index 0000000..824e09b --- /dev/null +++ b/Source/DSP/CustomCompressor.h @@ -0,0 +1,132 @@ +/* + ============================================================================== + + CustomCompressor.h + Created: 7 Feb 2023 4:07:01pm + Author: Utente + + ============================================================================== +*/ + +#pragma once +#include + +class CustomCompressor +{ + +public: + CustomCompressor(); + + void prepare(juce::dsp::ProcessSpec& spec) noexcept; + + void process(juce::AudioBuffer& buffer) noexcept + { + //the process method is defined in the header file + //because it is passed through the translation unit + //and has a better chance of being optimized + //bypassing the dsp + + if (_isBypassed == true) + return; + + auto data = buffer.getArrayOfWritePointers(); + + //sample/channel loop + for(int sample = 0; sample < buffer.getNumSamples(); ++sample) + { + + for (int ch = 0; ch < buffer.getNumChannels(); ++ch) + { + data[ch][sample] = processSample(data[ch][sample]); + } + } + } + + float processSample(float inputValue) + { + //attack and release variable from Eric Tarr Hack Audio + auto alphaAttack = std::exp((std::log(9) * -1.0) / (_sampleRate * _attack)); + auto alphaRelease = std::exp((std::log(9) * -1.0) / (_sampleRate * _release)); + + const auto input = inputValue; + + //input dividedin unipolar (absolute value) and dB values + auto input_uni = std::abs(input); //maybe remove std + auto input_dB = juce::Decibels::gainToDecibels(input_uni / 1.0); + + //checking that no value in dB are negative infinity + if (input_dB < -96) + { + input_dB = -96; + } + + if (input_dB > _thresh) + { + _gainSC = _thresh + (input_dB - _thresh) / _ratio; + } + + else + { + _gainSC = input_dB; + } + + _gainChange_dB = _gainSC - input_dB; + + if (_gainChange_dB < _gainSmoothPrevious) + { + _gainSmooth = ((1.0 - alphaAttack) * _gainChange_dB) + (alphaAttack * _gainSmoothPrevious); + _currentSignal = _gainSmooth; + } + + else + { + _gainSmooth = ((1.0 - alphaRelease) * _gainChange_dB) + (alphaRelease * _gainSmoothPrevious); + _currentSignal = _gainSmooth; + + } + + auto output = input * juce::Decibels::decibelsToGain(_gainSmooth); + _gainSmoothPrevious = _gainSmooth; + + //output signal + return output; + + } + + void setThreshold(float newThresh); + void setRatio(float newRatio); + void setAttack(float newAttack); + void setRelease(float newRelease); + void setBypass(bool newBypass); + + +private: + + //compressor parameters + float _thresh = 0.0f; + float _ratio = 1.0f; + float _attack = 50.0f / 1000.0f ; + float _release = 160.0f / 1000.0f; + bool _isBypassed = false; + + //sample rate + float _sampleRate = 44100.0f; + + //gain sidechain + float _gainSC = 0.0f; + + //gain smooth + float _gainSmooth = 0.0f; + + //gain smooth previous + float _gainSmoothPrevious = 0.0f; + + //current signal + float _currentSignal = 0.0f; + + //gain change in decibels + float _gainChange_dB = 0.0f; + + + +}; \ No newline at end of file diff --git a/Source/GUI/Buttons/Buttons.cpp b/Source/GUI/Buttons/Buttons.cpp new file mode 100644 index 0000000..46cd72d --- /dev/null +++ b/Source/GUI/Buttons/Buttons.cpp @@ -0,0 +1,16 @@ +/* + ============================================================================== + + Buttons.cpp + Created: 7 Feb 2023 8:21:22pm + Author: Utente + + ============================================================================== +*/ + +#include "../../PluginEditor.h" + +void QuasoCompressorAudioProcessorEditor::setButtonProps(juce::ToggleButton& button) +{ + addAndMakeVisible(button); +} diff --git a/Source/GUI/Labels/Labels.cpp b/Source/GUI/Labels/Labels.cpp new file mode 100644 index 0000000..aabb49e --- /dev/null +++ b/Source/GUI/Labels/Labels.cpp @@ -0,0 +1,19 @@ +/* + ============================================================================== + + Labels.cpp + Created: 7 Feb 2023 8:23:29pm + Author: Utente + + ============================================================================== +*/ + +#include "../../PluginEditor.h" + +void QuasoCompressorAudioProcessorEditor::setCommonLabelProps(juce::Label& label) +{ + //setting properties common to every slider + addAndMakeVisible(label); + label.setFont(juce::Font("Helvetica", 16.0f, juce::Font::FontStyleFlags::bold)); + label.setJustificationType(juce::Justification::centred); +} diff --git a/Source/GUI/Sliders/SliderProps.cpp b/Source/GUI/Sliders/SliderProps.cpp index 0991d5c..92719e6 100644 --- a/Source/GUI/Sliders/SliderProps.cpp +++ b/Source/GUI/Sliders/SliderProps.cpp @@ -52,12 +52,3 @@ void QuasoCompressorAudioProcessorEditor::attachSliders() outputAttach = std::make_unique(audioProcessor.apvts, outputID, outputDial); } - -void QuasoCompressorAudioProcessorEditor::setCommonLabelProps(juce::Label& label) -{ - //setting properties common to every slider - addAndMakeVisible(label); - label.setFont(juce::Font("Helvetica", 16.0f, juce::Font::FontStyleFlags::bold)); - label.setJustificationType(juce::Justification::centred); -} - diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 7269aba..e5b3c32 100644 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -37,6 +37,11 @@ QuasoCompressorAudioProcessorEditor::QuasoCompressorAudioProcessorEditor (QuasoC setGroupProps(*groups[i]); } + for (int i = 0; i < buttons.size(); i++) + { + setButtonProps(*buttons[i]); + } + //some properties are different between dials like the textbox suffix //inputDial.setColour(juce::Slider::ColourIds::thumbColourId, juce::Colours::indianred.darker(0.3)); inputDial.setTextValueSuffix(" dB"); @@ -138,6 +143,8 @@ void QuasoCompressorAudioProcessorEditor::resized() limiterGroup.setBounds(limThreshDial.getX(), limThreshDial.getY() * 0.1, limThreshDial.getWidth(), limThreshDial.getY() + limThreshDial.getHeight() * 2.4); + + compBypassButton.setBounds(ratioDial.getX() , getLocalBounds().getY() / 2, 100, 100); diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h index 4e37e34..2d51fb0 100644 --- a/Source/PluginEditor.h +++ b/Source/PluginEditor.h @@ -96,10 +96,23 @@ class QuasoCompressorAudioProcessorEditor : public juce::AudioProcessorEditor &limiterGroup }; - //method to set some properties common to every silder, label and group + //buttons + juce::ToggleButton compBypassButton; + juce::ToggleButton limBypassButton; + + //buttons vector + std::vector buttons = + { + &compBypassButton, + &limBypassButton + }; + + + //method to set some properties common to every silders, labels, groups and buttons void setCommonSliderProps(juce::Slider& slider); void setCommonLabelProps(juce::Label& label); void setGroupProps(juce::GroupComponent& group); + void setButtonProps(juce::ToggleButton& button); //setting up attachment using Attachment = std::unique_ptr; diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 9e624e2..36928eb 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -102,10 +102,10 @@ void QuasoCompressorAudioProcessor::updateParameters() { //the load method is needed because the raw parameters are atomic inputModule.setGainDecibels(apvts.getRawParameterValue(inputID)->load()); - compressorModule.setThreshold(apvts.getRawParameterValue(threshID)->load()); - compressorModule.setRatio(apvts.getRawParameterValue(ratioID)->load()); - compressorModule.setAttack(apvts.getRawParameterValue(attackID)->load()); - compressorModule.setRelease(apvts.getRawParameterValue(releaseID)->load()); + customCompressorModule.setThreshold(apvts.getRawParameterValue(threshID)->load()); + customCompressorModule.setRatio(apvts.getRawParameterValue(ratioID)->load()); + customCompressorModule.setAttack(apvts.getRawParameterValue(attackID)->load()); + customCompressorModule.setRelease(apvts.getRawParameterValue(releaseID)->load()); limiterModule.setThreshold(apvts.getRawParameterValue(limThreshID)->load()); limiterModule.setRelease(apvts.getRawParameterValue(limReleaseID)->load()); outputModule.setGainDecibels(apvts.getRawParameterValue(outputID)->load()); @@ -192,7 +192,7 @@ void QuasoCompressorAudioProcessor::prepareToPlay (double sampleRate, int sample outputModule.setRampDurationSeconds(0.02); outputModule.prepare(spec); - compressorModule.prepare(spec); + customCompressorModule.prepare(spec); limiterModule.prepare(spec); @@ -241,7 +241,7 @@ void QuasoCompressorAudioProcessor::processBlock (juce::AudioBuffer& buff //process DSP modules inputModule.process(juce::dsp::ProcessContextReplacing(block)); - compressorModule.process(juce::dsp::ProcessContextReplacing(block)); + customCompressorModule.process(buffer); limiterModule.process(juce::dsp::ProcessContextReplacing(block)); outputModule.process(juce::dsp::ProcessContextReplacing(block)); diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index 9147ae8..e181ce7 100644 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -10,6 +10,7 @@ #include #include "./Parameters/Parameters.h" +#include "./DSP/CustomCompressor.h" //============================================================================== /** @@ -72,6 +73,9 @@ class QuasoCompressorAudioProcessor : public juce::AudioProcessor, juce::AudioP //the dsp module also implements a compressor module juce::dsp::Compressor compressorModule; + //custom dsp compressor module based on Eric Tarr HACK AUDIO + CustomCompressor customCompressorModule; + //limiter module juce::dsp::Limiter limiterModule; diff --git a/quasoCompressor.filtergraph b/quasoCompressor.filtergraph index f0bb757..50ba1b6 100644 --- a/quasoCompressor.filtergraph +++ b/quasoCompressor.filtergraph @@ -61,13 +61,14 @@ - + - 191.VMjLgXK....O+fWarAhckI2bo8la8HRLt.iHfTlai8FYo41Y8HRUTYTK3HxO9.BOVMEUy.Ea0cVZtMEcgQWY9vSRC8Vav8lak4Fc9XCLt3hKt3hKt3hKt3hYRUUSTEETIckVwTjQisVTTgkdEYjKAQjYPQSPWgUdMcjKAQjct3hdA4hKt3hKt3hKtnTUv.UQAslXuk0UXoWUFE0YQcEV77RRC8Vav8lak4Fc9vyKVMEUy.Ea0cVZtMEcgQWY9.. + 635.VMjLgHm....O+fWarAhckI2bo8la8HRLt.iHfTlai8FYo41Y8HRUTYTK3HxO9.BOVMEUy.Ea0cVZtMEcgQWY9vSRC8Vav8lak4Fc9LSNx3BTEoFUAACUQQUUpQ0TA4hKAYlKTETRUAUSAAkKBolQY4BQtHTQDYzX5UTLXEWPlM1Y2Y0XqEDTtjDTt3hKt3hKt3hKM4RPtPUPIUETMEDTtHjZFkkKDYWPEoFagYWUGMlKXcEVxU0UY4BQPIDQt3hKt3hKt3hKt3hKtTETRUDUS4BQl4xaQYjKAYGTAI2ZVElTUYTXqUTLhsVPlM1Y2Y0XqEDTtjDTt3hKt3hKt3hdg4RPtPUPIUETMEDTtHjZFkkKDYmPEYmUZMWTEoEdUEiXtEjYic1cVM1ZAAkKIAkKt3hKt3hKt3hKt3hKTETRUAUSAAkKBolQY4BQtHTQ2X0X5EzUioWPlM1Y2Y0XqEDTtjDTt3hKt3hYLkGSL4RPtPUPIUETMEDTtHjZFkkKDYWPEgzUXo2ZwDlKXcEVxU0UY4BQPIDQt3hKt3hKt3xLBAkKtTETRUDUS4BQl4xaQYjKAoFTAgWUFE1ZEEiXqEjYic1cVM1ZAAkKIAkKt3hKt3hKt3RStDjKTETRUAUSAAkKBolQY4BQtHTQPcjV3UULh4VPlM1Y2Y0XqEDTtjDTt3hKt3ha1ASaQ4xPt3hKt3hKt3hKt3haTU0PUQDU3sFaicVTWkEQEYzXmEDTtDDRTQlcEEiX4EDTtDDSt3xXt3hKt3hKt3hKlIUUMQUTPkzUZESQFM1ZQQEV5UjQ77RRC8Vav8lak4Fc9vyKVMEUy.Ea0cVZtMEcgQWY9.. @@ -77,14 +78,14 @@ - + - 350.VMjLgTU....O+fWarAhckI2bo8la8HRLt.iHfTlai8FYo41Y8HRUTYTK3HxO9.BOVMEUy.Ea0cVZtMEcgQWY9vSRC8Vav8lak4Fc9DyM33BTIISX1UEaho2ZVkUdAAkKAwDUigWRWkEcQ0VTucmUY4BQlYUQLolShUELhsVRxHlXUUzXqQiQis1cEE0ZMIiV5giQhIVTUE0TqQzUJUkLXsVPBQEd3vlVq0jQik2cUMEL2YzXuEzQgs1ZpElcUczXhUDUio1ZwDFUIcEVoMWLhI1cTkkdMcETxcmQSUWVWkESEYkVzQiTgYWSC4hKt3hKt3hKt3hKt3hRUACTEEzZh8VVWgkdUYTTmE0UX4BQP4hPqcjXm0jLh4BQP4xPt.0Qt3hKt3hKt3hKtQUUCUEQTg2ZrM1YQcUVDUjQicVP77RRC8Vav8lak4Fc9vyKVMEUy.Ea0cVZtMEcgQWY9.. + 319.VMjLgXS....O+fWarAhckI2bo8la8HRLt.iHfTlai8FYo41Y8HRUTYTK3HxO9.BOVMEUy.Ea0cVZtMEcgQWY9vSRC8Vav8lak4Fc9DSM03BTIISX1UEaho2ZVkUdAAkKAwDUigWRWkEcQ0VTucmUY4BQ1AUQLolShUELhsVRxHlXUUzXqQiQis1cEEUci0VXxgiUXoVSGckdLMESyH1TMUFNUkUdEwlXq0jLWUVQowjc5gFV1AiUKoVRWM1bvHTX0giQhMGRosjLEw1Xt3hKt3hKt3hKt3hKt3FUUMTUDQEdqw1XmE0UYQTQFM1YAAkKAgDUjYWQwHVdAAkKAwjKtLlKt3hKt3hKt3hYRUUSTEETIckVwTjQisVTTgkdEYDOujzPu0Fbu4VYtQmO77hUSQ0LPwVcmklaSQWXzUlO.. @@ -96,6 +97,6 @@ - - + +