Commit 9df90ef2 authored by Jonathan Hyde's avatar Jonathan Hyde

Update meters

parent f90557da
...@@ -101,7 +101,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -101,7 +101,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_gain.setRange(-35.0f, 35.0f, 0.1f); m_gain.setRange(-35.0f, 35.0f, 0.1f);
m_gain.setMouseCursor(MouseCursor::UpDownResizeCursor); m_gain.setMouseCursor(MouseCursor::UpDownResizeCursor);
m_gain.setVelocityBasedMode(false); m_gain.setVelocityBasedMode(false);
m_gain.setVelocityModeParameters(0.5, 0.1, 0.01); m_gain.setVelocityModeParameters(0.5, 2, 0.01);
m_gain.setValue(Decibels::gainToDecibels(gainParam), NotificationType::dontSendNotification); m_gain.setValue(Decibels::gainToDecibels(gainParam), NotificationType::dontSendNotification);
m_gain.setDoubleClickReturnValue(true, 0.0f); m_gain.setDoubleClickReturnValue(true, 0.0f);
m_gain.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_gain.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -113,7 +113,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -113,7 +113,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_pan.setRange(0.0f, 1.0f, 0.01f); m_pan.setRange(0.0f, 1.0f, 0.01f);
m_pan.setMouseCursor(MouseCursor::UpDownResizeCursor); m_pan.setMouseCursor(MouseCursor::UpDownResizeCursor);
m_pan.setVelocityBasedMode(false); m_pan.setVelocityBasedMode(false);
m_pan.setVelocityModeParameters(0.5, 0.1, 0.01); m_pan.setVelocityModeParameters(0.5, 2, 0.01);
m_pan.setValue(*processor.p_pan, NotificationType::dontSendNotification); m_pan.setValue(*processor.p_pan, NotificationType::dontSendNotification);
m_pan.setDoubleClickReturnValue(true, 0.5f); m_pan.setDoubleClickReturnValue(true, 0.5f);
m_pan.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_pan.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -124,7 +124,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -124,7 +124,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_gainL.setSliderStyle(Slider::LinearVertical); m_gainL.setSliderStyle(Slider::LinearVertical);
m_gainL.setRange(-35.0f, 35.0f, 0.1f); m_gainL.setRange(-35.0f, 35.0f, 0.1f);
m_gainL.setVelocityBasedMode(false); m_gainL.setVelocityBasedMode(false);
m_gainL.setVelocityModeParameters(0.5, 0.1, 0.01); m_gainL.setVelocityModeParameters(0.5, 2, 0.01);
m_gainL.setValue(*processor.p_gainL, NotificationType::dontSendNotification); m_gainL.setValue(*processor.p_gainL, NotificationType::dontSendNotification);
m_gainL.setDoubleClickReturnValue(true, 0.0f); m_gainL.setDoubleClickReturnValue(true, 0.0f);
m_gainL.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_gainL.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -134,7 +134,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -134,7 +134,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_gainR.setSliderStyle(Slider::LinearVertical); m_gainR.setSliderStyle(Slider::LinearVertical);
m_gainR.setRange(-35.0f, 35.0f, 0.1f); m_gainR.setRange(-35.0f, 35.0f, 0.1f);
m_gainR.setVelocityBasedMode(false); m_gainR.setVelocityBasedMode(false);
m_gainR.setVelocityModeParameters(0.5, 0.1, 0.01); m_gainR.setVelocityModeParameters(0.5, 2, 0.01);
m_gainR.setValue(*processor.p_gainR, NotificationType::dontSendNotification); m_gainR.setValue(*processor.p_gainR, NotificationType::dontSendNotification);
m_gainR.setDoubleClickReturnValue(true, 0.0f); m_gainR.setDoubleClickReturnValue(true, 0.0f);
m_gainR.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_gainR.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -144,7 +144,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -144,7 +144,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_gainM.setSliderStyle(Slider::LinearVertical); m_gainM.setSliderStyle(Slider::LinearVertical);
m_gainM.setRange(-60.0f, 20.0f, 0.1f); m_gainM.setRange(-60.0f, 20.0f, 0.1f);
m_gainM.setVelocityBasedMode(false); m_gainM.setVelocityBasedMode(false);
m_gainM.setVelocityModeParameters(0.5, 0.1, 0.01); m_gainM.setVelocityModeParameters(0.5, 2, 0.01);
m_gainM.setValue(*processor.p_gainM, NotificationType::dontSendNotification); m_gainM.setValue(*processor.p_gainM, NotificationType::dontSendNotification);
m_gainM.setDoubleClickReturnValue(true, 0.0f); m_gainM.setDoubleClickReturnValue(true, 0.0f);
m_gainM.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_gainM.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -154,7 +154,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -154,7 +154,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_gainS.setSliderStyle(Slider::LinearVertical); m_gainS.setSliderStyle(Slider::LinearVertical);
m_gainS.setRange(-60.0f, 20.0f, 0.1f); m_gainS.setRange(-60.0f, 20.0f, 0.1f);
m_gainS.setVelocityBasedMode(false); m_gainS.setVelocityBasedMode(false);
m_gainS.setVelocityModeParameters(0.5, 0.1, 0.01); m_gainS.setVelocityModeParameters(0.5, 2, 0.01);
m_gainS.setValue(*processor.p_gainS, NotificationType::dontSendNotification); m_gainS.setValue(*processor.p_gainS, NotificationType::dontSendNotification);
m_gainS.setDoubleClickReturnValue(true, 0.0f); m_gainS.setDoubleClickReturnValue(true, 0.0f);
m_gainS.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_gainS.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -165,7 +165,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -165,7 +165,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_width.setRange(-1.0f, 1.0f, 0.01f); m_width.setRange(-1.0f, 1.0f, 0.01f);
m_width.setMouseCursor(MouseCursor::UpDownResizeCursor); m_width.setMouseCursor(MouseCursor::UpDownResizeCursor);
m_width.setVelocityBasedMode(false); m_width.setVelocityBasedMode(false);
m_width.setVelocityModeParameters(0.5, 0.1, 0.01); m_width.setVelocityModeParameters(0.5, 2, 0.01);
m_width.setValue(*processor.p_width, NotificationType::dontSendNotification); m_width.setValue(*processor.p_width, NotificationType::dontSendNotification);
m_width.setDoubleClickReturnValue(true, 0.0f); m_width.setDoubleClickReturnValue(true, 0.0f);
m_width.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_width.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -177,7 +177,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -177,7 +177,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_highPass.setRange(20.0f, fmin(20000.0f, processor.getSampleRate() /2.0f), 1.0f); m_highPass.setRange(20.0f, fmin(20000.0f, processor.getSampleRate() /2.0f), 1.0f);
m_highPass.setMouseCursor(MouseCursor::UpDownResizeCursor); m_highPass.setMouseCursor(MouseCursor::UpDownResizeCursor);
m_highPass.setVelocityBasedMode(false); m_highPass.setVelocityBasedMode(false);
m_highPass.setVelocityModeParameters(0.5, 0.1, 0.01); m_highPass.setVelocityModeParameters(0.5, 2, 0.01);
m_highPass.setValue(*processor.p_highPass, NotificationType::dontSendNotification); m_highPass.setValue(*processor.p_highPass, NotificationType::dontSendNotification);
m_highPass.setDoubleClickReturnValue(true, 0.5f); m_highPass.setDoubleClickReturnValue(true, 0.5f);
m_highPass.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_highPass.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -192,7 +192,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -192,7 +192,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
m_lowPass.setRange(20.0f, fmin(20000.0f, processor.getSampleRate() / 2.0f), 1.0f); m_lowPass.setRange(20.0f, fmin(20000.0f, processor.getSampleRate() / 2.0f), 1.0f);
m_lowPass.setMouseCursor(MouseCursor::UpDownResizeCursor); m_lowPass.setMouseCursor(MouseCursor::UpDownResizeCursor);
m_lowPass.setVelocityBasedMode(false); m_lowPass.setVelocityBasedMode(false);
m_lowPass.setVelocityModeParameters(0.5, 0.1, 0.01); m_lowPass.setVelocityModeParameters(0.5, 2, 0.01);
m_lowPass.setValue(*processor.p_lowPass, NotificationType::dontSendNotification); m_lowPass.setValue(*processor.p_lowPass, NotificationType::dontSendNotification);
m_lowPass.setDoubleClickReturnValue(true, 0.5f); m_lowPass.setDoubleClickReturnValue(true, 0.5f);
m_lowPass.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); m_lowPass.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
...@@ -226,7 +226,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -226,7 +226,7 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
lnfIn->setColour(LevelMeter::lmMeterGradientLowColour, juce::Colours::green); lnfIn->setColour(LevelMeter::lmMeterGradientLowColour, juce::Colours::green);
lnfOut->setColour(LevelMeter::lmMeterGradientLowColour, juce::Colours::green); lnfOut->setColour(LevelMeter::lmMeterGradientLowColour, juce::Colours::green);
meterIn = new LevelMeter(LevelMeter::MeterFlags::HasBorder); meterIn = new LevelMeter(LevelMeter::MeterFlags::Default);
meterIn->setLookAndFeel(lnfIn); meterIn->setLookAndFeel(lnfIn);
meterIn->setMeterSource(processor.getMeterSourceIn()); meterIn->setMeterSource(processor.getMeterSourceIn());
meterOut = new LevelMeter(LevelMeter::MeterFlags::HasBorder); meterOut = new LevelMeter(LevelMeter::MeterFlags::HasBorder);
...@@ -235,6 +235,9 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor& ...@@ -235,6 +235,9 @@ UtilityAudioProcessorEditor::UtilityAudioProcessorEditor (UtilityAudioProcessor&
addAndMakeVisible(meterIn); addAndMakeVisible(meterIn);
addAndMakeVisible(meterOut); addAndMakeVisible(meterOut);
meterIn->addListener(this);
meterOut->addListener(this);
setSize (400, 500); setSize (400, 500);
} }
...@@ -447,6 +450,18 @@ void UtilityAudioProcessorEditor::comboBoxChanged(ComboBox * comboBoxThatHasChan ...@@ -447,6 +450,18 @@ void UtilityAudioProcessorEditor::comboBoxChanged(ComboBox * comboBoxThatHasChan
processor.updateHostDisplay(); processor.updateHostDisplay();
} }
void UtilityAudioProcessorEditor::clipLightClicked(LevelMeter* meter, const int channel, juce::ModifierKeys mods)
{
if (meter == meterIn)
meterIn->clearClipIndicator();
else if (meter == meterOut)
meterOut->clearClipIndicator();
}
void UtilityAudioProcessorEditor::maxLevelClicked(LevelMeter* meter, const int channel, juce::ModifierKeys mods)
{
}
void UtilityAudioProcessorEditor::getGainDB() void UtilityAudioProcessorEditor::getGainDB()
{ {
float val = m_gain.getValue(); float val = m_gain.getValue();
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
//============================================================================== //==============================================================================
/** /**
*/ */
class UtilityAudioProcessorEditor : public AudioProcessorEditor, private ButtonListener, private SliderListener, private ComboBoxListener class UtilityAudioProcessorEditor : public AudioProcessorEditor, private ButtonListener, private SliderListener, private ComboBoxListener, private LevelMeter::Listener
{ {
public: public:
UtilityAudioProcessorEditor (UtilityAudioProcessor&); UtilityAudioProcessorEditor (UtilityAudioProcessor&);
...@@ -21,6 +21,8 @@ public: ...@@ -21,6 +21,8 @@ public:
void buttonClicked(juce::Button * button) override; void buttonClicked(juce::Button * button) override;
void sliderValueChanged(Slider* slider) override; void sliderValueChanged(Slider* slider) override;
void comboBoxChanged(ComboBox *comboBoxThatHasChanged) override; void comboBoxChanged(ComboBox *comboBoxThatHasChanged) override;
void clipLightClicked(LevelMeter* meter, const int channel, juce::ModifierKeys mods) override;
void maxLevelClicked(LevelMeter* meter, const int channel, juce::ModifierKeys mods) override;
Slider m_highPass; Slider m_highPass;
Slider m_lowPass; Slider m_lowPass;
......
...@@ -109,19 +109,19 @@ void UtilityAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBloc ...@@ -109,19 +109,19 @@ void UtilityAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBloc
m_midBuffer.setSize(1, samplesPerBlock); m_midBuffer.setSize(1, samplesPerBlock);
m_sideBuffer.setSize(1, samplesPerBlock); m_sideBuffer.setSize(1, samplesPerBlock);
m_lpf.setup(3, sampleRate, fmin(20000.0f, (sampleRate / 2.0f) - 500.0f)); *p_highPass = fmin(static_cast<float>(*p_highPass), sampleRate / 2.0f);
m_hpf.setup(3, sampleRate, 20.0f); *p_lowPass = fmin(static_cast<float>(*p_lowPass), sampleRate / 2.0f);
m_lpf.setup(3, sampleRate, fmin((double)*p_lowPass, (sampleRate / 2.0f) - 500.0f));
m_hpf.setup(hpforder, sampleRate, fmin((double)*p_highPass, (sampleRate / 2.0f) - 500.0f));
m_sampleRate = sampleRate; m_sampleRate = sampleRate;
lowPassCutoff.reset(sampleRate, 0.0005); lowPassCutoff.reset(sampleRate, 0.0005);
highPassCutoff.reset(sampleRate, 0.0005); highPassCutoff.reset(sampleRate, 0.0005);
m_prevHighPass = 0.0f; m_prevHighPass = *p_highPass;
m_prevLowPass = 0.0f; m_prevLowPass = *p_lowPass;
*p_highPass = fmin(static_cast<float>(*p_highPass), sampleRate / 2.0f);
*p_lowPass = fmin(static_cast<float>(*p_lowPass), sampleRate / 2.0f);
if (getActiveEditor() != nullptr) if (getActiveEditor() != nullptr)
{ {
...@@ -173,7 +173,7 @@ void UtilityAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& ...@@ -173,7 +173,7 @@ void UtilityAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer&
{ {
highPassCutoff.setValue(*p_highPass); highPassCutoff.setValue(*p_highPass);
float newVal = highPassCutoff.getNextValue(); float newVal = highPassCutoff.getNextValue();
m_hpf.setup(3, m_sampleRate, fmin(newVal, ((m_sampleRate / 2.0f) - 500.0f))); m_hpf.setup(hpforder, m_sampleRate, fmin(newVal, ((m_sampleRate / 2.0f) - 500.0f)));
m_prevHighPass = newVal; m_prevHighPass = newVal;
} }
...@@ -204,18 +204,6 @@ void UtilityAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& ...@@ -204,18 +204,6 @@ void UtilityAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer&
float instantGainL = *p_phaseL ? -1.0f : 1.0f; float instantGainL = *p_phaseL ? -1.0f : 1.0f;
float instantGainR = *p_phaseR ? -1.0f : 1.0f; float instantGainR = *p_phaseR ? -1.0f : 1.0f;
instantGainL *= *p_muteL ? 0.0f : 1.0f;
instantGainR *= *p_muteR ? 0.0f : 1.0f;
if (*p_pad)
{
instantGainL *= 0.1f;
instantGainR *= 0.1f;
}
buffer.applyGain(0, 0, numSamples, instantGainL);
buffer.applyGain(1, 0, numSamples, instantGainR);
midSideProcess(buffer); midSideProcess(buffer);
if (*p_pan != 0.5f) if (*p_pan != 0.5f)
...@@ -250,6 +238,18 @@ void UtilityAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& ...@@ -250,6 +238,18 @@ void UtilityAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer&
if (*p_lpfOn) if (*p_lpfOn)
m_lpf.process(numSamples, buffer.getArrayOfWritePointers()); m_lpf.process(numSamples, buffer.getArrayOfWritePointers());
instantGainL *= *p_muteL ? 0.0f : 1.0f;
instantGainR *= *p_muteR ? 0.0f : 1.0f;
if (*p_pad)
{
instantGainL *= 0.1f;
instantGainR *= 0.1f;
}
buffer.applyGain(0, 0, numSamples, instantGainL);
buffer.applyGain(1, 0, numSamples, instantGainR);
if (*p_hardClip || *p_softClip) if (*p_hardClip || *p_softClip)
clipSamples(buffer); clipSamples(buffer);
...@@ -270,15 +270,62 @@ AudioProcessorEditor* UtilityAudioProcessor::createEditor() ...@@ -270,15 +270,62 @@ AudioProcessorEditor* UtilityAudioProcessor::createEditor()
//============================================================================== //==============================================================================
void UtilityAudioProcessor::getStateInformation (MemoryBlock& destData) void UtilityAudioProcessor::getStateInformation (MemoryBlock& destData)
{ {
// You should use this method to store your parameters in the memory block. ScopedPointer<XmlElement> xml(new XmlElement("PluginSettings"));
// You could do that either as raw data, or use the XML or ValueTree classes xml->setAttribute("p_input", (int)*p_input);
// as intermediaries to make it easy to save and load complex data. xml->setAttribute("p_mute", (bool)*p_mute);
xml->setAttribute("p_pad", (bool)*p_pad);
xml->setAttribute("p_DCoffset", (bool)*p_DCoffset);
xml->setAttribute("p_gain", (double)*p_gain);
xml->setAttribute("p_pan", (double)*p_pan);
xml->setAttribute("p_gainL", (double)*p_gainL);
xml->setAttribute("p_gainR", (double)*p_gainR);
xml->setAttribute("p_phaseL", (bool)*p_phaseL);
xml->setAttribute("p_phaseR", (bool)*p_phaseR);
xml->setAttribute("p_muteL", (bool)*p_phaseL);
xml->setAttribute("p_muteR", (bool)*p_muteR);
xml->setAttribute("p_gainM", (double)*p_gainM);
xml->setAttribute("p_gainS", (double)*p_gainS);
xml->setAttribute("p_width", (double)*p_width);
xml->setAttribute("p_muteM", (bool)*p_muteS);
xml->setAttribute("p_lowPass", (double)*p_lowPass);
xml->setAttribute("p_highPass", (double)*p_highPass);
xml->setAttribute("p_hpfOn", (bool)*p_hpfOn);
xml->setAttribute("p_lpfOn", (bool)*p_lpfOn);
xml->setAttribute("p_hardClip", (bool)*p_hardClip);
xml->setAttribute("p_softClip", (bool)*p_softClip);
copyXmlToBinary(*xml, destData);
} }
void UtilityAudioProcessor::setStateInformation (const void* data, int sizeInBytes) void UtilityAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{ {
// You should use this method to restore your parameters from this memory block, ScopedPointer<XmlElement> xmlState(getXmlFromBinary(data, sizeInBytes));
// whose contents will have been created by the getStateInformation() call. if (xmlState != nullptr)
if (xmlState->hasTagName("PluginSettings"))
{
*p_input = xmlState->getIntAttribute("p_input", 1);
*p_mute = xmlState->getBoolAttribute("p_mute", false);
*p_pad = xmlState->getBoolAttribute("p_pad", false);
*p_DCoffset = xmlState->getBoolAttribute("p_DCoffset", false);
*p_gain = xmlState->getDoubleAttribute("p_gain", 1.0f);
*p_pan = xmlState->getDoubleAttribute("p_pan", 0.5f);
*p_gainL = xmlState->getDoubleAttribute("p_gainL", 1.0f);
*p_gainR = xmlState->getDoubleAttribute("p_gainR", 1.0f);
*p_phaseL = xmlState->getBoolAttribute("p_phaseL", false);
*p_phaseR = xmlState->getBoolAttribute("p_phaseR", false);
*p_muteL = xmlState->getBoolAttribute("p_muteL", false);
*p_muteR = xmlState->getBoolAttribute("p_muteR", false);
*p_gainM = xmlState->getDoubleAttribute("p_gainM", 1.0f);
*p_gainS = xmlState->getDoubleAttribute("p_gainS", 1.0f);
*p_width = xmlState->getDoubleAttribute("p_width", 0.0f);
*p_muteM = xmlState->getBoolAttribute("p_muteM", false);
*p_muteS = xmlState->getBoolAttribute("p_muteS", false);
*p_lowPass = xmlState->getDoubleAttribute("p_lowPass", 20000.0f);
*p_highPass = xmlState->getDoubleAttribute("p_highPass", 20.0f);
*p_hpfOn = xmlState->getBoolAttribute("p_hpfOn", false);
*p_lpfOn = xmlState->getBoolAttribute("p_lpfOn", false);
*p_hardClip = xmlState->getBoolAttribute("p_hardClip", false);
*p_hardClip = xmlState->getBoolAttribute("p_softClip", false);
}
} }
//============================================================================== //==============================================================================
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "../JuceLibraryCode/JuceHeader.h" #include "../JuceLibraryCode/JuceHeader.h"
#include "DspFilters/Dsp.h" #include "DspFilters/Dsp.h"
#define HPFORDER 4
//============================================================================== //==============================================================================
/** /**
...@@ -102,12 +103,12 @@ private: ...@@ -102,12 +103,12 @@ private:
AudioSampleBuffer m_sideBuffer; AudioSampleBuffer m_sideBuffer;
Dsp::SimpleFilter <Dsp::Butterworth::LowPass <3>, 2> m_lpf; Dsp::SimpleFilter <Dsp::Butterworth::LowPass <3>, 2> m_lpf;
Dsp::SimpleFilter <Dsp::Butterworth::HighPass <3>, 2> m_hpf; Dsp::SimpleFilter <Dsp::Butterworth::HighPass <HPFORDER>, 2> m_hpf;
float m_prevLowPass = 20000.0f; float m_prevLowPass = 20000.0f;
float m_prevHighPass = 0.0f; float m_prevHighPass = 0.0f;
float m_sampleRate = 44100.0f; double m_sampleRate = 44100.0f;
LinearSmoothedValue<float> lowPassCutoff; LinearSmoothedValue<float> lowPassCutoff;
LinearSmoothedValue<float> highPassCutoff; LinearSmoothedValue<float> highPassCutoff;
...@@ -121,6 +122,8 @@ private: ...@@ -121,6 +122,8 @@ private:
LevelMeterSource meterSourceIn; LevelMeterSource meterSourceIn;
LevelMeterSource meterSourceOut; LevelMeterSource meterSourceOut;
const int hpforder = HPFORDER;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UtilityAudioProcessor) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UtilityAudioProcessor)
}; };
......
.DS* .DS*
html/ html/
/.git/
...@@ -34,7 +34,7 @@ or set it only to the meters, if you don't want it to interfere. ...@@ -34,7 +34,7 @@ or set it only to the meters, if you don't want it to interfere.
// adjust the colours to how you like them // adjust the colours to how you like them
lnf->setColour (LevelMeter::lmMeterGradientLowColour, juce::Colours::green); lnf->setColour (LevelMeter::lmMeterGradientLowColour, juce::Colours::green);
meter = new LevelMeter (LevelMeter::VerticalMeters); meter = new LevelMeter (); // See LevelMeter::MeterFlags for options
meter->setLookAndFeel (lnf); meter->setLookAndFeel (lnf);
meter->setMeterSource (processor.getMeterSource()); meter->setMeterSource (processor.getMeterSource());
addAndMakeVisible (meter); addAndMakeVisible (meter);
......
...@@ -152,14 +152,14 @@ void LevelMeter::mouseDown (const juce::MouseEvent &event) ...@@ -152,14 +152,14 @@ void LevelMeter::mouseDown (const juce::MouseEvent &event)
innerBounds, innerBounds,
source); source);
if (hit >= 0) { if (hit >= 0) {
listeners.call (&LevelMeter::Listener::clipLightClicked, hit); listeners.call (&LevelMeter::Listener::clipLightClicked, this, hit, event.mods);
} }
hit = lnf->hitTestMaxNumber (event.getPosition(), hit = lnf->hitTestMaxNumber (event.getPosition(),
meterType, meterType,
innerBounds, innerBounds,
source); source);
if (hit >= 0) { if (hit >= 0) {
listeners.call (&LevelMeter::Listener::maxLevelClicked, hit); listeners.call (&LevelMeter::Listener::maxLevelClicked, this, hit, event.mods);
} }
} }
} }
......
...@@ -33,12 +33,13 @@ ...@@ -33,12 +33,13 @@
============================================================================== ==============================================================================
*/ */
#ifndef LEVELMETER_H_INCLUDED #pragma once
#define LEVELMETER_H_INCLUDED
//============================================================================== //==============================================================================
/* /*
\class LevelMeter
\brief A component to display live gain and RMS readings
This class is used to display a level reading. It supports max and RMS levels. This class is used to display a level reading. It supports max and RMS levels.
You can also set a reduction value to display, the definition of that value is up to you. You can also set a reduction value to display, the definition of that value is up to you.
*/ */
...@@ -47,35 +48,40 @@ class LevelMeter : public juce::Component, private juce::Timer ...@@ -47,35 +48,40 @@ class LevelMeter : public juce::Component, private juce::Timer
public: public:
enum MeterFlags { enum MeterFlags {
Default = 0x0000, Default = 0x0000, /**< Default is showing all channels in the LevelMeterSource without a border */
Horizontal = 0x0001, Horizontal = 0x0001, /**< Displays the level bars horizontally */
Vintage = 0x0002, Vintage = 0x0002, /**< Switches to a special mode of old school meters (to come) */
SingleChannel = 0x0004, SingleChannel = 0x0004, /**< Display only one channel meter. \see setSelectedChannel */
HasBorder = 0x0008, HasBorder = 0x0008, /**< Displays a rounded border around the meter. This is used with the default constructor */
Reduction = 0x0010, Reduction = 0x0010, /**< Add a reduction meter to be displayed within the meter bar. The value can be set in the LevelMeterSource, \see LevelMeterSource::setReductionLevel (currently unavailable) */
Minimal = 0x0020 Minimal = 0x0020 /**< For a stereo meter, this tries to save space by showing only one line tickmarks in the middle and no max numbers */
}; };
enum ColourIds { enum ColourIds {
lmTextColour = 0x2200001, lmTextColour = 0x2200001, /**< Colour for the numbers etc. */
lmTextDeactiveColour, lmTextDeactiveColour, /**< Unused, will eventually be removed */
lmTextClipColour, lmTextClipColour, /**< Colour to print the max number if it has clipped */
lmTicksColour, lmTicksColour, /**< Colour for the tick marks */
lmOutlineColour, lmOutlineColour, /**< Colour for the frame around all */
lmBackgroundColour, lmBackgroundColour, /**< Background colour */
lmBackgroundClipColour, lmBackgroundClipColour, /**< This is the colour of the clip indicator if it has clipped */
lmMeterForegroundColour, lmMeterForegroundColour, /**< Unused, will eventually be removed */
lmMeterOutlineColour, lmMeterOutlineColour, /**< Colour for the outlines of meter bars etc. */
lmMeterBackgroundColour, lmMeterBackgroundColour, /**< Background colour for the actual meter bar and the max number */
lmMeterMaxNormalColour, lmMeterMaxNormalColour, /**< Text colour for the max number, if under warn threshold */
lmMeterMaxWarnColour, lmMeterMaxWarnColour, /**< Text colour for the max number, if between warn threshold and clip threshold */
lmMeterMaxOverColour, lmMeterMaxOverColour, /**< Text colour for the max number, if above the clip threshold */
lmMeterGradientLowColour, lmMeterGradientLowColour, /**< Colour for the meter bar under the warn threshold */
lmMeterGradientMidColour, lmMeterGradientMidColour, /**< Colour for the meter bar in the warn area */
lmMeterGradientMaxColour, lmMeterGradientMaxColour, /**< Colour for the meter bar at the clip threshold */
lmMeterReductionColour lmMeterReductionColour /**< Colour for the reduction meter displayed within the meter */
}; };
/**
These methods define a interface for the LookAndFeel class of juce.
The LevelMeter needs a LookAndFeel, that implements these methods.
There is a default implementation to be included in your custom LookAndFeel class, \see LookAndFeelMethods.h
*/
class LookAndFeelMethods { class LookAndFeelMethods {
public: public:
virtual ~LookAndFeelMethods() {} virtual ~LookAndFeelMethods() {}
...@@ -204,23 +210,62 @@ public: ...@@ -204,23 +210,62 @@ public:
void timerCallback () override; void timerCallback () override;
/**
Set a LevelMeterSource to display. This separation is used, so the source can work in the processing and the
GUI can display the values.
*/
void setMeterSource (LevelMeterSource* source); void setMeterSource (LevelMeterSource* source);
/**
Set a specific channel to display. This is only useful, if MeterFlags::SingleChannel is set.
*/
void setSelectedChannel (const int c); void setSelectedChannel (const int c);
void setRefreshRateHz (const int newRefreshRate); void setRefreshRateHz (const int newRefreshRate);
/**
Unset the clip indicator flag for a channel. Use -1 to reset all clip indicators.
*/
void clearClipIndicator (const int channel=-1); void clearClipIndicator (const int channel=-1);
/**
Set the max level display back to -inf for a channel. Use -1 to reset all max levels.
*/
void clearMaxLevelDisplay (const int channel=-1); void clearMaxLevelDisplay (const int channel=-1);
void mouseDown (const juce::MouseEvent& event) override; void mouseDown (const juce::MouseEvent& event) override;
/**
This Listener interface is meant to implement behaviour if either the clip indicator or the max level text
is clicked.
An example implementation could look like this (+alt means clear all, else clear the clicked number):
\code{.cpp}
void clipLightClicked (LevelMeter* clickedMeter, const int channel, ModifierKeys mods) override
{
clickedMeter->clearClipIndicator (mods.isAltDown() ? -1 : channel);
}
void maxLevelClicked (LevelMeter* clickedMeter, const int channel, ModifierKeys mods) override
{
clickedMeter->clearMaxLevelDisplay (mods.isAltDown() ? -1 : channel);
}
\endcode
*/
class Listener { class Listener {
public: public:
virtual ~Listener () {} virtual ~Listener () {}
virtual void clipLightClicked (const int channel) = 0; /**
virtual void maxLevelClicked (const int channel) = 0; This is called, when the user clicks a clip indicator. It can be used to reset the clip indicator.
To allow different behaviour, e.g. resetting only one indicator or even all meters spread over the UI.
\see clearClipIndicator, maxLevelClicked
*/
virtual void clipLightClicked (LevelMeter* meter, const int channel, juce::ModifierKeys mods) = 0;
/**
This is called, when the user clicks a max level text. It can be used to reset the max number.
\see clearMaxLevelDisplay, clipLightClicked
*/
virtual void maxLevelClicked (LevelMeter* meter, const int channel, juce::ModifierKeys mods) = 0;
}; };
void addListener (Listener*); void addListener (Listener*);
...@@ -249,5 +294,3 @@ private: ...@@ -249,5 +294,3 @@ private:
inline LevelMeter::MeterFlags operator|(LevelMeter::MeterFlags a, LevelMeter::MeterFlags b) inline LevelMeter::MeterFlags operator|(LevelMeter::MeterFlags a, LevelMeter::MeterFlags b)
{return static_cast<LevelMeter::MeterFlags>(static_cast<int>(a) | static_cast<int>(b));} {return static_cast<LevelMeter::MeterFlags>(static_cast<int>(a) | static_cast<int>(b));}
#endif // LEVELMETER_H_INCLUDED
...@@ -101,7 +101,7 @@ private: ...@@ -101,7 +101,7 @@ private:
pushNextRMS (newRms); pushNextRMS (newRms);
} }
void setRMSsize (const int numBlocks) { void setRMSsize (const int numBlocks) {
rmsHistory.resize (numBlocks); rmsHistory.resize (numBlocks, 0.0f);
rmsPtr %= rmsHistory.size(); rmsPtr %= rmsHistory.size();
} }
private: private:
...@@ -109,9 +109,11 @@ private: ...@@ -109,9 +109,11 @@ private:
const float squaredRMS = std::min (newRMS * newRMS, 1.0f); const float squaredRMS = std::min (newRMS * newRMS, 1.0f);
if (rmsHistory.size() > 0) { if (rmsHistory.size() > 0) {
float oldRMS = rmsSum - rmsHistory [rmsPtr]; float oldRMS = rmsSum - rmsHistory [rmsPtr];
if (abs(oldRMS) < 0.00001f)
oldRMS = 0.0f;
rmsSum = oldRMS + squaredRMS; rmsSum = oldRMS + squaredRMS;
rmsHistory [rmsPtr] = squaredRMS; rmsHistory [rmsPtr] = squaredRMS;
rmsPtr = ++rmsPtr % rmsHistory.size(); rmsPtr = (rmsPtr + 1) % rmsHistory.size();
} }
else { else {
rmsSum = squaredRMS; rmsSum = squaredRMS;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
============================================================================== ==============================================================================
ff_meters_LookAndFeel.h \file ff_meters_LookAndFeel.h
Author: Daniel Walz Author: Daniel Walz
============================================================================== ==============================================================================
...@@ -37,6 +37,26 @@ ...@@ -37,6 +37,26 @@
class LevelMeterSource; class LevelMeterSource;
/**
\class LevelMeterLookAndFeel
\brief Convenience LookAndFeel which derives from LookAndFeel_V3 and LevelMeter::LookAndFeelMethods
This is the shortcut, to get a component going without inheriting any LookAndFeel class.
If you write your own LookAndFeel, you can include ff_meters_LookAndFeelMethods.h inside your LookAndFeel:
\code{.cpp}
class MyLookAndFeel : public LookAndFeel_V4, LevelMeter::LookAndFeelMethods
{
public:
#include "ff_meters_LookAndFeelMethods.h"