Problem updating Attachments from Sliders on an Audio Compressor

Hi!

I’m trying to develop an user friendly compressor. I had lots of doubts at the beginning and I’m based finally on two projects that are named in the code, under GNU.

I’m updating some plug in parameters values from an inc/dec button, just depending of compression degree, and switching that inc/dec value (from 1 to 5) acting directly into the compressor to change the value.

I am implementing the setting of the audio compressor machine in the “parameter changed” function, as shown below:

void SimpleCompressorAudioProcessor::parameterChanged(const String& parameterID, float newValue)
{
	if (parameterID == "threshold")
	{
		
			compressor.setThreshold(newValue);
			characteristicChanged = true;
		
	}
	else if (parameterID == "knee")
	{
		
			compressor.setKnee(newValue);
			characteristicChanged = true;
		
	}
	else if (parameterID == "attack") {
		
			compressor.setAttackTime(newValue / 1000);
			characteristicChanged = true;
		
	}
	else if (parameterID == "release") {
		
			compressor.setReleaseTime(newValue / 1000);
			characteristicChanged = true;
		
	}
	else if (parameterID == "ratio")
	{
		
			if (newValue > 15.9f)
				compressor.setRatio(std::numeric_limits<float>::infinity());
			else
				compressor.setRatio(newValue);
			characteristicChanged = true;
		
	}
	else if (parameterID == "makeUp")
	{
		
			compressor.setMakeUpGain(newValue);
			characteristicChanged = true;
		
	}
	else if (parameterID == "bypass")
	{
		
		
		characteristicChanged = true;
	}
	else if (parameterID == "hpf")
	{
		
			//hpf = (bool)newValue;
			characteristicChanged = true;
		
	}
	else if (parameterID == "expMode") {
		
			characteristicChanged = true;
		
	}
	else if (parameterID == "compDegree") {
		
		compressor.setKnee(0.5);
		compressor.setThreshold(-20);
		compressor.setRatio(3.0);
		switch (((int)*parameters.getRawParameterValue("compDegree")))
		{
		case 1:

			compressor.setAttackTime(6 / 1000);
			compressor.setReleaseTime(2 / 1000);
			compressor.setMakeUpGain(1);
			
			break;
		case 2:

			compressor.setAttackTime(5 / 1000);
			compressor.setReleaseTime(3 / 1000);
			compressor.setMakeUpGain(2);



			break;
		case 3:

			compressor.setAttackTime(4 / 1000);
			compressor.setReleaseTime(4 / 1000);
			compressor.setMakeUpGain(3);



			break;
		case 4:
			
			compressor.setAttackTime(3 / 1000);
			compressor.setReleaseTime(5 / 1000);
			compressor.setMakeUpGain(4);


			break;
		case 5:
			
			compressor.setAttackTime(2 / 1000);
			compressor.setReleaseTime(6 / 1000);
			compressor.setMakeUpGain(5);


			break;
		default:
			break;
		}
		parameters.state.sendPropertyChangeMessage("attack");
		parameters.state.sendPropertyChangeMessage("release");
		parameters.state.sendPropertyChangeMessage("makeUp");
		
	 
			characteristicChanged = true;
			
			updateHostDisplay();
			

	}
	else
		jassertfalse;
}

I’m so surprised so there’s no way for me to do the sliderAttachments textboxes update their values with the ones I set.

If anybody could help and also suggest some style or best-practice coding I’ll be glad, because at now the project is stopped. I’ve uploaded it to github @

Best regards,
ealcober.

Are you deriving your editor from Slider::Listener?

Forgive my ignorance, but for what purpose?

For a slider text box to take calls from the processor (w/ addListener(this), you have to add Slider::Listener as a publicly inherited base class of your editor. Not sure how to paste code in here but I have some I’ll try to copy.

Like this - class ExamplePluginEditor : public AudioProcessorEditor, Slider::Listener, Value::Listener…

in the header file

Oh… That sounds great! Let me try this evening and I’ll be back with results… Thank you very much :raised_hands:

Sorry to interrupt, but that is the wrong approach.

The textual representation of a parameter is defined in the parameter itself, because it is used for the hosts parameter display as well.

Have a look at the arguments of the AudioParameterFloat constructor. You supply two lambdas, one to convert the value into a string and one to parse the string into a value for user input.

By using the AudioProcessorValueTreeState::SliderAttachment this lambdas are also used in the Slider without further customisation necessary. In fact, adding the SliderAttachment reverts most of the Slider settings intentionally.

Oh, OK, so if lambdas are defined, sliderValueChanged will use floating point lambda in the callbacks ?

I am working with components attachments, as SliderAttachment, but as said, no update on the sliders when a change on the main component is done

So you mean with this changes, changes on the editor will be broadcasted to Processor?

I’ve been testing this idea and the project dont compile with that inherit class, Slider::Listener and also not Value::Listener

So do you suggest then, is to create a Lambda for update? I dont understand you so much

Not a lambda but a SliderProcessorAttachment. That has all logic implemented to synchronise the parameter value and the slider value, without update loops. And it takes care of initial update. It also takes care of thread safety and begin-/endChangeGesture().

If you use the Slider::Listener and the AudioProcessorValueTreeState::Listener, you need to take care of those things manually, that you will write each time you connect a control with a parameter.

The DSP and the GUI should individually look at the AudioProcessorParameter, instead of updating from control directly to the DSP.

And where can I found some example about this, please?

I have the SilderAttachment as public variables on pluginEditor.h

    std::unique_ptr<SliderAttachment> thresholdAttachment, kneeAttachment, attackAttachment,
        releaseAttachment, ratioAttachment, makeUpAttachment, compDegreeAttachment;

Anyway I cant access from PluginProcessor.cpp and that’s the problem…

I understand the point is to advice this components, but how?

If you use the Slider::Listener and the AudioProcessorValueTreeState::Listener, you need to take care of those things manually, that you will write each time you connect a control with a parameter.

could you please @daniel be just a little more speciffic with the code I’ve uploaded? I’ve been trying with tests on the code with no result…

Best regards…
Edu A.

You don’t need to update the attachment. By changing the parameter, it will automatically update the control. And by changing the control, it will change the parameter, if the host’s automation settings allow that.

The AudioProcessorParameter is the single source of truth, or the data model, whichever term you prefer.
The Control is the GUI, in MVC terms the view, and the attachment the controller, that takes care that view and model always stay in sync.

I wondered this, for sure… but in terms of host, OBS doesnt reflects any changes at all on Sliders when I change the compressor parameters. That’s the question

Hello Daniel, I’ve been doing several tests with nuendo and other hosts, just to try if the update of the sliders suceded as you told me. It does not happen.
I’ve tried

parameters.processor.updateHostDisplay();
		updateHostDisplay();

with same no result.

Finally working just using the SliderAttachment and changing the parameters from the layout like this

attack = parameters.getParameterAsValue("attack");
attack = 40.0;